1
0
Fork 0
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:
nagai 2006-07-10 09:52:30 +00:00
parent a1a07fbfa1
commit d2271cbdd1
9 changed files with 543 additions and 40 deletions

View file

@ -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> Mon Jul 10 17:32:38 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
* sample/test.rb: update test suites. * sample/test.rb: update test suites.

View file

@ -33,6 +33,64 @@ class << TclTkIp
end 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 # exceptiopn to treat the return value from IP
class MultiTkIp_OK < Exception class MultiTkIp_OK < Exception
@ -54,6 +112,8 @@ MultiTkIp_OK.freeze
################################################ ################################################
# methods for construction # methods for construction
class MultiTkIp class MultiTkIp
BASE_DIR = File.dirname(__FILE__)
@@SLAVE_IP_ID = ['slave'.freeze, '0'.taint].freeze @@SLAVE_IP_ID = ['slave'.freeze, '0'.taint].freeze
@@IP_TABLE = {}.taint unless defined?(@@IP_TABLE) @@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){ @assign_request = Class.new(Exception){
def self.new(target, ret) def self.new(target, ret)
obj = super() 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 class << self
undef :instance_eval undef :instance_eval
end end
} }
@@DEFAULT_MASTER.freeze # defend against modification @@DEFAULT_MASTER.freeze # defend against modification
###################################### ######################################
@ -1115,6 +1245,8 @@ class MultiTkIp
@threadgroup = ThreadGroup.new @threadgroup = ThreadGroup.new
@pseudo_toplevel = [false, nil]
@cmd_queue = Queue.new @cmd_queue = Queue.new
=begin =begin
@ -1424,6 +1556,17 @@ class MultiTkIp
} }
end 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) 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.eval_proc{script.call(self)}}
init_ip_env.each{|script| self._init_ip_env(script)} init_ip_env.each{|script| self._init_ip_env(script)}
@ -1450,9 +1593,21 @@ class MultiTkIp
__getip._tk_table_list[id] __getip._tk_table_list[id]
end end
def self.create_table def self.create_table
#if __getip.slave? if __getip.slave?
# raise SecurityError, "slave-IP has no permission creating a new table" begin
#end 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 id = @@TK_TABLE_LIST.size
obj = Object.new obj = Object.new
@@TK_TABLE_LIST << obj @@TK_TABLE_LIST << obj
@ -1468,15 +1623,48 @@ class MultiTkIp
def self.init_ip_env(script = Proc.new) def self.init_ip_env(script = Proc.new)
@@INIT_IP_ENV << script @@INIT_IP_ENV << script
@@IP_TABLE.each{|tg, ip| if __getip.slave?
ip._init_ip_env(script) 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 end
def self.add_tk_procs(name, args=nil, body=nil) def self.add_tk_procs(name, args=nil, body=nil)
@@ADD_TK_PROCS << [name, args, body] 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_TABLE.each{|tg, ip|
ip._add_tk_procs(name, args, body) ip._remove_tk_procs(*names)
} }
end end
@ -1565,6 +1753,46 @@ class MultiTkIp
end 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 # evaluate a procedure on the proper interpreter
class MultiTkIp class MultiTkIp
# instance method # instance method

View file

@ -1192,8 +1192,22 @@ module TkCore
script.call(self) script.call(self)
end end
def INTERP.add_tk_procs(name, args = nil, body = nil) def INTERP.add_tk_procs(name, args = nil, body = nil)
@add_tk_procs << [name, args, body] if name.kind_of?(Array)
self._invoke('proc', name, args, body) if args && body 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 end
def INTERP.init_ip_internal def INTERP.init_ip_internal
ip = self ip = self
@ -1285,6 +1299,8 @@ module TkCore
EOL EOL
=end =end
at_exit{ INTERP.remove_tk_procs(TclTkLib::FINALIZE_PROC_NAME) }
EventFlag = TclTkLib::EventFlag EventFlag = TclTkLib::EventFlag
def callback_break def callback_break
@ -3886,12 +3902,14 @@ class TkObject<TkKernel
begin begin
cget(name) cget(name)
rescue rescue
fail NameError, super(id, *args)
"undefined local variable or method `#{name}' for #{self.to_s}", # fail NameError,
error_at # "undefined local variable or method `#{name}' for #{self.to_s}",
# error_at
end end
else 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
end end
@ -4563,7 +4581,7 @@ end
#Tk.freeze #Tk.freeze
module Tk module Tk
RELEASE_DATE = '2006-07-03'.freeze RELEASE_DATE = '2006-07-10'.freeze
autoload :AUTO_PATH, 'tk/variable' autoload :AUTO_PATH, 'tk/variable'
autoload :TCL_PACKAGE_PATH, 'tk/variable' autoload :TCL_PACKAGE_PATH, 'tk/variable'

View file

@ -859,10 +859,12 @@ class TkFont
begin begin
configinfo name configinfo name
rescue rescue
fail NameError, "undefined local variable or method `#{name}' for #{self.to_s}", error_at super(id, *args)
end # fail NameError, "undefined local variable or method `#{name}' for #{self.to_s}", error_at
# end
else 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
end end

