* 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/trunk@6384 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
nagai 2004-05-21 20:45:27 +00:00
Родитель 11784c2c4b
Коммит 56761e29f6
18 изменённых файлов: 562 добавлений и 43 удалений

Просмотреть файл

@ -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> Fri May 21 09:22:05 2004 Dave Thomas <dave@pragprog.com>
* lib/rdoc/parsers/parse_rb.rb (RDoc::RubyParser::parse_method_parameters): * lib/rdoc/parsers/parse_rb.rb (RDoc::RubyParser::parse_method_parameters):

Просмотреть файл

@ -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 Therefore, if you want running Tk under a child process, please call
"require 'tk'" in the child process. "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 For example, the following sample1 will NOT work, and sample2 will
work properly. work properly.
@ -26,4 +31,4 @@ TkButton.new(:text=>'QUIT', :command=>proc{exit}).pack
Tk.mainloop Tk.mainloop
------------------------------------------------------------- -------------------------------------------------------------
2004/04/20 Hidetoshi NAGAI 2004/05/22 Hidetoshi NAGAI

Просмотреть файл

@ -6,6 +6,10 @@ require 'tcltklib'
require 'tkutil' require 'tkutil'
require 'thread' require 'thread'
if defined? Tk
fail RuntimeError, "'multi-tk' library must be required before requiring 'tk'"
end
################################################ ################################################
# ignore exception on the mainloop? # ignore exception on the mainloop?
@ -37,14 +41,14 @@ MultiTkIp_OK.freeze
class MultiTkIp class MultiTkIp
SLAVE_IP_ID = ['slave'.freeze, '0'.taint].freeze 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 @@INIT_IP_ENV = [].taint unless defined?(@@INIT_IP_ENV) # table of Procs
@@ADD_TK_PROCS = [].taint # table of [name, args, body] @@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 # get target IP
class MultiTkIp class MultiTkIp
def self._ip_id_
__getip._ip_id_
end
def _ip_id_
''
end
def self.__getip def self.__getip
if Thread.current.group == ThreadGroup::Default if Thread.current.group == ThreadGroup::Default
@@DEFAULT_MASTER @@DEFAULT_MASTER
@ -636,7 +647,7 @@ class << MultiTkIp
ip.eval_proc(&b) if b ip.eval_proc(&b) if b
ip ip
end end
alias new_trusted_slave new_master alias new_trusted_slave new_slave
def new_safe_slave(keys={},&b) def new_safe_slave(keys={},&b)
ip = __new(__getip, true, keys) ip = __new(__getip, true, keys)
@ -798,7 +809,7 @@ class MultiTkIp
@@TK_TABLE_LIST << obj @@TK_TABLE_LIST << obj
obj.instance_eval <<-EOD obj.instance_eval <<-EOD
def self.method_missing(m, *args) def self.method_missing(m, *args)
MultiTkIp.tk_object_table(#{id}).send(m, *args) MultiTkIp.tk_object_table(#{id}).__send__(m, *args)
end end
EOD EOD
obj.freeze obj.freeze
@ -972,7 +983,7 @@ end
# class methods to delegate to TclTkIp # class methods to delegate to TclTkIp
class << MultiTkIp class << MultiTkIp
def method_missing(id, *args) def method_missing(id, *args)
__getip.send(id, *args) __getip.__send__(id, *args)
end end
def make_safe def make_safe
@ -1184,6 +1195,14 @@ class MultiTkIp
@interp.restart @interp.restart
end end
def __eval(str)
@interp.__eval(str)
end
def __invoke(*args)
@interp.__invoke(*args)
end
def _eval(str) def _eval(str)
@interp._eval(str) @interp._eval(str)
end end
@ -1555,7 +1574,7 @@ class MultiTkIp
conf = _lst2ary(ip._eval("::safe::interpConfigure " + conf = _lst2ary(ip._eval("::safe::interpConfigure " +
@ip_name + " -#{slot}")) @ip_name + " -#{slot}"))
if conf[0] == '-deleteHook' 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] ret[conf[0][1..-1]] = MultiTkIp._tk_cmd_tbl[$1]
else else
ret[conf[0][1..-1]] = conf[1] ret[conf[0][1..-1]] = conf[1]
@ -1567,7 +1586,7 @@ class MultiTkIp
Hash[*_lst2ary(ip._eval("::safe::interpConfigure " + Hash[*_lst2ary(ip._eval("::safe::interpConfigure " +
@ip_name))].each{|k, v| @ip_name))].each{|k, v|
if k == '-deleteHook' 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] ret[k[1..-1]] = MultiTkIp._tk_cmd_tbl[$1]
else else
ret[k[1..-1]] = v ret[k[1..-1]] = v

397
ext/tk/lib/remote-tk.rb Normal file
Просмотреть файл

@ -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

Просмотреть файл

@ -14,6 +14,10 @@ class TclTkIp
# backup original (without encoding) _eval and _invoke # backup original (without encoding) _eval and _invoke
alias _eval_without_enc _eval alias _eval_without_enc _eval
alias _invoke_without_enc _invoke alias _invoke_without_enc _invoke
def _ip_id_
''
end
end end
# define TkComm module (step 1: basic functions) # define TkComm module (step 1: basic functions)
@ -36,12 +40,12 @@ module TkComm
# for backward compatibility # for backward compatibility
Tk_CMDTBL = Object.new Tk_CMDTBL = Object.new
def Tk_CMDTBL.method_missing(id, *args) def Tk_CMDTBL.method_missing(id, *args)
TkCore::INTERP.tk_cmd_tbl.send(id, *args) TkCore::INTERP.tk_cmd_tbl.__send__(id, *args)
end end
Tk_CMDTBL.freeze Tk_CMDTBL.freeze
Tk_WINDOWS = Object.new Tk_WINDOWS = Object.new
def Tk_WINDOWS.method_missing(id, *args) def Tk_WINDOWS.method_missing(id, *args)
TkCore::INTERP.tk_windows.send(id, *args) TkCore::INTERP.tk_windows.__send__(id, *args)
end end
Tk_WINDOWS.freeze Tk_WINDOWS.freeze
@ -111,7 +115,7 @@ module TkComm
module_function :_genobj_for_tkwidget module_function :_genobj_for_tkwidget
def tk_tcl2ruby(val, enc_mode = nil) 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 Tk_CMDTBL[$1]
return TkCore::INTERP.tk_cmd_tbl[$1] return TkCore::INTERP.tk_cmd_tbl[$1]
#cmd_obj = 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) #Tk_WINDOWS[val] ? Tk_WINDOWS[val] : _genobj_for_tkwidget(val)
TkCore::INTERP.tk_windows[val]? TkCore::INTERP.tk_windows[val]?
TkCore::INTERP.tk_windows[val] : _genobj_for_tkwidget(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 TkImage::Tk_IMGTBL[val]? TkImage::Tk_IMGTBL[val] : val
when /^-?\d+\.?\d*(e[-+]?\d+)?$/ when /^-?\d+\.?\d*(e[-+]?\d+)?$/
val.to_f val.to_f
@ -437,14 +441,14 @@ end
end end
end end
def image_obj(val) def image_obj(val)
if val =~ /^i\d+$/ if val =~ /^i(_\d+_)?\d+$/
TkImage::Tk_IMGTBL[val]? TkImage::Tk_IMGTBL[val] : val TkImage::Tk_IMGTBL[val]? TkImage::Tk_IMGTBL[val] : val
else else
val val
end end
end end
def procedure(val) def procedure(val)
if val =~ /^rb_out (c\d+)/ if val =~ /^rb_out\S* (c(_\d+_)?\d+)/
#Tk_CMDTBL[$1] #Tk_CMDTBL[$1]
#TkCore::INTERP.tk_cmd_tbl[$1] #TkCore::INTERP.tk_cmd_tbl[$1]
TkCore::INTERP.tk_cmd_tbl[$1].cmd TkCore::INTERP.tk_cmd_tbl[$1].cmd
@ -591,7 +595,7 @@ end
def _curr_cmd_id def _curr_cmd_id
#id = format("c%.4d", Tk_IDs[0]) #id = format("c%.4d", Tk_IDs[0])
id = "c" + TkComm::Tk_IDs[0] id = "c" + TkCore::INTERP._ip_id_ + TkComm::Tk_IDs[0]
end end
def _next_cmd_id def _next_cmd_id
id = _curr_cmd_id id = _curr_cmd_id
@ -615,10 +619,10 @@ end
@cmdtbl.taint unless @cmdtbl.tainted? @cmdtbl.taint unless @cmdtbl.tainted?
@cmdtbl.push id @cmdtbl.push id
#return Kernel.format("rb_out %s", id); #return Kernel.format("rb_out %s", id);
return 'rb_out ' + id return 'rb_out' + TkCore::INTERP._ip_id_ + ' ' + id
end end
def uninstall_cmd(id) 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) #Tk_CMDTBL.delete(id)
TkCore::INTERP.tk_cmd_tbl.delete(id) TkCore::INTERP.tk_cmd_tbl.delete(id)
end end
@ -655,7 +659,7 @@ end
return TkCore::INTERP.tk_windows[@path] = self return TkCore::INTERP.tk_windows[@path] = self
end end
else else
name = "w" + Tk_IDs[1] name = "w" + TkCore::INTERP._ip_id_ + Tk_IDs[1]
Tk_IDs[1].succ! Tk_IDs[1].succ!
end end
if !ppath or ppath == '.' if !ppath or ppath == '.'
@ -736,7 +740,7 @@ module TkComm
def _bindinfo(what, context=nil) def _bindinfo(what, context=nil)
if context if context
tk_call_without_enc(*what+["<#{tk_event_sequence(context)}>"]) .collect {|cmdline| 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] #[Tk_CMDTBL[$1], $2]
[TkCore::INTERP.tk_cmd_tbl[$1], $2] [TkCore::INTERP.tk_cmd_tbl[$1], $2]
else else
@ -876,7 +880,7 @@ module TkCore
@id = id @id = id
end end
def method_missing(m, *args, &b) 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
end end
@ -1098,7 +1102,20 @@ module TkCore
tk_call('tk', 'appname', name) tk_call('tk', 'appname', name)
end end
def appsend_deny
tk_call('rename', 'send', '')
end
def appsend(interp, async, *args) 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 if async
tk_call('send', '-async', '--', interp, *args) tk_call('send', '-async', '--', interp, *args)
else else
@ -1107,14 +1124,34 @@ module TkCore
end end
def rb_appsend(interp, async, *args) 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 = args.collect!{|c| _get_eval_string(c).gsub(/[\[\]$"\\]/, '\\\\\&')} args = args.collect!{|c| _get_eval_string(c).gsub(/[\[\]$"\\]/, '\\\\\&')}
args.push(').to_s"') # args.push(').to_s"')
appsend(interp, async, 'ruby "(', *args) # appsend(interp, async, 'ruby "(', *args)
args.push('}.call)"')
appsend(interp, async, 'ruby "TkComm._get_eval_string(proc{', *args)
end end
def appsend_displayof(interp, win, async, *args) 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 win = '.' if win == nil
if async != true && async != false && async != nil
args.unshift(async)
async = false
end
if async if async
tk_call('send', '-async', '-displayof', win, '--', interp, *args) tk_call('send', '-async', '-displayof', win, '--', interp, *args)
else else
@ -1123,10 +1160,22 @@ module TkCore
end end
def rb_appsend_displayof(interp, win, async, *args) 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 = args.collect!{|c| _get_eval_string(c).gsub(/[\[\]$"\\]/, '\\\\\&')} args = args.collect!{|c| _get_eval_string(c).gsub(/[\[\]$"\\]/, '\\\\\&')}
args.push(').to_s"') # args.push(').to_s"')
appsend_displayof(interp, win, async, 'ruby "(', *args) # appsend_displayof(interp, win, async, 'ruby "(', *args)
args.push('}.call)"')
appsend(interp, win, async, 'ruby "TkComm._get_eval_string(proc{', *args)
end end
def info(*args) def info(*args)

Просмотреть файл

@ -26,7 +26,8 @@ class TkBindTag
end end
def initialize(*args, &b) 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! Tk_BINDTAG_ID[1].succ!
BTagID_TBL[@id] = self BTagID_TBL[@id] = self
bind(*args, &b) if args != [] bind(*args, &b) if args != []

Просмотреть файл

@ -191,7 +191,8 @@ class TkcTag<TkObject
end end
@c = parent @c = parent
@cpath = parent.path @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] = {} unless CTagID_TBL[@cpath]
CTagID_TBL[@cpath][@id] = self CTagID_TBL[@cpath][@id] = self
Tk_CanvasTag_ID[1].succ! Tk_CanvasTag_ID[1].succ!
@ -313,7 +314,8 @@ class TkcGroup<TkcTag
end end
@c = parent @c = parent
@cpath = parent.path @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] = {} unless CTagID_TBL[@cpath]
CTagID_TBL[@cpath][@id] = self CTagID_TBL[@cpath][@id] = self
Tk_cGroup_ID[1].succ! Tk_cGroup_ID[1].succ!

Просмотреть файл

@ -278,7 +278,8 @@ class TkFont
private private
################################### ###################################
def initialize(ltn=nil, knj=nil, keys=nil) 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_FontID[1].succ!
Tk_FontNameTBL[@id] = self Tk_FontNameTBL[@id] = self

Просмотреть файл

@ -15,7 +15,8 @@ class TkImage<TkObject
TkCore::INTERP.init_ip_env{ Tk_IMGTBL.clear } TkCore::INTERP.init_ip_env{ Tk_IMGTBL.clear }
def initialize(keys=nil) 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_Image_ID[1].succ!
tk_call_without_enc('image', 'create', @type, @path, *hash_kv(keys, true)) tk_call_without_enc('image', 'create', @type, @path, *hash_kv(keys, true))
Tk_IMGTBL[@path] = self Tk_IMGTBL[@path] = self

Просмотреть файл

@ -88,7 +88,8 @@ class TkNamespace < TkObject
def initialize(name = nil, parent = nil) def initialize(name = nil, parent = nil)
unless name 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! Tk_Namespace_ID[1].succ!
end end
name = __tk_call('namespace', 'current') if name == '' name = __tk_call('namespace', 'current') if name == ''

Просмотреть файл

@ -37,9 +37,9 @@ class TkRoot<TkWindow
if keys # wm commands if keys # wm commands
keys.each{|k,v| keys.each{|k,v|
if v.kind_of? Array if v.kind_of? Array
root.send(k,*v) root.__send__(k,*v)
else else
root.send(k,v) root.__send__(k,v)
end end
} }
end end

