diff options
author | nagai <nagai@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2003-08-29 08:34:14 +0000 |
---|---|---|
committer | nagai <nagai@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2003-08-29 08:34:14 +0000 |
commit | 24ff3f444882ba60418a6736d6c5d57ba3c0b80c (patch) | |
tree | 813a69918ff8435617ca58e193f9440c06febdb7 | |
parent | 22a5aec4b322c1be9eced78967e5cfd0ae54b6cb (diff) |
* doc/ChangeLog-1.8.0: add changes of Ruby/Tk
* ext/tcltklib/tcltklib.c : some methods have no effect if on slave-IP
* ext/tcltklib/tcltklib.c : can create a interpreter without Tk
* ext/tcltklib/tcltklib.c : bug fix on handling exceptions
* ext/tcltklib/MANUAL.euc : modify
* ext/tk/lib/tk.rb : freeze some core modules
* ext/tk/lib/multi-tk.rb : more secure
* ext/tk/lib/tk.rb: TkVariable.new(array) --> treat the array as the
Tk's list
* ext/tk/lib/tk.rb: improve accessibility of TkVariable object
* ext/tk/lib/tk.rb, ext/tk/lib/tkfont.rb, ext/tk/lib/tkcanvas.rb,
ext/tk/lib/tktext.rb : fix bug of font handling
* ext/tk/lib/tkfont.rb TkFont.new() accepts compound fonts
* process.c: bug fix
* process.c: add rb_secure(2) to methods of Process::{UID,GID,Sys}
* process.c: deny handling IDs during evaluating the block given to
the Process::{UID,GID}.switch method
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@4456 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r-- | ChangeLog | 31 | ||||
-rw-r--r-- | doc/ChangeLog-1.8.0 | 468 | ||||
-rw-r--r-- | ext/tcltklib/MANUAL.euc | 40 | ||||
-rw-r--r-- | ext/tcltklib/tcltklib.c | 304 | ||||
-rw-r--r-- | ext/tk/lib/multi-tk.rb | 196 | ||||
-rw-r--r-- | ext/tk/lib/tk.rb | 308 | ||||
-rw-r--r-- | ext/tk/lib/tkcanvas.rb | 22 | ||||
-rw-r--r-- | ext/tk/lib/tkfont.rb | 239 | ||||
-rw-r--r-- | ext/tk/lib/tktext.rb | 34 | ||||
-rw-r--r-- | process.c | 188 |
10 files changed, 1660 insertions, 170 deletions
@@ -1,3 +1,34 @@ +Fri Aug 29 17:30:15 2003 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp> + + * process.c: bug fix + + * process.c: add rb_secure(2) to methods of Process::{UID,GID,Sys} + + * process.c: deny handling IDs during evaluating the block given to + the Process::{UID,GID}.switch method + + * ext/tcltklib/tcltklib.c : some methods have no effect if on slave-IP + + * ext/tcltklib/tcltklib.c : can create a interpreter without Tk + + * ext/tcltklib/tcltklib.c : bug fix on handling exceptions + + * ext/tcltklib/MANUAL.euc : modify + + * ext/tk/lib/tk.rb : freeze some core modules + + * ext/tk/lib/multi-tk.rb : more secure + + * ext/tk/lib/tk.rb: TkVariable.new(array) --> treat the array as the + Tk's list + + * ext/tk/lib/tk.rb: improve accessibility of TkVariable object + + * ext/tk/lib/tk.rb, ext/tk/lib/tkfont.rb, ext/tk/lib/tkcanvas.rb, + ext/tk/lib/tktext.rb : fix bug of font handling + + * ext/tk/lib/tkfont.rb TkFont.new() accepts compound fonts + Thu Aug 28 17:30:24 2003 Yukihiro Matsumoto <matz@ruby-lang.org> * variable.c (rb_const_get_0): should check constants defined in diff --git a/doc/ChangeLog-1.8.0 b/doc/ChangeLog-1.8.0 index 6acb8ff20f..d168a50f80 100644 --- a/doc/ChangeLog-1.8.0 +++ b/doc/ChangeLog-1.8.0 @@ -40,6 +40,13 @@ Sun Aug 3 23:56:50 2003 Nobuyoshi Nakada <nobu@ruby-lang.org> * eval.c (rb_call_super): should propagate previous block for super call. [ruby-talk:77884] +Sun Aug 3 22:07:47 2003 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp> + + * ext/tk/lib/tkentry.rb: support 'validatecommand' option of + TkEntry/TkSpinbox widget + + * ext/tk/sample/{demos-en,demos-jp}/spin.rb: add + Sun Aug 3 19:25:28 2003 Nobuyoshi Nakada <nobu@ruby-lang.org> * eval.c (call_trace_func): clear exception flag temporarily. @@ -51,6 +58,21 @@ Sun Aug 3 18:03:44 2003 WATANABE Hirofumi <eban@ruby-lang.org> * lib/un.h (help): new. % ruby -run -e help cp +Sun Aug 3 08:53:06 2003 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp> + + * ext/tk/sample/{demos-en,demos-jp}/image3.rb: add + + * ext/tk/lib/tkcanvas.rb: bug fix on Tk object ID management + + * ext/tk/lib/tktext.rb: ditto + +Sun Aug 3 02:55:52 2003 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp> + + * process.c: modify macro to detect 'MacOS X' [ruby-talk:77849] + + * ext/tcltklib/lib/tcltk.rb: bug fix ( NOT MAINTAINED : only + for running 'line2.rb' demo. ) + Sun Aug 3 02:45:06 2003 Koji Arai <jca02266@nifty.ne.jp> * numeric.c (flo_to_s): get rid of buffer overflow. @@ -60,6 +82,14 @@ Sat Aug 2 23:51:52 2003 Yukihiro Matsumoto <matz@ruby-lang.org> * io.c (appendline): clearerr(3) before raising exception, since exception may be captured by rescue. [ruby-talk:77794] +Sat Aug 2 09:58:13 2003 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp> + + * ext/tk/lib/tk.rb: bug fix --- TkGrid failed to treat + RELATIVE PLACEMENT + + * ext/tk/sample/demos-en/, demos-jp/: add or modify some + widget demo scripts + Sat Aug 2 20:59:38 2003 GOTOU Yuuzou <gotoyuzo@notwork.org> * lib/webrick/https.rb: change an option name. @@ -90,6 +120,24 @@ Sat Aug 2 14:02:39 2003 Nobuyoshi Nakada <nobu@ruby-lang.org> * variable.c (classname): find regular class name if not set. [ruby-dev:20496] +Sat Aug 2 09:58:13 2003 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp> + + * ext/tk/lib/tk.rb: bug fix --- forgot to entry a widget class + name of 'labelframe' widget + + * ext/tk/sample/{demos-en,demos-jp}/{labelframe.rb,paned1.rb, + paned2.rb,spin.rb}: add demo-scripts to the JP/EN widget demos + +Sat Aug 2 05:04:30 2003 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp> + + * ext/tk/lib/tkentry.rb: bug fix of TkEntry#delete + + * ext/tk/samples/: bug fix of some widget demos + + * ext/tk/lib/tk.rb: support <TkVariable object> == <Symbol> + + * ext/tk/lib/*.rb: freeze some object for security reason + Sat Aug 2 03:30:25 2003 Yukihiro Matsumoto <matz@ruby-lang.org> * class.c (rb_obj_singleton_methods): should not go up to @@ -141,6 +189,10 @@ Fri Aug 1 19:48:56 2003 Yukihiro Matsumoto <matz@ruby-lang.org> * gc.c (rb_gc): should mark backing store region on IA64. +Fri Aug 1 18:51:10 2003 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp> + + * process.c: bug fix --- preprocessor errors occur on OpenBSD-current + Fri Aug 1 17:13:23 2003 Nobuyoshi Nakada <nobu@ruby-lang.org> * ext/openssl/extconf.rb: should replace literally. @@ -184,6 +236,13 @@ Fri Aug 1 09:54:38 2003 Yukihiro Matsumoto <matz@ruby-lang.org> * hash.c (env_clear): ditto. +Fri Aug 1 04:58:55 2003 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp> + + * ext/tk/lib/tk.rb: bug fix --- forget to eval given block to + TkRoot.new method + + * ext/tk/sample/tkoptdb-safeTk.rb: new sample script + Fri Aug 1 00:52:58 2003 Yukihiro Matsumoto <matz@ruby-lang.org> * gc.c (Init_stack): IA64 requires STACK_LEVEL_MAX to be less than @@ -194,11 +253,38 @@ Thu Jul 31 23:44:00 2003 Masatoshi SEKI <m_seki@mva.biglobe.ne.jp> * lib/erb.rb: import erb-2.0.4b4. +Thu Jul 31 23:04:45 2003 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp> + + * ext/tk/sample/resource.en, ext/tk/sample/resource.jp: + wrong resource file format + + * ext/tk/lib/tk.rb: add Tk::Encoding.{encoding_convertfrom, + encoding_convertto} + + * ext/tk/lib/tk.rb: add TkOptionDB.read_with_encoding to read + non-utf8 resource file + Thu Jul 31 23:02:47 2003 NAKAMURA Usaku <usa@ruby-lang.org> * ext/etc/etc.c: revert getenv()'s prototype. use it only when _WIN32 is not defined. +Thu Jul 31 20:52:40 2003 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp> + + * ext/tk/lib/tk.rb: (IMPORTANT BUG FIX) scan of event keywords + doesn't work on recent versions of Tck/Tk + + * ext/tk/lib/tk.rb: initialize error of instance variable on + TkComposite + + * ext/tk/lib/multi-tk.rb: initialize error on encoding-system on + MultiTkIp + + * ext/tk/lib/tk.rb: trouble on destroying widgets + + * ext/tk/sample/demos-en/, demos-jp/: add JP and EN version of + Ruby/Tk widget demos + Thu Jul 31 15:25:12 2003 NAKAMURA Usaku <usa@ruby-lang.org> * array.c (rb_ary_collect): must get length of array for each @@ -223,6 +309,17 @@ Thu Jul 31 08:18:00 2003 Nathaniel Talbott <ntalbott@ruby-lang.org> * lib/test/unit.rb: A useful return code is now set if tests fail when running automatically using the Console::TestRunner. +Thu Jul 31 07:59:18 2003 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp> + + * ext/tk/lib/tk.rb: wrap the command-proc of TkScale --- pass + the numeric object to the proc + + * ext/tk/lib/tk.rb: better support for widgets created on + Tk interpreter (without Ruby) + + * ext/tk/lib/multi-tk.rb: a little more stable on Multiple Tk + interpreters running + Thu Jul 31 00:17:19 2003 Shugo Maeda <shugo@ruby-lang.org> * lib/net/ftp.rb (return_code): obsolete. @@ -310,6 +407,23 @@ Wed Jul 30 09:31:55 2003 Nobuyoshi Nakada <nobu.nokada@softhome.net> * ext/socket/socket.c (sock_initialize): rename from sock_init() to get rid of conflict with OS/2 socket library. +Wed Jul 30 07:23:14 2003 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp> + + * ext/tk/lib/tkentry.rb: fix lack of methods for TkEntry + + * ext/tk/lib/multi-tk.rb, ext/tk/lib/tk.rb, + ext/tk/lib/tkdialog.rb, ext/tk/lib/tkentry.rb, + ext/tk/sample/safe-tk.rb, ext/tk/sample/tktimer2.rb: bug fix + + * ext/tk/lib/multi-tk.rb: MultiTkIp.new_* accept a block to + eval under the new interpreter + +Wed Jul 30 04:36:30 2003 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp> + + * ext/tcltklib/tcltklib.c, + ext/tk/lib/tk.rb, ext/tk/lib/tkafter.rb: additional check of + Tk interpreters' status for a little more safety + Wed Jul 30 02:37:12 2003 Yukihiro Matsumoto <matz@ruby-lang.org> * marshal.c (w_object): if object responds to 'marshal_dump', @@ -398,6 +512,18 @@ Mon Jul 28 22:57:52 2003 Yukihiro Matsumoto <matz@ruby-lang.org> * io.c (rb_f_getc): $stdin may not be IO. [ruby-dev:20973] +Tue Jul 29 16:20:36 2003 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp> + + * ext/tcltklib/tcltklib.c: bug fix and + change mainloop_abort_on_no_widget_cmd => mainloop_abort_on_exception + ( to avoid thread timing trouble on accessing destroyed widgets ) + + * ext/tk/lib/multi-tk.rb: change default mode of + mainloop_abort_on_exception on multi-tk.rb + + * ext/tk/lib/multi-tk.rb: fix a bug of the procedure for + 'Delete' button on the safe-Tk frmae + Tue Jul 29 12:22:28 2003 why the lucky stiff <ruby-cvs@whytheluckystiff.net> * ext/syck/token.c: prefixed many constants and definitions @@ -413,6 +539,12 @@ Tue Jul 29 12:15:37 2003 NAKAMURA Usaku <usa@ruby-lang.org> * win32/win32.h: add arguments to definitions of functions if possible. +Tue Jul 29 08:05:30 2003 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp> + + * ext/tk/lib/tk.rb, ext/tk/lib/tkdialog.rb, ext/tk/lib/tktext.rb, + ext/tk/sample/tkbiff.rb, ext/tk/sample/tkdialog.rb, + ext/tk/sample/tkform.rb: bug fix ( tested with Ruby/Tk widget demo ) + Tue Jul 29 04:22:08 2003 why the lucky stiff <ruby-cvs@whytheluckystiff.net> * ext/syck/syck.h: Added 'syck' yacc prefixes. @@ -428,6 +560,20 @@ Tue Jul 29 03:53:28 2003 GOTOU Yuuzou <gotoyuzo@notwork.org> * ext/openssl/lib/net/https.rb (use_ssl=): raise ProtocolError if connection is set up already. +Tue Jul 29 01:45:32 2003 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp> + + * ext/tcltklib/tcltklib.c: use RTEST() + +Tue Jul 29 01:24:32 2003 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp> + + * ext/tcltklib/tcltklib.c: bug fix + + * ext/tk/lib/multi-tk.rb: bug fix and pack options are pssed + to the safeTk container + + * ext/tk/sample/safe-tk.rb: add example for pack options of + safeTk container + Mon Jul 28 23:23:08 2003 Nobuyoshi Nakada <nobu.nokada@softhome.net> * file.c (Init_File): IO should include File::Const. @@ -460,6 +606,16 @@ Mon Jul 28 15:32:04 2003 Yukihiro Matsumoto <matz@ruby-lang.org> * io.c (argf_forward): utility function to forward method to current_file. +Mon Jul 28 06:10:13 2003 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp> + + * ext/tcltklib/tcltklib.c: bug fix + + * ext/lib/tk/multi-tk.rb: bug fix + + * ext/lib/tk/multi-tk.rb: add methods depend on Tcl's 'interp' command + + * ext/lib/tk/multi-tk.rb: suppot safe-level control of each interpreter + Mon Jul 28 03:08:47 2003 Akinori MUSHA <knu@iDaemons.org> * lib/set.rb: each() should return self. @@ -482,6 +638,22 @@ Sun Jul 27 21:16:30 2003 WATANABE Hirofumi <eban@ruby-lang.org> * mkconfig.rb: initialize global variables to avoid warnings. +Sun Jul 27 19:35:06 2003 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp> + + * ext/tcltklib/tcltklib.c: add some methods to support + multiple interpreters (low level) + + * ext/tk/lib/multi-tk.rb: new library to support multiple Tk + interpreters (high level) + + * ext/tcltklib/demo/safeTk.rb: new sample of safeTk interpreter + + * ext/tk/sample/safe-tk.rb: new sample of multi-tk.rb + + * ext/tk/lib/tk.rb: bug fix and add feature to supprt multi-tk + + * ext/tk/lib/tkafter.rb: ditto + Sun Jul 27 14:43:37 2003 NAKAMURA, Hiroshi <nahi@ruby-lang.org> * lib/debug.rb: fix breakpoint parameter parsing/checking. @@ -558,6 +730,18 @@ Fri Jul 26 00:04:25 2003 NAKAMURA, Hiroshi <nakahiro@sarion.co.jp> - cert_store_view.rb: certificate store viewer with FXRuby. Uses c_rehash.rb, crlstore.rb and certstore.rb. +Fri Jul 25 16:43:03 2003 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp> + + * ext/tcltklib/tcltklib.c: add TclTkIp#create_slave, + TclTkIp#_make_safe and TclTkIp#safe? + + * ext/tcltklib/MANUAL.euc: modify descriptions + + * ext/tk/lib/tk.rb: bug fix [ruby-talk:76980] and modify to + support multi Tk IPs + + * ext/tk/lib/tkafter.rb: modify to support multi Tk IPs + Fri Jul 25 15:47:39 2003 GOTOU Yuuzou <gotoyuzo@notwork.org> * ext/openssl/extconf.rb: add check for BN_rand_range() and @@ -725,6 +909,18 @@ Wed Jul 23 18:21:52 2003 Nobuyoshi Nakada <nobu.nokada@softhome.net> * ext/io/wait: imported. +Wed Jul 23 16:07:35 2003 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp> + + * process.c: unify indentation + + * configure.in: add --enable-setreuid option + + * ext/tcltklib/tcltklib.c: TclTkIp.new accepts 'ip-name' and 'options' + + * ext/tk/lib/tk.rb: support arguments of TclTkIp.new + + * ext/tk/lib/tk*.rb: preparations for multi-Tk interpreter support + Wed Jul 23 15:49:01 2003 Yukihiro Matsumoto <matz@ruby-lang.org> * string.c (rb_str_lstrip_bang): strip NUL along with white @@ -743,6 +939,12 @@ Wed Jul 23 10:11:15 2003 Nobuyoshi Nakada <nobu.nokada@softhome.net> * ext/iconv/iconv.c (iconv_convert): stringify argument. +Wed Jul 23 02:39:46 2003 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp> + + * process.c: add a module for raw syscalls to control UID/GID + + * process.c: add modules for portable UID/GID control + Tue Jul 22 19:16:40 2003 Tanaka Akira <akr@m17n.org> * ext/iconv/iconv.c (iconv_failure_initialize): limit @@ -906,6 +1108,11 @@ Thu Jul 17 13:42:53 2003 WATANABE Hirofumi <eban@ruby-lang.org> * lib/ftools.rb (File::makedirs): do not handle "//" as a directory. +Thu Jul 17 06:40:28 2003 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp> + + * ext/tk/lib/tk.rb: recover and fix typo : Tk.chooseDirectory + (Tk8.4 feature) + Wed Jul 16 16:23:58 2003 Yukihiro Matsumoto <matz@ruby-lang.org> * eval.c (rb_proc_new): call svalue_to_avalue for yield argument. @@ -987,6 +1194,13 @@ Fri Jul 11 16:09:09 2003 Yukihiro Matsumoto <matz@ruby-lang.org> * util.c (ruby_strtod): exp should be less than MDMAXEXPT. +Fri Jul 11 07:17:47 2003 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp> + + * ext/tk/lib/tk.rb: not create a Tcl/Tk interpreter if already + defined TkCore::INTERP + + * ext/tk/lib/tk.rb: bugfix on TkWindow#configure + Thu Jul 10 14:42:02 2003 WATANABE Hirofumi <eban@ruby-lang.org> * math.c (math_log): nan takes a dummy argument on Cygwin 1.5.0. @@ -1176,6 +1390,13 @@ Wed Jul 2 01:32:40 2003 WATANABE Hirofumi <eban@ruby-lang.org> * lib/net/pop.rb (Net::POP3#start): typofix. +Tue Jul 1 22:08:19 2003 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp> + + * ext/tk/lib/tk.rb: TkWindow include TkWinfo + + * ext/tk/lib/tk.rb: treat unknown widget classes as subclasses + of TkWindow + Tue Jul 1 19:02:12 2003 WATANABE Hirofumi <eban@ruby-lang.org> * parse.y (rb_intern): should use mbclen instead of mblen. @@ -1236,17 +1457,48 @@ Thu Jun 26 21:34:49 2003 Nobuyoshi Nakada <nobu.nokada@softhome.net> arguement type mismatch, and inline method_list(). [ruby-core:01198] +Wed Jun 25 14:40:33 2003 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp> + + * ext/tk/lib/tk.rb: add and modify methods --- + TkWidget.database_class, TkWidget.database_classname, + TkWidget#database_class, TkWidget#database_classname + + * ext/tk/lib/tk.rb: instances of a subclass of TkToplevel or + TkFrame are created with ":class=>subclass" option as default. + + * ext/tk/sample/tkoptdb.rb: add a new part + Wed Jun 25 12:52:58 2003 Matthew Dempsky <jivera@flame.org> * class.c (rb_generic_class_instance_methods): merge argument check (and warning) into one function; following DRY principle. [ruby-core:01193] +Wed Jun 25 05:49:10 2003 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp> + + * ext/tk/lib/tk.rb: add widget destroy hook binding to TkBindTag::ALL + + * ext/tk/lib/tkcanvas.rb: Although requiring manual control of GC, + memory eating problem of TkCanvas Items is fixed. + + * ext/tk/lib/tktext.rb: add some methods and bug fix + Wed Jun 25 00:14:30 2003 Yukihiro Matsumoto <matz@ruby-lang.org> * variable.c (autoload_delete): should delete Qundef from iv_tbl. (ruby-bugs-ja PR#504) +Tue Jun 24 16:46:07 2003 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp> + + * ext/tk/lib/tk.rb: bug fix on TkToplevel, TkFrame, + TkPanedwindow, TkOptionDB + + * ext/tk/lib/tk.rb: TkOptionDB --- make it more secure to use procs + defined on resourceDB + + * ext/tk/sample/tkoptdb.rb, resource.ja, resource.en: + sample script how to use TkOptionDB. + Tue Jun 24 14:22:41 2003 why the lucky stiff <ruby-cvs@whytheluckystiff.net> * lib/yaml/types.rb: replaced Kernel::Hash reference with Object::Hash @@ -1318,6 +1570,10 @@ Mon Jun 23 16:18:12 2003 Tanaka Akira <akr@m17n.org> * time.c (time_arg): initialize v[6] even when argc is 10 to avoid valgrind error. +Mon Jun 23 14:22:44 2003 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp> + + * ext/tk/lib/tk.rb: bug fix on TkRoot and TkToplevel + Mon Jun 23 08:24:01 2003 Florian Frank <flori@nixe.ping.de> * string.c (rb_str_upto): generate sequence according to "succ" @@ -1352,6 +1608,18 @@ Sun Jun 22 23:42:20 2003 Nobuyoshi Nakada <nobu.nokada@softhome.net> * file.c (rb_file_s_readlink): expand buffer until readlink succeed. +Sun Jun 22 16:17:02 2003 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp> + + * ext/tk/lib/tk.rb: TkRoot.new and TkToplevel.new accept Wm + commands as elements + + * ext/tk/lib/tk.rb: TkMenu --- add some methods + + * ext/tk/lib/tk.rb: TkOptionMenubutton --- bug fix + + * ext/tk/sample/tkmenubutton.rb: sample of TkMenubutton and + TkOptionMenubutton + Sat Jun 21 23:15:08 2003 Yukihiro Matsumoto <matz@ruby-lang.org> * eval.c (proc_invoke): should not propagate distination tag if @@ -1366,6 +1634,25 @@ Sat Jun 21 13:56:09 2003 Takaaki Uematsu <uema2x@jcom.home.ne.jp> * wince/resource.rb: include winver.h in wince3.0. +Sat Jun 21 12:55:17 2003 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp> + + * ext/tk/lib/tk.rb: TkRoot.new and TkToplevel.new accept Wm commands + as elements of a hash argument. + + * ext/tk/sample/tktimer2.rb: add comments about the usage of a + TkTimer object. + +Sat Jun 21 08:47:22 2003 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp> + + * ext/tk/lib/tk*.rb: remove direct-accesses to TkComm::INTERP and + TkComm::INITIALIZE_TARGETS + + * ext/tk/lib/tk*.rb: use TkINTERP_SETUP_SCRIPTS constant for setting + up the interpreter + + * ext/tcltklib/tcltklib.c: support to create a safe interpreter + with safe-Tk + Fri Jun 20 23:28:27 2003 Yukihiro Matsumoto <matz@ruby-lang.org> * eval.c (proc_invoke): should not propagate TAG_BREAK and @@ -1385,6 +1672,10 @@ Fri Jun 20 15:04:28 2003 NAKAMURA Usaku <usa@ruby-lang.org> * ruby.c (proc_options): ditto. +Fri Jun 20 14:52:46 2003 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp> + + * ext/tcltklib/tcltklib.c: Tk interpreter returns TAINTED strings. + Fri Jun 20 03:09:21 2003 Yukihiro Matsumoto <matz@ruby-lang.org> * parse.y (new_yield): distinguish "yield 1,2" and "yield [1,2]". @@ -1410,6 +1701,42 @@ Thu Jun 19 22:51:41 2003 Masatoshi SEKI <m_seki@mva.biglobe.ne.jp> lib/drb/invokemethod.rb, lib/drb/observer.rb, lib/drb/timeridconv.rb, lib/drb/unix.rb: import drb-2.0.4b3 +Thu Jun 19 16:14:43 2003 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp> + + * ext/tcltklib/tcltklib.c (lib_do_one_event): change default + value of the argument + + * ext/tcltklib/tcltklib.c (lib_do_one_event): returns true/false + + * ext/tcltklib/tcltklib.c: add TclTkLib::EventFlag::NONE ( == 0 ) + + * ext/tcltklib/tcltklib.c: add set_no_event_wait() and + get_no_event_wait() + + * ext/tcltklib/MANUAL.euc: modify + + * ext/tcltklib/README.euc: ditto + + * ext/tk/lib/tk.rb: change default value of TkCore.do_one_event + argument + + * ext/tk/lib/tk.rb: add TkCore.set_no_event_wait(wait) and + TkCore.get_no_event_wait + + * ext/tk/lib/tk.rb: add Tk.exit ( == destroy root widget ) + + * ext/tk/lib/tkafter.rb: rename TkAfter => TkTimer (TkAfter is + an alias name) + + * ext/tk/lib/tkafter.rb: set_callback returns self + + * ext/tk/lib/tkafter.rb: continue() raises an exception, if already + running or no procedure. + + * ext/tk/lib/tkafter.rb: skip() raises an exception, if not running. + + * ext/tk/sample/tktimer2.rb: new sample for TkTimer class. + Thu Jun 19 16:13:54 2003 WATANABE Hirofumi <eban@ruby-lang.org> * rubytest.rb: add library path to include standard libraries. @@ -1435,6 +1762,88 @@ Wed Jun 18 23:41:27 2003 Marc Cartright <marc@isri.unlv.edu> deflate/inflate will return Z_BUF_ERROR, even though another call is required by the zlib library. +Wed Jun 18 19:46:21 2003 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp> + + * ext/tk/lib/tk.rb: bug fix + + * ext/tk/lib/tk.rb: rename 'no_create' option to 'without_creating' + + * ext/tk/lib/tk.rb: add TkWindow#pack_in, TkWindow#grid_in, + TkWindow#place_in + + * ext/tk/lib/tk.rb: add TkWindow#bind_class and TkWindow#database_class + + * ext/tk/lib/tk.rb: add TkBindTag.new_by_name and TkDatabaseClass + for binding to database class + + * ext/tk/lib/tk.rb: check varname whether already exsist or not. + (TkVarAccess.new) + + * ext/tk/lib/tk.rb: TkTextWin#bbox returns an array of four numbers + + * ext/tk/lib/tk.rb: autoload TkDialog2, TkWarning2 + + * ext/tk/lib/tk.rb: scan event callback arguments and convert + to proper type + + * ext/tk/lib/tk.rb: TkBindTag.new accepts a block + + * ext/tk/lib/tk.rb: If given taglist, TkWindow#bindtags(taglist) + returns taglist + + * ext/tk/lib/tk.rb: add TkWindow#bindtags=(taglist) + + * ext/tk/lib/tk.rb: Tk.focue and Tk.focus_lastfor return nil + if there is no target widget. + + * ext/tk/lib/tk.rb: Tk::Wm.client returns the argument string + when setting name + + * ext/tk/lib/tk.rb: TkGrid.columnconfiginfo and rowconfiginfo + given a slot return a number. + + * ext/tk/lib/tk.rb: TkWindow.grid_columnconfiginfo and + grid_rowconfiginfo --- ditto + + * ext/tk/lib/tk.rb: rename and define alias :: TkOption ==> TkOptionDB + + * ext/tk/lib/tk.rb: define alias :: TkTimer ==> TkAfter + + * ext/tk/lib/tk.rb: some instance methods change from public to private + + * ext/tk/lib/tk.rb: some TkComm methods change to module functions + + * ext/tk/lib/tk.rb: add support for -displayof option to some + TkWinfo methods + + * ext/tk/lib/tk.rb: bind, bind_append and bind_remove --- + returns the target of event-binding + + * ext/tk/lib/tk.rb: add Tk8.4 features + + * ext/tk/lib/tk.rb: add TkPaneWindow + + * ext/tk/lib/tkdialog.rb: bug fix + + * ext/tk/lib/tkdialog.rb: some methods return self + + * ext/tk/lib/tkdialog.rb: add TkTextMark#+(mod) and TkTextMark#-(mod) + + * ext/tk/lib/tkdialog.rb: add some methods + + * ext/tk/lib/tkcanvas.rb: bug fix and some methods return self + + * ext/tk/lib/tkentry.rb: some methods return self + + * ext/tk/lib/tkentry.rb: TkEntry#bbox returns an array of four numbers + + * ext/tk/lib/tkentry.rb: scan validatecommand arguments and + convert to proper type + + * ext/tk/lib/tkbgerror.rb: support to define a error handler by user + + * ext/tcltklib/tcltklib.c: [ruby-talk:60759] + Wed Jun 18 13:50:06 2003 Yukihiro Matsumoto <matz@ruby-lang.org> * eval.c (rb_eval): should dispatch based on ID type. @@ -1520,6 +1929,27 @@ Fri Jun 13 09:24:39 2003 Shugo Maeda <shugo@ruby-lang.org> * lib/net/ftp.rb (putbinaryfile): rescue FTPPermError. +Thu Jun 12 22:13:13 2003 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp> + + * ext/tk/lib/tk.rb : add 'no_create' option to widget + initialize method. + + * ext/tk/MANIFEST : forgot to commit when added tkmacpkg.rb + and tkwinpkg.rb + + * ext/tk/lib/README : ditto. + +Thu Jun 12 21:14:11 2003 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp> + + * ext/tk/lib/tk.rb : widget configure returns self (for method + call chain) + + * ext/tk/lib/tkmacpkg.rb : Mac resource (not new but not + included until now) + + * ext/tk/lib/tkwinpkg.rb : Win DDE and registry (not new but not + included until now) + Tue Jun 10 14:26:30 2003 why the lucky stiff <ruby-cvs@whytheluckystiff.net> * ext/syck/token.c: preserve newlines prepended to a block. @@ -1550,6 +1980,14 @@ Mon Jun 9 19:02:33 2003 Nobuyoshi Nakada <nobu.nokada@softhome.net> * process.c (proc_getgroups, proc_setgroups): raise NotImplementedError unless available. [ruby-talk:73014] +Mon Jun 9 18:09:11 2003 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp> + + * ext/tcltklib/tcltklib.c: fixed 100% CPU problem of Tk.mainloop + +Mon Jun 9 15:50:24 2003 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp> + + * ext/tcltklib/tcltklib.c: renewal Tk.mainloop + Sun Jun 8 13:37:21 2003 Takaaki Uematsu <uema2x@jcom.home.ne.jp> * wince/setup.mak: set SUBSYSTEM in each platform. @@ -7886,6 +8324,11 @@ Thu Jun 6 11:42:15 2002 Nobuyoshi Nakada <nobu.nokada@softhome.net> * lib/thread.rb (Queue::pop): get rid of race condition. +Wed Jun 5 01:56:47 2002 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp> + + * ext/tcltklib/tcltklib.c: Stop the running zombi-eventloop when + mainloop_watchdog is killed. + Tue Jun 4 23:09:24 2002 Yukihiro Matsumoto <matz@ruby-lang.org> * range.c (range_include): should be based on "<=>", whereas @@ -7899,6 +8342,31 @@ Tue Jun 4 18:28:37 2002 WATANABE Hirofumi <eban@ruby-lang.org> * ext/Win32API/extconf.rb: refactoring. +Tue Jun 4 07:03:33 2002 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp> + + * ext/tk/lib/tkfont.rb: Fix bugs on TkFont.init_widget_font for Tk8.x. + + * ext/tk/lib/tkafter.rb: Add self to 1st argument of interval- + and loop-proc + TkAfter#current_interval returns an interval (sleep) time value + TkAfter#current_args returns an array of arguments + TkAfter#return_value returns a return value of last loop-proc + + * ext/tk/lib/tk*.rb: Allow to use Symbols for parameters. + + * ext/tk/lib/tkcanvas.rb: (TkcItem) Add 'coords' parameter to the + canvas item constructor (for new notation of constructor). + + * ext/tcltklib/tcltklib.c: New 'mainloop' and 'mainloop_watchdog'. + + * ext/tk/lib/tk.rb: (Tk.restart) Add 'app-name' paramater and + 'use' parameter. + + * ext/tk/lib/tk.rb: Add new parameter 'widgetname' to the widget + constructor to support effective use of Resource Database. + + * ext/tk/lib/tk.rb: TkOption::get always returns a tainted string. + Tue Jun 4 00:45:50 2002 Nobuyoshi Nakada <nobu.nokada@softhome.net> * ext/socket/addrinfo.h: typo. diff --git a/ext/tcltklib/MANUAL.euc b/ext/tcltklib/MANUAL.euc index 30cfd8c107..f04d036c64 100644 --- a/ext/tcltklib/MANUAL.euc +++ b/ext/tcltklib/MANUAL.euc @@ -1,5 +1,5 @@ (tof) - 2003/07/25 Hidetoshi NAGAI + 2003/08/07 Hidetoshi NAGAI 本ドキュメントには古い tcltk ライブラリ,tcltklib ライブラリの説明 が含まれていますが,その記述内容は古いものとなっています. @@ -263,6 +263,12 @@ require "tcltklib" すると, 以下のモジュール, クラスが利用可能です. : Tk インタープリタ上で例外を発生した際に,イベントループをエ : ラー停止させるかどうかの設定状態を true/false で得る. + num_of_mainwindows + : 現在のメインウィンドウ (ルートウィジェット) の数を返す. + : メインウィンドウは一つのインタープリタに付き最大一つである + : ので,この値は現在 Tk の機能が有効であるインタープリタの総 + : 数に等しい. + クラス TclTkIp クラスメソッド @@ -274,6 +280,11 @@ require "tcltklib" すると, 以下のモジュール, クラスが利用可能です. : 引数として与えるオプションと同様の情報を文字列として与える. : 与えられた情報は,root widget 生成の際に用いられる. : ( e.g. TclTkIp.new('FOO', '-geometry 500x200 -use 0x2200009') ) + : もし options に敢えて nil または false を与えた場合,Tk ライ + : ブラリが導入されていない (つまりは Tcl のみの) インタープリ + : タを生成する.この場合は GUI 環境は必要ないため,ウインドウ + : システムが存在しない,または使用できない環境でも Tcl インター + : プリタを生成し,Tcl やその拡張ライブラリを活用することができる. インスタンスメソッド create_slave(name, safe=false) @@ -331,17 +342,26 @@ require "tcltklib" すると, 以下のモジュール, クラスが利用可能です. _return_value : 直前の Tcl/Tk 上での評価の実行結果としての戻り値を返す. - mainloop : 引数を含めて TclTkLib.mainloop に同じ - mainloop_watchdog : 引数を含めて TclTkLib.mainloop_watchdog に同じ - do_one_event : 引数を含めて TclTkLib.do_one_event に同じ - set_eventloop_tick : 引数を含めて TclTkLib.set_eventloop_tick に同じ - get_eventloop_tick : 引数を含めて TclTkLib.get_eventloop_tick に同じ - set_eventloop_weight : 引数を含めて TclTkLib.set_eventloop_weight に同じ - get_eventloop_weight : 引数を含めて TclTkLib.set_eventloop_weight に同じ + mainloop + mainloop_watchdog + : スレーブ IP の場合にはイベントループを起動せずに nil を返す. + : それ以外の点では引数を含めて TclTkLib の同名メソッドに同じ. + + do_one_event + : スレーブ IP の場合には引数のイベントフラグに DONT_WAIT が + : 強制的に追加される (イベント待ちでスリープすることは禁止). + : それ以外の点では引数を含めて TclTkLib の同名メソッドに同じ. + + set_eventloop_tick + get_eventloop_tick + set_no_event_wait + get_no_event_wait + set_eventloop_weight + get_eventloop_weight mainloop_abort_on_exception - : 引数を含めて TclTkLib.mainloop_abort_on_exception に同じ mainloop_abort_on_exception= - : 引数を含めて TclTkLib.mainloop_abort_on_exception= に同じ + : スレーブ IP の場合には値の設定が許されない (無視される). + : それ以外の点では引数を含めて TclTkLib の同名メソッドに同じ. クラス TkCallbackBreak < StandardError クラス TkCallbackContinue < StandardError diff --git a/ext/tcltklib/tcltklib.c b/ext/tcltklib/tcltklib.c index ec00cea217..cb2036296a 100644 --- a/ext/tcltklib/tcltklib.c +++ b/ext/tcltklib/tcltklib.c @@ -8,6 +8,13 @@ #include "rubysig.h" #undef EXTERN /* avoid conflict with tcl.h of tcl8.2 or before */ #include <stdio.h> +#ifdef HAVE_STDARG_PROTOTYPES +#include <stdarg.h> +#define va_init_list(a,b) va_start(a,b) +#else +#include <varargs.h> +#define va_init_list(a,b) va_start(a) +#endif #include <string.h> #include <tcl.h> #include <tk.h> @@ -93,6 +100,25 @@ static int ip_ruby _((ClientData, Tcl_Interp *, int, Tcl_Obj *CONST*)); static int ip_ruby _((ClientData, Tcl_Interp *, int, char **)); #endif +/*---- class TclTkIp ----*/ +struct tcltkip { + Tcl_Interp *ip; /* the interpreter */ + int return_value; /* return value */ +}; + +static struct tcltkip * +get_ip(self) + VALUE self; +{ + struct tcltkip *ptr; + + Data_Get_Struct(self, struct tcltkip, ptr); + if (ptr == 0) { + rb_raise(rb_eTypeError, "uninitialized TclTkIp"); + } + return ptr; +} + /* Tk_ThreadTimer */ static Tcl_TimerToken timer_token = (Tcl_TimerToken)NULL; @@ -156,6 +182,27 @@ get_eventloop_tick(self) } static VALUE +ip_set_eventloop_tick(self, tick) + VALUE self; + VALUE tick; +{ + struct tcltkip *ptr = get_ip(self); + + if (Tcl_GetMaster(ptr->ip) != (Tcl_Interp*)NULL) { + /* slave IP */ + return get_eventloop_tick(self); + } + return set_eventloop_tick(self, tick); +} + +static VALUE +ip_get_eventloop_tick(self) + VALUE self; +{ + return get_eventloop_tick(self); +} + +static VALUE set_no_event_wait(self, wait) VALUE self; VALUE wait; @@ -180,6 +227,27 @@ get_no_event_wait(self) } static VALUE +ip_set_no_event_wait(self, wait) + VALUE self; + VALUE wait; +{ + struct tcltkip *ptr = get_ip(self); + + if (Tcl_GetMaster(ptr->ip) != (Tcl_Interp*)NULL) { + /* slave IP */ + return get_no_event_wait(self); + } + return set_no_event_wait(self, wait); +} + +static VALUE +ip_get_no_event_wait(self) + VALUE self; +{ + return get_no_event_wait(self); +} + +static VALUE set_eventloop_weight(self, loop_max, no_event) VALUE self; VALUE loop_max; @@ -206,7 +274,29 @@ get_eventloop_weight(self) } static VALUE -rb_evloop_abort_on_exc(self) +ip_set_eventloop_weight(self, loop_max, no_event) + VALUE self; + VALUE loop_max; + VALUE no_event; +{ + struct tcltkip *ptr = get_ip(self); + + if (Tcl_GetMaster(ptr->ip) != (Tcl_Interp*)NULL) { + /* slave IP */ + return get_eventloop_weight(self); + } + return set_eventloop_weight(self, loop_max, no_event); +} + +static VALUE +ip_get_eventloop_weight(self) + VALUE self; +{ + return get_eventloop_weight(self); +} + +static VALUE +lib_evloop_abort_on_exc(self) VALUE self; { if (event_loop_abort_on_exc > 0) { @@ -219,7 +309,14 @@ rb_evloop_abort_on_exc(self) } static VALUE -rb_evloop_abort_on_exc_set(self, val) +ip_evloop_abort_on_exc(self) + VALUE self; +{ + return lib_evloop_abort_on_exc(self); +} + +static VALUE +lib_evloop_abort_on_exc_set(self, val) VALUE self, val; { rb_secure(4); @@ -230,7 +327,27 @@ rb_evloop_abort_on_exc_set(self, val) } else { event_loop_abort_on_exc = 0; } - return rb_evloop_abort_on_exc(self); + return lib_evloop_abort_on_exc(self); +} + +static VALUE +ip_evloop_abort_on_exc_set(self, val) + VALUE self, val; +{ + struct tcltkip *ptr = get_ip(self); + + if (Tcl_GetMaster(ptr->ip) != (Tcl_Interp*)NULL) { + /* slave IP */ + return lib_evloop_abort_on_exc(self); + } + return lib_evloop_abort_on_exc_set(self, val); +} + +static VALUE +lib_num_of_mainwindows(self) + VALUE self; +{ + return INT2FIX(Tk_GetNumMainWindows()); } VALUE @@ -379,6 +496,21 @@ lib_mainloop(argc, argv, self) return lib_mainloop_launcher(check_rootwidget); } +static VALUE +ip_mainloop(argc, argv, self) + int argc; + VALUE *argv; + VALUE self; +{ + struct tcltkip *ptr = get_ip(self); + + if (Tcl_GetMaster(ptr->ip) != (Tcl_Interp*)NULL) { + /* slave IP */ + return Qnil; + } + return lib_mainloop(argc, argv, self); +} + VALUE lib_watchdog_core(check_rootwidget) VALUE check_rootwidget; @@ -464,10 +596,26 @@ lib_mainloop_watchdog(argc, argv, self) } static VALUE -lib_do_one_event(argc, argv, self) +ip_mainloop_watchdog(argc, argv, self) + int argc; + VALUE *argv; + VALUE self; +{ + struct tcltkip *ptr = get_ip(self); + + if (Tcl_GetMaster(ptr->ip) != (Tcl_Interp*)NULL) { + /* slave IP */ + return Qnil; + } + return lib_mainloop_watchdog(argc, argv, self); +} + +static VALUE +lib_do_one_event_core(argc, argv, self, is_ip) int argc; VALUE *argv; VALUE self; + int is_ip; { VALUE vflags; int flags; @@ -479,6 +627,16 @@ lib_do_one_event(argc, argv, self) Check_Type(vflags, T_FIXNUM); flags = FIX2INT(vflags); } + + if (is_ip) { + /* check IP */ + struct tcltkip *ptr = get_ip(self); + if (Tcl_GetMaster(ptr->ip) != (Tcl_Interp*)NULL) { + /* slave IP */ + flags |= TCL_DONT_WAIT; + } + } + ret = Tcl_DoOneEvent(flags); if (ret) { return Qtrue; @@ -487,25 +645,25 @@ lib_do_one_event(argc, argv, self) } } -/*---- class TclTkIp ----*/ -struct tcltkip { - Tcl_Interp *ip; /* the interpreter */ - int return_value; /* return value */ -}; - -static struct tcltkip * -get_ip(self) +static VALUE +lib_do_one_event(argc, argv, self) + int argc; + VALUE *argv; VALUE self; { - struct tcltkip *ptr; + return lib_do_one_event_core(argc, argv, self, 0); +} - Data_Get_Struct(self, struct tcltkip, ptr); - if (ptr == 0) { - rb_raise(rb_eTypeError, "uninitialized TclTkIp"); - } - return ptr; +static VALUE +ip_do_one_event(argc, argv, self) + int argc; + VALUE *argv; + VALUE self; +{ + return lib_do_one_event_core(argc, argv, self, 0); } + /* Tcl command `ruby' */ static VALUE ip_eval_rescue(failed, einfo) @@ -551,6 +709,19 @@ lib_restart(self) return Qnil; } +static VALUE +ip_restart(self) + VALUE self; +{ + struct tcltkip *ptr = get_ip(self); + + if (Tcl_GetMaster(ptr->ip) != (Tcl_Interp*)NULL) { + /* slave IP */ + return Qnil; + } + return lib_restart(self); +} + static int #if TCL_MAJOR_VERSION >= 8 ip_ruby(clientData, interp, argc, argv) @@ -651,6 +822,7 @@ ip_init(argc, argv, self) struct tcltkip *ptr; /* tcltkip data struct */ VALUE argv0, opts; int cnt; + int with_tk = 1; /* create object */ Data_Get_Struct(self, struct tcltkip, ptr); @@ -675,7 +847,12 @@ ip_init(argc, argv, self) switch(cnt) { case 2: /* options */ - Tcl_SetVar(ptr->ip, "argv", StringValuePtr(opts), 0); + if (opts == Qnil || opts == Qfalse) { + /* without Tk */ + with_tk = 0; + } else { + Tcl_SetVar(ptr->ip, "argv", StringValuePtr(opts), 0); + } case 1: /* argv0 */ if (argv0 != Qnil) { @@ -687,17 +864,19 @@ ip_init(argc, argv, self) } /* from Tcl_AppInit() */ - DUMP1("Tk_Init"); - if (Tk_Init(ptr->ip) == TCL_ERROR) { - rb_raise(rb_eRuntimeError, "%s", ptr->ip->result); - } - DUMP1("Tcl_StaticPackage(\"Tk\")"); + if (with_tk) { + DUMP1("Tk_Init"); + if (Tk_Init(ptr->ip) == TCL_ERROR) { + rb_raise(rb_eRuntimeError, "%s", ptr->ip->result); + } + DUMP1("Tcl_StaticPackage(\"Tk\")"); #if TCL_MAJOR_VERSION >= 8 - Tcl_StaticPackage(ptr->ip, "Tk", Tk_Init, Tk_SafeInit); + Tcl_StaticPackage(ptr->ip, "Tk", Tk_Init, Tk_SafeInit); #else - Tcl_StaticPackage(ptr->ip, "Tk", Tk_Init, - (Tcl_PackageInitProc *) NULL); + Tcl_StaticPackage(ptr->ip, "Tk", Tk_Init, + (Tcl_PackageInitProc *) NULL); #endif + } /* add ruby command to the interpreter */ #if TCL_MAJOR_VERSION >= 8 @@ -901,6 +1080,32 @@ ip_fromUTF8(self, str, encodename) static VALUE +#ifdef HAVE_STDARG_PROTOTYPES +create_ip_exc(VALUE interp, VALUE exc, const char *fmt, ...) +#else +create_ip_exc(interp, exc, fmt, va_alist) + VALUE interp: + VALUE exc; + const char *fmt; + va_dcl +#endif +{ + va_list args; + char buf[BUFSIZ]; + VALUE einfo; + + va_init_list(args,fmt); + vsnprintf(buf, BUFSIZ, fmt, args); + buf[BUFSIZ - 1] = '\0'; + va_end(args); + einfo = rb_exc_new2(exc, buf); + rb_iv_set(einfo, "interp", interp); + Tcl_ResetResult(get_ip(interp)->ip); + return einfo; +} + + +static VALUE ip_invoke_real(argc, argv, obj) int argc; VALUE *argv; @@ -934,7 +1139,9 @@ ip_invoke_real(argc, argv, obj) if (!Tcl_GetCommandInfo(ptr->ip, cmd, &info)) { /* if (event_loop_abort_on_exc || cmd[0] != '.') { */ if (event_loop_abort_on_exc > 0) { - rb_raise(rb_eNameError, "invalid command name `%s'", cmd); + /*rb_ip_raise(obj, rb_eNameError, "invalid command name `%s'", cmd);*/ + return create_ip_exc(obj, rb_eNameError, + "invalid command name `%s'", cmd); } else { if (event_loop_abort_on_exc < 0) { rb_warning("invalid command name `%s' (ignore)", cmd); @@ -1021,7 +1228,8 @@ ip_invoke_real(argc, argv, obj) /* exception on mainloop */ if (ptr->return_value == TCL_ERROR) { if (event_loop_abort_on_exc > 0 && !Tcl_InterpDeleted(ptr->ip)) { - rb_raise(rb_eRuntimeError, "%s", ptr->ip->result); + /*rb_ip_raise(obj, rb_eRuntimeError, "%s", ptr->ip->result);*/ + return create_ip_exc(obj, rb_eRuntimeError, "%s", ptr->ip->result); } else { if (event_loop_abort_on_exc < 0) { rb_warning("%s (ignore)", ptr->ip->result); @@ -1137,6 +1345,9 @@ ip_invoke(argc, argv, obj) /* get result & free allocated memory */ result = *alloc_result; + if (rb_obj_is_kind_of(result, rb_eException)) { + rb_exc_raise(result); + } free(alloc_argv); free(alloc_result); @@ -1197,6 +1408,10 @@ Init_tcltklib() rb_define_module_function(lib, "mainloop_watchdog", lib_mainloop_watchdog, -1); rb_define_module_function(lib, "do_one_event", lib_do_one_event, -1); + rb_define_module_function(lib, "mainloop_abort_on_exception", + lib_evloop_abort_on_exc, 0); + rb_define_module_function(lib, "mainloop_abort_on_exception=", + lib_evloop_abort_on_exc_set, 1); rb_define_module_function(lib, "set_eventloop_tick",set_eventloop_tick,1); rb_define_module_function(lib, "get_eventloop_tick",get_eventloop_tick,0); rb_define_module_function(lib, "set_no_event_wait", set_no_event_wait, 1); @@ -1205,10 +1420,8 @@ Init_tcltklib() set_eventloop_weight, 2); rb_define_module_function(lib, "get_eventloop_weight", get_eventloop_weight, 0); - rb_define_module_function(lib, "mainloop_abort_on_exception", - rb_evloop_abort_on_exc, 0); - rb_define_module_function(lib, "mainloop_abort_on_exception=", - rb_evloop_abort_on_exc_set, 1); + rb_define_module_function(lib, "num_of_mainwindows", + lib_num_of_mainwindows, 0); rb_define_alloc_func(ip, ip_alloc); rb_define_method(ip, "initialize", ip_init, -1); @@ -1222,20 +1435,21 @@ Init_tcltklib() rb_define_method(ip, "_fromUTF8",ip_fromUTF8,2); rb_define_method(ip, "_invoke", ip_invoke, -1); rb_define_method(ip, "_return_value", ip_retval, 0); - rb_define_method(ip, "mainloop", lib_mainloop, -1); - rb_define_method(ip, "mainloop_watchdog", lib_mainloop_watchdog, -1); - rb_define_method(ip, "do_one_event", lib_do_one_event, -1); + + rb_define_method(ip, "mainloop", ip_mainloop, -1); + rb_define_method(ip, "mainloop_watchdog", ip_mainloop_watchdog, -1); + rb_define_method(ip, "do_one_event", ip_do_one_event, -1); rb_define_method(ip, "mainloop_abort_on_exception", - rb_evloop_abort_on_exc, 0); + ip_evloop_abort_on_exc, 0); rb_define_method(ip, "mainloop_abort_on_exception=", - rb_evloop_abort_on_exc_set, 1); - rb_define_method(ip, "set_eventloop_tick", set_eventloop_tick, 1); - rb_define_method(ip, "get_eventloop_tick", get_eventloop_tick, 0); - rb_define_method(ip, "set_no_event_wait", set_no_event_wait, 1); - rb_define_method(ip, "get_no_event_wait", get_no_event_wait, 0); - rb_define_method(ip, "set_eventloop_weight", set_eventloop_weight, 2); - rb_define_method(ip, "get_eventloop_weight", get_eventloop_weight, 0); - rb_define_method(ip, "restart", lib_restart, 0); + ip_evloop_abort_on_exc_set, 1); + rb_define_method(ip, "set_eventloop_tick", ip_set_eventloop_tick, 1); + rb_define_method(ip, "get_eventloop_tick", ip_get_eventloop_tick, 0); + rb_define_method(ip, "set_no_event_wait", ip_set_no_event_wait, 1); + rb_define_method(ip, "get_no_event_wait", ip_get_no_event_wait, 0); + rb_define_method(ip, "set_eventloop_weight", ip_set_eventloop_weight, 2); + rb_define_method(ip, "get_eventloop_weight", ip_get_eventloop_weight, 0); + rb_define_method(ip, "restart", ip_restart, 0); eventloop_thread = 0; watchdog_thread = 0; diff --git a/ext/tk/lib/multi-tk.rb b/ext/tk/lib/multi-tk.rb index d1bf21164a..12ed7aceff 100644 --- a/ext/tk/lib/multi-tk.rb +++ b/ext/tk/lib/multi-tk.rb @@ -6,10 +6,12 @@ require 'tcltklib' require 'thread' ################################################ -# ignore exception on the mainloop +# ignore exception on the mainloop? +TclTkLib.mainloop_abort_on_exception = true # TclTkLib.mainloop_abort_on_exception = false -TclTkLib.mainloop_abort_on_exception = nil +# TclTkLib.mainloop_abort_on_exception = nil + ################################################ @@ -71,9 +73,16 @@ class MultiTkIp end private :_keys2opts - def _check_and_return(thread, exception, wait=3) - # wait to stop the caller thread + def _check_and_return(thread, exception, wait=0) return nil unless thread + + if wait == 0 + # no wait + thread.raise exception + return thread + end + + # wait to stop the caller thread wait.times{ if thread.stop? # ready to send exception @@ -104,22 +113,36 @@ class MultiTkIp def _create_receiver_and_watchdog() # command-procedures receiver receiver = Thread.new{ + safe_level = $SAFE loop do thread, cmd, *args = @cmd_queue.deq if thread == @system + # control command case cmd when 'set_safe_level' begin - $SAFE = args[0] + safe_level = args[0] if safe_level < args[0] rescue Exception nil end else # ignore end + else + # procedure begin - ret = cmd.call(*args) + ret = proc{$SAFE = safe_level; cmd.call(*args)}.call + rescue SystemExit + # delete IP + unless @interp.deleted? + if @interp._invoke('info', 'command', '.') != "" + @interp._invoke('destroy', '.') + end + @interp.delete + end + _check_and_return(thread, MultiTkIp_OK.new(nil)) + break rescue Exception => e # raise exception _check_and_return(thread, e) @@ -134,7 +157,10 @@ class MultiTkIp # watchdog of receiver watchdog = Thread.new{ begin - receiver.join + loop do + sleep 1 + break unless receiver.alive? + end rescue Exception # ignore all kind of Exception end @@ -621,7 +647,9 @@ end # instance methods to treat tables class MultiTkIp def _tk_cmd_tbl - MultiTkIp.tk_cmd_tbl.collect{|ent| ent.ip == self } + tbl = {} + MultiTkIp.tk_cmd_tbl.each{|id, ent| tbl[id] = ent if ent.ip == self } + tbl end def _tk_windows @@ -632,6 +660,10 @@ class MultiTkIp @tk_table_list end + def _add_new_tables + (@@TK_TABLE_LIST.size - @tk_table_list.size).times{ @tk_table_list << {} } + end + def _init_ip_env(script) script.call(self) end @@ -669,10 +701,10 @@ class MultiTkIp __getip._tk_table_list[id] end def self.create_table + if __getip.slave? + raise SecurityError, "slave-IP has no permission creating a new table" + end id = @@TK_TABLE_LIST.size - @@IP_TABLE.each{|tg, ip| - ip.instance_eval{@tk_table_list << {}} - } obj = Object.new @@TK_TABLE_LIST << obj obj.instance_eval <<-EOD @@ -681,6 +713,7 @@ class MultiTkIp end EOD obj.freeze + @@IP_TABLE.each{|tg, ip| ip._add_new_tables } return obj end @@ -719,33 +752,62 @@ end # evaluate a procedure on the proper interpreter class MultiTkIp # instance method - def eval_proc_core(req_val=true, cmd = Proc.new, *args) + def eval_proc_core(req_val, cmd, *args) # cmd string ==> proc if cmd.kind_of?(String) - cmd = proc{ TkComm._get_eval_string(TkUtil.eval_cmd(cmd, *args)) } + xcmd = cmd + xargs = args + cmd = proc{ TkComm._get_eval_string(TkUtil.eval_cmd(xcmd, *xargs)) } args = [] end + # check + unless cmd.kind_of?(Proc) + raise RuntimeError, "A Proc object is expected for the 'cmd' argument" + end + # on IP thread if (@cmd_receiver == Thread.current) - return cmd.call(*args) + begin + ret = cmd.call(*args) + rescue SystemExit + # exit IP + warn("Warning: "+ $! + " on " + self.inspect) if $DEBUG + self.delete + ret = nil + rescue Exception => e + warn("Warning: " + e.class.inspect + + ((e.message.length > 0)? ' "' + e.message + '"': '') + + " on " + self.inspect) + ret = nil + end + return ret end # send cmd to the proc-queue - if req_val - @cmd_queue.enq([Thread.current, cmd, *args]) - else + unless req_val @cmd_queue.enq([nil, cmd, *args]) return nil end - # wait and get return value by exception + # send and get return value by exception begin + @cmd_queue.enq([Thread.current, cmd, *args]) Thread.stop rescue MultiTkIp_OK => ret # return value return ret.value + rescue SystemExit + # exit IP + warn("Warning: " + $! + " on " + self.inspect) if $DEBUG + self.delete + rescue Exception => e + # others --> warning + warn("Warning: " + e.class.inspect + + ((e.message.length > 0)? ' "' + e.message + '"': '') + + " on " + self.inspect) end + return nil end private :eval_proc_core @@ -757,48 +819,57 @@ class MultiTkIp eval_proc_core(true, cmd, *args) end alias call eval_proc - + alias eval_string eval_proc +end +class << MultiTkIp # class method - def self.eval_proc(cmd = Proc.new, *args) + def eval_proc(cmd = Proc.new, *args) # class ==> interp object __getip.eval_proc(cmd, *args) end + alias call eval_proc + alias eval_string eval_proc end -# depend on TclTkLib +# event loop # all master/slave IPs are controled by only one event-loop class << MultiTkIp def mainloop(check_root = true) - TclTkLib.mainloop(check_root) + __getip.mainloop(check_root) end def mainloop_watchdog(check_root = true) - TclTkLib.mainloop_watchdog(check_root) + __getip.mainloop_watchdog(check_root) end def do_one_event(flag = TclTkLib::EventFlag::ALL) - TclTkLib.do_one_event(flag) + __getip.do_one_event(flag) + end + def mainloop_abort_on_exception + __getip.mainloop_abort_on_exception + end + def mainloop_abort_on_exception=(mode) + __getip.mainloop_abort_on_exception=(mode) end def set_eventloop_tick(tick) - TclTkLib.set_eventloop_tick(tick) + __getip.set_eventloop_tick(tick) end def get_eventloop_tick - TclTkLib.get_eventloop_tick + __getip.get_eventloop_tick end def set_no_event_wait(tick) - TclTkLib.set_no_event_wait(tick) + __getip.set_no_event_wait(tick) end def get_no_event_wait - TclTkLib.get_no_event_wait + __getip.get_no_event_wait end def set_eventloop_weight(loop_max, no_event_tick) - TclTkLib.set_eventloop_weight(loop_max, no_event_tick) + __getip.set_eventloop_weight(loop_max, no_event_tick) end def get_eventloop_weight - TclTkLib.get_eventloop_weight + __getip.get_eventloop_weight end end - # class methods to delegate to TclTkIp class << MultiTkIp def method_missing(id, *args) @@ -839,32 +910,76 @@ class << MultiTkIp end +# wrap methods on TclTkLib : not permit calling TclTkLib module methods +class << TclTkLib + def mainloop(check_root = true) + MultiTkIp.mainloop(check_root) + end + def mainloop_watchdog(check_root = true) + MultiTkIp.mainloop_watchdog(check_root) + end + def do_one_event(flag = TclTkLib::EventFlag::ALL) + MultiTkIp.do_one_event(flag) + end + def mainloop_abort_on_exception + MultiTkIp.mainloop_abort_on_exception + end + def mainloop_abort_on_exception=(mode) + MultiTkIp.mainloop_abort_on_exception=(mode) + end + def set_eventloop_tick(tick) + MultiTkIp.set_eventloop_tick(tick) + end + def get_eventloop_tick + MultiTkIp.get_eventloop_tick + end + def set_no_event_wait(tick) + MultiTkIp.set_no_event_wait(tick) + end + def get_no_event_wait + MultiTkIp.get_no_event_wait + end + def set_eventloop_weight(loop_max, no_event_tick) + MultiTkIp.set_eventloop_weight(loop_max, no_event_tick) + end + def get_eventloop_weight + MultiTkIp.get_eventloop_weight + end + def restart + MultiTkIp.restart + end +end + + # depend on TclTkIp class MultiTkIp def mainloop(check_root = true, restart_on_dead = true) + return self if self.slave? unless restart_on_dead @interp.mainloop(check_root) else begin loop do - @interp.mainloop(check_root) + break unless self.alive? if check_root begin - break if @interp._invoke('winfo', 'exists?', '.') == "1" + break if TclTkLib.num_of_mainwindows == 0 rescue Exception break end end + @interp.mainloop(check_root) end rescue StandardError if TclTkLib.mainloop_abort_on_exception != nil - STDERR.print("warning: Tk mainloop on ", @interp.inspect, + STDERR.print("Warning: Tk mainloop on ", @interp.inspect, " receives ", $!.class.inspect, " exception (ignore) : ", $!.message, "\n"); end retry end end + self end def make_safe @@ -1187,10 +1302,19 @@ class MultiTkIp end -# end of MultiTkIp definition +# remove methods for security +class MultiTkIp + undef_method :instance_eval + undef_method :instance_variable_get + undef_method :instance_variable_set +end -MultiTkIp.freeze # defend against modification +# end of MultiTkIp definition + +# defend against modification +MultiTkIp.freeze +TclTkLib.freeze ######################################## # start Tk which depends on MultiTkIp diff --git a/ext/tk/lib/tk.rb b/ext/tk/lib/tk.rb index 0941635716..a03e6823bb 100644 --- a/ext/tk/lib/tk.rb +++ b/ext/tk/lib/tk.rb @@ -14,6 +14,7 @@ module TkComm def None.to_s 'None' end + None.freeze #Tk_CMDTBL = {} #Tk_WINDOWS = {} @@ -24,10 +25,16 @@ module TkComm def Tk_CMDTBL.method_missing(id, *args) TkCore::INTERP.tk_cmd_tbl.send(id, *args) end + Tk_CMDTBL.freeze Tk_WINDOWS = Object.new def Tk_WINDOWS.method_missing(id, *args) TkCore::INTERP.tk_windows.send(id, *args) end + Tk_WINDOWS.freeze + + self.instance_eval{ + @cmdtbl = [] + } def error_at frames = caller() @@ -894,30 +901,8 @@ module TkCore tk_call('info', *args) end - def mainloop(check_root = true, restart_on_dead = true) - unless restart_on_dead - TclTkLib.mainloop(check_root) - else - begin - loop do - TclTkLib.mainloop(check_root) - if check_root - begin - break if TkWinfo.exist?('.') - rescue Exception - break - end - end - end - rescue StandardError - if TclTkLib.mainloop_abort_on_exception != nil - STDERR.print("warning: Tk mainloop on ", TkCore::INTERP.inspect, - " receives ", $!.class.inspect, - " exception (ignore) : ", $!.message, "\n"); - end - retry - end - end + def mainloop(check_root = true) + TclTkLib.mainloop(check_root) end def mainloop_watchdog(check_root = true) @@ -1020,15 +1005,15 @@ module TkCore print "=> ", args.join(" ").inspect, "\n" if $DEBUG begin # res = INTERP._invoke(*args).taint - res = INTERP._invoke(*args) # _invoke returns a TAITED string - rescue NameError - err = $! + res = INTERP._invoke(*args) # _invoke returns a TAINTED string + rescue NameError => err +# err = $! begin args.unshift "unknown" #res = INTERP._invoke(*args).taint - res = INTERP._invoke(*args) # _invoke returns a TAITED string - rescue - fail unless /^invalid command/ =~ $! + res = INTERP._invoke(*args) # _invoke returns a TAINTED string + rescue StandardError => err2 + fail err2 unless /^invalid command/ =~ err2 fail err end end @@ -1136,7 +1121,7 @@ module Tk TkRoot.new end - def bell(nice = false) + def Tk.bell(nice = false) if nice tk_call 'bell', '-nice' else @@ -1144,7 +1129,7 @@ module Tk end end - def bell_on_display(win, nice = false) + def Tk.bell_on_display(win, nice = false) if nice tk_call('bell', '-displayof', win, '-nice') else @@ -1720,6 +1705,8 @@ class TkVariable include Tk extend TkCore + include Comparable + TkCommandNames = ['tkwait'.freeze].freeze #TkVar_CB_TBL = {} @@ -1749,13 +1736,16 @@ class TkVariable @trace_elem = nil @trace_opts = nil +=begin if val == [] - INTERP._eval(format('global %s; set %s(0) 0; unset %s(0)', - @id, @id, @id)) + # INTERP._eval(format('global %s; set %s(0) 0; unset %s(0)', + # @id, @id, @id)) elsif val.kind_of?(Array) a = [] - val.each_with_index{|e,i| a.push(i); a.push(array2tk_list(e))} - s = '"' + a.join(" ").gsub(/[\[\]$"]/, '\\\\\&') + '"' + # val.each_with_index{|e,i| a.push(i); a.push(array2tk_list(e))} + # s = '"' + a.join(" ").gsub(/[\[\]$"]/, '\\\\\&') + '"' + val.each_with_index{|e,i| a.push(i); a.push(e)} + s = '"' + array2tk_list(a).gsub(/[\[\]$"]/, '\\\\\&') + '"' INTERP._eval(format('global %s; array set %s %s', @id, @id, s)) elsif val.kind_of?(Hash) s = '"' + val.to_a.collect{|e| array2tk_list(e)}.join(" ")\ @@ -1765,6 +1755,15 @@ class TkVariable s = '"' + _get_eval_string(val).gsub(/[\[\]$"]/, '\\\\\&') + '"' INTERP._eval(format('global %s; set %s %s', @id, @id, s)) end +=end + if val.kind_of?(Hash) + s = '"' + val.to_a.collect{|e| array2tk_list(e)}.join(" ")\ + .gsub(/[\[\]$"]/, '\\\\\&') + '"' + INTERP._eval(format('global %s; array set %s %s', @id, @id, s)) + else + s = '"' + _get_eval_string(val).gsub(/[\[\]$"]/, '\\\\\&') + '"' + INTERP._eval(format('global %s; set %s %s', @id, @id, s)) + end end def wait @@ -1782,8 +1781,9 @@ class TkVariable if INTERP._eval(format('global %s; array exists %s', @id, @id)) != "1" fail else - Hash[*tk_split_simplelist(INTERP._eval(format('global %s; array get %s', - @id, @id)))] + Hash[*tk_split_simplelist(INTERP. + _eval(format('global %s; array get %s', + @id, @id)))] end end end @@ -1827,6 +1827,20 @@ class TkVariable _get_eval_string(index), _get_eval_string(val))) end + def numeric + number(value) + end + def numeric=(val) + case val + when Numeric + self.value=(val) + when TkVariable + self.value=(val.numeric) + else + raise ArgumentError, "Numeric is expected" + end + end + def to_i number(value).to_i end @@ -1843,10 +1857,104 @@ class TkVariable value.intern end + def list + tk_split_list(value) + end + alias to_a list + + def list=(val) + case val + when Array + self.value=(val) + when TkVariable + self.value=(val.list) + else + raise ArgumentError, "Array is expected" + end + end + def inspect format "#<TkVariable: %s>", @id end + def coerce(other) + case other + when TkVariable + [other.value, self.value] + when String + [other, self.to_s] + when Symbol + [other, self.to_sym] + when Integer + [other, self.to_i] + when Float + [other, self.to_f] + when Array + [other, self.to_a] + else + [other, self.value] + end + end + + def &(other) + if other.kind_of?(Array) + self.to_a & other.to_a + else + self.to_i & other.to_i + end + end + def |(other) + if other.kind_of?(Array) + self.to_a | other.to_a + else + self.to_i | other.to_i + end + end + def +(other) + case other + when Array + self.to_a + other + when String + self.value + other + else + begin + number(self.value) + other + rescue + self.value + other.to_s + end + end + end + def -(other) + if other.kind_of?(Array) + self.to_a - other + else + number(self.value) - other + end + end + def *(other) + begin + number(self.value) * other + rescue + self.value * other + end + end + def /(other) + number(self.value) / other + end + def %(other) + begin + number(self.value) % other + rescue + self.value % other + end + end + def **(other) + number(self.value) ** other + end + def =~(other) + self.value =~ other + end + def ==(other) case other when TkVariable @@ -1861,13 +1969,38 @@ class TkVariable self.to_f == other when Array self.to_a == other + when Hash + self.value == other else false end end - def to_a - list(value) + def zero? + numeric.zero? + end + def nonzero? + !(numeric.zero?) + end + + def <=>(other) + if other.kind_of?(TkVariable) + begin + val = other.numeric + other = val + rescue + other = other.value + end + end + if other.kind_of?(Numeric) + begin + return self.numeric <=> other + rescue + return self.value <=> other.to_s + end + else + return self.value <=> other + end end def to_eval @@ -3082,9 +3215,16 @@ TkOption = TkOptionDB TkResourceDB = TkOptionDB module TkTreatFont - def font_configinfo + def font_configinfo(name = nil) ret = TkFont.used_on(self.path) if ret == nil +=begin + if name + ret = name + else + ret = TkFont.init_widget_font(self.path, self.path, 'configure') + end +=end ret = TkFont.init_widget_font(self.path, self.path, 'configure') end ret @@ -3097,7 +3237,10 @@ module TkTreatFont if fnt.kind_of? TkFont return fnt.call_font_configure(self.path, self.path,'configure',slot) else - latinfont_configure(fnt) if fnt + if fnt + latinfont_configure(fnt) + kanjifont_configure(fnt) + end end end if (ltn = slot.delete('latinfont')) @@ -3192,10 +3335,18 @@ module TkTreatItemFont end private :__conf_cmd, :__item_pathname - def tagfont_configinfo(tagOrId) + def tagfont_configinfo(tagOrId, name = nil) pathname = __item_pathname(tagOrId) ret = TkFont.used_on(pathname) if ret == nil +=begin + if name + ret = name + else + ret = TkFont.init_widget_font(pathname, self.path, + __conf_cmd(0), __conf_cmd(1), tagOrId) + end +=end ret = TkFont.init_widget_font(pathname, self.path, __conf_cmd(0), __conf_cmd(1), tagOrId) end @@ -3212,7 +3363,10 @@ module TkTreatItemFont __conf_cmd(0), __conf_cmd(1), tagOrId, slot) else - latintagfont_configure(tagOrId, fnt) if fnt + if fnt + latintagfont_configure(tagOrId, fnt) + kanjitagfont_configure(tagOrId, fnt) + end end end if (ltn = slot.delete('latinfont')) @@ -3358,6 +3512,12 @@ class TkObject<TkKernel case slot.to_s when 'text', 'label', 'show', 'data', 'file' tk_call path, 'cget', "-#{slot}" + when 'font', 'kanjifont' + fnt = tk_tcl2ruby(tk_call(path, 'cget', "-#{slot}")) + unless fnt.kind_of?(TkFont) + fnt = fontobj(fnt) + end + fnt else tk_tcl2ruby tk_call(path, 'cget', "-#{slot}") end @@ -3398,7 +3558,10 @@ class TkObject<TkKernel def configinfo(slot = nil) if slot == 'font' || slot == :font || slot == 'kanjifont' || slot == :kanjifont - fontobj + conf = tk_split_simplelist(tk_send('configure', "-#{slot}") ) + conf[0] = conf[0][1..-1] + conf[4] = fontobj(conf[4]) + conf else if slot case slot.to_s @@ -3436,7 +3599,7 @@ class TkObject<TkKernel fontconf = ret.assoc('font') if fontconf ret.delete_if{|item| item[0] == 'font' || item[0] == 'kanjifont'} - fontconf[4] = fontobj + fontconf[4] = fontobj(fontconf[4]) ret.push(fontconf) else ret @@ -4367,6 +4530,7 @@ class TkPanedWindow<TkWindow end self end + alias pane_config paneconfigure def paneconfiginfo(win, key=nil) if key @@ -4395,6 +4559,7 @@ class TkPanedWindow<TkWindow } end end + alias pane_configinfo paneconfiginfo def panes list(tk_send('panes')) @@ -4717,6 +4882,12 @@ class TkListbox<TkTextWin case key.to_s when 'text', 'label', 'show' tk_send('itemcget', index, "-#{key}") + when 'font', 'kanjifont' + fnt = tk_tcl2ruby(tk_send('itemcget', index, "-#{key}")) + unless fnt.kind_of?(TkFont) + fnt = tagfontobj(index, fnt) + end + fnt else tk_tcl2ruby(tk_send('itemcget', index, "-#{key}")) end @@ -4750,13 +4921,17 @@ class TkListbox<TkTextWin case key.to_s when 'text', 'label', 'show' conf = tk_split_simplelist(tk_send('itemconfigure',index,"-#{key}")) + when 'font', 'kanjifont' + conf = tk_split_simplelist(tk_send('itemconfigure',index,"-#{key}") ) + conf[4] = tagfont_configinfo(index, conf[4]) else conf = tk_split_list(tk_send('itemconfigure',index,"-#{key}")) end conf[0] = conf[0][1..-1] conf else - tk_split_simplelist(tk_send('itemconfigure', index)).collect{|conflist| + ret = tk_split_simplelist(tk_send('itemconfigure', + index)).collect{|conflist| conf = tk_split_simplelist(conflist) conf[0] = conf[0][1..-1] case conf[0] @@ -4779,6 +4954,14 @@ class TkListbox<TkTextWin end conf } + fontconf = ret.assoc('font') + if fontconf + ret.delete_if{|item| item[0] == 'font' || item[0] == 'kanjifont'} + fontconf[4] = tagfont_configinfo(index, fontconf[4]) + ret.push(fontconf) + else + ret + end end end end @@ -4881,8 +5064,14 @@ class TkMenu<TkWindow case key.to_s when 'text', 'label', 'show' tk_send 'entrycget', index, "-#{key}" + when 'font', 'kanjifont' + fnt = tk_tcl2ruby(tk_send('entrycget', index, "-#{key}")) + unless fnt.kind_of?(TkFont) + fnt = tagfontobj(index, fnt) + end + fnt else - tk_tcl2ruby tk_send('entrycget', index, "-#{key}") + tk_tcl2ruby(tk_send('entrycget', index, "-#{key}")) end end def entryconfigure(index, key, val=None) @@ -4914,13 +5103,17 @@ class TkMenu<TkWindow case key.to_s when 'text', 'label', 'show' conf = tk_split_simplelist(tk_send('entryconfigure',index,"-#{key}")) + when 'font', 'kanjifont' + conf = tk_split_simplelist(tk_send('entryconfigure',index,"-#{key}")) + conf[4] = tagfont_configinfo(index, conf[4]) else conf = tk_split_list(tk_send('entryconfigure',index,"-#{key}")) end conf[0] = conf[0][1..-1] conf else - tk_split_simplelist(tk_send('entryconfigure', index)).collect{|conflist| + ret = tk_split_simplelist(tk_send('entryconfigure', + index)).collect{|conflist| conf = tk_split_simplelist(conflist) conf[0] = conf[0][1..-1] case conf[0] @@ -4943,6 +5136,13 @@ class TkMenu<TkWindow end conf } + if fontconf + ret.delete_if{|item| item[0] == 'font' || item[0] == 'kanjifont'} + fontconf[4] = tagfont_configinfo(index, fontconf[4]) + ret.push(fontconf) + else + ret + end end end end @@ -5246,6 +5446,16 @@ TkBindTag::ALL.bind(TkVirtualEvent.new('Destroy'), proc{|xpath| end }, 'x%W') +# freeze core modules +TclTkLib.freeze +TclTkIp.freeze +TkUtil.freeze +TkKernel.freeze +TkComm.freeze +TkComm::Event.freeze +TkCore.freeze +Tk.freeze + # autoload autoload :TkCanvas, 'tkcanvas' autoload :TkImage, 'tkcanvas' diff --git a/ext/tk/lib/tkcanvas.rb b/ext/tk/lib/tkcanvas.rb index a899c9caaf..9e386ee50d 100644 --- a/ext/tk/lib/tkcanvas.rb +++ b/ext/tk/lib/tkcanvas.rb @@ -211,6 +211,12 @@ class TkCanvas<TkWindow end when 'text', 'label', 'show', 'data', 'file', 'maskdata', 'maskfile' tk_send 'itemcget', tagid(tagOrId), "-#{option}" + when 'font', 'kanjifont' + fnt = tk_tcl2ruby(tk_send('itemcget', tagid(tagOrId), "-#{option}")) + unless fnt.kind_of?(TkFont) + fnt = tagfontobj(tagid(tagOrId), fnt) + end + fnt else tk_tcl2ruby tk_send('itemcget', tagid(tagOrId), "-#{option}") end @@ -264,6 +270,10 @@ class TkCanvas<TkWindow when 'text', 'label', 'show', 'data', 'file', 'maskdata', 'maskfile' conf = tk_split_simplelist(tk_send('itemconfigure', tagid(tagOrId), "-#{key}")) + when 'font', 'kanjifont' + conf = tk_split_simplelist(tk_send('itemconfigure', + tagid(tagOrId),"-#{key}") ) + conf[4] = tagfont_configinfo(tagid(tagOrId), conf[4]) else conf = tk_split_list(tk_send('itemconfigure', tagid(tagOrId), "-#{key}")) @@ -271,8 +281,8 @@ class TkCanvas<TkWindow conf[0] = conf[0][1..-1] conf else - tk_split_simplelist(tk_send('itemconfigure', - tagid(tagOrId))).collect{|conflist| + ret = tk_split_simplelist(tk_send('itemconfigure', + tagid(tagOrId))).collect{|conflist| conf = tk_split_simplelist(conflist) conf[0] = conf[0][1..-1] case conf[0] @@ -302,6 +312,14 @@ class TkCanvas<TkWindow end conf } + fontconf = ret.assoc('font') + if fontconf + ret.delete_if{|item| item[0] == 'font' || item[0] == 'kanjifont'} + fontconf[4] = tagfont_configinfo(tagid(tagOrId), fontconf[4]) + ret.push(fontconf) + else + ret + end end end diff --git a/ext/tk/lib/tkfont.rb b/ext/tk/lib/tkfont.rb index eb21b1fabf..f0c88e432d 100644 --- a/ext/tk/lib/tkfont.rb +++ b/ext/tk/lib/tkfont.rb @@ -34,19 +34,21 @@ class TkFont # Tcl/Tk-JP for Windows ltn = 'defaultgui' knj = 'defaultgui' - when /Mincho:Helvetica-12/ + when /Mincho:Helvetica-Bold-12/ # Tcl/Tk-JP for UNIX/X ltn, knj = tk_split_simplelist(tk_call('font', 'configure', - 'Mincho:Helvetica-12', + 'Mincho:Helvetica-Bold-12', '-compound')) else # unknown Tcl/Tk-JP platform = tk_call('set', 'tcl_platform(platform)') case platform when 'unix' - ltn = {'family'=>'Helvetica'.freeze, 'size'=>-12} - knj = 'k14' + ltn = {'family'=>'Helvetica'.freeze, + 'size'=>-12, 'weight'=>'bold'.freeze} + #knj = 'k14' #knj = '-misc-fixed-medium-r-normal--14-*-*-*-c-*-jisx0208.1983-0' + knj = '-*-fixed-bold-r-normal--12-*-*-*-c-*-jisx0208.1983-0' when 'windows' ltn = {'family'=>'MS Sans Serif'.freeze, 'size'=>8} knj = 'mincho' @@ -68,9 +70,11 @@ class TkFont platform = tk_call('set', 'tcl_platform(platform)') case platform when 'unix' - ltn = {'family'=>'Helvetica'.freeze, 'size'=>-12} - knj = 'k14' + ltn = {'family'=>'Helvetica'.freeze, + 'size'=>-12, 'weight'=>'bold'.freeze} + #knj = 'k14' #knj = '-misc-fixed-medium-r-normal--14-*-*-*-c-*-jisx0208.1983-0' + knj = '-*-fixed-bold-r-normal--12-*-*-*-c-*-jisx0208.1983-0' when 'windows' ltn = {'family'=>'MS Sans Serif'.freeze, 'size'=>8} knj = 'mincho' @@ -133,7 +137,7 @@ class TkFont end def TkFont.create_copy(font) - fail 'source-font need to be TkFont' unless font.kind_of? TkFont + fail 'source-font must be a TkFont object' unless font.kind_of? TkFont keys = {} font.configinfo.each{|key,value| keys[key] = value } TkFont.new(font.latin_font, font.kanji_font, keys) @@ -220,11 +224,46 @@ class TkFont ################################### private ################################### - def initialize(ltn=DEFAULT_LATIN_FONT_NAME, knj=nil, keys=nil) + def initialize(ltn=nil, knj=nil, keys=nil) @id = Tk_FontID.join Tk_FontID[1].succ! Tk_FontNameTBL[@id] = self - knj = DEFAULT_KANJI_FONT_NAME if JAPANIZED_TK && !knj + + if knj.kind_of?(Hash) && !keys + keys = knj + knj = nil + end + + # compound font check + if /^8\.*/ === Tk::TK_VERSION && JAPANIZED_TK + begin + compound = tk_split_simplelist(tk_call('font', 'configure', + ltn, '-compound')) + if knj == nil + if compound != [] + ltn, knj = compound + end + else + if compound != [] + ltn = compound[0] + end + compound = tk_split_simplelist(tk_call('font', 'configure', + knj, '-compound')) + if compound != [] + knj = compound[1] + end + end + rescue + end + end + + if ltn + knj = ltn if JAPANIZED_TK && !knj + else + ltn = DEFAULT_LATIN_FONT_NAME + knj = DEFAULT_KANJI_FONT_NAME if JAPANIZED_TK && !knj + end + create_compoundfont(ltn, knj, keys) end @@ -457,8 +496,48 @@ class TkFont @compoundfont = @id + 'c' if JAPANIZED_TK @fontslot = {'font'=>@compoundfont} - tk_call('font', 'create', @compoundfont, - '-compound', [@latinfont, @kanjifont], *hash_kv(keys)) + begin + tk_call('font', 'create', @compoundfont, + '-compound', [@latinfont, @kanjifont], *hash_kv(keys)) + rescue RuntimeError => e + if ltn == knj + if e.message =~ /kanji font .* specified/ + tk_call('font', 'delete', @latinfont) + create_latinfont(DEFAULT_LATIN_FONT_NAME) + opts = [] + Hash[*(tk_split_simplelist(tk_call('font', 'configure', + @kanjifont)))].each{|k,v| + case k + when '-size', '-weight', '-slant', '-underline', '-overstrike' + opts << k << v + end + } + tk_call('font', 'configure', @latinfont, *opts) + tk_call('font', 'create', @compoundfont, + '-compound', [@latinfont, @kanjifont], *hash_kv(keys)) + + elsif e.message =~ /ascii font .* specified/ + tk_call('font', 'delete', @kanjifont) + create_kanjifont(DEFAULT_KANJI_FONT_NAME) + opts = [] + Hash[*(tk_split_simplelist(tk_call('font', 'configure', + @latinfont)))].each{|k,v| + case k + when '-size', '-weight', '-slant', '-underline', '-overstrike' + opts << k << v + end + } + tk_call('font', 'configure', @kanjifont, *opts) + tk_call('font', 'create', @compoundfont, + '-compound', [@latinfont, @kanjifont], *hash_kv(keys)) + + else + raise e + end + else + raise e + end + end else tk_call('font', 'create', @compoundfont) @@ -529,7 +608,8 @@ class TkFont end def configure_core_tk4x(font, slot, value=None) - "" + #"" + self end def configinfo_core_tk4x(font, option=nil) @@ -544,11 +624,70 @@ class TkFont end def configure_core_tk8x(font, slot, value=None) + if JAPANIZED_TK + begin + padjust = tk_call('font', 'configure', font, '-pointadjust') + rescue + padjust = nil + end + else + padjust = nil + end if slot.kind_of? Hash - tk_call 'font', 'configure', font, *hash_kv(slot) + if JAPANIZED_TK && (slot.key?('family') || slot.key?(:family)) + slot = _symbolkey2str(slot) + configure_core_tk8x(font, 'family', slot.delete('family')) + end + + if ((slot.key?('size') || slot.key?(:size)) && + padjust && !slot.key?('pointadjust') && !slot.key?(:pointadjust)) + tk_call('font', 'configure', font, + '-pointadjust', padjust, *hash_kv(slot)) + else + tk_call('font', 'configure', font, *hash_kv(slot)) + end + elsif (slot == 'size' || slot == :size) && padjust != nil + tk_call('font', 'configure', font, + "-#{slot}", value, '-pointadjust', padjust) + elsif JAPANIZED_TK && (slot == 'family' || slot == :family) + # coumpund font? + begin + compound = tk_split_simplelist(tk_call('font', 'configure', + font, '-compound')) + rescue + tk_call('font', 'configure', font, '-family', value) + return self + end + if compound == [] + tk_call('font', 'configure', font, '-family', value) + return self + end + ltn, knj = compound + + lfnt = tk_call('font', 'create', '-copy', ltn) + begin + tk_call('font', 'configure', lfnt, '-family', value) + latin_replace_core_tk8x(lfnt) + rescue RuntimeError => e + fail e if $DEBUG + ensure + tk_call('font', 'delete', lfnt) if lfnt != '' + end + + kfnt = tk_call('font', 'create', '-copy', knj) + begin + tk_call('font', 'configure', kfnt, '-family', value) + kanji_replace_core_tk8x(lfnt) + rescue RuntimeError => e + fail e if $DEBUG + ensure + tk_call('font', 'delete', kfnt) if kfnt != '' + end + else - tk_call 'font', 'configure', font, "-#{slot}", value + tk_call('font', 'configure', font, "-#{slot}", value) end + self end def configinfo_core_tk8x(font, option=nil) @@ -659,20 +798,90 @@ class TkFont end def latin_replace_core_tk8x(ltn) + if JAPANIZED_TK + begin + tk_call('font', 'delete', '@font_tmp') + rescue + end + begin + fnt_bup = tk_call('font', 'create', '@font_tmp', '-copy', @latinfont) + rescue + fnt_bup = '' + end + end + begin tk_call('font', 'delete', @latinfont) rescue end create_latinfont(ltn) + + if JAPANIZED_TK + keys = self.configinfo + tk_call('font', 'delete', @compoundfont) + begin + tk_call('font', 'create', @compoundfont, + '-compound', [@latinfont, @kanjifont], *hash_kv(keys)) + rescue RuntimeError => e + tk_call('font', 'delete', @latinfont) + if fnt_bup != '' + tk_call('font', 'create', @latinfont, '-copy', fnt_bup) + tk_call('font', 'create', @compoundfont, + '-compound', [@latinfont, @kanjifont], *hash_kv(keys)) + tk_call('font', 'delete', fnt_bup) + end + fail e + end + else + latinkeys = {} + begin + actual_core(@latinfont).each{|key,val| latinkeys[key] = val} + rescue + latinkeys {} + end + if latinkeys != {} + tk_call('font', 'configure', @compoundfont, *hash_kv(latinkeys)) + end + end self end def kanji_replace_core_tk8x(knj) + if JAPANIZED_TK + begin + tk_call('font', 'delete', '@font_tmp') + rescue + end + begin + fnt_bup = tk_call('font', 'create', '@font_tmp', '-copy', @kanjifont) + rescue + fnt_bup = '' + end + end + begin tk_call('font', 'delete', @kanjifont) rescue end create_kanjifont(knj) + + if JAPANIZED_TK + keys = self.configinfo + tk_call('font', 'delete', @compoundfont) + begin + tk_call('font', 'create', @compoundfont, + '-compound', [@latinfont, @kanjifont], *hash_kv(keys)) + rescue RuntimeError => e + tk_call('font', 'delete', @kanjifont) + if fnt_bup != '' + tk_call('font', 'create', @kanjifont, '-copy', fnt_bup) + tk_call('font', 'create', @compoundfont, + '-compound', [@latinfont, @kanjifont], *hash_kv(keys)) + tk_call('font', 'delete', fnt_bup) + end + fail e + end + end self end @@ -737,7 +946,7 @@ class TkFont alias measure_core measure_core_tk4x alias metrics_core metrics_core_tk4x - when /^8\.[0123]/ + when /^8\.[0-4]/ alias create_latinfont create_latinfont_tk8x alias create_kanjifont create_kanjifont_tk8x alias create_compoundfont create_compoundfont_tk8x diff --git a/ext/tk/lib/tktext.rb b/ext/tk/lib/tktext.rb index ae40ac8750..9f1ad24665 100644 --- a/ext/tk/lib/tktext.rb +++ b/ext/tk/lib/tktext.rb @@ -330,6 +330,12 @@ class TkText<TkTextWin case key.to_s when 'text', 'label', 'show', 'data', 'file' tk_call(@path, 'tag', 'cget', tag, "-#{key}") + when 'font', 'kanjifont' + fnt = tk_tcl2ruby(tk_send('tag', 'cget', tag, "-#{key}")) + unless fnt.kind_of?(TkFont) + fnt = tagfontobj(tag, fnt) + end + fnt else tk_tcl2ruby(tk_call(@path, 'tag', 'cget', tag, "-#{key}")) end @@ -363,13 +369,17 @@ class TkText<TkTextWin case key.to_s when 'text', 'label', 'show', 'data', 'file' conf = tk_split_simplelist(tk_send('tag','configure',tag,"-#{key}")) + when 'font', 'kanjifont' + conf = tk_split_simplelist(tk_send('tag','configure',tag,"-#{key}") ) + conf[4] = tagfont_configinfo(tag, conf[4]) else conf = tk_split_list(tk_send('tag','configure',tag,"-#{key}")) end conf[0] = conf[0][1..-1] conf else - tk_split_simplelist(tk_send('tag', 'configure', tag)).collect{|conflist| + ret = tk_split_simplelist(tk_send('tag', 'configure', + tag)).collect{|conflist| conf = tk_split_simplelist(conflist) conf[0] = conf[0][1..-1] case conf[0] @@ -392,6 +402,14 @@ class TkText<TkTextWin end conf } + fontconf = ret.assoc('font') + if fontconf + ret.delete_if{|item| item[0] == 'font' || item[0] == 'kanjifont'} + fontconf[4] = tagfont_configinfo(tag, fontconf[4]) + ret.push(fontconf) + else + ret + end end end @@ -431,6 +449,12 @@ class TkText<TkTextWin case slot.to_s when 'text', 'label', 'show', 'data', 'file' tk_send('window', 'cget', index, "-#{slot}") + when 'font', 'kanjifont' + fnt = tk_tcl2ruby(tk_send('window', 'cget', index, "-#{slot}")) + unless fnt.kind_of?(TkFont) + fnt = tagfontobj(index, fnt) + end + fnt else tk_tcl2ruby(tk_send('window', 'cget', index, "-#{slot}")) end @@ -853,8 +877,14 @@ class TkTextTag<TkObject case key.to_s when 'text', 'label', 'show', 'data', 'file' tk_call @t.path, 'tag', 'cget', @id, "-#{key}" + when 'font', 'kanjifont' + fnt = tk_tcl2ruby(tk_call(@t.path, 'tag', 'cget', @id, "-#{key}")) + unless fnt.kind_of?(TkFont) + fnt = tagfontobj(@id, fnt) + end + fnt else - tk_tcl2ruby tk_call(@t.path, 'tag', 'cget', @id, "-#{key}") + tk_tcl2ruby(tk_call(@t.path, 'tag', 'cget', @id, "-#{key}")) end end @@ -1180,11 +1180,18 @@ proc_setpriority(obj, which, who, prio) #endif } +static int under_uid_switch = 0; +static int under_gid_switch = 0; + static VALUE p_sys_setuid(obj, id) VALUE obj, id; { #if defined HAVE_SETUID + rb_secure(2); + if (under_uid_switch) { + rb_raise(rb_eRuntimeError, "can't handle UID during evaluating the block given to the Process::UID.switch method"); + } if (setuid(NUM2INT(id)) != 0) rb_sys_fail(0); #else rb_notimplement(); @@ -1197,6 +1204,10 @@ p_sys_setruid(obj, id) VALUE obj, id; { #if defined HAVE_SETRUID + rb_secure(2); + if (under_uid_switch) { + rb_raise(rb_eRuntimeError, "can't handle UID during evaluating the block given to the Process::UID.switch method"); + } if (setruid(NUM2INT(id)) != 0) rb_sys_fail(0); #else rb_notimplement(); @@ -1209,6 +1220,10 @@ p_sys_seteuid(obj, id) VALUE obj, id; { #if defined HAVE_SETEUID + rb_secure(2); + if (under_uid_switch) { + rb_raise(rb_eRuntimeError, "can't handle UID during evaluating the block given to the Process::UID.switch method"); + } if (seteuid(NUM2INT(id)) != 0) rb_sys_fail(0); #else rb_notimplement(); @@ -1221,6 +1236,10 @@ p_sys_setreuid(obj, rid, eid) VALUE obj, rid, eid; { #if defined HAVE_SETREUID + rb_secure(2); + if (under_uid_switch) { + rb_raise(rb_eRuntimeError, "can't handle UID during evaluating the block given to the Process::UID.switch method"); + } if (setreuid(NUM2INT(rid),NUM2INT(eid)) != 0) rb_sys_fail(0); #else rb_notimplement(); @@ -1233,6 +1252,10 @@ p_sys_setresuid(obj, rid, eid, sid) VALUE obj, rid, eid, sid; { #if defined HAVE_SETRESUID + rb_secure(2); + if (under_uid_switch) { + rb_raise(rb_eRuntimeError, "can't handle UID during evaluating the block given to the Process::UID.switch method"); + } if (setresuid(NUM2INT(rid),NUM2INT(eid),NUM2INT(sid)) != 0) rb_sys_fail(0); #else rb_notimplement(); @@ -1254,6 +1277,10 @@ proc_setuid(obj, id) { int uid = NUM2INT(id); + rb_secure(2); + if (under_uid_switch) { + rb_raise(rb_eRuntimeError, "can't handle UID during evaluating the block given to the Process::UID.switch method"); + } #if defined(HAVE_SETRESUID) && !defined(__CHECKER__) if (setresuid(uid, -1, -1) < 0) rb_sys_fail(0); #elif defined HAVE_SETREUID @@ -1284,6 +1311,11 @@ p_uid_change_privilege(obj, id) extern int errno; int uid; + rb_secure(2); + if (under_uid_switch) { + rb_raise(rb_eRuntimeError, "can't handle UID during evaluating the block given to the Process::UID.switch method"); + } + uid = NUM2INT(id); if (geteuid() == 0) { /* root-user */ @@ -1420,6 +1452,10 @@ p_sys_setgid(obj, id) VALUE obj, id; { #if defined HAVE_SETGID + rb_secure(2); + if (under_gid_switch) { + rb_raise(rb_eRuntimeError, "can't handle GID during evaluating the block given to the Process::GID.switch method"); + } if (setgid(NUM2INT(id)) != 0) rb_sys_fail(0); #else rb_notimplement(); @@ -1432,6 +1468,10 @@ p_sys_setrgid(obj, id) VALUE obj, id; { #if defined HAVE_SETRGID + rb_secure(2); + if (under_gid_switch) { + rb_raise(rb_eRuntimeError, "can't handle GID during evaluating the block given to the Process::GID.switch method"); + } if (setrgid(NUM2INT(id)) != 0) rb_sys_fail(0); #else rb_notimplement(); @@ -1444,6 +1484,10 @@ p_sys_setegid(obj, id) VALUE obj, id; { #if defined HAVE_SETEGID + rb_secure(2); + if (under_gid_switch) { + rb_raise(rb_eRuntimeError, "can't handle GID during evaluating the block given to the Process::GID.switch method"); + } if (setegid(NUM2INT(id)) != 0) rb_sys_fail(0); #else rb_notimplement(); @@ -1456,6 +1500,10 @@ p_sys_setregid(obj, rid, eid) VALUE obj, rid, eid; { #if defined HAVE_SETREGID + rb_secure(2); + if (under_gid_switch) { + rb_raise(rb_eRuntimeError, "can't handle GID during evaluating the block given to the Process::GID.switch method"); + } if (setregid(NUM2INT(rid),NUM2INT(eid)) != 0) rb_sys_fail(0); #else rb_notimplement(); @@ -1468,6 +1516,10 @@ p_sys_setresgid(obj, rid, eid, sid) VALUE obj, rid, eid, sid; { #if defined HAVE_SETRESGID + rb_secure(2); + if (under_gid_switch) { + rb_raise(rb_eRuntimeError, "can't handle GID during evaluating the block given to the Process::GID.switch method"); + } if (setresgid(NUM2INT(rid),NUM2INT(eid),NUM2INT(sid)) != 0) rb_sys_fail(0); #else rb_notimplement(); @@ -1505,6 +1557,10 @@ proc_setgid(obj, id) { int gid = NUM2INT(id); + rb_secure(2); + if (under_gid_switch) { + rb_raise(rb_eRuntimeError, "can't handle GID during evaluating the block given to the Process::GID.switch method"); + } #if defined(HAVE_SETRESGID) && !defined(__CHECKER__) if (setresgid(gid, -1, -1) < 0) rb_sys_fail(0); #elif defined HAVE_SETREGID @@ -1650,6 +1706,11 @@ p_gid_change_privilege(obj, id) extern int errno; int gid; + rb_secure(2); + if (under_gid_switch) { + rb_raise(rb_eRuntimeError, "can't handle GID during evaluating the block given to the Process::GID.switch method"); + } + gid = NUM2INT(id); if (geteuid() == 0) { /* root-user */ @@ -1794,6 +1855,10 @@ static VALUE proc_seteuid(obj, euid) VALUE obj, euid; { + rb_secure(2); + if (under_uid_switch) { + rb_raise(rb_eRuntimeError, "can't handle UID during evaluating the block given to the Process::UID.switch method"); + } #if defined(HAVE_SETRESUID) && !defined(__CHECKER__) if (setresuid(-1, NUM2INT(euid), -1) < 0) rb_sys_fail(0); #elif defined HAVE_SETREUID @@ -1820,6 +1885,11 @@ rb_seteuid_core(euid) { int uid; + rb_secure(2); + if (under_uid_switch) { + rb_raise(rb_eRuntimeError, "can't handle UID during evaluating the block given to the Process::UID.switch method"); + } + uid = getuid(); #if defined(HAVE_SETRESUID) && !defined(__CHECKER__) @@ -1868,6 +1938,9 @@ proc_setegid(obj, egid) VALUE obj, egid; { rb_secure(2); + if (under_gid_switch) { + rb_raise(rb_eRuntimeError, "can't handle GID during evaluating the block given to the Process::GID.switch method"); + } #if defined(HAVE_SETRESGID) && !defined(__CHECKER__) if (setresgid(-1, NUM2INT(egid), -1) < 0) rb_sys_fail(0); #elif defined HAVE_SETREGID @@ -1894,6 +1967,11 @@ rb_setegid_core(egid) { int gid; + rb_secure(2); + if (under_gid_switch) { + rb_raise(rb_eRuntimeError, "can't handle GID during evaluating the block given to the Process::GID.switch method"); + } + gid = getgid(); #if defined(HAVE_SETRESGID) && !defined(__CHECKER__) @@ -1946,6 +2024,11 @@ p_uid_exchange(obj) { int uid, euid; + rb_secure(2); + if (under_uid_switch) { + rb_raise(rb_eRuntimeError, "can't handle UID during evaluating the block given to the Process::UID.switch method"); + } + uid = getuid(); euid = geteuid(); @@ -1979,6 +2062,11 @@ p_gid_exchange(obj) { int gid, egid; + rb_secure(2); + if (under_gid_switch) { + rb_raise(rb_eRuntimeError, "can't handle GID during evaluating the block given to the Process::GID.switch method"); + } + gid = getgid(); egid = getegid(); @@ -2004,6 +2092,16 @@ p_uid_have_saved_id() #endif } + +#if defined(HAVE_SETRESUID) || defined(HAVE_SETEUID) || defined(_POSIX_SAVED_IDS) +static VALUE +p_uid_sw_ensure(id) + int id; +{ + under_uid_switch = 0; + return rb_seteuid_core(id); +} + static VALUE p_uid_switch(obj) VALUE obj; @@ -2011,21 +2109,27 @@ p_uid_switch(obj) extern int errno; int uid, euid; + rb_secure(2); + if (under_uid_switch) { + rb_raise(rb_eRuntimeError, "can't handle UID during evaluating the block given to the Process::UID.switch method"); + } + uid = getuid(); euid = geteuid(); -#if defined(HAVE_SETRESUID) || defined(HAVE_SETEUID) || defined(_POSIX_SAVED_IDS) if (uid != euid) { proc_seteuid(obj, INT2FIX(uid)); if (rb_block_given_p()) { - return rb_ensure(rb_yield, Qnil, rb_seteuid_core, SAVED_USER_ID); + under_uid_switch = 1; + return rb_ensure(rb_yield, Qnil, p_uid_sw_ensure, SAVED_USER_ID); } else { return INT2FIX(euid); } } else if (euid != SAVED_USER_ID) { proc_seteuid(obj, INT2FIX(SAVED_USER_ID)); if (rb_block_given_p()) { - return rb_ensure(rb_yield, Qnil, rb_seteuid_core, euid); + under_uid_switch = 1; + return rb_ensure(rb_yield, Qnil, p_uid_sw_ensure, euid); } else { return INT2FIX(uid); } @@ -2033,14 +2137,39 @@ p_uid_switch(obj) errno = EPERM; rb_sys_fail(0); } + #else +static VALUE +p_uid_sw_ensure(obj) + VALUE obj; +{ + under_uid_switch = 0; + return p_uid_exchange(obj); +} + +static VALUE +p_uid_switch(obj) + VALUE obj; +{ + extern int errno; + int uid, euid; + + rb_secure(2); + if (under_uid_switch) { + rb_raise(rb_eRuntimeError, "can't handle UID during evaluating the block given to the Process::UID.switch method"); + } + + uid = getuid(); + euid = geteuid(); + if (uid == euid) { errno = EPERM; rb_sys_fail(0); } - p_uid_switch(obj); + p_uid_exchange(obj); if (rb_block_given_p()) { - return rb_ensure(rb_yield, Qnil, p_uid_switch, obj); + under_uid_switch = 1; + return rb_ensure(rb_yield, Qnil, p_uid_sw_ensure, obj); } else { return INT2FIX(euid); } @@ -2057,6 +2186,15 @@ p_gid_have_saved_id() #endif } +#if defined(HAVE_SETRESGID) || defined(HAVE_SETEGID) || defined(_POSIX_SAVED_IDS) +static VALUE +p_gid_sw_ensure(id) + int id; +{ + under_gid_switch = 0; + rb_setegid_core(id); +} + static VALUE p_gid_switch(obj) VALUE obj; @@ -2064,22 +2202,27 @@ p_gid_switch(obj) extern int errno; int gid, egid; + rb_secure(2); + if (under_gid_switch) { + rb_raise(rb_eRuntimeError, "can't handle GID during evaluating the block given to the Process::GID.switch method"); + } + gid = getgid(); egid = getegid(); -#if defined(HAVE_SETRESGID) || defined(HAVE_SETEGID) || defined(_POSIX_SAVED_IDS) if (gid != egid) { proc_setegid(obj, INT2FIX(gid)); if (rb_block_given_p()) { - return rb_ensure(rb_yield, Qnil, proc_setegid, - INT2FIX(SAVED_GROUP_ID)); + under_gid_switch = 1; + return rb_ensure(rb_yield, Qnil, p_gid_sw_ensure, SAVED_GROUP_ID); } else { return INT2FIX(egid); } } else if (egid != SAVED_GROUP_ID) { proc_setegid(obj, INT2FIX(SAVED_GROUP_ID)); if (rb_block_given_p()) { - return rb_ensure(rb_yield, Qnil, proc_setegid, INT2FIX(egid)); + under_gid_switch = 1; + return rb_ensure(rb_yield, Qnil, p_gid_sw_ensure, egid); } else { return INT2FIX(gid); } @@ -2088,13 +2231,36 @@ p_gid_switch(obj) rb_sys_fail(0); } #else +p_gid_sw_ensure(obj) + VALUE obj; +{ + under_gid_switch = 0; + p_gid_exchange(obj); +} + +static VALUE +p_gid_switch(obj) + VALUE obj; +{ + extern int errno; + int gid, egid; + + rb_secure(2); + if (under_gid_switch) { + rb_raise(rb_eRuntimeError, "can't handle GID during evaluating the block given to the Process::GID.switch method"); + } + + gid = getgid(); + egid = getegid(); + if (gid == egid) { errno = EPERM; rb_sys_fail(0); } - p_gid_switch(obj); + p_gid_exchange(obj); if (rb_block_given_p()) { - return rb_ensure(rb_yield, Qnil, p_gid_switch, obj); + under_gid_switch = 1; + return rb_ensure(rb_yield, Qnil, p_gid_sw_ensure, obj); } else { return INT2FIX(egid); } |