From c9ec81289744231cb3ca9aa2c2bda3de6a668442 Mon Sep 17 00:00:00 2001 From: nagai Date: Thu, 4 Aug 2005 09:41:57 +0000 Subject: * ext/tk/tcltklib.c: cannot compile for Tcl7.6/Tk4.2. * ext/tk/tcltklib.c: add nativethread consistency check. * ext/tk/stubs.c: ditto. * ext/tk/lib/tk.rb: forgot to define TclTkIp.encoding and encoding= when Tcl is 7.6 or 8.0. * ext/tk/lib/tk/wm.rb: support to make some methods as options of root or toplevel widget. [ruby-talk:150336] * ext/tk/lib/tk/root.rb: ditto. * ext/tk/lib/tk/toplevel.rb: ditto. * ext/tk/lib/tkextlib/SUPPRT_STATUS: update RELEASE_DATE git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@8911 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ext/tk/lib/tk.rb | 4 +- ext/tk/lib/tk/root.rb | 19 +++++++- ext/tk/lib/tk/toplevel.rb | 12 ++++- ext/tk/lib/tk/wm.rb | 78 +++++++++++++++++++++++++++++--- ext/tk/lib/tkextlib/SUPPORT_STATUS | 2 +- ext/tk/stubs.c | 51 ++++++++++++++++++++- ext/tk/tcltklib.c | 92 ++++++++++++++++++++++++++++++++++---- 7 files changed, 238 insertions(+), 20 deletions(-) (limited to 'ext/tk') diff --git a/ext/tk/lib/tk.rb b/ext/tk/lib/tk.rb index 77257fe185..74fa4f38dd 100644 --- a/ext/tk/lib/tk.rb +++ b/ext/tk/lib/tk.rb @@ -2288,6 +2288,8 @@ if (/^(8\.[1-9]|9\.|[1-9][0-9])/ =~ Tk::TCL_VERSION && !Tk::JAPANIZED_TK) else # dummy methods class TclTkIp + attr_accessor :encoding + alias __eval _eval alias __invoke _invoke @@ -4201,7 +4203,7 @@ end #Tk.freeze module Tk - RELEASE_DATE = '2005-08-03'.freeze + RELEASE_DATE = '2005-08-04'.freeze autoload :AUTO_PATH, 'tk/variable' autoload :TCL_PACKAGE_PATH, 'tk/variable' diff --git a/ext/tk/lib/tk/root.rb b/ext/tk/lib/tk/root.rb index dd5f52ca82..0e5584c7c1 100644 --- a/ext/tk/lib/tk/root.rb +++ b/ext/tk/lib/tk/root.rb @@ -9,6 +9,11 @@ class TkRootmethod, ... } + TOPLEVEL_METHODCALL_OPTKEYS + end + private :__methodcall_optkeys + =begin ROOT = [] def TkRoot.new(keys=nil) @@ -36,7 +41,18 @@ class TkRoottrue, :widgetname=>'.'){} end root = TkCore::INTERP.tk_windows['.'] - if keys # wm commands + + keys = _symbolkey2str(keys) + + # wm commands + root.instance_eval{ + __methodcall_optkeys.each{|key, method| + value = keys.delete(key.to_s) + self.__send__(method, value) if value + } + } + + if keys # wm commands ( for backward comaptibility ) keys.each{|k,v| if v.kind_of? Array root.__send__(k,*v) @@ -45,6 +61,7 @@ class TkRootmethod, ... } + TOPLEVEL_METHODCALL_OPTKEYS + end + private :__methodcall_optkeys + def _wm_command_option_chk(keys) keys = {} unless keys new_keys = {} wm_cmds = {} + + conf_methods = _symbolkey2str(__methodcall_optkeys()) + keys.each{|k,v| - if Wm.method_defined?(k) + if conf_methods.key?(k) + wm_cmds[conf_methods[k]] = v + elsif Wm.method_defined?(k) case k when 'screen','class','colormap','container','use','visual' new_keys[k] = v diff --git a/ext/tk/lib/tk/wm.rb b/ext/tk/lib/tk/wm.rb index f3cfb0afb1..1f432a3848 100644 --- a/ext/tk/lib/tk/wm.rb +++ b/ext/tk/lib/tk/wm.rb @@ -9,14 +9,18 @@ module Tk TkCommandNames = ['wm'.freeze].freeze + TOPLEVEL_METHODCALL_OPTKEYS = {} + def aspect(*args) if args.length == 0 list(tk_call_without_enc('wm', 'aspect', path)) else + args = args[0] if args.length == 1 && args[0].kind_of?(Array) tk_call('wm', 'aspect', path, *args) self end end + TOPLEVEL_METHODCALL_OPTKEYS['aspect'] = 'aspect' def attributes(slot=nil,value=None) if slot == nil @@ -36,6 +40,7 @@ module Tk self end end + TOPLEVEL_METHODCALL_OPTKEYS['attributes'] = 'attributes' def client(name=None) if name == None @@ -46,15 +51,18 @@ module Tk self end end + TOPLEVEL_METHODCALL_OPTKEYS['client'] = 'client' def colormapwindows(*args) if args.size == 0 list(tk_call_without_enc('wm', 'colormapwindows', path)) else + args = args[0] if args.length == 1 && args[0].kind_of?(Array) tk_call_without_enc('wm', 'colormapwindows', path, *args) self end end + TOPLEVEL_METHODCALL_OPTKEYS['colormapwindows'] = 'colormapwindows' def wm_command(value=nil) if value @@ -65,9 +73,14 @@ module Tk tk_call('wm', 'command', path) end end + TOPLEVEL_METHODCALL_OPTKEYS['wm_command'] = 'wm_command' def deiconify(ex = true) - tk_call_without_enc('wm', 'deiconify', path) if ex + if ex + tk_call_without_enc('wm', 'deiconify', path) + else + self.iconify + end self end @@ -79,6 +92,7 @@ module Tk tk_call_without_enc('wm', 'focusmodel', path) end end + TOPLEVEL_METHODCALL_OPTKEYS['focusmodel'] = 'focusmodel' def frame tk_call_without_enc('wm', 'frame', path) @@ -92,15 +106,18 @@ module Tk tk_call_without_enc('wm', 'geometry', path) end end + TOPLEVEL_METHODCALL_OPTKEYS['geometry'] = 'geometry' def wm_grid(*args) if args.size == 0 list(tk_call_without_enc('wm', 'grid', path)) else + args = args[0] if args.length == 1 && args[0].kind_of?(Array) tk_call_without_enc('wm', 'grid', path, *args) self end end + TOPLEVEL_METHODCALL_OPTKEYS['wm_grid'] = 'wm_grid' def group(leader = nil) if leader @@ -110,6 +127,7 @@ module Tk window(tk_call('wm', 'group', path)) end end + TOPLEVEL_METHODCALL_OPTKEYS['group'] = 'group' def iconbitmap(bmp=nil) if bmp @@ -119,21 +137,33 @@ module Tk image_obj(tk_call_without_enc('wm', 'iconbitmap', path)) end end + TOPLEVEL_METHODCALL_OPTKEYS['iconbitmap'] = 'iconbitmap' def iconphoto(*imgs) - # Windows only + if imgs.empty? + @wm_iconphoto = nil unless defined? @wm_iconphoto + return @wm_iconphoto + end + + imgs = imgs[0] if imgs.length == 1 && imgs[0].kind_of?(Array) tk_call_without_enc('wm', 'iconphoto', path, *imgs) + @wm_iconphoto = imgs self end + TOPLEVEL_METHODCALL_OPTKEYS['iconphoto'] = 'iconphoto' def iconphoto_default(*imgs) - # Windows only + imgs = imgs[0] if imgs.length == 1 && imgs[0].kind_of?(Array) tk_call_without_enc('wm', 'iconphoto', path, '-default', *imgs) self end def iconify(ex = true) - tk_call_without_enc('wm', 'iconify', path) if ex + if ex + tk_call_without_enc('wm', 'iconify', path) + else + self.deiconify + end self end @@ -145,6 +175,7 @@ module Tk image_obj(tk_call_without_enc('wm', 'iconmask', path)) end end + TOPLEVEL_METHODCALL_OPTKEYS['iconmask'] = 'iconmask' def iconname(name=nil) if name @@ -154,15 +185,18 @@ module Tk tk_call('wm', 'iconname', path) end end + TOPLEVEL_METHODCALL_OPTKEYS['iconname'] = 'iconname' def iconposition(*args) if args.size == 0 list(tk_call_without_enc('wm', 'iconposition', path)) else + args = args[0] if args.length == 1 && args[0].kind_of?(Array) tk_call_without_enc('wm', 'iconposition', path, *args) self end end + TOPLEVEL_METHODCALL_OPTKEYS['iconposition'] = 'iconposition' def iconwindow(win = nil) if win @@ -173,24 +207,29 @@ module Tk (w == '')? nil: window(w) end end + TOPLEVEL_METHODCALL_OPTKEYS['iconwindow'] = 'iconwindow' def maxsize(*args) if args.size == 0 list(tk_call_without_enc('wm', 'maxsize', path)) else + args = args[0] if args.length == 1 && args[0].kind_of?(Array) tk_call_without_enc('wm', 'maxsize', path, *args) self end end + TOPLEVEL_METHODCALL_OPTKEYS['maxsize'] = 'maxsize' def minsize(*args) if args.size == 0 list(tk_call_without_enc('wm', 'minsize', path)) else + args = args[0] if args.length == 1 && args[0].kind_of?(Array) tk_call_without_enc('wm', 'minsize', path, *args) self end end + TOPLEVEL_METHODCALL_OPTKEYS['minsize'] = 'minsize' def overrideredirect(mode=None) if mode == None @@ -200,6 +239,7 @@ module Tk self end end + TOPLEVEL_METHODCALL_OPTKEYS['overrideredirect'] = 'overrideredirect' def positionfrom(who=None) if who == None @@ -210,6 +250,7 @@ module Tk self end end + TOPLEVEL_METHODCALL_OPTKEYS['positionfrom'] = 'positionfrom' def protocol(name=nil, cmd=nil, &b) if cmd @@ -226,14 +267,33 @@ module Tk end end + def protocols(kv=nil) + unless kv + ret = {} + self.protocol.each{|name| + ret[name] = self.protocol(name) + } + return ret + end + + unless kv.kind_of?(Hash) + fail ArgumentError, 'expect a hash of protocol=>command' + end + kv.each{|k, v| self.protocol(k, v)} + self + end + TOPLEVEL_METHODCALL_OPTKEYS['protocols'] = 'protocols' + def resizable(*args) if args.length == 0 list(tk_call_without_enc('wm', 'resizable', path)).collect{|e| bool(e)} else + args = args[0] if args.length == 1 && args[0].kind_of?(Array) tk_call_without_enc('wm', 'resizable', path, *args) self end end + TOPLEVEL_METHODCALL_OPTKEYS['resizable'] = 'resizable' def sizefrom(who=None) if who == None @@ -244,6 +304,7 @@ module Tk self end end + TOPLEVEL_METHODCALL_OPTKEYS['sizefrom'] = 'sizefrom' def stackorder list(tk_call('wm', 'stackorder', path)) @@ -265,6 +326,7 @@ module Tk tk_call_without_enc('wm', 'state', path) end end + TOPLEVEL_METHODCALL_OPTKEYS['state'] = 'state' def title(str=nil) if str @@ -274,6 +336,7 @@ module Tk tk_call('wm', 'title', path) end end + TOPLEVEL_METHODCALL_OPTKEYS['title'] = 'title' def transient(master=nil) if master @@ -283,9 +346,14 @@ module Tk window(tk_call_without_enc('wm', 'transient', path)) end end + TOPLEVEL_METHODCALL_OPTKEYS['transient'] = 'transient' def withdraw(ex = true) - tk_call_without_enc('wm', 'withdraw', path) if ex + if ex + tk_call_without_enc('wm', 'withdraw', path) + else + self.deiconify + end self end end diff --git a/ext/tk/lib/tkextlib/SUPPORT_STATUS b/ext/tk/lib/tkextlib/SUPPORT_STATUS index 587af51bdb..2d49676a29 100644 --- a/ext/tk/lib/tkextlib/SUPPORT_STATUS +++ b/ext/tk/lib/tkextlib/SUPPORT_STATUS @@ -1,7 +1,7 @@ [ current support status of Tcl/Tk extensions ] - *******<<< RELEASE_DATE of the libraries : 2005/06/16 >>>******* + *******<<< RELEASE_DATE of the libraries : 2005/08/04 >>>******* The following list shows *CURRENT* status when this file was modifyed at last. If you want to add other Tcl/Tk extensions to the planed list diff --git a/ext/tk/stubs.c b/ext/tk/stubs.c index e8b05355a9..050333cf63 100644 --- a/ext/tk/stubs.c +++ b/ext/tk/stubs.c @@ -24,6 +24,37 @@ _macinit() /*------------------------------*/ +static int nativethread_checked = 0; + +static void +_nativethread_consistency_check(ip) + Tcl_Interp *ip; +{ + if (nativethread_checked || ip == (Tcl_Interp *)NULL) { + return; + } + + if (Tcl_Eval(ip, "set ::tcl_platform(threaded)") == TCL_OK) { +#ifdef HAVE_NATIVETHREAD + /* consistent */ +#else + rb_warn("Inconsistency. Loaded Tcl/Tk libraries are enabled nativethread-support. But `tcltklib' is not. The inconsistency causes SEGV or other troubles frequently."); +#endif + } else { +#ifdef HAVE_NATIVETHREAD + rb_warning("Inconsistency.`tcltklib' is enabled nativethread-support. But loaded Tcl/Tk libraries are not. (Probably, the inconsistency doesn't cause any troubles.)"); +#else + /* consistent */ +#endif + } + + Tcl_ResetResult(ip); + + nativethread_checked = 1; +} + +/*------------------------------*/ + #if defined USE_TCL_STUBS && defined USE_TK_STUBS #if defined _WIN32 || defined __CYGWIN__ @@ -158,14 +189,25 @@ Tcl_Interp * ruby_tcl_create_ip_and_stubs_init(st) int *st; { + Tcl_Interp *tcl_ip; + if (st) *st = 0; if (tcl_stubs_init_p()) { - return Tcl_CreateInterp(); + tcl_ip = Tcl_CreateInterp(); + + if (!tcl_ip) { + if (st) *st = FAIL_CreateInterp; + return (Tcl_Interp*)NULL; + } + + _nativethread_consistency_check(tcl_ip); + + return tcl_ip; + } else { Tcl_Interp *(*p_Tcl_CreateInterp)(); Tcl_Interp *(*p_Tcl_DeleteInterp)(); - Tcl_Interp *tcl_ip; if (!tcl_dll) { int ret = ruby_open_tcl_dll(RSTRING(rb_argv0)->ptr); @@ -195,6 +237,8 @@ ruby_tcl_create_ip_and_stubs_init(st) return (Tcl_Interp*)NULL; } + _nativethread_consistency_check(tcl_ip); + if (!Tcl_InitStubs(tcl_ip, "8.1", 0)) { if (st) *st = FAIL_Tcl_InitStubs; (*p_Tcl_DeleteInterp)(tcl_ip); @@ -401,6 +445,9 @@ ruby_tcl_create_ip_and_stubs_init(st) if (st) *st = FAIL_CreateInterp; return (Tcl_Interp*)NULL; } + + _nativethread_consistency_check(tcl_ip); + return tcl_ip; } diff --git a/ext/tk/tcltklib.c b/ext/tk/tcltklib.c index 0c01be0bdb..c3f038ef66 100644 --- a/ext/tk/tcltklib.c +++ b/ext/tk/tcltklib.c @@ -4,7 +4,7 @@ * Oct. 24, 1997 Y. Matsumoto */ -#define TCLTKLIB_RELEASE_DATE "2005-08-01" +#define TCLTKLIB_RELEASE_DATE "2005-08-04" #include "ruby.h" #include "rubysig.h" @@ -141,6 +141,12 @@ tcl_global_eval(interp, cmd) #undef Tcl_GlobalEval #define Tcl_GlobalEval tcl_global_eval +/* Tcl_{Incr|Decr}RefCount for tcl7.x or earlier */ +#if TCL_MAJOR_VERSION < 8 +#define Tcl_IncrRefCount(obj) (1) +#define Tcl_DecrRefCount(obj) (1) +#endif + /* Tcl_GetStringResult for tcl7.x or earlier */ #if TCL_MAJOR_VERSION < 8 #define Tcl_GetStringResult(interp) ((interp)->result) @@ -2992,16 +2998,16 @@ ip_RubyExitCommand(clientData, interp, argc, argv) { int state; char *cmd, *param; +#if TCL_MAJOR_VERSION < 8 + char *endptr; + cmd = argv[0]; +#endif DUMP1("start ip_RubyExitCommand"); #if TCL_MAJOR_VERSION >= 8 /* cmd = Tcl_GetString(argv[0]); */ cmd = Tcl_GetStringFromObj(argv[0], (int*)NULL); - -#else /* TCL_MAJOR_VERSION < 8 */ - char *endptr; - cmd = argv[0]; #endif if (argc < 1 || argc > 2) { @@ -3129,6 +3135,7 @@ ip_rbUpdateCommand(clientData, interp, objc, objv) flags = TCL_ALL_EVENTS|TCL_DONT_WAIT; } else if (objc == 2) { +#if TCL_MAJOR_VERSION >= 8 if (Tcl_GetIndexFromObj(interp, objv[1], (CONST84 char **)updateOptions, "option", 0, &optionIndex) != TCL_OK) { return TCL_ERROR; @@ -3142,6 +3149,14 @@ ip_rbUpdateCommand(clientData, interp, objc, objv) rb_bug("ip_rbUpdateObjCmd: bad option index to UpdateOptions"); } } +#else + if (strncmp(objv[1], "idletasks", strlen(objv[1])) != 0) { + Tcl_AppendResult(interp, "bad option \"", objv[1], + "\": must be idletasks", (char *) NULL); + return TCL_ERROR; + } + flags = TCL_WINDOW_EVENTS|TCL_IDLE_EVENTS|TCL_DONT_WAIT; +#endif } else { #ifdef Tcl_WrongNumArgs Tcl_WrongNumArgs(interp, 1, objv, "[ idletasks ]"); @@ -3281,6 +3296,7 @@ ip_rb_threadUpdateCommand(clientData, interp, objc, objv) flags = TCL_ALL_EVENTS|TCL_DONT_WAIT; } else if (objc == 2) { +#if TCL_MAJOR_VERSION >= 8 if (Tcl_GetIndexFromObj(interp, objv[1], (CONST84 char **)updateOptions, "option", 0, &optionIndex) != TCL_OK) { return TCL_ERROR; @@ -3294,6 +3310,14 @@ ip_rb_threadUpdateCommand(clientData, interp, objc, objv) rb_bug("ip_rb_threadUpdateObjCmd: bad option index to UpdateOptions"); } } +#else + if (strncmp(objv[1], "idletasks", strlen(objv[1])) != 0) { + Tcl_AppendResult(interp, "bad option \"", objv[1], + "\": must be idletasks", (char *) NULL); + return TCL_ERROR; + } + flags = TCL_WINDOW_EVENTS|TCL_IDLE_EVENTS|TCL_DONT_WAIT; +#endif } else { #ifdef Tcl_WrongNumArgs Tcl_WrongNumArgs(interp, 1, objv, "[ idletasks ]"); @@ -4555,6 +4579,7 @@ ip_thread_tkwait(self, mode, target) /* delete slave interpreters */ +#if TCL_MAJOR_VERSION >= 8 static void delete_slaves(ip) Tcl_Interp *ip; @@ -4603,6 +4628,46 @@ delete_slaves(ip) rb_thread_critical = thr_crit_bup; } +#else /* TCL_MAJOR_VERSION < 8 */ +static void +delete_slaves(ip) + Tcl_Interp *ip; +{ + int thr_crit_bup; + Tcl_Interp *slave; + int argc; + char **argv; + char *slave_list; + char *slave_name; + int i, len; + + DUMP1("delete slaves"); + thr_crit_bup = rb_thread_critical; + rb_thread_critical = Qtrue; + + if (!Tcl_InterpDeleted(ip) && Tcl_Eval(ip, "interp slaves") == TCL_OK) { + slave_list = ip->result; + if (Tcl_SplitList((Tcl_Interp*)NULL, + slave_list, &argc, &argv) == TCL_OK) { + for(i = 0; i < argc; i++) { + slave_name = argv[i]; + + DUMP2("delete slave:'%s'", slave_name); + + slave = Tcl_GetSlave(ip, slave_name); + if (slave == (Tcl_Interp*)NULL) continue; + + /* call ip_finalize */ + ip_finalize(slave); + + Tcl_DeleteInterp(slave); + } + } + } + + rb_thread_critical = thr_crit_bup; +} +#endif /* finalize operation */ @@ -4870,12 +4935,9 @@ static void ip_wrap_namespace_command(interp) Tcl_Interp *interp; { +#if TCL_MAJOR_VERSION >= 8 Tcl_CmdInfo orig_info; -#if TCL_MAJOR_VERSION < 8 - return; -#endif - if (!Tcl_GetCommandInfo(interp, "namespace", &(orig_info))) { return; } @@ -4892,6 +4954,7 @@ ip_wrap_namespace_command(interp) Tcl_CreateObjCommand(interp, "namespace", ip_rbNamespaceObjCmd, (ClientData) 0, (Tcl_CmdDeleteProc *)NULL); +#endif } @@ -5776,6 +5839,7 @@ tk_funcall(func, argc, argv, obj) /* eval string in tcl by Tcl_Eval() */ +#if TCL_MAJOR_VERSION >= 8 struct call_eval_info { struct tcltkip *ptr; Tcl_Obj *cmd; @@ -5791,6 +5855,7 @@ call_tcl_eval(arg) return Qnil; } +#endif static VALUE ip_eval_real(self, cmd_str, cmd_len) @@ -7323,6 +7388,7 @@ ip_get_variable2_core(interp, argc, argv) #else /* TCL_MAJOR_VERSION < 8 */ { char *ret; + volatile VALUE strval; /* ip is deleted? */ if (deleted_ip(ptr)) { @@ -7500,6 +7566,7 @@ ip_set_variable2_core(interp, argc, argv) #else /* TCL_MAJOR_VERSION < 8 */ { CONST char *ret; + volatile VALUE strval; /* ip is deleted? */ if (deleted_ip(ptr)) { @@ -8065,6 +8132,7 @@ tcltklib_compile_info() return ret; } + /*---- initialization ----*/ void Init_tcltklib() @@ -8286,6 +8354,12 @@ Init_tcltklib() /* --------------------------------------------------------------- */ + /* if ruby->nativethread-supprt and tcltklib->doen't, + the following will cause link-error. */ + is_ruby_native_thread(); + + /* --------------------------------------------------------------- */ + ret = ruby_open_tcl_dll(RSTRING(rb_argv0)->ptr); switch(ret) { case TCLTK_STUBS_OK: -- cgit v1.2.3