Просмотреть файл

@ -22,7 +22,8 @@ class TkTextMark<TkObject
end end
@parent = @t = parent @parent = @t = parent
@tpath = parent.path @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[@id] = self
TMarkID_TBL[@tpath] = {} unless TMarkID_TBL[@tpath] TMarkID_TBL[@tpath] = {} unless TMarkID_TBL[@tpath]
TMarkID_TBL[@tpath][@id] = self TMarkID_TBL[@tpath][@id] = self

Просмотреть файл

@ -25,7 +25,8 @@ class TkTextTag<TkObject
end end
@parent = @t = parent @parent = @t = parent
@tpath = parent.path @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[@id] = self
TTagID_TBL[@tpath] = {} unless TTagID_TBL[@tpath] TTagID_TBL[@tpath] = {} unless TTagID_TBL[@tpath]
TTagID_TBL[@tpath][@id] = self TTagID_TBL[@tpath][@id] = self

Просмотреть файл

@ -123,7 +123,8 @@ class TkTimer
end end
def initialize(*args) def initialize(*args)
@id = Tk_CBID.join('') # @id = Tk_CBID.join('')
@id = Tk_CBID.join(TkCore::INTERP._ip_id_)
Tk_CBID[1].succ! Tk_CBID[1].succ!
@wait_var = TkVariable.new(0) @wait_var = TkVariable.new(0)