View file

@ -130,7 +130,8 @@ class TkMsgCatalog < TkObject
self.set_translation(loc, *args) self.set_translation(loc, *args)
else 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
end end

View file

@ -289,7 +289,8 @@ module Tk
end end
# unknown method # unknown method
fail RuntimeError, "unknown method '#{name}' for #{self.inspect}" super(id, *args)
# fail RuntimeError, "unknown method '#{name}' for #{self.inspect}"
end end
def tk_send(cmd, *rest) def tk_send(cmd, *rest)

View file

@ -509,12 +509,93 @@ else # ver >= 8.4
alias showVars showVars2 alias showVars showVars2
end 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 def _null_binding
Module.new.instance_eval{extend PseudoToplevel_Evaluable}
# binding # binding
Module.new.instance_eval{binding} # Module.new.instance_eval{binding}
end end
private :_null_binding private :_null_binding
def eval_samplecode(code)
Thread.new{ _null_binding.pseudo_toplevel_eval{ eval(code) } }.run
Tk.update
end
# invoke -- # invoke --
# This procedure is called when the user clicks on a demo description. # This procedure is called when the user clicks on a demo description.
# It is responsible for invoking the demonstration. # It is responsible for invoking the demonstration.
@ -529,8 +610,9 @@ def invoke(txt, idx)
cursor = txt.cget('cursor') cursor = txt.cget('cursor')
txt.cursor('watch') txt.cursor('watch')
Tk.update Tk.update
eval(IO.readlines("#{[$demo_dir, tag[5..-1]].join(File::Separator)}.rb").join, _null_binding) # eval(IO.readlines("#{[$demo_dir, tag[5..-1]].join(File::Separator)}.rb").join, _null_binding)
Tk.update # Tk.update
eval_samplecode(IO.readlines("#{[$demo_dir, tag[5..-1]].join(File::Separator)}.rb").join)
txt.cursor(cursor) txt.cursor(cursor)
$tag_visited.add("#{idx} linestart +1 chars", "#{idx} lineend +1 chars") $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) }.pack('side'=>'left', 'expand'=>'yes', 'pady'=>2)
TkButton.new(f) { TkButton.new(f) {
text "Rerun Demo" 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) }.pack('side'=>'left', 'expand'=>'yes', 'pady'=>2)
# f.pack('side'=>'bottom', 'expand'=>'yes', 'fill'=>'x') # f.pack('side'=>'bottom', 'expand'=>'yes', 'fill'=>'x')
f.pack('side'=>'bottom', 'fill'=>'x') f.pack('side'=>'bottom', 'fill'=>'x')
@ -690,7 +773,8 @@ def showCode2(demo)
:image=>$image['print'], :compound=>:left) :image=>$image['print'], :compound=>:left)
b_run = TkButton.new(bf, :text=>'Rerun Demo', b_run = TkButton.new(bf, :text=>'Rerun Demo',
:command=>proc{ :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) :image=>$image['refresh'], :compound=>:left)
@ -812,7 +896,7 @@ end
# #
def aboutBox def aboutBox
Tk.messageBox('icon'=>'info', 'type'=>'ok', 'title'=>'About Widget Demo', 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 " + "based on demos of Tk8.1 -- 8.5 " +
"( Copyright:: " + "( Copyright:: " +
"(c) 1996-1997 Sun Microsystems, Inc. / " + "(c) 1996-1997 Sun Microsystems, Inc. / " +
@ -837,11 +921,12 @@ ARGV.each{|cmd|
if cmd =~ /(.*).rb/ if cmd =~ /(.*).rb/
cmd = $1 cmd = $1
end end
eval(IO.readlines("#{[$demo_dir, cmd].join(File::Separator)}.rb").join, #eval(IO.readlines("#{[$demo_dir, cmd].join(File::Separator)}.rb").join,
_null_binding) # _null_binding)
eval_samplecode(IO.readlines("#{[$demo_dir, cmd].join(File::Separator)}.rb").join)
} }
if no_launcher if no_launcher
$root.withdraw # hide root window $root.withdraw # hide root window
Thread.start{ Thread.start{
loop do loop do
count = 0 count = 0

View file

@ -551,12 +551,93 @@ else # ver >= 8.4
alias showVars showVars2 alias showVars showVars2
end 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 def _null_binding
Module.new.instance_eval{extend PseudoToplevel_Evaluable}
# binding # binding
Module.new.instance_eval{binding} # Module.new.instance_eval{binding}
end end
private :_null_binding private :_null_binding
def eval_samplecode(code)
Thread.new{ _null_binding.pseudo_toplevel_eval{ eval(code) } }.run
Tk.update
end
# テキスト上での click に対する動作 # テキスト上での click に対する動作
def invoke(txt, idx) def invoke(txt, idx)
tag = txt.tag_names(idx).find{|t| t.kind_of?(String) && t =~ /^demo-/} 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') cursor = txt.cget('cursor')
txt.cursor('watch') txt.cursor('watch')
Tk.update Tk.update
eval(IO.readlines("#{[$demo_dir, tag[5..-1]].join(File::Separator)}.rb").join, _null_binding) # eval(IO.readlines("#{[$demo_dir, tag[5..-1]].join(File::Separator)}.rb").join, _null_binding)
Tk.update # Tk.update
eval_samplecode(IO.readlines("#{[$demo_dir, tag[5..-1]].join(File::Separator)}.rb").join)
txt.cursor(cursor) txt.cursor(cursor)
$tag_visited.add("#{idx} linestart +1 chars", "#{idx} lineend +1 chars") $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) }.pack('side'=>'left', 'expand'=>'yes', 'pady'=>2)
TkButton.new(f) { TkButton.new(f) {
text "再実行" 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) }.pack('side'=>'left', 'expand'=>'yes', 'pady'=>2)
# f.pack('side'=>'bottom', 'expand'=>'yes', 'fill'=>'x') # f.pack('side'=>'bottom', 'expand'=>'yes', 'fill'=>'x')
f.pack('side'=>'bottom', 'fill'=>'x') f.pack('side'=>'bottom', 'fill'=>'x')
@ -716,7 +799,8 @@ def showCode2(demo)
:image=>$image['print'], :compound=>:left) :image=>$image['print'], :compound=>:left)
b_run = TkButton.new(bf, :text=>'再実行', b_run = TkButton.new(bf, :text=>'再実行',
:command=>proc{ :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) :image=>$image['refresh'], :compound=>:left)
@ -842,7 +926,7 @@ end
# #
def aboutBox def aboutBox
Tk.messageBox('icon'=>'info', 'type'=>'ok', 'title'=>'About Widget Demo', 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 " + "based on demos of Tk8.1 -- 8.5 " +
"( Copyright:: " + "( Copyright:: " +
"(c) 1996-1997 Sun Microsystems, Inc. / " + "(c) 1996-1997 Sun Microsystems, Inc. / " +
@ -867,8 +951,9 @@ ARGV.each{|cmd|
if cmd =~ /(.*).rb/ if cmd =~ /(.*).rb/
cmd = $1 cmd = $1
end end
eval(IO.readlines("#{[$demo_dir, cmd].join(File::Separator)}.rb").join, #eval(IO.readlines("#{[$demo_dir, cmd].join(File::Separator)}.rb").join,
_null_binding) # _null_binding)
eval_samplecode(IO.readlines("#{[$demo_dir, cmd].join(File::Separator)}.rb").join)
} }
if no_launcher if no_launcher
$root.withdraw # hide root window $root.withdraw # hide root window

View file

@ -4,7 +4,7 @@
* Oct. 24, 1997 Y. Matsumoto * Oct. 24, 1997 Y. Matsumoto
*/ */
#define TCLTKLIB_RELEASE_DATE "2006-07-03" #define TCLTKLIB_RELEASE_DATE "2006-07-10"
#include "ruby.h" #include "ruby.h"
#include "rubysig.h" #include "rubysig.h"
@ -81,6 +81,8 @@ static char *finalize_hook_name = "INTERP_FINALIZE_HOOK";
static void ip_finalize _((Tcl_Interp*)); static void ip_finalize _((Tcl_Interp*));
static int at_exit = 0;
/* for callback break & continue */ /* for callback break & continue */
static VALUE eTkCallbackReturn; static VALUE eTkCallbackReturn;
@ -4358,6 +4360,33 @@ delete_slaves(ip)
/* finalize operation */ /* 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 static void
ip_finalize(ip) ip_finalize(ip)
Tcl_Interp *ip; Tcl_Interp *ip;
@ -4403,6 +4432,29 @@ ip_finalize(ip)
/* delete slaves */ /* delete slaves */
delete_slaves(ip); 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 */ /* delete root widget */
#if 0 #if 0
DUMP1("check `destroy'"); DUMP1("check `destroy'");
@ -4425,7 +4477,7 @@ ip_finalize(ip)
/* call finalize-hook-proc */ /* call finalize-hook-proc */
DUMP1("check `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); DUMP2("call finalize hook proc '%s'", finalize_hook_name);
ruby_debug = Qfalse; ruby_debug = Qfalse;
ruby_verbose = Qnil; ruby_verbose = Qnil;
@ -4680,7 +4732,6 @@ ip_CallWhenDeleted(clientData, ip)
rb_thread_critical = thr_crit_bup; rb_thread_critical = thr_crit_bup;
} }
/* initialize interpreter */ /* initialize interpreter */
static VALUE static VALUE
ip_init(argc, argv, self) 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", lib_mainloop, -1);
rb_define_module_function(lib, "mainloop_thread?", rb_define_module_function(lib, "mainloop_thread?",
lib_evloop_thread_p, 0); 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); ret = ruby_open_tcl_dll(rb_argv0 ? RSTRING(rb_argv0)->ptr : 0);
switch(ret) { switch(ret) {
case TCLTK_STUBS_OK: case TCLTK_STUBS_OK: