summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authornagai <nagai@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2004-05-21 20:45:27 +0000
committernagai <nagai@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2004-05-21 20:45:27 +0000
commitea710f0dcad908c46d3e58291db45ea3738991da (patch)
tree577835e82903eb19d713f91c830ef62bd6e08f40
parentdfdffdd9a3eb2c56a8913277d00a7598aaf2aa16 (diff)
* ext/tk/lib/tk.rb: add Tk.appsend_deny and improve Tk.rb_appsend
* ext/tk/lib/tk.rb, ext/tk/lib/tk/*.rb : replace obj.send() -> obj.__send__() * ext/tk/lib/remote-tk.rb: add a new library which create an object to control a Tk interpreter on the other process git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_1_8@6384 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r--ChangeLog5
-rw-r--r--ext/tk/README.fork7
-rw-r--r--ext/tk/lib/multi-tk.rb39
-rw-r--r--ext/tk/lib/remote-tk.rb397
-rw-r--r--ext/tk/lib/tk.rb81
-rw-r--r--ext/tk/lib/tk/bindtag.rb3
-rw-r--r--ext/tk/lib/tk/canvastag.rb6
-rw-r--r--ext/tk/lib/tk/font.rb3
-rw-r--r--ext/tk/lib/tk/image.rb3
-rw-r--r--ext/tk/lib/tk/namespace.rb3
-rw-r--r--ext/tk/lib/tk/root.rb4
-rw-r--r--ext/tk/lib/tk/textmark.rb3
-rw-r--r--ext/tk/lib/tk/texttag.rb3
-rw-r--r--ext/tk/lib/tk/timer.rb3
-rw-r--r--ext/tk/lib/tk/toplevel.rb4
-rw-r--r--ext/tk/lib/tk/variable.rb3
-rw-r--r--ext/tk/lib/tk/virtevent.rb5
-rw-r--r--ext/tk/sample/remote-ip_sample.rb33
18 files changed, 562 insertions, 43 deletions
diff --git a/ChangeLog b/ChangeLog
index b55f323e04..31af24f974 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+Sat May 22 05:37:11 2004 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/lib/remote-tk.rb: (NEW library) controll Tk interpreters
+ on the other processes by Tcl/Tk's 'send' command
+
Fri May 21 09:22:05 2004 Dave Thomas <dave@pragprog.com>
* lib/rdoc/parsers/parse_rb.rb (RDoc::RubyParser::parse_method_parameters):
diff --git a/ext/tk/README.fork b/ext/tk/README.fork
index cda89b003c..707d78fc12 100644
--- a/ext/tk/README.fork
+++ b/ext/tk/README.fork
@@ -4,6 +4,11 @@ process). In the library 'tk.rb', a Tk interpreter is initialized.
Therefore, if you want running Tk under a child process, please call
"require 'tk'" in the child process.
+# If do fork and exec(<new Ruby/Tk>) on the child process, you can
+# control Ruby/Tk interpreter on the child process by 'send' command
+# of Tcl/Tk. About this, please see Tk.appsend and Tk.rb_appsend, or
+# 'remote-tk.rb' and the sample 'sample/remote-ip_sample.rb'.
+
For example, the following sample1 will NOT work, and sample2 will
work properly.
@@ -26,4 +31,4 @@ TkButton.new(:text=>'QUIT', :command=>proc{exit}).pack
Tk.mainloop
-------------------------------------------------------------
- 2004/04/20 Hidetoshi NAGAI
+ 2004/05/22 Hidetoshi NAGAI
diff --git a/ext/tk/lib/multi-tk.rb b/ext/tk/lib/multi-tk.rb
index a3cd3857a0..ba1dc733ca 100644
--- a/ext/tk/lib/multi-tk.rb
+++ b/ext/tk/lib/multi-tk.rb
@@ -6,6 +6,10 @@ require 'tcltklib'
require 'tkutil'
require 'thread'
+if defined? Tk
+ fail RuntimeError, "'multi-tk' library must be required before requiring 'tk'"
+end
+
################################################
# ignore exception on the mainloop?
@@ -37,14 +41,14 @@ MultiTkIp_OK.freeze
class MultiTkIp
SLAVE_IP_ID = ['slave'.freeze, '0'.taint].freeze
- @@IP_TABLE = {}.taint
+ @@IP_TABLE = {}.taint unless defined?(@@IP_TABLE)
- @@INIT_IP_ENV = [].taint # table of Procs
- @@ADD_TK_PROCS = [].taint # table of [name, args, body]
+ @@INIT_IP_ENV = [].taint unless defined?(@@INIT_IP_ENV) # table of Procs
+ @@ADD_TK_PROCS = [].taint unless defined?(@@ADD_TK_PROCS) # table of [name, args, body]
- @@TK_TABLE_LIST = [].taint
+ @@TK_TABLE_LIST = [].taint unless defined?(@@TK_TABLE_LIST)
- @@TK_CMD_TBL = {}.taint
+ @@TK_CMD_TBL = {}.taint unless defined?(@@TK_CMD_TBL)
######################################
@@ -603,6 +607,13 @@ end
# get target IP
class MultiTkIp
+ def self._ip_id_
+ __getip._ip_id_
+ end
+ def _ip_id_
+ ''
+ end
+
def self.__getip
if Thread.current.group == ThreadGroup::Default
@@DEFAULT_MASTER
@@ -636,7 +647,7 @@ class << MultiTkIp
ip.eval_proc(&b) if b
ip
end
- alias new_trusted_slave new_master
+ alias new_trusted_slave new_slave
def new_safe_slave(keys={},&b)
ip = __new(__getip, true, keys)
@@ -798,7 +809,7 @@ class MultiTkIp
@@TK_TABLE_LIST << obj
obj.instance_eval <<-EOD
def self.method_missing(m, *args)
- MultiTkIp.tk_object_table(#{id}).send(m, *args)
+ MultiTkIp.tk_object_table(#{id}).__send__(m, *args)
end
EOD
obj.freeze
@@ -972,7 +983,7 @@ end
# class methods to delegate to TclTkIp
class << MultiTkIp
def method_missing(id, *args)
- __getip.send(id, *args)
+ __getip.__send__(id, *args)
end
def make_safe
@@ -1184,6 +1195,14 @@ class MultiTkIp
@interp.restart
end
+ def __eval(str)
+ @interp.__eval(str)
+ end
+
+ def __invoke(*args)
+ @interp.__invoke(*args)
+ end
+
def _eval(str)
@interp._eval(str)
end
@@ -1555,7 +1574,7 @@ class MultiTkIp
conf = _lst2ary(ip._eval("::safe::interpConfigure " +
@ip_name + " -#{slot}"))
if conf[0] == '-deleteHook'
- if conf[1] =~ /^rb_out (c\d+)/
+ if conf[1] =~ /^rb_out\S* (c(_\d+_)?\d+)/
ret[conf[0][1..-1]] = MultiTkIp._tk_cmd_tbl[$1]
else
ret[conf[0][1..-1]] = conf[1]
@@ -1567,7 +1586,7 @@ class MultiTkIp
Hash[*_lst2ary(ip._eval("::safe::interpConfigure " +
@ip_name))].each{|k, v|
if k == '-deleteHook'
- if v =~ /^rb_out (c\d+)/
+ if v =~ /^rb_out\S* (c(_\d+_)?\d+)/
ret[k[1..-1]] = MultiTkIp._tk_cmd_tbl[$1]
else
ret[k[1..-1]] = v
diff --git a/ext/tk/lib/remote-tk.rb b/ext/tk/lib/remote-tk.rb
new file mode 100644
index 0000000000..79fb20380c
--- /dev/null
+++ b/ext/tk/lib/remote-tk.rb
@@ -0,0 +1,397 @@
+#
+# remote-tk.rb - supports to control remote Tk interpreters
+# by Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+if defined? MultiTkIp
+ fail RuntimeError, "'remote-tk' library must be required before requiring 'multi-tk'"
+end
+
+class MultiTkIp; end
+class RemoteTkIp < MultiTkIp; end
+
+class MultiTkIp
+ @@IP_TABLE = {}.taint unless defined?(@@IP_TABLE)
+ @@TK_TABLE_LIST = {}.taint unless defined?(@@TK_TABLE_LIST)
+ def self._IP_TABLE; @@IP_TABLE; end
+ def self._TK_TABLE_LIST; @@TK_TABLE_LIST; end
+end
+class RemoteTkIp < MultiTkIp
+ @@IP_TABLE = MultiTkIp._IP_TABLE unless defined?(@@IP_TABLE)
+ @@TK_TABLE_LIST = MultiTkIp._TK_TABLE_LIST unless defined?(@@TK_TABLE_LIST)
+end
+class << MultiTkIp
+ undef _IP_TABLE
+ undef _TK_TABLE_LIST
+end
+
+require 'multi-tk'
+
+###############################
+
+class RemoteTkIp < MultiTkIp
+ include TkUtil
+
+ def initialize(remote_ip, displayof=nil)
+ if $SAFE >= 4
+ fail SecurityError, "cannot access another interpreter at level #{$SAFE}"
+ end
+
+ @interp = MultiTkIp.__getip
+ @appname = @interp._invoke('tk', 'appname')
+ @remote = remote_ip.dup.freeze
+ if displayof.kind_of?(TkWindow)
+ @displayof = displayof.path.dup.freeze
+ else
+ @displayof = nil
+ end
+ if self.deleted?
+ fail RuntimeError, "no Tk application named \"#{@remote}\""
+ end
+
+ @tk_windows = {}
+ @tk_table_list = []
+ @slave_ip_tbl = {}
+ @slave_ip_top = {}
+
+ @tk_windows.taint unless @tk_windows.tainted?
+ @tk_table_list.taint unless @tk_table_list.tainted?
+ @slave_ip_tbl.taint unless @slave_ip_tbl.tainted?
+ @slave_ip_top.taint unless @slave_ip_top.tainted?
+
+ @system = Object.new
+
+ @threadgroup = ThreadGroup.new
+
+ @cmd_queue = Queue.new
+
+ @cmd_receiver, @receiver_watchdog = _create_receiver_and_watchdog()
+
+ @threadgroup.add @cmd_receiver
+ @threadgroup.add @receiver_watchdog
+
+ @threadgroup.enclose
+
+ @@IP_TABLE[@threadgroup] = self
+ @@TK_TABLE_LIST.size.times{
+ (tbl = {}).tainted? || tbl.taint
+ @tk_table_list << tbl
+ }
+
+ @ip_id = _create_connection
+
+ self.freeze # defend against modification
+ end
+
+ def _ip_id_
+ @ip_id
+ end
+
+ def _create_connection
+ ip_id = '_' + @interp._invoke('send', @remote, <<-'EOS') + '_'
+ if {[catch {set _rubytk_control_ip_id_} ret] != 0} {
+ set _rubytk_control_ip_id_ 0
+ } else {
+ set _rubytk_control_ip_id_ [expr $ret + 1]
+ }
+ return $_rubytk_control_ip_id_
+ EOS
+
+ @interp._invoke('send', @remote, <<-EOS)
+ proc rb_out#{ip_id} args {
+ send #{@appname} rb_out \$args
+ }
+ EOS
+
+ ip_id
+ end
+ private :_create_connection
+
+ def _appsend(enc_mode, async, *cmds)
+ p ['_appsend', [@remote, @displayof], enc_mode, async, cmds] if $DEBUG
+ if $SAFE >= 4
+ fail SecurityError, "cannot send commands at level 4"
+ elsif $SAFE >= 1 && cmds.find{|obj| obj.tainted?}
+ fail SecurityError, "cannot send tainted commands at level #{$SAFE}"
+ end
+
+ cmds = @interp._merge_tklist(*_conv_args([], enc_mode, *cmds))
+ if @displayof
+ if async
+ @interp.__invoke('send', '-async', '-displayof', @displayof,
+ '--', @remote, *cmds)
+ else
+ @interp.__invoke('send', '-displayof', @displayof,
+ '--', @remote, *cmds)
+ end
+ else
+ if async
+ @interp.__invoke('send', '-async', '--', @remote, *cmds)
+ else
+ @interp.__invoke('send', '--', @remote, *cmds)
+ end
+ end
+ end
+ private :_appsend
+
+ def is_rubytk?
+ if _appsend(false, false, 'info', 'command', 'ruby') == ""
+ false
+ else
+ true
+ end
+ end
+
+ def appsend(async, *args)
+ if async != true && async != false && async != nil
+ args.unshift(async)
+ async = false
+ end
+ if @displayof
+ Tk.appsend_displayof(@remote, @displayof, async, *args)
+ else
+ Tk.appsend(@remote, async, *args)
+ end
+ end
+
+ def rb_appsend(async, *args)
+ if async != true && async != false && async != nil
+ args.unshift(async)
+ async = false
+ end
+ if @displayof
+ Tk.rb_appsend_displayof(@remote, @displayof, async, *args)
+ else
+ Tk.rb_appsend(@remote, async, *args)
+ end
+ end
+
+ def create_slave(name, safe=false)
+ if safe
+ safe_opt = ''
+ else
+ safe_opt = '-safe'
+ end
+ _appsend(false, false, "interp create #{safe_opt} -- #{name}")
+ end
+
+ def make_safe
+ fail RuntimeError, 'cannot change safe mode of the remote interpreter'
+ end
+
+ def safe?
+ _appsend(false, false, 'interp issafe')
+ end
+
+ def delete
+ _appsend(false, true, 'exit')
+ end
+
+ def deleted?
+ if @displayof
+ lst = @interp._invoke_without_enc('winfo', 'interps',
+ '-displayof', @displayof)
+ else
+ lst = @interp._invoke_without_enc('winfo', 'interps')
+ end
+ unless @interp._split_tklist(lst).index(@remote)
+ true
+ else
+ false
+ end
+ end
+
+ def restart
+ fail RuntimeError, 'cannot restart the remote interpreter'
+ end
+
+ def __eval(str)
+ _appsend(false, false, str)
+ end
+ def _eval(str)
+ _appsend(nil, false, str)
+ end
+ def _eval_without_enc(str)
+ _appsend(false, false, str)
+ end
+ def _eval_with_enc(str)
+ _appsend(true, false, str)
+ end
+
+ def _invoke(*args)
+ _appsend(nil, false, *args)
+ end
+
+ def __invoke(*args)
+ _appsend(false, false, *args)
+ end
+ def _invoke(*args)
+ _appsend(nil, false, *args)
+ end
+ def _invoke_without_enc(*args)
+ _appsend(false, false, *args)
+ end
+ def _invoke_with_enc(*args)
+ _appsend(true, false, *args)
+ end
+
+ def _toUTF8(str, encoding)
+ @interp._toUTF8(str, encoding)
+ end
+
+ def _fromUTF8(str, encoding)
+ @interp._fromUTF8(str, encoding)
+ end
+
+ def _thread_vwait(var_name)
+ _appsend(false, 'thread_vwait', varname)
+ end
+
+ def _thread_tkwait(mode, target)
+ _appsend(false, 'thread_tkwait', mode, target)
+ end
+
+ def _return_value
+ @interp._return_value
+ end
+
+ def _get_variable(var_name, flag)
+ # ignore flag
+ _appsend(false, 'set', _get_eval_string(var_name))
+ end
+ def _get_variable2(var_name, index_name, flag)
+ # ignore flag
+ _appsend(false, 'set', "#{_get_eval_string(var_name)}(#{_get_eval_string(index_name)})")
+ end
+
+ def _set_variable(var_name, value, flag)
+ # ignore flag
+ _appsend(false, 'set', _get_eval_string(var_name), _get_eval_string(value))
+ end
+ def _set_variable2(var_name, index_name, value, flag)
+ # ignore flag
+ _appsend(false, 'set', "#{_get_eval_string(var_name)}(#{_get_eval_string(index_name)})", _get_eval_string(value))
+ end
+
+ def _unset_variable(var_name, flag)
+ # ignore flag
+ _appsend(false, 'unset', _get_eval_string(var_name))
+ end
+ def _unset_variable2(var_name, index_name, flag)
+ # ignore flag
+ _appsend(false, 'unset', "#{var_name}(#{index_name})")
+ end
+
+ def _get_global_var(var_name)
+ _appsend(false, 'set', _get_eval_string(var_name))
+ end
+ def _get_global_var2(var_name, index_name)
+ _appsend(false, 'set', "#{_get_eval_string(var_name)}(#{_get_eval_string(index_name)})")
+ end
+
+ def _set_global_var(var_name, value)
+ _appsend(false, 'set', _get_eval_string(var_name), _get_eval_string(value))
+ end
+ def _set_global_var2(var_name, index_name, value)
+ _appsend(false, 'set', "#{_get_eval_string(var_name)}(#{_get_eval_string(index_name)})", _get_eval_string(value))
+ end
+
+ def _unset_global_var(var_name)
+ _appsend(false, 'unset', _get_eval_string(var_name))
+ end
+ def _unset_global_var2(var_name, index_name)
+ _appsend(false, 'unset', "#{var_name}(#{index_name})")
+ end
+
+ def _split_tklist(str)
+ @interp._split_tklist(str)
+ end
+
+ def _merge_tklist(*args)
+ @interp._merge_tklist(*args)
+ end
+
+ def _conv_listelement(str)
+ @interp._conv_listelement(str)
+ end
+
+ def mainloop
+ fail RuntimeError, 'not support "mainloop" on the remote interpreter'
+ end
+ def mainloop_watchdog
+ fail RuntimeError, 'not support "mainloop_watchdog" on the remote interpreter'
+ end
+ def do_one_evant(flag = nil)
+ fail RuntimeError, 'not support "do_one_event" on the remote interpreter'
+ end
+ def set_eventloop_tick(*args)
+ fail RuntimeError, 'not support "set_eventloop_tick" on the remote interpreter'
+ end
+ def get_eventloop_tick
+ fail RuntimeError, 'not support "get_eventloop_tick" on the remote interpreter'
+ end
+ def set_no_event_wait(*args)
+ fail RuntimeError, 'not support "set_no_event_wait" on the remote interpreter'
+ end
+ def get_no_event_wait
+ fail RuntimeError, 'not support "get_no_event_wait" on the remote interpreter'
+ end
+ def set_eventloop_weight(*args)
+ fail RuntimeError, 'not support "set_eventloop_weight" on the remote interpreter'
+ end
+ def get_eventloop_weight
+ fail RuntimeError, 'not support "get_eventloop_weight" on the remote interpreter'
+ end
+ def mainloop_abort_on_exception
+ fail RuntimeError, 'not support "mainloop_abort_on_exception" on the remote interpreter'
+ end
+ def mainloop_abort_on_exception=(*args)
+ fail RuntimeError, 'not support "mainloop_abort_on_exception=" on the remote interpreter'
+ end
+end
+
+class << RemoteTkIp
+ undef new_master, new_slave, new_safe_slave
+ undef new_trusted_slave, new_safeTk
+
+ def new(ip_name, displayof=nil, &b)
+ ip = __new(ip_name, displayof)
+ ip.eval_proc(&b) if b
+ ip
+ end
+end
+
+class << RemoteTkIp
+ def mainloop
+ fail RuntimeError, 'not support "mainloop" on the remote interpreter'
+ end
+ def mainloop_watchdog
+ fail RuntimeError, 'not support "mainloop_watchdog" on the remote interpreter'
+ end
+ def do_one_evant(flag = nil)
+ fail RuntimeError, 'not support "do_one_event" on the remote interpreter'
+ end
+ def set_eventloop_tick(*args)
+ fail RuntimeError, 'not support "set_eventloop_tick" on the remote interpreter'
+ end
+ def get_eventloop_tick
+ fail RuntimeError, 'not support "get_eventloop_tick" on the remote interpreter'
+ end
+ def set_no_event_wait(*args)
+ fail RuntimeError, 'not support "set_no_event_wait" on the remote interpreter'
+ end
+ def get_no_event_wait
+ fail RuntimeError, 'not support "get_no_event_wait" on the remote interpreter'
+ end
+ def set_eventloop_weight(*args)
+ fail RuntimeError, 'not support "set_eventloop_weight" on the remote interpreter'
+ end
+ def get_eventloop_weight
+ fail RuntimeError, 'not support "get_eventloop_weight" on the remote interpreter'
+ end
+ def mainloop_abort_on_exception
+ fail RuntimeError, 'not support "mainloop_abort_on_exception" on the remote interpreter'
+ end
+ def mainloop_abort_on_exception=(*args)
+ fail RuntimeError, 'not support "mainloop_abort_on_exception=" on the remote interpreter'
+ end
+end
diff --git a/ext/tk/lib/tk.rb b/ext/tk/lib/tk.rb
index f337bbb8b6..12d60245e7 100644
--- a/ext/tk/lib/tk.rb
+++ b/ext/tk/lib/tk.rb
@@ -14,6 +14,10 @@ class TclTkIp
# backup original (without encoding) _eval and _invoke
alias _eval_without_enc _eval
alias _invoke_without_enc _invoke
+
+ def _ip_id_
+ ''
+ end
end
# define TkComm module (step 1: basic functions)
@@ -36,12 +40,12 @@ module TkComm
# for backward compatibility
Tk_CMDTBL = Object.new
def Tk_CMDTBL.method_missing(id, *args)
- TkCore::INTERP.tk_cmd_tbl.send(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)
+ TkCore::INTERP.tk_windows.__send__(id, *args)
end
Tk_WINDOWS.freeze
@@ -111,7 +115,7 @@ module TkComm
module_function :_genobj_for_tkwidget
def tk_tcl2ruby(val, enc_mode = nil)
- if val =~ /^rb_out (c\d+)/
+ if val =~ /^rb_out\S* (c(_\d+_)?\d+)/
#return Tk_CMDTBL[$1]
return TkCore::INTERP.tk_cmd_tbl[$1]
#cmd_obj = TkCore::INTERP.tk_cmd_tbl[$1]
@@ -133,7 +137,7 @@ module TkComm
#Tk_WINDOWS[val] ? Tk_WINDOWS[val] : _genobj_for_tkwidget(val)
TkCore::INTERP.tk_windows[val]?
TkCore::INTERP.tk_windows[val] : _genobj_for_tkwidget(val)
- when /^i\d+$/
+ when /^i(_\d+_)?\d+$/
TkImage::Tk_IMGTBL[val]? TkImage::Tk_IMGTBL[val] : val
when /^-?\d+\.?\d*(e[-+]?\d+)?$/
val.to_f
@@ -437,14 +441,14 @@ end
end
end
def image_obj(val)
- if val =~ /^i\d+$/
+ if val =~ /^i(_\d+_)?\d+$/
TkImage::Tk_IMGTBL[val]? TkImage::Tk_IMGTBL[val] : val
else
val
end
end
def procedure(val)
- if val =~ /^rb_out (c\d+)/
+ if val =~ /^rb_out\S* (c(_\d+_)?\d+)/
#Tk_CMDTBL[$1]
#TkCore::INTERP.tk_cmd_tbl[$1]
TkCore::INTERP.tk_cmd_tbl[$1].cmd
@@ -591,7 +595,7 @@ end
def _curr_cmd_id
#id = format("c%.4d", Tk_IDs[0])
- id = "c" + TkComm::Tk_IDs[0]
+ id = "c" + TkCore::INTERP._ip_id_ + TkComm::Tk_IDs[0]
end
def _next_cmd_id
id = _curr_cmd_id
@@ -615,10 +619,10 @@ end
@cmdtbl.taint unless @cmdtbl.tainted?
@cmdtbl.push id
#return Kernel.format("rb_out %s", id);
- return 'rb_out ' + id
+ return 'rb_out' + TkCore::INTERP._ip_id_ + ' ' + id
end
def uninstall_cmd(id)
- id = $1 if /rb_out (c\d+)/ =~ id
+ id = $1 if /rb_out\S* (c(_\d+_)?\d+)/ =~ id
#Tk_CMDTBL.delete(id)
TkCore::INTERP.tk_cmd_tbl.delete(id)
end
@@ -655,7 +659,7 @@ end
return TkCore::INTERP.tk_windows[@path] = self
end
else
- name = "w" + Tk_IDs[1]
+ name = "w" + TkCore::INTERP._ip_id_ + Tk_IDs[1]
Tk_IDs[1].succ!
end
if !ppath or ppath == '.'
@@ -736,7 +740,7 @@ module TkComm
def _bindinfo(what, context=nil)
if context
tk_call_without_enc(*what+["<#{tk_event_sequence(context)}>"]) .collect {|cmdline|
- if cmdline =~ /^rb_out (c\d+)\s+(.*)$/
+ if cmdline =~ /^rb_out\S* (c(_\d+_)?\d+)\s+(.*)$/
#[Tk_CMDTBL[$1], $2]
[TkCore::INTERP.tk_cmd_tbl[$1], $2]
else
@@ -876,7 +880,7 @@ module TkCore
@id = id
end
def method_missing(m, *args, &b)
- TkCore::INTERP.tk_object_table(@id).send(m, *args, &b)
+ TkCore::INTERP.tk_object_table(@id).__send__(m, *args, &b)
end
end
@@ -1098,7 +1102,20 @@ module TkCore
tk_call('tk', 'appname', name)
end
+ def appsend_deny
+ tk_call('rename', 'send', '')
+ end
+
def appsend(interp, async, *args)
+ if $SAFE >= 4
+ fail SecurityError, "cannot send Tk commands at level 4"
+ elsif $SAFE >= 1 && args.find{|obj| obj.tainted?}
+ fail SecurityError, "cannot send tainted Tk commands at level #{$SAFE}"
+ end
+ if async != true && async != false && async != nil
+ args.unshift(async)
+ async = false
+ end
if async
tk_call('send', '-async', '--', interp, *args)
else
@@ -1107,14 +1124,34 @@ module TkCore
end
def rb_appsend(interp, async, *args)
+ if $SAFE >= 4
+ fail SecurityError, "cannot send Ruby commands at level 4"
+ elsif $SAFE >= 1 && args.find{|obj| obj.tainted?}
+ fail SecurityError, "cannot send tainted Ruby commands at level #{$SAFE}"
+ end
+ if async != true && async != false && async != nil
+ args.unshift(async)
+ async = false
+ end
#args = args.collect!{|c| _get_eval_string(c).gsub(/[\[\]$"]/, '\\\\\&')}
args = args.collect!{|c| _get_eval_string(c).gsub(/[\[\]$"\\]/, '\\\\\&')}
- args.push(').to_s"')
- appsend(interp, async, 'ruby "(', *args)
+ # args.push(').to_s"')
+ # appsend(interp, async, 'ruby "(', *args)
+ args.push('}.call)"')
+ appsend(interp, async, 'ruby "TkComm._get_eval_string(proc{', *args)
end
def appsend_displayof(interp, win, async, *args)
+ if $SAFE >= 4
+ fail SecurityError, "cannot send Tk commands at level 4"
+ elsif $SAFE >= 1 && args.find{|obj| obj.tainted?}
+ fail SecurityError, "cannot send tainted Tk commands at level #{$SAFE}"
+ end
win = '.' if win == nil
+ if async != true && async != false && async != nil
+ args.unshift(async)
+ async = false
+ end
if async
tk_call('send', '-async', '-displayof', win, '--', interp, *args)
else
@@ -1123,10 +1160,22 @@ module TkCore
end
def rb_appsend_displayof(interp, win, async, *args)
+ if $SAFE >= 4
+ fail SecurityError, "cannot send Ruby commands at level 4"
+ elsif $SAFE >= 1 && args.find{|obj| obj.tainted?}
+ fail SecurityError, "cannot send tainted Ruby commands at level #{$SAFE}"
+ end
+ win = '.' if win == nil
+ if async != true && async != false && async != nil
+ args.unshift(async)
+ async = false
+ end
#args = args.collect!{|c| _get_eval_string(c).gsub(/[\[\]$"]/, '\\\\\&')}
args = args.collect!{|c| _get_eval_string(c).gsub(/[\[\]$"\\]/, '\\\\\&')}
- args.push(').to_s"')
- appsend_displayof(interp, win, async, 'ruby "(', *args)
+ # args.push(').to_s"')
+ # appsend_displayof(interp, win, async, 'ruby "(', *args)
+ args.push('}.call)"')
+ appsend(interp, win, async, 'ruby "TkComm._get_eval_string(proc{', *args)
end
def info(*args)
diff --git a/ext/tk/lib/tk/bindtag.rb b/ext/tk/lib/tk/bindtag.rb
index d309ea6423..adf96b9e3d 100644
--- a/ext/tk/lib/tk/bindtag.rb
+++ b/ext/tk/lib/tk/bindtag.rb
@@ -26,7 +26,8 @@ class TkBindTag
end
def initialize(*args, &b)
- @id = Tk_BINDTAG_ID.join('')
+ # @id = Tk_BINDTAG_ID.join('')
+ @id = Tk_BINDTAG_ID.join(TkCore::INTERP._ip_id_)
Tk_BINDTAG_ID[1].succ!
BTagID_TBL[@id] = self
bind(*args, &b) if args != []
diff --git a/ext/tk/lib/tk/canvastag.rb b/ext/tk/lib/tk/canvastag.rb
index 962e08b6e0..5a98127f6b 100644
--- a/ext/tk/lib/tk/canvastag.rb
+++ b/ext/tk/lib/tk/canvastag.rb
@@ -191,7 +191,8 @@ class TkcTag<TkObject
end
@c = parent
@cpath = parent.path
- @path = @id = Tk_CanvasTag_ID.join('')
+ # @path = @id = Tk_CanvasTag_ID.join('')
+ @path = @id = Tk_CanvasTag_ID.join(TkCore::INTERP._ip_id_)
CTagID_TBL[@cpath] = {} unless CTagID_TBL[@cpath]
CTagID_TBL[@cpath][@id] = self
Tk_CanvasTag_ID[1].succ!
@@ -313,7 +314,8 @@ class TkcGroup<TkcTag
end
@c = parent
@cpath = parent.path
- @path = @id = Tk_cGroup_ID.join('')
+ # @path = @id = Tk_cGroup_ID.join('')
+ @path = @id = Tk_cGroup_ID.join(TkCore::INTERP._ip_id_)
CTagID_TBL[@cpath] = {} unless CTagID_TBL[@cpath]
CTagID_TBL[@cpath][@id] = self
Tk_cGroup_ID[1].succ!
diff --git a/ext/tk/lib/tk/font.rb b/ext/tk/lib/tk/font.rb
index b8f7f1b991..9b38531f59 100644
--- a/ext/tk/lib/tk/font.rb
+++ b/ext/tk/lib/tk/font.rb
@@ -278,7 +278,8 @@ class TkFont
private
###################################
def initialize(ltn=nil, knj=nil, keys=nil)
- @id = Tk_FontID.join('')
+ # @id = Tk_FontID.join('')
+ @id = Tk_FontID.join(TkCore::INTERP._ip_id_)
Tk_FontID[1].succ!
Tk_FontNameTBL[@id] = self
diff --git a/ext/tk/lib/tk/image.rb b/ext/tk/lib/tk/image.rb
index 70dd096434..e7da1ba207 100644
--- a/ext/tk/lib/tk/image.rb
+++ b/ext/tk/lib/tk/image.rb
@@ -15,7 +15,8 @@ class TkImage<TkObject
TkCore::INTERP.init_ip_env{ Tk_IMGTBL.clear }
def initialize(keys=nil)
- @path = Tk_Image_ID.join('')
+ # @path = Tk_Image_ID.join('')
+ @path = Tk_Image_ID.join(TkCore::INTERP._ip_id_)
Tk_Image_ID[1].succ!
tk_call_without_enc('image', 'create', @type, @path, *hash_kv(keys, true))
Tk_IMGTBL[@path] = self
diff --git a/ext/tk/lib/tk/namespace.rb b/ext/tk/lib/tk/namespace.rb
index 72e9500a49..1ab9623692 100644
--- a/ext/tk/lib/tk/namespace.rb
+++ b/ext/tk/lib/tk/namespace.rb
@@ -88,7 +88,8 @@ class TkNamespace < TkObject
def initialize(name = nil, parent = nil)
unless name
- name = Tk_Namespace_ID.join('')
+ # name = Tk_Namespace_ID.join('')
+ name = Tk_Namespace_ID.join(TkCore::INTERP._ip_id_)
Tk_Namespace_ID[1].succ!
end
name = __tk_call('namespace', 'current') if name == ''
diff --git a/ext/tk/lib/tk/root.rb b/ext/tk/lib/tk/root.rb
index 487eb78fef..a32972561c 100644
--- a/ext/tk/lib/tk/root.rb
+++ b/ext/tk/lib/tk/root.rb
@@ -37,9 +37,9 @@ class TkRoot<TkWindow
if keys # wm commands
keys.each{|k,v|
if v.kind_of? Array
- root.send(k,*v)
+ root.__send__(k,*v)
else
- root.send(k,v)
+ root.__send__(k,v)
end
}
end
diff --git a/ext/tk/lib/tk/textmark.rb b/ext/tk/lib/tk/textmark.rb
index faf19b7a62..8b42df2f0c 100644
--- a/ext/tk/lib/tk/textmark.rb
+++ b/ext/tk/lib/tk/textmark.rb
@@ -22,7 +22,8 @@ class TkTextMark<TkObject
end
@parent = @t = parent
@tpath = parent.path
- @path = @id = Tk_TextMark_ID.join('')
+ # @path = @id = Tk_TextMark_ID.join('')
+ @path = @id = Tk_TextMark_ID.join(TkCore::INTERP._ip_id_)
TMarkID_TBL[@id] = self
TMarkID_TBL[@tpath] = {} unless TMarkID_TBL[@tpath]
TMarkID_TBL[@tpath][@id] = self
diff --git a/ext/tk/lib/tk/texttag.rb b/ext/tk/lib/tk/texttag.rb
index c08dffd66f..561a027f08 100644
--- a/ext/tk/lib/tk/texttag.rb
+++ b/ext/tk/lib/tk/texttag.rb
@@ -25,7 +25,8 @@ class TkTextTag<TkObject
end
@parent = @t = parent
@tpath = parent.path
- @path = @id = Tk_TextTag_ID.join('')
+ # @path = @id = Tk_TextTag_ID.join('')
+ @path = @id = Tk_TextTag_ID.join(TkCore::INTERP._ip_id_)
TTagID_TBL[@id] = self
TTagID_TBL[@tpath] = {} unless TTagID_TBL[@tpath]
TTagID_TBL[@tpath][@id] = self
diff --git a/ext/tk/lib/tk/timer.rb b/ext/tk/lib/tk/timer.rb
index c53e67682d..aa42c4ed7d 100644
--- a/ext/tk/lib/tk/timer.rb
+++ b/ext/tk/lib/tk/timer.rb
@@ -123,7 +123,8 @@ class TkTimer
end
def initialize(*args)
- @id = Tk_CBID.join('')
+ # @id = Tk_CBID.join('')
+ @id = Tk_CBID.join(TkCore::INTERP._ip_id_)
Tk_CBID[1].succ!
@wait_var = TkVariable.new(0)
diff --git a/ext/tk/lib/tk/toplevel.rb b/ext/tk/lib/tk/toplevel.rb
index f8b0f77936..b7f9bed740 100644
--- a/ext/tk/lib/tk/toplevel.rb
+++ b/ext/tk/lib/tk/toplevel.rb
@@ -101,9 +101,9 @@ class TkToplevel<TkWindow
super(keys)
cmds.each{|k,v|
if v.kind_of? Array
- self.send(k,*v)
+ self.__send__(k,*v)
else
- self.send(k,v)
+ self.__send__(k,v)
end
}
return
diff --git a/ext/tk/lib/tk/variable.rb b/ext/tk/lib/tk/variable.rb
index c4ec91741d..f50fca5697 100644
--- a/ext/tk/lib/tk/variable.rb
+++ b/ext/tk/lib/tk/variable.rb
@@ -85,7 +85,8 @@ TkCore::INTERP.add_tk_procs('rb_var', 'args', <<-'EOL')
end
def initialize(val="")
- @id = Tk_VARIABLE_ID.join('')
+ # @id = Tk_VARIABLE_ID.join('')
+ @id = Tk_VARIABLE_ID.join(TkCore::INTERP._ip_id_)
Tk_VARIABLE_ID[1].succ!
TkVar_ID_TBL[@id] = self
diff --git a/ext/tk/lib/tk/virtevent.rb b/ext/tk/lib/tk/virtevent.rb
index bb95ed2421..d64c0a3193 100644
--- a/ext/tk/lib/tk/virtevent.rb
+++ b/ext/tk/lib/tk/virtevent.rb
@@ -9,7 +9,7 @@ class TkVirtualEvent<TkObject
TkCommandNames = ['event'.freeze].freeze
- TkVirtualEventID = ["<VirtEvent".freeze, "00000".taint, ">".freeze].freeze
+ TkVirtualEventID = ["VirtEvent".freeze, "00000".taint].freeze
TkVirtualEventTBL = TkCore::INTERP.create_table
TkCore::INTERP.init_ip_env{ TkVirtualEventTBL.clear }
@@ -41,7 +41,8 @@ class TkVirtualEvent<TkObject
end
def initialize(*sequences)
- @path = @id = TkVirtualEventID.join('')
+ # @path = @id = '<' + TkVirtualEventID.join('') + '>'
+ @path = @id = '<' + TkVirtualEventID.join(TkCore::INTERP._ip_id_) + '>'
TkVirtualEventID[1].succ!
add(*sequences)
end
diff --git a/ext/tk/sample/remote-ip_sample.rb b/ext/tk/sample/remote-ip_sample.rb
new file mode 100644
index 0000000000..3a2dbe4852
--- /dev/null
+++ b/ext/tk/sample/remote-ip_sample.rb
@@ -0,0 +1,33 @@
+#!/usr/bin/env ruby
+require 'remote-tk'
+
+puts <<EOM
+This sample controls the other Tk interpreter (Ruby/Tk, Tcl/Tk, and so on)
+which running on the other process. For this purpose, Ruby/Tk uses Tcl/Tk's
+'send' command. Availability of the command depends on your GUI environment.
+If this script doesn't work, please check your environment (see Tcl/Tk FAQ).
+EOM
+#'
+
+unless (wish = TkWinfo.interps.find{|ip| ip =~ /^wish/})
+ puts ''
+ puts 'Please start "wish" (Tcl/Tk shell) before running this sample script.'
+ exit 1
+end
+
+ip = RemoteTkIp.new(wish)
+ip.eval_proc{TkButton.new(:command=>proc{puts 'This procesure is on the controller-ip (Rubh/Tk)'}, :text=>'print on Ruby/Tk (controller-ip)').pack(:fill=>:x)}
+ip.eval_proc{TkButton.new(:command=>'puts {This procesure is on the remote-ip (wish)}', :text=>'print on wish (remote-ip)').pack(:fill=>:x)}
+
+# If your remote-ip is Ruby/Tk, you can control the remote Ruby by
+# 'ruby' or 'ruby_eval' or 'ruby_cmd' on the Tk interpreter.
+if ip.is_rubytk?
+ ip.eval_proc{TkButton.new(:command=>'ruby {p 111; p Array.new(3,"ruby")}', :text=>'ruby cmd on the remote-ip').pack(:fill=>:x)}
+end
+
+ip.eval_proc{TkButton.new(:command=>'exit', :text=>'QUIT').pack(:fill=>:x)}
+
+TkButton.new(:command=>proc{exit}, :text=>'QUIT',
+ :padx=>10, :pady=>7).pack(:padx=>10, :pady=>7)
+
+Tk.mainloop