mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
* ext/tk/tcltklib.c: make SEGV risk lower at exit.
* ext/tk/lib/tk.rb: ditto. * ext/tk/lib/multi-tk.rb: fail to call function-style methods on slave interpreters. The strategy (MultiTkIp_PseudoToplevel_Evaluable) to fix the problem is a little tricky. You may have to take care of conflicting with it. * ext/tk/lib/tk.rb: a little change for the pseudo-toplevel strategy. * ext/tk/lib/tk/font.rb: ditto. * ext/tk/lib/tk/msgcat.rb: ditto. * ext/tk/lib/tkextlib/itk/incr_tk.rb: ditto. * ext/tk/sample/demos-en/widget: fail to call function-style methods on sample scripts. To fix it, a strategy which similar to the way on MultiTiIp is used. Please take care when re-write and re-run a demo script on the Widget-Demo code viewer. * ext/tk/sample/demos-jp/widget: ditto. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@10505 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
a1a07fbfa1
commit
d2271cbdd1
9 changed files with 543 additions and 40 deletions
26
ChangeLog
26
ChangeLog
|
@ -1,3 +1,29 @@
|
|||
Mon Jul 10 18:46:52 2006 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
|
||||
|
||||
* ext/tk/tcltklib.c: make SEGV risk lower at exit.
|
||||
|
||||
* ext/tk/lib/tk.rb: ditto.
|
||||
|
||||
* ext/tk/lib/multi-tk.rb: fail to call function-style methods on slave
|
||||
interpreters. The strategy (MultiTkIp_PseudoToplevel_Evaluable) to
|
||||
fix the problem is a little tricky. You may have to take care of
|
||||
conflicting with it.
|
||||
|
||||
* ext/tk/lib/tk.rb: a little change for the pseudo-toplevel strategy.
|
||||
|
||||
* ext/tk/lib/tk/font.rb: ditto.
|
||||
|
||||
* ext/tk/lib/tk/msgcat.rb: ditto.
|
||||
|
||||
* ext/tk/lib/tkextlib/itk/incr_tk.rb: ditto.
|
||||
|
||||
* ext/tk/sample/demos-en/widget: fail to call function-style methods
|
||||
on sample scripts. To fix it, a strategy which similar to the way
|
||||
on MultiTiIp is used. Please take care when re-write and re-run a
|
||||
demo script on the Widget-Demo code viewer.
|
||||
|
||||
* ext/tk/sample/demos-jp/widget: ditto.
|
||||
|
||||
Mon Jul 10 17:32:38 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
|
||||
|
||||
* sample/test.rb: update test suites.
|
||||
|
|
|
@ -33,6 +33,64 @@ class << TclTkIp
|
|||
end
|
||||
|
||||
|
||||
################################################
|
||||
# use pseudo-toplevel feature of MultiTkIp ?
|
||||
if (!defined?(Use_PseudoToplevel_Feature_of_MultiTkIp) ||
|
||||
Use_PseudoToplevel_Feature_of_MultiTkIp)
|
||||
module MultiTkIp_PseudoToplevel_Evaluable
|
||||
#def pseudo_toplevel_eval(body = Proc.new)
|
||||
# Thread.current[:TOPLEVEL] = self
|
||||
# begin
|
||||
# body.call
|
||||
# ensure
|
||||
# Thread.current[:TOPLEVEL] = nil
|
||||
# end
|
||||
#end
|
||||
|
||||
def pseudo_toplevel_evaluable?
|
||||
@pseudo_toplevel_evaluable
|
||||
end
|
||||
|
||||
def pseudo_toplevel_evaluable=(mode)
|
||||
@pseudo_toplevel_evaluable = (mode)? true: false
|
||||
end
|
||||
|
||||
def self.extended(mod)
|
||||
mod.__send__(:extend_object, mod)
|
||||
mod.instance_variable_set('@pseudo_toplevel_evaluable', true)
|
||||
end
|
||||
end
|
||||
|
||||
class Object
|
||||
alias __method_missing_alias_for_MultiTkIp__ method_missing
|
||||
private :__method_missing_alias_for_MultiTkIp__
|
||||
|
||||
def method_missing(id, *args)
|
||||
begin
|
||||
has_top = (top = MultiTkIp.__getip.__pseudo_toplevel) &&
|
||||
top.respond_to?(:pseudo_toplevel_evaluable?) &&
|
||||
top.pseudo_toplevel_evaluable? &&
|
||||
top.respond_to?(id)
|
||||
rescue Exception => e
|
||||
has_top = false
|
||||
end
|
||||
|
||||
if has_top
|
||||
top.__send__(id, *args)
|
||||
else
|
||||
__method_missing_alias_for_MultiTkIp__(id, *args)
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
# dummy
|
||||
module MultiTkIp_PseudoToplevel_Evaluable
|
||||
def pseudo_toplevel_evaluable?
|
||||
false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
################################################
|
||||
# exceptiopn to treat the return value from IP
|
||||
class MultiTkIp_OK < Exception
|
||||
|
@ -54,6 +112,8 @@ MultiTkIp_OK.freeze
|
|||
################################################
|
||||
# methods for construction
|
||||
class MultiTkIp
|
||||
BASE_DIR = File.dirname(__FILE__)
|
||||
|
||||
@@SLAVE_IP_ID = ['slave'.freeze, '0'.taint].freeze
|
||||
|
||||
@@IP_TABLE = {}.taint unless defined?(@@IP_TABLE)
|
||||
|
@ -692,6 +752,46 @@ class MultiTkIp
|
|||
|
||||
#################################
|
||||
|
||||
@pseudo_toplevel = [false, nil]
|
||||
|
||||
def self.__pseudo_toplevel
|
||||
self.__pseudo_toplevel_evaluable? && @pseudo_toplevel[1]
|
||||
end
|
||||
|
||||
def self.__pseudo_toplevel=(m)
|
||||
unless (Thread.current.group == ThreadGroup::Default &&
|
||||
MultiTkIp.__getip == @@DEFAULT_MASTER)
|
||||
fail SecurityError, "no permission to manipulate"
|
||||
end
|
||||
|
||||
if m.kind_of?(Module) && m.respond_to?(:pseudo_toplevel_evaluable?)
|
||||
@pseudo_toplevel[0] = true
|
||||
@pseudo_toplevel[1] = m
|
||||
else
|
||||
fail ArgumentError, 'fail to set pseudo-toplevel'
|
||||
end
|
||||
self
|
||||
end
|
||||
|
||||
def self.__pseudo_toplevel_evaluable?
|
||||
begin
|
||||
@pseudo_toplevel[0] && @pseudo_toplevel[1].pseudo_toplevel_evaluable?
|
||||
rescue Exception
|
||||
false
|
||||
end
|
||||
end
|
||||
|
||||
def self.__pseudo_toplevel_evaluable=(mode)
|
||||
unless (Thread.current.group == ThreadGroup::Default &&
|
||||
MultiTkIp.__getip == @@DEFAULT_MASTER)
|
||||
fail SecurityError, "no permission to manipulate"
|
||||
end
|
||||
|
||||
@pseudo_toplevel[0] = (mode)? true: false
|
||||
end
|
||||
|
||||
#################################
|
||||
|
||||
@assign_request = Class.new(Exception){
|
||||
def self.new(target, ret)
|
||||
obj = super()
|
||||
|
@ -746,10 +846,40 @@ class MultiTkIp
|
|||
|
||||
#################################
|
||||
|
||||
@init_ip_env_queue = Queue.new
|
||||
Thread.new{
|
||||
current = Thread.current
|
||||
loop {
|
||||
mtx, ret, table, script = @init_ip_env_queue.deq
|
||||
begin
|
||||
ret[0] = table.each{|tg, ip| ip._init_ip_env(script) }
|
||||
rescue Exception => e
|
||||
ret[0] = e
|
||||
ensure
|
||||
mtx.unlock
|
||||
end
|
||||
}
|
||||
}
|
||||
|
||||
def self.__init_ip_env__(table, script)
|
||||
ret = []
|
||||
mtx = Mutex.new.lock
|
||||
@init_ip_env_queue.enq([mtx, ret, table, script])
|
||||
mtx.lock
|
||||
if ret[0].kind_of?(Exception)
|
||||
raise ret[0]
|
||||
else
|
||||
ret[0]
|
||||
end
|
||||
end
|
||||
|
||||
#################################
|
||||
|
||||
class << self
|
||||
undef :instance_eval
|
||||
end
|
||||
}
|
||||
|
||||
@@DEFAULT_MASTER.freeze # defend against modification
|
||||
|
||||
######################################
|
||||
|
@ -1115,6 +1245,8 @@ class MultiTkIp
|
|||
|
||||
@threadgroup = ThreadGroup.new
|
||||
|
||||
@pseudo_toplevel = [false, nil]
|
||||
|
||||
@cmd_queue = Queue.new
|
||||
|
||||
=begin
|
||||
|
@ -1424,6 +1556,17 @@ class MultiTkIp
|
|||
}
|
||||
end
|
||||
|
||||
def _remove_tk_procs(*names)
|
||||
return if slave?
|
||||
names.each{|name|
|
||||
name = name.to_s
|
||||
@interp._invoke('rename', name, '')
|
||||
@interp._invoke('interp', 'slaves').split.each{|slave|
|
||||
@interp._invoke('interp', 'alias', slave, name, '') rescue nil
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
def _init_ip_internal(init_ip_env, add_tk_procs)
|
||||
#init_ip_env.each{|script| self.eval_proc{script.call(self)}}
|
||||
init_ip_env.each{|script| self._init_ip_env(script)}
|
||||
|
@ -1450,9 +1593,21 @@ 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
|
||||
if __getip.slave?
|
||||
begin
|
||||
raise SecurityError, "slave-IP has no permission creating a new table"
|
||||
rescue SecurityError => e
|
||||
#p e.backtrace
|
||||
# Is called on a Ruby/Tk library?
|
||||
caller_info = e.backtrace[1]
|
||||
if caller_info =~ %r{^#{MultiTkIp::BASE_DIR}/(tk|tkextlib)/[^:]+\.rb:}
|
||||
# Probably, caller is a Ruby/Tk library --> allow creating
|
||||
else
|
||||
raise e
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
id = @@TK_TABLE_LIST.size
|
||||
obj = Object.new
|
||||
@@TK_TABLE_LIST << obj
|
||||
|
@ -1468,17 +1623,50 @@ class MultiTkIp
|
|||
|
||||
def self.init_ip_env(script = Proc.new)
|
||||
@@INIT_IP_ENV << script
|
||||
@@IP_TABLE.each{|tg, ip|
|
||||
ip._init_ip_env(script)
|
||||
}
|
||||
if __getip.slave?
|
||||
begin
|
||||
raise SecurityError, "slave-IP has no permission initializing IP env"
|
||||
rescue SecurityError => e
|
||||
#p e.backtrace
|
||||
# Is called on a Ruby/Tk library?
|
||||
caller_info = e.backtrace[1]
|
||||
if caller_info =~ %r{^#{MultiTkIp::BASE_DIR}/(tk|tkextlib)/[^:]+\.rb:}
|
||||
# Probably, caller is a Ruby/Tk library --> allow creating
|
||||
else
|
||||
raise e
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# @@IP_TABLE.each{|tg, ip|
|
||||
# ip._init_ip_env(script)
|
||||
# }
|
||||
@@DEFAULT_MASTER.__init_ip_env__(@@IP_TABLE, script)
|
||||
end
|
||||
|
||||
def self.add_tk_procs(name, args=nil, body=nil)
|
||||
if name.kind_of?(Array) # => an array of [name, args, body]
|
||||
name.each{|param| self.add_tk_procs(*param)}
|
||||
else
|
||||
name = name.to_s
|
||||
@@ADD_TK_PROCS << [name, args, body]
|
||||
@@IP_TABLE.each{|tg, ip|
|
||||
ip._add_tk_procs(name, args, body)
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
def self.remove_tk_procs(*names)
|
||||
names.each{|name|
|
||||
name = name.to_s
|
||||
@@ADD_TK_PROCS.delete_if{|elem|
|
||||
elem.kind_of?(Array) && elem[0].to_s == name
|
||||
}
|
||||
}
|
||||
@@IP_TABLE.each{|tg, ip|
|
||||
ip._remove_tk_procs(*names)
|
||||
}
|
||||
end
|
||||
|
||||
def self.init_ip_internal
|
||||
__getip._init_ip_internal(@@INIT_IP_ENV, @@ADD_TK_PROCS)
|
||||
|
@ -1565,6 +1753,46 @@ class MultiTkIp
|
|||
|
||||
end
|
||||
|
||||
# pseudo-toplevel operation support
|
||||
class MultiTkIp
|
||||
# instance method
|
||||
def __pseudo_toplevel
|
||||
self.__pseudo_toplevel_evaluable? && @pseudo_toplevel[1]
|
||||
end
|
||||
|
||||
def __pseudo_toplevel=(m)
|
||||
unless (Thread.current.group == ThreadGroup::Default &&
|
||||
MultiTkIp.__getip == @@DEFAULT_MASTER)
|
||||
fail SecurityError, "no permission to manipulate"
|
||||
end
|
||||
|
||||
if m.kind_of?(Module) && m.respond_to?(:pseudo_toplevel_evaluable?)
|
||||
@pseudo_toplevel[0] = true
|
||||
@pseudo_toplevel[1] = m
|
||||
else
|
||||
fail ArgumentError, 'fail to set pseudo-toplevel'
|
||||
end
|
||||
self
|
||||
end
|
||||
|
||||
def __pseudo_toplevel_evaluable?
|
||||
begin
|
||||
@pseudo_toplevel[0] && @pseudo_toplevel[1].pseudo_toplevel_evaluable?
|
||||
rescue Exception
|
||||
false
|
||||
end
|
||||
end
|
||||
|
||||
def __pseudo_toplevel_evaluable=(mode)
|
||||
unless (Thread.current.group == ThreadGroup::Default &&
|
||||
MultiTkIp.__getip == @@DEFAULT_MASTER)
|
||||
fail SecurityError, "no permission to manipulate"
|
||||
end
|
||||
|
||||
@pseudo_toplevel[0] = (mode)? true: false
|
||||
end
|
||||
end
|
||||
|
||||
# evaluate a procedure on the proper interpreter
|
||||
class MultiTkIp
|
||||
# instance method
|
||||
|
|
|
@ -1192,9 +1192,23 @@ module TkCore
|
|||
script.call(self)
|
||||
end
|
||||
def INTERP.add_tk_procs(name, args = nil, body = nil)
|
||||
if name.kind_of?(Array)
|
||||
name.each{|param| self.add_tk_procs(*param)}
|
||||
else
|
||||
name = name.to_s
|
||||
@add_tk_procs << [name, args, body]
|
||||
self._invoke('proc', name, args, body) if args && body
|
||||
end
|
||||
end
|
||||
def INTERP.remove_tk_procs(*names)
|
||||
names.each{|name|
|
||||
name = name.to_s
|
||||
@add_tk_procs.delete_if{|elem|
|
||||
elem.kind_of?(Array) && elem[0].to_s == name
|
||||
}
|
||||
self._invoke('rename', name, '')
|
||||
}
|
||||
end
|
||||
def INTERP.init_ip_internal
|
||||
ip = self
|
||||
@init_ip_env.each{|script| script.call(ip)}
|
||||
|
@ -1285,6 +1299,8 @@ module TkCore
|
|||
EOL
|
||||
=end
|
||||
|
||||
at_exit{ INTERP.remove_tk_procs(TclTkLib::FINALIZE_PROC_NAME) }
|
||||
|
||||
EventFlag = TclTkLib::EventFlag
|
||||
|
||||
def callback_break
|
||||
|
@ -3886,12 +3902,14 @@ class TkObject<TkKernel
|
|||
begin
|
||||
cget(name)
|
||||
rescue
|
||||
fail NameError,
|
||||
"undefined local variable or method `#{name}' for #{self.to_s}",
|
||||
error_at
|
||||
super(id, *args)
|
||||
# fail NameError,
|
||||
# "undefined local variable or method `#{name}' for #{self.to_s}",
|
||||
# error_at
|
||||
end
|
||||
else
|
||||
fail NameError, "undefined method `#{name}' for #{self.to_s}", error_at
|
||||
super(id, *args)
|
||||
# fail NameError, "undefined method `#{name}' for #{self.to_s}", error_at
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -4563,7 +4581,7 @@ end
|
|||
#Tk.freeze
|
||||
|
||||
module Tk
|
||||
RELEASE_DATE = '2006-07-03'.freeze
|
||||
RELEASE_DATE = '2006-07-10'.freeze
|
||||
|
||||
autoload :AUTO_PATH, 'tk/variable'
|
||||
autoload :TCL_PACKAGE_PATH, 'tk/variable'
|
||||
|
|
|
@ -859,10 +859,12 @@ class TkFont
|
|||
begin
|
||||
configinfo name
|
||||
rescue
|
||||
fail NameError, "undefined local variable or method `#{name}' for #{self.to_s}", error_at
|
||||
end
|
||||
super(id, *args)
|
||||
# fail NameError, "undefined local variable or method `#{name}' for #{self.to_s}", error_at
|
||||
# end
|
||||
else
|
||||
fail NameError, "undefined method `#{name}' for #{self.to_s}", error_at
|
||||
super(id, *args)
|
||||
# fail NameError, "undefined method `#{name}' for #{self.to_s}", error_at
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -130,7 +130,8 @@ class TkMsgCatalog < TkObject
|
|||
self.set_translation(loc, *args)
|
||||
|
||||
else
|
||||
fail NameError, "undefined method `#{name}' for #{self.to_s}", error_at
|
||||
super(id, *args)
|
||||
# fail NameError, "undefined method `#{name}' for #{self.to_s}", error_at
|
||||
|
||||
end
|
||||
end
|
||||
|
|
|
@ -289,7 +289,8 @@ module Tk
|
|||
end
|
||||
|
||||
# unknown method
|
||||
fail RuntimeError, "unknown method '#{name}' for #{self.inspect}"
|
||||
super(id, *args)
|
||||
# fail RuntimeError, "unknown method '#{name}' for #{self.inspect}"
|
||||
end
|
||||
|
||||
def tk_send(cmd, *rest)
|
||||
|
|
|
@ -509,12 +509,93 @@ else # ver >= 8.4
|
|||
alias showVars showVars2
|
||||
end
|
||||
|
||||
# Pseudo-Toplevel support
|
||||
module PseudoToplevel_Evaluable
|
||||
def pseudo_toplevel_eval(body = Proc.new)
|
||||
Thread.current[:TOPLEVEL] = self
|
||||
begin
|
||||
body.call
|
||||
ensure
|
||||
Thread.current[:TOPLEVEL] = nil
|
||||
end
|
||||
end
|
||||
|
||||
def pseudo_toplevel_evaluable?
|
||||
@pseudo_toplevel_evaluable
|
||||
end
|
||||
def pseudo_toplevel_evaluable=(mode)
|
||||
@pseudo_toplevel_evaluable = (mode)? true: false
|
||||
end
|
||||
|
||||
def self.extended(mod)
|
||||
mod.__send__(:extend_object, mod)
|
||||
mod.instance_variable_set('@pseudo_toplevel_evaluable', true)
|
||||
end
|
||||
end
|
||||
|
||||
class Object
|
||||
alias __method_missing__ method_missing
|
||||
private :__method_missing__
|
||||
|
||||
def method_missing(id, *args)
|
||||
begin
|
||||
has_top = (top = Thread.current[:TOPLEVEL]) &&
|
||||
top.respond_to?(:pseudo_toplevel_evaluable?) &&
|
||||
top.pseudo_toplevel_evaluable? &&
|
||||
top.respond_to?(id)
|
||||
rescue Exception => e
|
||||
has_top = false
|
||||
end
|
||||
|
||||
if has_top
|
||||
top.__send__(id, *args)
|
||||
else
|
||||
__method_missing__(id, *args)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
class Proc
|
||||
def initialize(*args, &b)
|
||||
super
|
||||
@__pseudo_toplevel__ = Thread.current[:TOPLEVEL]
|
||||
end
|
||||
|
||||
alias __call__ call
|
||||
def call(*args, &b)
|
||||
if top = @__pseudo_toplevel__
|
||||
orig_top = Thread.current[:TOPLEVEL]
|
||||
Thread.current[:TOPLEVEL] = top
|
||||
begin
|
||||
__call__(*args, &b)
|
||||
ensure
|
||||
Thread.current[:TOPLEVEL] = orig_top
|
||||
end
|
||||
else
|
||||
__call__(*args, &b)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def proc(&b)
|
||||
Proc.new(&b)
|
||||
end
|
||||
def lambda(&b)
|
||||
Proc.new(&b)
|
||||
end
|
||||
|
||||
def _null_binding
|
||||
Module.new.instance_eval{extend PseudoToplevel_Evaluable}
|
||||
# binding
|
||||
Module.new.instance_eval{binding}
|
||||
# Module.new.instance_eval{binding}
|
||||
end
|
||||
private :_null_binding
|
||||
|
||||
def eval_samplecode(code)
|
||||
Thread.new{ _null_binding.pseudo_toplevel_eval{ eval(code) } }.run
|
||||
Tk.update
|
||||
end
|
||||
|
||||
# invoke --
|
||||
# This procedure is called when the user clicks on a demo description.
|
||||
# It is responsible for invoking the demonstration.
|
||||
|
@ -529,8 +610,9 @@ def invoke(txt, idx)
|
|||
cursor = txt.cget('cursor')
|
||||
txt.cursor('watch')
|
||||
Tk.update
|
||||
eval(IO.readlines("#{[$demo_dir, tag[5..-1]].join(File::Separator)}.rb").join, _null_binding)
|
||||
Tk.update
|
||||
# eval(IO.readlines("#{[$demo_dir, tag[5..-1]].join(File::Separator)}.rb").join, _null_binding)
|
||||
# Tk.update
|
||||
eval_samplecode(IO.readlines("#{[$demo_dir, tag[5..-1]].join(File::Separator)}.rb").join)
|
||||
txt.cursor(cursor)
|
||||
|
||||
$tag_visited.add("#{idx} linestart +1 chars", "#{idx} lineend +1 chars")
|
||||
|
@ -596,7 +678,8 @@ def showCode1(demo)
|
|||
}.pack('side'=>'left', 'expand'=>'yes', 'pady'=>2)
|
||||
TkButton.new(f) {
|
||||
text "Rerun Demo"
|
||||
command proc{eval($code_text.get('1.0','end'), _null_binding)}
|
||||
# command proc{eval($code_text.get('1.0','end'), _null_binding)}
|
||||
command proc{eval_samplecode($code_text.get('1.0','end'))}
|
||||
}.pack('side'=>'left', 'expand'=>'yes', 'pady'=>2)
|
||||
# f.pack('side'=>'bottom', 'expand'=>'yes', 'fill'=>'x')
|
||||
f.pack('side'=>'bottom', 'fill'=>'x')
|
||||
|
@ -690,7 +773,8 @@ def showCode2(demo)
|
|||
:image=>$image['print'], :compound=>:left)
|
||||
b_run = TkButton.new(bf, :text=>'Rerun Demo',
|
||||
:command=>proc{
|
||||
eval($code_text.get('1.0','end'), _null_binding)
|
||||
# eval($code_text.get('1.0','end'), _null_binding)
|
||||
eval_samplecode($code_text.get('1.0','end'))
|
||||
},
|
||||
:image=>$image['refresh'], :compound=>:left)
|
||||
|
||||
|
@ -812,7 +896,7 @@ end
|
|||
#
|
||||
def aboutBox
|
||||
Tk.messageBox('icon'=>'info', 'type'=>'ok', 'title'=>'About Widget Demo',
|
||||
'message'=>"Ruby/Tk widget demonstration Ver.1.5.6-en\n\n" +
|
||||
'message'=>"Ruby/Tk widget demonstration Ver.1.6.0-en\n\n" +
|
||||
"based on demos of Tk8.1 -- 8.5 " +
|
||||
"( Copyright:: " +
|
||||
"(c) 1996-1997 Sun Microsystems, Inc. / " +
|
||||
|
@ -837,8 +921,9 @@ ARGV.each{|cmd|
|
|||
if cmd =~ /(.*).rb/
|
||||
cmd = $1
|
||||
end
|
||||
eval(IO.readlines("#{[$demo_dir, cmd].join(File::Separator)}.rb").join,
|
||||
_null_binding)
|
||||
#eval(IO.readlines("#{[$demo_dir, cmd].join(File::Separator)}.rb").join,
|
||||
# _null_binding)
|
||||
eval_samplecode(IO.readlines("#{[$demo_dir, cmd].join(File::Separator)}.rb").join)
|
||||
}
|
||||
if no_launcher
|
||||
$root.withdraw # hide root window
|
||||
|
|
|
@ -551,12 +551,93 @@ else # ver >= 8.4
|
|||
alias showVars showVars2
|
||||
end
|
||||
|
||||
# 疑似トップレベルサポート
|
||||
module PseudoToplevel_Evaluable
|
||||
def pseudo_toplevel_eval(body = Proc.new)
|
||||
Thread.current[:TOPLEVEL] = self
|
||||
begin
|
||||
body.call
|
||||
ensure
|
||||
Thread.current[:TOPLEVEL] = nil
|
||||
end
|
||||
end
|
||||
|
||||
def pseudo_toplevel_evaluable?
|
||||
@pseudo_toplevel_evaluable
|
||||
end
|
||||
def pseudo_toplevel_evaluable=(mode)
|
||||
@pseudo_toplevel_evaluable = (mode)? true: false
|
||||
end
|
||||
|
||||
def self.extended(mod)
|
||||
mod.__send__(:extend_object, mod)
|
||||
mod.instance_variable_set('@pseudo_toplevel_evaluable', true)
|
||||
end
|
||||
end
|
||||
|
||||
class Object
|
||||
alias __method_missing__ method_missing
|
||||
private :__method_missing__
|
||||
|
||||
def method_missing(id, *args)
|
||||
begin
|
||||
has_top = (top = Thread.current[:TOPLEVEL]) &&
|
||||
top.respond_to?(:pseudo_toplevel_evaluable?) &&
|
||||
top.pseudo_toplevel_evaluable? &&
|
||||
top.respond_to?(id)
|
||||
rescue Exception => e
|
||||
has_top = false
|
||||
end
|
||||
|
||||
if has_top
|
||||
top.__send__(id, *args)
|
||||
else
|
||||
__method_missing__(id, *args)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
class Proc
|
||||
def initialize(*args, &b)
|
||||
super
|
||||
@__pseudo_toplevel__ = Thread.current[:TOPLEVEL]
|
||||
end
|
||||
|
||||
alias __call__ call
|
||||
def call(*args, &b)
|
||||
if top = @__pseudo_toplevel__
|
||||
orig_top = Thread.current[:TOPLEVEL]
|
||||
Thread.current[:TOPLEVEL] = top
|
||||
begin
|
||||
__call__(*args, &b)
|
||||
ensure
|
||||
Thread.current[:TOPLEVEL] = orig_top
|
||||
end
|
||||
else
|
||||
__call__(*args, &b)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def proc(&b)
|
||||
Proc.new(&b)
|
||||
end
|
||||
def lambda(&b)
|
||||
Proc.new(&b)
|
||||
end
|
||||
|
||||
def _null_binding
|
||||
Module.new.instance_eval{extend PseudoToplevel_Evaluable}
|
||||
# binding
|
||||
Module.new.instance_eval{binding}
|
||||
# Module.new.instance_eval{binding}
|
||||
end
|
||||
private :_null_binding
|
||||
|
||||
def eval_samplecode(code)
|
||||
Thread.new{ _null_binding.pseudo_toplevel_eval{ eval(code) } }.run
|
||||
Tk.update
|
||||
end
|
||||
|
||||
# テキスト上での click に対する動作
|
||||
def invoke(txt, idx)
|
||||
tag = txt.tag_names(idx).find{|t| t.kind_of?(String) && t =~ /^demo-/}
|
||||
|
@ -565,8 +646,9 @@ def invoke(txt, idx)
|
|||
cursor = txt.cget('cursor')
|
||||
txt.cursor('watch')
|
||||
Tk.update
|
||||
eval(IO.readlines("#{[$demo_dir, tag[5..-1]].join(File::Separator)}.rb").join, _null_binding)
|
||||
Tk.update
|
||||
# eval(IO.readlines("#{[$demo_dir, tag[5..-1]].join(File::Separator)}.rb").join, _null_binding)
|
||||
# Tk.update
|
||||
eval_samplecode(IO.readlines("#{[$demo_dir, tag[5..-1]].join(File::Separator)}.rb").join)
|
||||
txt.cursor(cursor)
|
||||
|
||||
$tag_visited.add("#{idx} linestart +1 chars", "#{idx} lineend +1 chars")
|
||||
|
@ -622,7 +704,8 @@ def showCode1(demo)
|
|||
}.pack('side'=>'left', 'expand'=>'yes', 'pady'=>2)
|
||||
TkButton.new(f) {
|
||||
text "再実行"
|
||||
command proc{eval($code_text.get('1.0','end'), _null_binding)}
|
||||
# command proc{eval($code_text.get('1.0','end'), _null_binding)}
|
||||
command proc{eval_samplecode($code_text.get('1.0','end'))}
|
||||
}.pack('side'=>'left', 'expand'=>'yes', 'pady'=>2)
|
||||
# f.pack('side'=>'bottom', 'expand'=>'yes', 'fill'=>'x')
|
||||
f.pack('side'=>'bottom', 'fill'=>'x')
|
||||
|
@ -716,7 +799,8 @@ def showCode2(demo)
|
|||
:image=>$image['print'], :compound=>:left)
|
||||
b_run = TkButton.new(bf, :text=>'再実行',
|
||||
:command=>proc{
|
||||
eval($code_text.get('1.0','end'), _null_binding)
|
||||
# eval($code_text.get('1.0','end'), _null_binding)
|
||||
eval_samplecode($code_text.get('1.0','end'))
|
||||
},
|
||||
:image=>$image['refresh'], :compound=>:left)
|
||||
|
||||
|
@ -842,7 +926,7 @@ end
|
|||
#
|
||||
def aboutBox
|
||||
Tk.messageBox('icon'=>'info', 'type'=>'ok', 'title'=>'About Widget Demo',
|
||||
'message'=>"Ruby/Tk ウィジェットデモ Ver.1.5.6-jp\n\n" +
|
||||
'message'=>"Ruby/Tk ウィジェットデモ Ver.1.6.0-jp\n\n" +
|
||||
"based on demos of Tk8.1 -- 8.5 " +
|
||||
"( Copyright:: " +
|
||||
"(c) 1996-1997 Sun Microsystems, Inc. / " +
|
||||
|
@ -867,8 +951,9 @@ ARGV.each{|cmd|
|
|||
if cmd =~ /(.*).rb/
|
||||
cmd = $1
|
||||
end
|
||||
eval(IO.readlines("#{[$demo_dir, cmd].join(File::Separator)}.rb").join,
|
||||
_null_binding)
|
||||
#eval(IO.readlines("#{[$demo_dir, cmd].join(File::Separator)}.rb").join,
|
||||
# _null_binding)
|
||||
eval_samplecode(IO.readlines("#{[$demo_dir, cmd].join(File::Separator)}.rb").join)
|
||||
}
|
||||
if no_launcher
|
||||
$root.withdraw # hide root window
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
* Oct. 24, 1997 Y. Matsumoto
|
||||
*/
|
||||
|
||||
#define TCLTKLIB_RELEASE_DATE "2006-07-03"
|
||||
#define TCLTKLIB_RELEASE_DATE "2006-07-10"
|
||||
|
||||
#include "ruby.h"
|
||||
#include "rubysig.h"
|
||||
|
@ -81,6 +81,8 @@ static char *finalize_hook_name = "INTERP_FINALIZE_HOOK";
|
|||
|
||||
static void ip_finalize _((Tcl_Interp*));
|
||||
|
||||
static int at_exit = 0;
|
||||
|
||||
|
||||
/* for callback break & continue */
|
||||
static VALUE eTkCallbackReturn;
|
||||
|
@ -4358,6 +4360,33 @@ delete_slaves(ip)
|
|||
|
||||
|
||||
/* finalize operation */
|
||||
static VALUE
|
||||
lib_mark_at_exit(self)
|
||||
VALUE self;
|
||||
{
|
||||
at_exit = 1;
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
static int
|
||||
#if TCL_MAJOR_VERSION >= 8
|
||||
ip_null_proc(clientData, interp, argc, argv)
|
||||
ClientData clientData;
|
||||
Tcl_Interp *interp;
|
||||
int argc;
|
||||
Tcl_Obj *CONST argv[];
|
||||
#else /* TCL_MAJOR_VERSION < 8 */
|
||||
ip_null_proc(clientData, interp, argc, argv)
|
||||
ClientData clientData;
|
||||
Tcl_Interp *interp;
|
||||
int argc;
|
||||
char *argv[];
|
||||
#endif
|
||||
{
|
||||
Tcl_ResetResult(interp);
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
static void
|
||||
ip_finalize(ip)
|
||||
Tcl_Interp *ip;
|
||||
|
@ -4403,6 +4432,29 @@ ip_finalize(ip)
|
|||
/* delete slaves */
|
||||
delete_slaves(ip);
|
||||
|
||||
/* shut off some connections from Tcl-proc to Ruby */
|
||||
if (at_exit) {
|
||||
/* NOTE: Only when at exit.
|
||||
Because, ruby removes objects, which depends on the deleted
|
||||
interpreter, on some callback operations.
|
||||
It is important for GC. */
|
||||
#if TCL_MAJOR_VERSION >= 8
|
||||
Tcl_CreateObjCommand(ip, "ruby", ip_null_proc,
|
||||
(ClientData)NULL, (Tcl_CmdDeleteProc *)NULL);
|
||||
Tcl_CreateObjCommand(ip, "ruby_eval", ip_null_proc,
|
||||
(ClientData)NULL, (Tcl_CmdDeleteProc *)NULL);
|
||||
Tcl_CreateObjCommand(ip, "ruby_cmd", ip_null_proc,
|
||||
(ClientData)NULL, (Tcl_CmdDeleteProc *)NULL);
|
||||
#else /* TCL_MAJOR_VERSION < 8 */
|
||||
Tcl_CreateCommand(ip, "ruby", ip_null_proc,
|
||||
(ClientData)NULL, (Tcl_CmdDeleteProc *)NULL);
|
||||
Tcl_CreateCommand(ip, "ruby_eval", ip_null_proc,
|
||||
(ClientData)NULL, (Tcl_CmdDeleteProc *)NULL);
|
||||
Tcl_CreateCommand(ip, "ruby_cmd", ip_null_proc,
|
||||
(ClientData)NULL, (Tcl_CmdDeleteProc *)NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* delete root widget */
|
||||
#if 0
|
||||
DUMP1("check `destroy'");
|
||||
|
@ -4425,7 +4477,7 @@ ip_finalize(ip)
|
|||
|
||||
/* call finalize-hook-proc */
|
||||
DUMP1("check `finalize-hook-proc'");
|
||||
if (Tcl_GetCommandInfo(ip, finalize_hook_name, &info)) {
|
||||
if ( Tcl_GetCommandInfo(ip, finalize_hook_name, &info)) {
|
||||
DUMP2("call finalize hook proc '%s'", finalize_hook_name);
|
||||
ruby_debug = Qfalse;
|
||||
ruby_verbose = Qnil;
|
||||
|
@ -4680,7 +4732,6 @@ ip_CallWhenDeleted(clientData, ip)
|
|||
rb_thread_critical = thr_crit_bup;
|
||||
}
|
||||
|
||||
|
||||
/* initialize interpreter */
|
||||
static VALUE
|
||||
ip_init(argc, argv, self)
|
||||
|
@ -7925,6 +7976,8 @@ Init_tcltklib()
|
|||
|
||||
/* --------------------------------------------------------------- */
|
||||
|
||||
rb_define_module_function(lib, "_mark_at_exit", lib_mark_at_exit, 0);
|
||||
|
||||
rb_define_module_function(lib, "mainloop", lib_mainloop, -1);
|
||||
rb_define_module_function(lib, "mainloop_thread?",
|
||||
lib_evloop_thread_p, 0);
|
||||
|
@ -8061,6 +8114,10 @@ Init_tcltklib()
|
|||
|
||||
/* --------------------------------------------------------------- */
|
||||
|
||||
rb_eval_string("at_exit{ TclTkLib._mark_at_exit }");
|
||||
|
||||
/* --------------------------------------------------------------- */
|
||||
|
||||
ret = ruby_open_tcl_dll(rb_argv0 ? RSTRING(rb_argv0)->ptr : 0);
|
||||
switch(ret) {
|
||||
case TCLTK_STUBS_OK:
|
||||
|
|
Loading…
Add table
Reference in a new issue