Просмотреть файл

@ -101,9 +101,9 @@ class TkToplevel<TkWindow
super(keys) super(keys)
cmds.each{|k,v| cmds.each{|k,v|
if v.kind_of? Array if v.kind_of? Array
self.send(k,*v) self.__send__(k,*v)
else else
self.send(k,v) self.__send__(k,v)
end end
} }
return return

Просмотреть файл

@ -85,7 +85,8 @@ TkCore::INTERP.add_tk_procs('rb_var', 'args', <<-'EOL')
end end
def initialize(val="") 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! Tk_VARIABLE_ID[1].succ!
TkVar_ID_TBL[@id] = self TkVar_ID_TBL[@id] = self

Просмотреть файл

@ -9,7 +9,7 @@ class TkVirtualEvent<TkObject
TkCommandNames = ['event'.freeze].freeze TkCommandNames = ['event'.freeze].freeze
TkVirtualEventID = ["<VirtEvent".freeze, "00000".taint, ">".freeze].freeze TkVirtualEventID = ["VirtEvent".freeze, "00000".taint].freeze
TkVirtualEventTBL = TkCore::INTERP.create_table TkVirtualEventTBL = TkCore::INTERP.create_table
TkCore::INTERP.init_ip_env{ TkVirtualEventTBL.clear } TkCore::INTERP.init_ip_env{ TkVirtualEventTBL.clear }
@ -41,7 +41,8 @@ class TkVirtualEvent<TkObject
end end
def initialize(*sequences) def initialize(*sequences)
@path = @id = TkVirtualEventID.join('') # @path = @id = '<' + TkVirtualEventID.join('') + '>'
@path = @id = '<' + TkVirtualEventID.join(TkCore::INTERP._ip_id_) + '>'
TkVirtualEventID[1].succ! TkVirtualEventID[1].succ!
add(*sequences) add(*sequences)
end end

Просмотреть файл

@ -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