曾与蒿藜同雨露,한때 잡초와 쑥과 함께 비와 이슬을 나누던 곳이 이제는 소나무와 삼나무와 함께 서리와 눈을 견뎌내고 있다.终随松柏到冰霜.かつては雑草やヨモギと共に雨や露を分かち合っていたが、今では松やヒノキと共に霜や雪に耐えている。曾与蒿藜同雨露,Once sharing rain and dew with weeds and wormwood, now enduring frost and snow with pines and cypresses.终随松柏到冰霜.曾与蒿藜同雨露한때 잡초와 쑥과 함께 비와 이슬을 나누던 곳이 이제는 소나무와 삼나무와 함께 서리와 눈을 견뎌내고 있다.,终随松柏到冰霜.譖セ荳手珍阯懷酔髮ィ髴イ�檎サ磯囂譚セ譟丞芦蜀ー髴�曾与蒿藜同雨露,鏇句笌钂胯棞鍚岄洦闇诧紝缁堥殢鏉炬煆鍒板啺闇�终随松柏到冰霜.曾与蒿藜同雨露,한때 잡초와 쑥과 함께 비와 이슬을 나누던 곳이 이제는 소나무와 삼나무와 함께 서리와 눈을 견뎌내고 있다.终随松柏到冰霜.曾与蒿藜同雨露,终随松柏到冰霜.
# frozen_string_literal: false
#
# tk.rb - Tk interface module using tcltklib
# by Yukihiro Matsumoto <matz@netlab.jp>
# use Shigehiro's tcltklib
require 'tcltklib'
require 'tkutil'
# autoload
require 'tk/autoload'
# for Mutex
require 'thread'
class TclTkIp
# backup original (without encoding) _eval and _invoke
alias _eval_without_enc _eval
alias __eval__ _eval
alias _invoke_without_enc _invoke
alias __invoke__ _invoke
def _ip_id_
# for RemoteTkIp
''
end
alias __initialize__ initialize
private :__initialize__
def initialize(*args)
__initialize__(*args)
@force_default_encoding ||= TkUtil.untrust([false])
@encoding ||= TkUtil.untrust([nil])
def @encoding.to_s; self.join(nil); end
end
end
# define TkComm module (step 1: basic functions)
module TkComm
include TkUtil
extend TkUtil
WidgetClassNames = TkUtil.untrust({})
TkExtlibAutoloadModule = TkUtil.untrust([])
# None = Object.new ### --> definition is moved to TkUtil module
# def None.to_s
# 'None'
# end
# None.freeze
#Tk_CMDTBL = {}
#Tk_WINDOWS = {}
Tk_IDs = [
TkUtil.untrust("00000"), # [0]-cmdid
TkUtil.untrust("00000") # [1]-winid
]
Tk_IDs.instance_eval{
@mutex = Mutex.new
def mutex; @mutex; end
freeze
}
# for backward compatibility
Tk_CMDTBL = Object.new
def Tk_CMDTBL.method_missing(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)
end
Tk_WINDOWS.freeze
self.instance_eval{
@cmdtbl = TkUtil.untrust([])
}
unless const_defined?(:GET_CONFIGINFO_AS_ARRAY)
# GET_CONFIGINFO_AS_ARRAY = false => returns a Hash { opt =>val, ... }
# true => returns an Array [[opt,val], ... ]
# val is a list which includes resource info.
GET_CONFIGINFO_AS_ARRAY = true
end
unless const_defined?(:GET_CONFIGINFOwoRES_AS_ARRAY)
# for configinfo without resource info; list of [opt, value] pair
# false => returns a Hash { opt=>val, ... }
# true => returns an Array [[opt,val], ... ]
GET_CONFIGINFOwoRES_AS_ARRAY = true
end
# *** ATTENTION ***
# 'current_configinfo' method always returns a Hash under all cases of above.
def error_at
frames = caller()
frames.delete_if do |c|
c =~ %r!/tk(|core|thcore|canvas|text|entry|scrollbox)\.rb:\d+!
end
frames
end
private :error_at
def _genobj_for_tkwidget(path)
return TkRoot.new if path == '.'
begin
#tk_class = TkCore::INTERP._invoke('winfo', 'class', path)
tk_class = Tk.ip_invoke_without_enc('winfo', 'class', path)
rescue
return path
end
if ruby_class = WidgetClassNames[tk_class]
ruby_class_name = ruby_class.name
# gen_class_name = ruby_class_name + 'GeneratedOnTk'
gen_class_name = ruby_class_name
classname_def = ''
else # ruby_class == nil
if Tk.const_defined?(tk_class)
Tk.const_get(tk_class) # auto_load
ruby_class = WidgetClassNames[tk_class]
end
unless ruby_class
mods = TkExtlibAutoloadModule.find_all{|m| m.const_defined?(tk_class)}
mods.each{|mod|
begin
mod.const_get(tk_class) # auto_load
break if (ruby_class = WidgetClassNames[tk_class])
rescue LoadError
# ignore load error
end
}
end
unless ruby_class
std_class = 'Tk' << tk_class
if Object.const_defined?(std_class)
Object.const_get(std_class) # auto_load
ruby_class = WidgetClassNames[tk_class]
end
end
unless ruby_class
if Tk.const_defined?('TOPLEVEL_ALIASES') &&
Tk::TOPLEVEL_ALIASES.const_defined?(std_class)
Tk::TOPLEVEL_ALIASES.const_get(std_class) # auto_load
ruby_class = WidgetClassNames[tk_class]
end
end
if ruby_class
# found
ruby_class_name = ruby_class.name
gen_class_name = ruby_class_name
classname_def = ''
else
# unknown
ruby_class_name = 'TkWindow'
gen_class_name = 'TkWidget_' + tk_class
classname_def = "WidgetClassName = '#{tk_class}'.freeze"
end
end
###################################
=begin
if ruby_class = WidgetClassNames[tk_class]
ruby_class_name = ruby_class.name
# gen_class_name = ruby_class_name + 'GeneratedOnTk'
gen_class_name = ruby_class_name
classname_def = ''
else
mod = TkExtlibAutoloadModule.find{|m| m.const_defined?(tk_class)}
if mod
ruby_class_name = mod.name + '::' + tk_class
gen_class_name = ruby_class_name
classname_def = ''
elsif Object.const_defined?('Tk' + tk_class)
ruby_class_name = 'Tk' + tk_class
# gen_class_name = ruby_class_name + 'GeneratedOnTk'
gen_class_name = ruby_class_name
classname_def = ''
else
ruby_class_name = 'TkWindow'
# gen_class_name = ruby_class_name + tk_class + 'GeneratedOnTk'
gen_class_name = 'TkWidget_' + tk_class
classname_def = "WidgetClassName = '#{tk_class}'.freeze"
end
end
=end
=begin
unless Object.const_defined? gen_class_name
Object.class_eval "class #{gen_class_name}<#{ruby_class_name}
#{classname_def}
end"
end
Object.class_eval "#{gen_class_name}.new('widgetname'=>'#{path}',
'without_creating'=>true)"
=end
base = Object
gen_class_name.split('::').each{|klass|
next if klass == ''
if base.const_defined?(klass)
base = base.class_eval klass
else
base = base.class_eval "class #{klass}<#{ruby_class_name}
#{classname_def}
end
#{klass}"
end
}
base.class_eval "#{gen_class_name}.new('widgetname'=>'#{path}',
'without_creating'=>true)"
end
private :_genobj_for_tkwidget
module_function :_genobj_for_tkwidget
def _at(x,y=nil)
if y
"@#{Integer(x)},#{Integer(y)}"
else
"@#{Integer(x)}"
end
end
module_function :_at
def tk_tcl2ruby(val, enc_mode = false, listobj = true)
=begin
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]
#if cmd_obj.kind_of?(Proc) || cmd_obj.kind_of?(Method)
# cmd_obj
#else
# cmd_obj.cmd
#end
end
=end
if val =~ /rb_out\S*(?:\s+(::\S*|[{](::.*)[}]|["](::.*)["]))? (c(_\d+_)?(\d+))/
return TkCore::INTERP.tk_cmd_tbl[$4]
end
#if val.include? ?\s
# return val.split.collect{|v| tk_tcl2ruby(v)}
#end
case val
when /\A@font\S+\z/
TkFont.get_obj(val)
when /\A-?\d+\z/
val.to_i
when /\A\.\S*\z/
#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 /\Ai(_\d+_)?\d+\z/
TkImage::Tk_IMGTBL.mutex.synchronize{
TkImage::Tk_IMGTBL[val]? TkImage::Tk_IMGTBL[val] : val
}
when /\A-?\d+\.?\d*(e[-+]?\d+)?\z/
val.to_f
when /\\ /
val.gsub(/\\ /, ' ')
when /[^\\] /
if listobj
#tk_split_escstr(val).collect{|elt|
# tk_tcl2ruby(elt, enc_mode, listobj)
#}
val = _toUTF8(val) unless enc_mode
tk_split_escstr(val, false, false).collect{|elt|
tk_tcl2ruby(elt, true, listobj)
}
elsif enc_mode
_fromUTF8(val)
else
val
end
else
if enc_mode
_fromUTF8(val)
else
val
end
end
end
private :tk_tcl2ruby
module_function :tk_tcl2ruby
#private_class_method :tk_tcl2ruby
unless const_defined?(:USE_TCLs_LIST_FUNCTIONS)
USE_TCLs_LIST_FUNCTIONS = true
end
if USE_TCLs_LIST_FUNCTIONS
###########################################################################
# use Tcl function version of split_list
###########################################################################
def tk_split_escstr(str, src_enc=true, dst_enc=true)
str = _toUTF8(str) if src_enc
if dst_enc
TkCore::INTERP._split_tklist(str).map!{|s| _fromUTF8(s)}
else
TkCore::INTERP._split_tklist(str)
end
end
def tk_split_sublist(str, depth=-1, src_enc=true, dst_enc=true)
# return [] if str == ""
# list = TkCore::INTERP._split_tklist(str)
str = _toUTF8(str) if src_enc
if depth == 0
return "" if str == ""
list = [str]
else
return [] if str == ""
list = TkCore::INTERP._split_tklist(str)
end
if list.size == 1
# tk_tcl2ruby(list[0], nil, false)
tk_tcl2ruby(list[0], dst_enc, false)
else
list.collect{|token| tk_split_sublist(token, depth - 1, false, dst_enc)}
end
end
def tk_split_list(str, depth=0, src_enc=true, dst_enc=true)
return [] if str == ""
str = _toUTF8(str) if src_enc
TkCore::INTERP._split_tklist(str).map!{|token|
tk_split_sublist(token, depth - 1, false, dst_enc)
}
end
def tk_split_simplelist(str, src_enc=true, dst_enc=true)
#lst = TkCore::INTERP._split_tklist(str)
#if (lst.size == 1 && lst =~ /^\{.*\}$/)
# TkCore::INTERP._split_tklist(str[1..-2])
#else
# lst
#end
str = _toUTF8(str) if src_enc
if dst_enc
TkCore::INTERP._split_tklist(str).map!{|s| _fromUTF8(s)}
else
TkCore::INTERP._split_tklist(str)
end
end
def array2tk_list(ary, enc=nil)
return "" if ary.size == 0
sys_enc = TkCore::INTERP.encoding
sys_enc = TclTkLib.encoding_system unless sys_enc
dst_enc = (enc == nil)? sys_enc: enc
dst = ary.collect{|e|
if e.kind_of? Array
s = array2tk_list(e, enc)
elsif e.kind_of? Hash
tmp_ary = []
#e.each{|k,v| tmp_ary << k << v }
e.each{|k,v| tmp_ary << "-#{_get_eval_string(k)}" << v }
s = array2tk_list(tmp_ary, enc)
else
s = _get_eval_string(e, enc)
end
if dst_enc != true && dst_enc != false
if (s_enc = s.instance_variable_get(:@encoding))
s_enc = s_enc.to_s
elsif TkCore::WITH_ENCODING
s_enc = s.encoding.name
else
s_enc = sys_enc
end
dst_enc = true if s_enc != dst_enc
end
s
}
if sys_enc && dst_enc
dst.map!{|s| _toUTF8(s)}
ret = TkCore::INTERP._merge_tklist(*dst)
if TkCore::WITH_ENCODING
if dst_enc.kind_of?(String)
ret = _fromUTF8(ret, dst_enc)
ret.force_encoding(dst_enc)
else
ret.force_encoding('utf-8')
end
else # without encoding
if dst_enc.kind_of?(String)
ret = _fromUTF8(ret, dst_enc)
ret.instance_variable_set(:@encoding, dst_enc)
else
ret.instance_variable_set(:@encoding, 'utf-8')
end
end
ret
else
TkCore::INTERP._merge_tklist(*dst)
end
end
else
###########################################################################
# use Ruby script version of split_list (traditional methods)
###########################################################################
def tk_split_escstr(str, src_enc=true, dst_enc=true)
return [] if str == ""
list = []
token = nil
escape = false
brace = 0
str.split('').each {|c|
brace += 1 if c == '{' && !escape
brace -= 1 if c == '}' && !escape
if brace == 0 && c == ' ' && !escape
list << token.gsub(/^\{(.*)\}$/, '\1') if token
token = nil
else
token = (token || "") << c
end
escape = (c == '\\' && !escape)
}
list << token.gsub(/^\{(.*)\}$/, '\1') if token
list
end
def tk_split_sublist(str, depth=-1, src_enc=true, dst_enc=true)
#return [] if str == ""
#return [tk_split_sublist(str[1..-2])] if str =~ /^\{.*\}$/
#list = tk_split_escstr(str)
if depth == 0
return "" if str == ""
str = str[1..-2] if str =~ /^\{.*\}$/
list = [str]
else
return [] if str == []
return [tk_split_sublist(str[1..-2], depth - 1)] if str =~ /^\{.*\}$/
list = tk_split_escstr(str)
end
if list.size == 1
tk_tcl2ruby(list[0], nil, false)
else
list.collect{|token| tk_split_sublist(token, depth - 1)}
end
end
def tk_split_list(str, depth=0, src_enc=true, dst_enc=true)
return [] if str == ""
tk_split_escstr(str).collect{|token|
tk_split_sublist(token, depth - 1)
}
end
def tk_split_simplelist(str, src_enc=true, dst_enc=true)
return [] if str == ""
list = []
token = nil
escape = false
brace = 0
str.split('').each {|c|
if c == '\\' && !escape
escape = true
token = (token || "") << c if brace > 0
next
end
brace += 1 if c == '{' && !escape
brace -= 1 if c == '}' && !escape
if brace == 0 && c == ' ' && !escape
list << token.gsub(/^\{(.*)\}$/, '\1') if token
token = nil
else
token = (token || "") << c
end
escape = false
}
list << token.gsub(/^\{(.*)\}$/, '\1') if token
list
end
def array2tk_list(ary, enc=nil)
ary.collect{|e|
if e.kind_of? Array
"{#{array2tk_list(e, enc)}}"
elsif e.kind_of? Hash
# "{#{e.to_a.collect{|ee| array2tk_list(ee)}.join(' ')}}"
e.each{|k,v| tmp_ary << "-#{_get_eval_string(k)}" << v }
array2tk_list(tmp_ary, enc)
else
s = _get_eval_string(e, enc)
(s.index(/\s/) || s.size == 0)? "{#{s}}": s
end
}.join(" ")
end
end
private :tk_split_escstr, :tk_split_sublist
private :tk_split_list, :tk_split_simplelist
private :array2tk_list
module_function :tk_split_escstr, :tk_split_sublist
module_function :tk_split_list, :tk_split_simplelist
module_function :array2tk_list
private_class_method :tk_split_escstr, :tk_split_sublist
private_class_method :tk_split_list, :tk_split_simplelist
# private_class_method :array2tk_list
=begin
### --> definition is moved to TkUtil module
def _symbolkey2str(keys)
h = {}
keys.each{|key,value| h[key.to_s] = value}
h
end
private :_symbolkey2str
module_function :_symbolkey2str
=end
=begin
### --> definition is moved to TkUtil module
# def hash_kv(keys, enc_mode = nil, conf = [], flat = false)
def hash_kv(keys, enc_mode = nil, conf = nil)
# Hash {key=>val, key=>val, ... } or Array [ [key, val], [key, val], ... ]
# ==> Array ['-key', val, '-key', val, ... ]
dst = []
if keys and keys != None
keys.each{|k, v|
#dst.push("-#{k}")
dst.push('-' + k.to_s)
if v != None
# v = _get_eval_string(v, enc_mode) if (enc_mode || flat)
v = _get_eval_string(v, enc_mode) if enc_mode
dst.push(v)
end
}
end
if conf
conf + dst
else
dst
end
end
private :hash_kv
module_function :hash_kv
=end
=begin
### --> definition is moved to TkUtil module
def bool(val)
case val
when "1", 1, 'yes', 'true'
true
else
false
end
end
def number(val)
case val
when /^-?\d+$/
val.to_i
when /^-?\d+\.?\d*(e[-+]?\d+)?$/
val.to_f
else
fail(ArgumentError, "invalid value for Number:'#{val}'")
end
end
def string(val)
if val == "{}"
''
elsif val[0] == ?{ && val[-1] == ?}
val[1..-2]
else
val
end
end
def num_or_str(val)
begin
number(val)
rescue ArgumentError
string(val)
end
end
=end
def list(val, depth=0, enc=true)
tk_split_list(val, depth, enc, enc)
end
def simplelist(val, src_enc=true, dst_enc=true)
tk_split_simplelist(val, src_enc, dst_enc)
end
def window(val)
if val =~ /^\./
#Tk_WINDOWS[val]? Tk_WINDOWS[val] : _genobj_for_tkwidget(val)
TkCore::INTERP.tk_windows[val]?
TkCore::INTERP.tk_windows[val] : _genobj_for_tkwidget(val)
else
nil
end
end
def image_obj(val)
if val =~ /^i(_\d+_)?\d+$/
TkImage::Tk_IMGTBL.mutex.synchronize{
TkImage::Tk_IMGTBL[val]? TkImage::Tk_IMGTBL[val] : val
}
else
val
end
end
def procedure(val)
=begin
if val =~ /^rb_out\S* (c(_\d+_)?\d+)/
#Tk_CMDTBL[$1]
#TkCore::INTERP.tk_cmd_tbl[$1]
TkCore::INTERP.tk_cmd_tbl[$1].cmd
=end
if val =~ /rb_out\S*(?:\s+(::\S*|[{](::.*)[}]|["](::.*)["]))? (c(_\d+_)?(\d+))/
return TkCore::INTERP.tk_cmd_tbl[$4].cmd
else
#nil
val
end
end
private :bool, :number, :num_or_str, :num_or_nil, :string
private :list, :simplelist, :window, :image_obj, :procedure
module_function :bool, :number, :num_or_str, :num_or_nil, :string
module_function :list, :simplelist, :window, :image_obj, :procedure
if (RUBY_VERSION.split('.').map{|n| n.to_i} <=> [1,8,7]) < 0
def slice_ary(ary, size)
sliced = []
wk_ary = ary.dup
until wk_ary.size.zero?
sub_ary = []
size.times{ sub_ary << wk_ary.shift }
yield(sub_ary) if block_given?
sliced << sub_ary
end
(block_given?)? ary: sliced
end
else
def slice_ary(ary, size, &b)
if b
ary.each_slice(size, &b)
else
ary.each_slice(size).to_a
end
end
end
private :slice_ary
module_function :slice_ary
def subst(str, *opts)
# opts := :nobackslashes | :nocommands | novariables
tk_call('subst',
*(opts.collect{|opt|
opt = opt.to_s
(opt[0] == ?-)? opt: '-' << opt
} << str))
end
def _toUTF8(str, encoding = nil)
TkCore::INTERP._toUTF8(str, encoding)
end
def _fromUTF8(str, encoding = nil)
TkCore::INTERP._fromUTF8(str, encoding)
end
private :_toUTF8, :_fromUTF8
module_function :_toUTF8, :_fromUTF8
def _callback_entry_class?(cls)
cls <= Proc || cls <= Method || cls <= TkCallbackEntry
end
private :_callback_entry_class?
module_function :_callback_entry_class?
def _callback_entry?(obj)
obj.kind_of?(Proc) || obj.kind_of?(Method) || obj.kind_of?(TkCallbackEntry)
end
private :_callback_entry?
module_function :_callback_entry?
=begin
### --> definition is moved to TkUtil module
def _get_eval_string(str, enc_mode = nil)
return nil if str == None
if str.kind_of?(TkObject)
str = str.path
elsif str.kind_of?(String)
str = _toUTF8(str) if enc_mode
elsif str.kind_of?(Symbol)
str = str.id2name
str = _toUTF8(str) if enc_mode
elsif str.kind_of?(Hash)
str = hash_kv(str, enc_mode).join(" ")
elsif str.kind_of?(Array)
str = array2tk_list(str)
str = _toUTF8(str) if enc_mode
elsif str.kind_of?(Proc)
str = install_cmd(str)
elsif str == nil
str = ""
elsif str == false
str = "0"
elsif str == true
str = "1"
elsif (str.respond_to?(:to_eval))
str = str.to_eval()
str = _toUTF8(str) if enc_mode
else
str = str.to_s() || ''
unless str.kind_of? String
fail RuntimeError, "fail to convert the object to a string"
end
str = _toUTF8(str) if enc_mode
end
return str
end
=end
=begin
def _get_eval_string(obj, enc_mode = nil)
case obj
when Numeric
obj.to_s
when String
(enc_mode)? _toUTF8(obj): obj
when Symbol
(enc_mode)? _toUTF8(obj.id2name): obj.id2name
when TkObject
obj.path
when Hash
hash_kv(obj, enc_mode).join(' ')
when Array
(enc_mode)? _toUTF8(array2tk_list(obj)): array2tk_list(obj)
when Proc, Method, TkCallbackEntry
install_cmd(obj)
when false
'0'
when true
'1'
when nil
''
when None
nil
else
if (obj.respond_to?(:to_eval))
(enc_mode)? _toUTF8(obj.to_eval): obj.to_eval
else
begin
obj = obj.to_s || ''
rescue
fail RuntimeError, "fail to convert object '#{obj}' to string"
end
(enc_mode)? _toUTF8(obj): obj
end
end
end
private :_get_eval_string
module_function :_get_eval_string
=end
=begin
### --> definition is moved to TkUtil module
def _get_eval_enc_str(obj)
return obj if obj == None
_get_eval_string(obj, true)
end
private :_get_eval_enc_str
module_function :_get_eval_enc_str
=end
=begin
### --> obsolete
def ruby2tcl(v, enc_mode = nil)
if v.kind_of?(Hash)
v = hash_kv(v)
v.flatten!
v.collect{|e|ruby2tcl(e, enc_mode)}
else
_get_eval_string(v, enc_mode)
end
end
private :ruby2tcl
=end
=begin
### --> definition is moved to TkUtil module
def _conv_args(args, enc_mode, *src_args)
conv_args = []
src_args.each{|arg|
conv_args << _get_eval_string(arg, enc_mode) unless arg == None
# if arg.kind_of?(Hash)
# arg.each{|k, v|
# args << '-' + k.to_s
# args << _get_eval_string(v, enc_mode)
# }
# elsif arg != None
# args << _get_eval_string(arg, enc_mode)
# end
}
args + conv_args
end
private :_conv_args
=end
def _curr_cmd_id
#id = format("c%.4d", Tk_IDs[0])
id = "c" + TkCore::INTERP._ip_id_ + TkComm::Tk_IDs[0]
end
def _next_cmd_id
TkComm::Tk_IDs.mutex.synchronize{
id = _curr_cmd_id
#Tk_IDs[0] += 1
TkComm::Tk_IDs[0].succ!
id
}
end
private :_curr_cmd_id, :_next_cmd_id
module_function :_curr_cmd_id, :_next_cmd_id
def TkComm.install_cmd(cmd, local_cmdtbl=nil)
return '' if cmd == ''
begin
ns = TkCore::INTERP._invoke_without_enc('namespace', 'current')
ns = nil if ns == '::' # for backward compatibility
rescue
# probably, Tcl7.6
ns = nil
end
id = _next_cmd_id
#Tk_CMDTBL[id] = cmd
if cmd.kind_of?(TkCallbackEntry)
TkCore::INTERP.tk_cmd_tbl[id] = cmd
else
TkCore::INTERP.tk_cmd_tbl[id] = TkCore::INTERP.get_cb_entry(cmd)
end
@cmdtbl = [] unless defined? @cmdtbl
TkUtil.untrust(@cmdtbl) unless @cmdtbl.tainted?
@cmdtbl.push id
if local_cmdtbl && local_cmdtbl.kind_of?(Array)
begin
local_cmdtbl << id
rescue Exception
# ignore
end
end
#return Kernel.format("rb_out %s", id);
if ns
'rb_out' << TkCore::INTERP._ip_id_ << ' ' << ns << ' ' << id
else
'rb_out' << TkCore::INTERP._ip_id_ << ' ' << id
end
end
def TkComm.uninstall_cmd(id, local_cmdtbl=nil)
#id = $1 if /rb_out\S* (c(_\d+_)?\d+)/ =~ id
id = $4 if id =~ /rb_out\S*(?:\s+(::\S*|[{](::.*)[}]|["](::.*)["]))? (c(_\d+_)?(\d+))/
if local_cmdtbl && local_cmdtbl.kind_of?(Array)
begin
local_cmdtbl.delete(id)
rescue Exception
# ignore
end
end
@cmdtbl.delete(id)
#Tk_CMDTBL.delete(id)
TkCore::INTERP.tk_cmd_tbl.delete(id)
end
# private :install_cmd, :uninstall_cmd
# module_function :install_cmd, :uninstall_cmd
def install_cmd(cmd)
TkComm.install_cmd(cmd, @cmdtbl)
end
def uninstall_cmd(id)
TkComm.uninstall_cmd(id, @cmdtbl)
end
=begin
def install_win(ppath,name=nil)
if !name or name == ''
#name = format("w%.4d", Tk_IDs[1])
#Tk_IDs[1] += 1
name = "w" + Tk_IDs[1]
Tk_IDs[1].succ!
end
if name[0] == ?.
@path = name.dup
elsif !ppath or ppath == "."
@path = Kernel.format(".%s", name);
else
@path = Kernel.format("%s.%s", ppath, name)
end
#Tk_WINDOWS[@path] = self
TkCore::INTERP.tk_windows[@path] = self
end
=end
def install_win(ppath,name=nil)
if name
if name == ''
raise ArgumentError, "invalid wiget-name '#{name}'"
end
if name[0] == ?.
@path = '' + name
@path.freeze
return TkCore::INTERP.tk_windows[@path] = self
end
else
Tk_IDs.mutex.synchronize{
name = "w" + TkCore::INTERP._ip_id_ + Tk_IDs[1]
Tk_IDs[1].succ!
}
end
if !ppath or ppath == '.'
@path = '.' + name
else
@path = ppath + '.' + name
end
@path.freeze
TkCore::INTERP.tk_windows[@path] = self
end
def uninstall_win()
#Tk_WINDOWS.delete(@path)
TkCore::INTERP.tk_windows.delete(@path)
end
private :install_win, :uninstall_win
def _epath(win)
if win.kind_of?(TkObject)
win.epath
elsif win.respond_to?(:epath)
win.epath
else
win
end
end
private :_epath
end
# define TkComm module (step 2: event binding)
module TkComm
include TkEvent
extend TkEvent
def tk_event_sequence(context)
if context.kind_of? TkVirtualEvent
context = context.path
end
if context.kind_of? Array
context = context.collect{|ev|
if ev.kind_of? TkVirtualEvent
ev.path
else
ev
end
}.join("><")
end
if /,/ =~ context
context = context.split(/\s*,\s*/).join("><")
else
context
end
end
def _bind_core(mode, what, context, cmd, *args)
id = install_bind(cmd, *args) if cmd
begin
tk_call_without_enc(*(what + ["<#{tk_event_sequence(context)}>",
mode + id]))
rescue
uninstall_cmd(id) if cmd
fail
end
end
def _bind(what, context, cmd, *args)
_bind_core('', what, context, cmd, *args)
end
def _bind_append(what, context, cmd, *args)
_bind_core('+', what, context, cmd, *args)
end
def _bind_remove(what, context)
tk_call_without_enc(*(what + ["<#{tk_event_sequence(context)}>", '']))
end
def _bindinfo(what, context=nil)
if context
if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!!
enum_obj = tk_call_without_enc(*what+["<#{tk_event_sequence(context)}>"]).each_line
else
enum_obj = tk_call_without_enc(*what+["<#{tk_event_sequence(context)}>"])
end
enum_obj.collect {|cmdline|
=begin
if cmdline =~ /^rb_out\S* (c(?:_\d+_)?\d+)\s+(.*)$/
#[Tk_CMDTBL[$1], $2]
[TkCore::INTERP.tk_cmd_tbl[$1], $2]
=end
if cmdline =~ /rb_out\S*(?:\s+(::\S*|[{](::.*)[}]|["](::.*)["]))? (c(_\d+_)?(\d+))/
[TkCore::INTERP.tk_cmd_tbl[$4], $5]
else
cmdline
end
}
else
tk_split_simplelist(tk_call_without_enc(*what)).collect!{|seq|
l = seq.scan(/<*[^<>]+>*/).collect!{|subseq|
case (subseq)
when /^<<[^<>]+>>$/
TkVirtualEvent.getobj(subseq[1..-2])
when /^<[^<>]+>$/
subseq[1..-2]
else
subseq.split('')
end
}.flatten
(l.size == 1) ? l[0] : l
}
end
end
def _bind_core_for_event_class(klass, mode, what, context, cmd, *args)
id = install_bind_for_event_class(klass, cmd, *args) if cmd
begin
tk_call_without_enc(*(what + ["<#{tk_event_sequence(context)}>",
mode + id]))
rescue
uninstall_cmd(id) if cmd
fail
end
end
def _bind_for_event_class(klass, what, context, cmd, *args)
_bind_core_for_event_class(klass, '', what, context, cmd, *args)
end
def _bind_append_for_event_class(klass, what, context, cmd, *args)
_bind_core_for_event_class(klass, '+', what, context, cmd, *args)
end
def _bind_remove_for_event_class(klass, what, context)
_bind_remove(what, context)
end
def _bindinfo_for_event_class(klass, what, context=nil)
_bindinfo(what, context)
end
private :tk_event_sequence
private :_bind_core, :_bind, :_bind_append, :_bind_remove, :_bindinfo
private :_bind_core_for_event_class, :_bind_for_event_class,
:_bind_append_for_event_class, :_bind_remove_for_event_class,
:_bindinfo_for_event_class
#def bind(tagOrClass, context, cmd=Proc.new, *args)
# _bind(["bind", tagOrClass], context, cmd, *args)
# tagOrClass
#end
def bind(tagOrClass, context, *args)
# if args[0].kind_of?(Proc) || args[0].kind_of?(Method)
if TkComm._callback_entry?(args[0]) || !block_given?
cmd = args.shift
else
cmd = Proc.new
end
_bind(["bind", tagOrClass], context, cmd, *args)
tagOrClass
end
#def bind_append(tagOrClass, context, cmd=Proc.new, *args)
# _bind_append(["bind", tagOrClass], context, cmd, *args)
# tagOrClass
#end
def bind_append(tagOrClass, context, *args)
# if args[0].kind_of?(Proc) || args[0].kind_of?(Method)
if TkComm._callback_entry?(args[0]) || !block_given?
cmd = args.shift
else
cmd = Proc.new
end
_bind_append(["bind", tagOrClass], context, cmd, *args)
tagOrClass
end
def bind_remove(tagOrClass, context)
_bind_remove(['bind', tagOrClass], context)
tagOrClass
end
def bindinfo(tagOrClass, context=nil)
_bindinfo(['bind', tagOrClass], context)
end
#def bind_all(context, cmd=Proc.new, *args)
# _bind(['bind', 'all'], context, cmd, *args)
# TkBindTag::ALL
#end
def bind_all(context, *args)
# if args[0].kind_of?(Proc) || args[0].kind_of?(Method)
if TkComm._callback_entry?(args[0]) || !block_given?
cmd = args.shift
else
cmd = Proc.new
end
_bind(['bind', 'all'], context, cmd, *args)
TkBindTag::ALL
end
#def bind_append_all(context, cmd=Proc.new, *args)
# _bind_append(['bind', 'all'], context, cmd, *args)
# TkBindTag::ALL
#end
def bind_append_all(context, *args)
# if args[0].kind_of?(Proc) || args[0].kind_of?(Method)
if TkComm._callback_entry?(args[0]) || !block_given?
cmd = args.shift
else
cmd = Proc.new
end
_bind_append(['bind', 'all'], context, cmd, *args)
TkBindTag::ALL
end
def bind_remove_all(context)
_bind_remove(['bind', 'all'], context)
TkBindTag::ALL
end
def bindinfo_all(context=nil)
_bindinfo(['bind', 'all'], context)
end
end
module TkCore
include TkComm
extend TkComm
WITH_RUBY_VM = Object.const_defined?(:RubyVM) && ::RubyVM.class == Class
WITH_ENCODING = defined?(::Encoding.default_external) && true
#WITH_ENCODING = Object.const_defined?(:Encoding) && ::Encoding.class == Class
unless self.const_defined? :INTERP
if self.const_defined? :IP_NAME
name = IP_NAME.to_s
else
#name = nil
name = $0
end
if self.const_defined? :IP_OPTS
if IP_OPTS.kind_of?(Hash)
opts = hash_kv(IP_OPTS).join(' ')
else
opts = IP_OPTS.to_s
end
else
opts = ''
end
# RUN_EVENTLOOP_ON_MAIN_THREAD = true
unless self.const_defined? :RUN_EVENTLOOP_ON_MAIN_THREAD
if WITH_RUBY_VM ### check Ruby 1.9 !!!!!!!
# *** NEED TO FIX ***
case RUBY_PLATFORM
when /cygwin/
RUN_EVENTLOOP_ON_MAIN_THREAD = true
when /darwin/ # MacOS X
=begin
ip = TclTkIp.new(name, opts)
if ip._invoke_without_enc('tk', 'windowingsystem') == 'aqua' &&
(TclTkLib.get_version<=>[8,4,TclTkLib::RELEASE_TYPE::FINAL,6]) > 0
=end
if TclTkLib::WINDOWING_SYSTEM == 'aqua' &&
(TclTkLib.get_version<=>[8,4,TclTkLib::RELEASE_TYPE::FINAL,6]) > 0
# *** KNOWN BUG ***
# Main event loop thread of TkAqua (> Tk8.4.9) must be the main
# application thread. So, ruby1.9 users must call Tk.mainloop on
# the main application thread.
#
# *** ADD (2009/05/10) ***
# In some cases (I don't know the description of conditions),
# TkAqua 8.4.7 has a same kind of hang-up trouble.
# So, if 8.4.7 or later, set RUN_EVENTLOOP_ON_MAIN_THREAD to true.
# When you want to control this mode, please call the following
# (set true/false as you want) before "require 'tk'".
# ----------------------------------------------------------
# module TkCore; RUN_EVENTLOOP_ON_MAIN_THREAD = true; end
# ----------------------------------------------------------
#
# *** ADD (2010/07/05) ***
# The value of TclTkLib::WINDOWING_SYSTEM is defined at compiling.
# If it is inconsistent with linked DLL, please call the following
# before "require 'tk'".
# ----------------------------------------------------------
# require 'tcltklib'
# module TclTkLib
# remove_const :WINDOWING_SYSTEM
# WINDOWING_SYSTEM = 'x11' # or 'aqua'
# end
# ----------------------------------------------------------
#
RUN_EVENTLOOP_ON_MAIN_THREAD = true
else
RUN_EVENTLOOP_ON_MAIN_THREAD = false
=begin
ip.delete
ip = nil
=end
end
else
RUN_EVENTLOOP_ON_MAIN_THREAD = false
end
else # Ruby 1.8.x
RUN_EVENTLOOP_ON_MAIN_THREAD = false
end
end
if !WITH_RUBY_VM || RUN_EVENTLOOP_ON_MAIN_THREAD ### check Ruby 1.9 !!!!!!!
INTERP = TclTkIp.new(name, opts) unless self.const_defined? :INTERP
else
INTERP_MUTEX = Mutex.new
INTERP_ROOT_CHECK = ConditionVariable.new
INTERP_THREAD = Thread.new{
begin
#Thread.current[:interp] = interp = TclTkIp.new(name, opts)
interp = TclTkIp.new(name, opts)
rescue => e
Thread.current[:interp] = e
raise e
end
interp.mainloop_abort_on_exception = true
Thread.current.instance_variable_set("@interp", interp)
status = [nil]
def status.value
self[0]
end
def status.value=(val)
self[0] = val
end
Thread.current[:status] = status
#sleep
# like as 1.8, withdraw a root widget before calling Tk.mainloop
interp._eval <<EOS
wm withdraw .
rename wm __wm_orig__
proc wm {subcmd win args} {
set val [eval [list __wm_orig__ $subcmd $win] $args]
if {[string equal $subcmd withdraw] && [string equal $win .]} {
rename wm {}
rename __wm_orig__ wm
}
return $val
}
proc __startup_rbtk_mainloop__ {args} {
rename __startup_rbtk_mainloop__ {}
if {[info command __wm_orig__] == "__wm_orig__"} {
rename wm {}
rename __wm_orig__ wm
if [string equal [wm state .] withdrawn] {
wm deiconify .
}
}
}
set __initial_state_of_rubytk__ 1
trace add variable __initial_state_of_rubytk__ unset __startup_rbtk_mainloop__
# complete initializing
ruby {TkCore::INTERP_THREAD[:interp] = TkCore::INTERP_THREAD.instance_variable_get('@interp')}
EOS
begin
begin
#TclTkLib.mainloop_abort_on_exception = false
#interp.mainloop_abort_on_exception = true
#Thread.current[:interp] = interp
#Thread.current[:status].value = TclTkLib.mainloop(true)
Thread.current[:status].value = interp.mainloop(true)
rescue SystemExit=>e
Thread.current[:status].value = e
rescue Exception=>e
Thread.current[:status].value = e
p e if $DEBUG
retry if interp.has_mainwindow?
ensure
INTERP_MUTEX.synchronize{ INTERP_ROOT_CHECK.broadcast }
end
unless interp.deleted?
begin
#Thread.current[:status].value = TclTkLib.mainloop(false)
Thread.current[:status].value = interp.mainloop(false)
rescue Exception=>e
puts "ignore exception on interp: #{e.inspect}\n" if $DEBUG
end
end
ensure
# interp must be deleted before the thread for interp is dead.
# If not, raise Tcl_Panic on Tcl_AsyncDelete because async handler
# deleted by the wrong thread.
interp.delete
end
}
# check a Tcl/Tk interpreter is initialized
until INTERP_THREAD[:interp]
# Thread.pass
INTERP_THREAD.run
end
# INTERP_THREAD.run
raise INTERP_THREAD[:interp] if INTERP_THREAD[:interp].kind_of? Exception
# check an eventloop is running
while INTERP_THREAD.alive? && TclTkLib.mainloop_thread?.nil?
INTERP_THREAD.run
end
INTERP = INTERP_THREAD[:interp]
INTERP_THREAD_STATUS = INTERP_THREAD[:status]
# delete the interpreter and kill the eventloop thread at exit
END{
if INTERP_THREAD.alive?
INTERP.delete
INTERP_THREAD.kill
end
}
# (for safety's sake) force the eventloop to run
INTERP_THREAD.run
end
def INTERP.__getip
self
end
def INTERP.default_master?
true
end
INTERP.instance_eval{
# @tk_cmd_tbl = TkUtil.untrust({})
@tk_cmd_tbl =
TkUtil.untrust(Hash.new{|hash, key|
fail IndexError, "unknown command ID '#{key}'"
})
def @tk_cmd_tbl.[]=(idx,val)
if self.has_key?(idx) && Thread.current.group != ThreadGroup::Default
fail SecurityError,"cannot change the entried command"
end
super(idx,val)
end
@tk_windows = TkUtil.untrust({})
@tk_table_list = TkUtil.untrust([])
@init_ip_env = TkUtil.untrust([]) # table of Procs
@add_tk_procs = TkUtil.untrust([]) # table of [name, args, body]
@force_default_encoding ||= TkUtil.untrust([false])
@encoding ||= TkUtil.untrust([nil])
def @encoding.to_s; self.join(nil); end
@cb_entry_class = Class.new(TkCallbackEntry){
class << self
def inspect
sprintf("#<Class(TkCallbackEntry):%0x>", self.__id__)
end
alias to_s inspect
end
def initialize(ip, cmd)
@ip = ip
@cmd = cmd
end
attr_reader :ip, :cmd
def call(*args)
@ip.cb_eval(@cmd, *args)
end
def inspect
sprintf("#<cb_entry:%0x>", self.__id__)
end
alias to_s inspect
}.freeze
}
def INTERP.cb_entry_class
@cb_entry_class
end
def INTERP.tk_cmd_tbl
@tk_cmd_tbl
end
def INTERP.tk_windows
@tk_windows
end
class Tk_OBJECT_TABLE
def initialize(id)
@id = id
@mutex = Mutex.new
end
def mutex
@mutex
end
def method_missing(m, *args, &b)
TkCore::INTERP.tk_object_table(@id).__send__(m, *args, &b)
end
end
def INTERP.tk_object_table(id)
@tk_table_list[id]
end
def INTERP.create_table
id = @tk_table_list.size
(tbl = {}).tainted? || TkUtil.untrust(tbl)
@tk_table_list << tbl
# obj = Object.new
# obj.instance_eval <<-EOD
# def self.method_missing(m, *args)
# TkCore::INTERP.tk_object_table(#{id}).send(m, *args)
# end
# EOD
# return obj
Tk_OBJECT_TABLE.new(id)
end
def INTERP.get_cb_entry(cmd)
@cb_entry_class.new(__getip, cmd).freeze
end
def INTERP.cb_eval(cmd, *args)
TkUtil._get_eval_string(TkUtil.eval_cmd(cmd, *args))
end
def INTERP.init_ip_env(script = Proc.new)
@init_ip_env << script
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, '')
self.__invoke__('rename', name, '')
}
end
def INTERP.init_ip_internal
ip = self
@init_ip_env.each{|script| script.call(ip)}
@add_tk_procs.each{|name,args,body| ip._invoke('proc',name,args,body)}
end
end
unless self.const_defined? :RUN_EVENTLOOP_ON_MAIN_THREAD
### Ruby 1.9 !!!!!!!!!!!!!!!!!!!!!!!!!!
RUN_EVENTLOOP_ON_MAIN_THREAD = false
end
WIDGET_DESTROY_HOOK = '<WIDGET_DESTROY_HOOK>'
INTERP._invoke_without_enc('event', 'add',
"<#{WIDGET_DESTROY_HOOK}>", '<Destroy>')
INTERP._invoke_without_enc('bind', 'all', "<#{WIDGET_DESTROY_HOOK}>",
install_cmd(proc{|path|
unless TkCore::INTERP.deleted?
begin
if (widget=TkCore::INTERP.tk_windows[path])
if widget.respond_to?(:__destroy_hook__)
widget.__destroy_hook__
end
end
rescue Exception=>e
p e if $DEBUG
end
end
}) << ' %W')
INTERP.add_tk_procs(TclTkLib::FINALIZE_PROC_NAME, '',
"catch { bind all <#{WIDGET_DESTROY_HOOK}> {} }")
INTERP.add_tk_procs('rb_out', 'ns args', <<-'EOL')
if [regexp {^::} $ns] {
set cmd {namespace eval $ns {ruby_cmd TkCore callback} $args}
} else {
set cmd {eval {ruby_cmd TkCore callback} $ns $args}
}
if {[set st [catch $cmd ret]] != 0} {
#return -code $st $ret
set idx [string first "\n\n" $ret]
if {$idx > 0} {
return -code $st \
-errorinfo [string range $ret [expr $idx + 2] \
[string length $ret]] \
[string range $ret 0 [expr $idx - 1]]
} else {
return -code $st $ret
}
} else {
return $ret
}
EOL
=begin
INTERP.add_tk_procs('rb_out', 'args', <<-'EOL')
if {[set st [catch {eval {ruby_cmd TkCore callback} $args} ret]] != 0} {
#return -code $st $ret
set idx [string first "\n\n" $ret]
if {$idx > 0} {
return -code $st \
-errorinfo [string range $ret [expr $idx + 2] \
[string length $ret]] \
[string range $ret 0 [expr $idx - 1]]
} else {
return -code $st $ret
}
} else {
return $ret
}
EOL
=end
=begin
INTERP.add_tk_procs('rb_out', 'args', <<-'EOL')
#regsub -all {\\} $args {\\\\} args
#regsub -all {!} $args {\\!} args
#regsub -all "{" $args "\\{" args
regsub -all {(\\|!|\{|\})} $args {\\\1} args
if {[set st [catch {ruby [format "TkCore.callback %%Q!%s!" $args]} ret]] != 0} {
#return -code $st $ret
set idx [string first "\n\n" $ret]
if {$idx > 0} {
return -code $st \
-errorinfo [string range $ret [expr $idx + 2] \
[string length $ret]] \
[string range $ret 0 [expr $idx - 1]]
} else {
return -code $st $ret
}
} else {
return $ret
}
EOL
=end
if !WITH_RUBY_VM || RUN_EVENTLOOP_ON_MAIN_THREAD ### check Ruby 1.9 !!!!!!!
at_exit{ INTERP.remove_tk_procs(TclTkLib::FINALIZE_PROC_NAME) }
else
at_exit{
Tk.root.destroy
INTERP.remove_tk_procs(TclTkLib::FINALIZE_PROC_NAME)
INTERP_THREAD.kill.join
}
end
EventFlag = TclTkLib::EventFlag
def callback_break
fail TkCallbackBreak, "Tk callback returns 'break' status"
end
def callback_continue
fail TkCallbackContinue, "Tk callback returns 'continue' status"
end
def callback_return
fail TkCallbackReturn, "Tk callback returns 'return' status"
end
def TkCore.callback(*arg)
begin
if TkCore::INTERP.tk_cmd_tbl.kind_of?(Hash)
#TkCore::INTERP.tk_cmd_tbl[arg.shift].call(*arg)
normal_ret = false
ret = catch(:IRB_EXIT) do # IRB hack
retval = TkCore::INTERP.tk_cmd_tbl[arg.shift].call(*arg)
normal_ret = true
retval
end
unless normal_ret
# catch IRB_EXIT
exit(ret)
end
ret
end
rescue SystemExit=>e
exit(e.status)
rescue Interrupt=>e
fail(e)
rescue Exception => e
begin
msg = _toUTF8(e.class.inspect) + ': ' +
_toUTF8(e.message) + "\n" +
"\n---< backtrace of Ruby side >-----\n" +
_toUTF8(e.backtrace.join("\n")) +
"\n---< backtrace of Tk side >-------"
if TkCore::WITH_ENCODING
msg.force_encoding('utf-8')
else
msg.instance_variable_set(:@encoding, 'utf-8')
end
rescue Exception
msg = e.class.inspect + ': ' + e.message + "\n" +
"\n---< backtrace of Ruby side >-----\n" +
e.backtrace.join("\n") +
"\n---< backtrace of Tk side >-------"
end
# TkCore::INTERP._set_global_var('errorInfo', msg)
# fail(e)
fail(e, msg)
end
end
=begin
def TkCore.callback(arg_str)
# arg = tk_split_list(arg_str)
arg = tk_split_simplelist(arg_str)
#_get_eval_string(TkUtil.eval_cmd(Tk_CMDTBL[arg.shift], *arg))
#_get_eval_string(TkUtil.eval_cmd(TkCore::INTERP.tk_cmd_tbl[arg.shift],
# *arg))
# TkCore::INTERP.tk_cmd_tbl[arg.shift].call(*arg)
begin
TkCore::INTERP.tk_cmd_tbl[arg.shift].call(*arg)
rescue Exception => e
raise(e, e.class.inspect + ': ' + e.message + "\n" +
"\n---< backtrace of Ruby side >-----\n" +
e.backtrace.join("\n") +
"\n---< backtrace of Tk side >-------")
end
#=begin
# cb_obj = TkCore::INTERP.tk_cmd_tbl[arg.shift]
# unless $DEBUG
# cb_obj.call(*arg)
# else
# begin
# raise 'check backtrace'
# rescue
# # ignore backtrace before 'callback'
# pos = -($!.backtrace.size)
# end
# begin
# cb_obj.call(*arg)
# rescue
# trace = $!.backtrace
# raise $!, "\n#{trace[0]}: #{$!.message} (#{$!.class})\n" +
# "\tfrom #{trace[1..pos].join("\n\tfrom ")}"
# end
# end
#=end
end
=end
def load_cmd_on_ip(tk_cmd)
bool(tk_call('auto_load', tk_cmd))
end
def after(ms, cmd=Proc.new)
cmdid = install_cmd(proc{ret = cmd.call;uninstall_cmd(cmdid); ret})
after_id = tk_call_without_enc("after",ms,cmdid)
after_id.instance_variable_set('@cmdid', cmdid)
after_id
end
=begin
def after(ms, cmd=Proc.new)
crit_bup = Thread.critical
Thread.critical = true
myid = _curr_cmd_id
cmdid = install_cmd(proc{ret = cmd.call;uninstall_cmd(myid); ret})
Thread.critical = crit_bup
tk_call_without_enc("after",ms,cmdid) # return id
# return
# if false #defined? Thread
# Thread.start do
# ms = Float(ms)/1000
# ms = 10 if ms == 0
# sleep ms/1000
# cmd.call
# end
# else
# cmdid = install_cmd(cmd)
# tk_call("after",ms,cmdid)
# end
end
=end
def after_idle(cmd=Proc.new)
cmdid = install_cmd(proc{ret = cmd.call;uninstall_cmd(cmdid); ret})
after_id = tk_call_without_enc('after','idle',cmdid)
after_id.instance_variable_set('@cmdid', cmdid)
after_id
end
=begin
def after_idle(cmd=Proc.new)
crit_bup = Thread.critical
Thread.critical = true
myid = _curr_cmd_id
cmdid = install_cmd(proc{ret = cmd.call;uninstall_cmd(myid); ret})
Thread.critical = crit_bup
tk_call_without_enc('after','idle',cmdid)
end
=end
def after_cancel(afterId)
tk_call_without_enc('after','cancel',afterId)
if (cmdid = afterId.instance_variable_get('@cmdid'))
afterId.instance_variable_set('@cmdid', nil)
uninstall_cmd(cmdid)
end
afterId
end
def windowingsystem
tk_call_without_enc('tk', 'windowingsystem')
end
def scaling(scale=nil)
if scale
tk_call_without_enc('tk', 'scaling', scale)
else
Float(number(tk_call_without_enc('tk', 'scaling')))
end
end
def scaling_displayof(win, scale=nil)
if scale
tk_call_without_enc('tk', 'scaling', '-displayof', win, scale)
else
Float(number(tk_call_without_enc('tk', '-displayof', win, 'scaling')))
end
end
def inactive
Integer(tk_call_without_enc('tk', 'inactive'))
end
def inactive_displayof(win)
Integer(tk_call_without_enc('tk', 'inactive', '-displayof', win))
end
def reset_inactive
tk_call_without_enc('tk', 'inactive', 'reset')
end
def reset_inactive_displayof(win)
tk_call_without_enc('tk', 'inactive', '-displayof', win, 'reset')
end
def appname(name=None)
tk_call('tk', 'appname', name)
end
def appsend_deny
tk_call('rename', 'send', '')
end
def appsend(interp, async, *args)
if $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
tk_call('send', '--', interp, *args)
end
end
def rb_appsend(interp, async, *args)
if $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('}.call)"')
appsend(interp, async, 'ruby "TkComm._get_eval_string(proc{', *args)
end
def appsend_displayof(interp, win, async, *args)
if $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
tk_call('send', '-displayor', win, '--', interp, *args)
end
end
def rb_appsend_displayof(interp, win, async, *args)
if $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('}.call)"')
appsend(interp, win, async, 'ruby "TkComm._get_eval_string(proc{', *args)
end
def info(*args)
tk_call('info', *args)
end
def mainloop(check_root = true)
if !TkCore::WITH_RUBY_VM
TclTkLib.mainloop(check_root)
elsif TkCore::RUN_EVENTLOOP_ON_MAIN_THREAD
# if TclTkLib::WINDOWING_SYSTEM == 'aqua' &&
#if TkCore::INTERP._invoke_without_enc('tk','windowingsystem')=='aqua' &&
# Thread.current != Thread.main &&
# (TclTkLib.get_version <=> [8,4,TclTkLib::RELEASE_TYPE::FINAL,9]) > 0
# raise RuntimeError,
# "eventloop on TkAqua ( > Tk8.4.9 ) works on the main thread only"
#end
if Thread.current != Thread.main
raise RuntimeError, "Tk.mainloop is allowed on the main thread only"
end
TclTkLib.mainloop(check_root)
else ### Ruby 1.9 !!!!!
unless TkCore::INTERP.default_master?
# [MultiTkIp] slave interp ?
return TkCore::INTERP._thread_tkwait('window', '.') if check_root
end
# like as 1.8, withdraw a root widget before calling Tk.mainloop
TkCore::INTERP._eval_without_enc('catch {unset __initial_state_of_rubytk__}')
INTERP_THREAD.run
begin
TclTkLib.set_eventloop_window_mode(true)
# force run the eventloop
TkCore::INTERP._eval_without_enc('update')
TkCore::INTERP._eval_without_enc('catch {set __initial_state_of_rubytk__}')
INTERP_THREAD.run
if check_root
INTERP_MUTEX.synchronize{
INTERP_ROOT_CHECK.wait(INTERP_MUTEX)
status = INTERP_THREAD_STATUS.value
if status && TkCore::INTERP.default_master?
INTERP_THREAD_STATUS.value = nil
raise status if status.kind_of?(Exception)
end
}
else
# INTERP_THREAD.value
begin
INTERP_THREAD.value
rescue Exception => e
raise e
end
end
rescue Exception => e
raise e
ensure
TclTkLib.set_eventloop_window_mode(false)
end
end
end
def mainloop_thread?
# true : current thread is mainloop
# nil : there is no mainloop
# false : mainloop is running on the other thread
# ( At then, it is dangerous to call Tk interpreter directly. )
if !TkCore::WITH_RUBY_VM || TkCore::RUN_EVENTLOOP_ON_MAIN_THREAD
### Ruby 1.9 !!!!!!!!!!!
TclTkLib.mainloop_thread?
else
Thread.current == INTERP_THREAD
end
end
def mainloop_exist?
TclTkLib.mainloop_thread? != nil
end
def is_mainloop?
TclTkLib.mainloop_thread? == true
end
def mainloop_watchdog(check_root = true)
# watchdog restarts mainloop when mainloop is dead
TclTkLib.mainloop_watchdog(check_root)
end
def do_one_event(flag = TclTkLib::EventFlag::ALL)
TclTkLib.do_one_event(flag)
end
def set_eventloop_tick(timer_tick)
TclTkLib.set_eventloop_tick(timer_tick)
end
def get_eventloop_tick()
TclTkLib.get_eventloop_tick
end
def set_no_event_wait(wait)
TclTkLib.set_no_even_wait(wait)
end
def get_no_event_wait()
TclTkLib.get_no_eventloop_wait
end
def set_eventloop_weight(loop_max, no_event_tick)
TclTkLib.set_eventloop_weight(loop_max, no_event_tick)
end
def get_eventloop_weight()
TclTkLib.get_eventloop_weight
end
def restart(app_name = nil, keys = {})
TkCore::INTERP.init_ip_internal
tk_call('set', 'argv0', app_name) if app_name
if keys.kind_of?(Hash)
# tk_call('set', 'argc', keys.size * 2)
tk_call('set', 'argv', hash_kv(keys).join(' '))
end
INTERP.restart
nil
end
def event_generate(win, context, keys=nil)
#win = win.path if win.kind_of?(TkObject)
if context.kind_of?(TkEvent::Event)
context.generate(win, ((keys)? keys: {}))
elsif keys
tk_call_without_enc('event', 'generate', win,
"<#{tk_event_sequence(context)}>",
*hash_kv(keys, true))
else
tk_call_without_enc('event', 'generate', win,
"<#{tk_event_sequence(context)}>")
end
nil
end
def messageBox(keys)
tk_call('tk_messageBox', *hash_kv(keys))
end
def getOpenFile(keys = nil)
tk_call('tk_getOpenFile', *hash_kv(keys))
end
def getMultipleOpenFile(keys = nil)
simplelist(tk_call('tk_getOpenFile', '-multiple', '1', *hash_kv(keys)))
end
def getSaveFile(keys = nil)
tk_call('tk_getSaveFile', *hash_kv(keys))
end
def getMultipleSaveFile(keys = nil)
simplelist(tk_call('tk_getSaveFile', '-multiple', '1', *hash_kv(keys)))
end
def chooseColor(keys = nil)
tk_call('tk_chooseColor', *hash_kv(keys))
end
def chooseDirectory(keys = nil)
tk_call('tk_chooseDirectory', *hash_kv(keys))
end
def _ip_eval_core(enc_mode, cmd_string)
case enc_mode
when nil
res = INTERP._eval(cmd_string)
when false
res = INTERP._eval_without_enc(cmd_string)
when true
res = INTERP._eval_with_enc(cmd_string)
end
if INTERP._return_value() != 0
fail RuntimeError, res, error_at
end
return res
end
private :_ip_eval_core
def ip_eval(cmd_string)
_ip_eval_core(nil, cmd_string)
end
def ip_eval_without_enc(cmd_string)
_ip_eval_core(false, cmd_string)
end
def ip_eval_with_enc(cmd_string)
_ip_eval_core(true, cmd_string)
end
def _ip_invoke_core(enc_mode, *args)
case enc_mode
when false
res = INTERP._invoke_without_enc(*args)
when nil
res = INTERP._invoke(*args)
when true
res = INTERP._invoke_with_enc(*args)
end
if INTERP._return_value() != 0
fail RuntimeError, res, error_at
end
return res
end
private :_ip_invoke_core
def ip_invoke(*args)
_ip_invoke_core(nil, *args)
end
def ip_invoke_without_enc(*args)
_ip_invoke_core(false, *args)
end
def ip_invoke_with_enc(*args)
_ip_invoke_core(true, *args)
end
def _tk_call_core(enc_mode, *args)
### puts args.inspect if $DEBUG
#args.collect! {|x|ruby2tcl(x, enc_mode)}
#args.compact!
#args.flatten!
args = _conv_args([], enc_mode, *args)
puts 'invoke args => ' + args.inspect if $DEBUG
### print "=> ", args.join(" ").inspect, "\n" if $DEBUG
begin
# res = TkUtil.untrust(INTERP._invoke(*args))
# res = INTERP._invoke(enc_mode, *args)
res = _ip_invoke_core(enc_mode, *args)
# >>>>> _invoke returns a TAINTED string <<<<<
rescue NameError => err
# err = $!
begin
args.unshift "unknown"
#res = TkUtil.untrust(INTERP._invoke(*args))
#res = INTERP._invoke(enc_mode, *args)
res = _ip_invoke_core(enc_mode, *args)
# >>>>> _invoke returns a TAINTED string <<<<<
rescue StandardError => err2
fail err2 unless /^invalid command/ =~ err2.message
fail err
end
end
if INTERP._return_value() != 0
fail RuntimeError, res, error_at
end
### print "==> ", res.inspect, "\n" if $DEBUG
return res
end
private :_tk_call_core
def tk_call(*args)
_tk_call_core(nil, *args)
end
def tk_call_without_enc(*args)
_tk_call_core(false, *args)
end
def tk_call_with_enc(*args)
_tk_call_core(true, *args)
end
def _tk_call_to_list_core(depth, arg_enc, val_enc, *args)
args = _conv_args([], arg_enc, *args)
val = _tk_call_core(false, *args)
if !depth.kind_of?(Integer) || depth == 0
tk_split_simplelist(val, false, val_enc)
else
tk_split_list(val, depth, false, val_enc)
end
end
#private :_tk_call_to_list_core
def tk_call_to_list(*args)
_tk_call_to_list_core(-1, nil, true, *args)
end
def tk_call_to_list_without_enc(*args)
_tk_call_to_list_core(-1, false, false, *args)
end
def tk_call_to_list_with_enc(*args)
_tk_call_to_list_core(-1, true, true, *args)
end
def tk_call_to_simplelist(*args)
_tk_call_to_list_core(0, nil, true, *args)
end
def tk_call_to_simplelist_without_enc(*args)
_tk_call_to_list_core(0, false, false, *args)
end
def tk_call_to_simplelist_with_enc(*args)
_tk_call_to_list_core(0, true, true, *args)
end
end
module Tk
include TkCore
extend Tk
TCL_VERSION = INTERP._invoke_without_enc("info", "tclversion").freeze
TCL_PATCHLEVEL = INTERP._invoke_without_enc("info", "patchlevel").freeze
major, minor = TCL_VERSION.split('.')
TCL_MAJOR_VERSION = major.to_i
TCL_MINOR_VERSION = minor.to_i
TK_VERSION = INTERP._invoke_without_enc("set", "tk_version").freeze
TK_PATCHLEVEL = INTERP._invoke_without_enc("set", "tk_patchLevel").freeze
major, minor = TK_VERSION.split('.')
TK_MAJOR_VERSION = major.to_i
TK_MINOR_VERSION = minor.to_i
JAPANIZED_TK = (INTERP._invoke_without_enc("info", "commands",
"kanji") != "").freeze
def Tk.const_missing(sym)
case(sym)
when :TCL_LIBRARY
INTERP._invoke_without_enc('global', 'tcl_library')
INTERP._invoke("set", "tcl_library").freeze
when :TK_LIBRARY
INTERP._invoke_without_enc('global', 'tk_library')
INTERP._invoke("set", "tk_library").freeze
when :LIBRARY
INTERP._invoke("info", "library").freeze
#when :PKG_PATH, :PACKAGE_PATH, :TCL_PACKAGE_PATH
# INTERP._invoke_without_enc('global', 'tcl_pkgPath')
# tk_split_simplelist(INTERP._invoke('set', 'tcl_pkgPath'))
#when :LIB_PATH, :LIBRARY_PATH, :TCL_LIBRARY_PATH
# INTERP._invoke_without_enc('global', 'tcl_libPath')
# tk_split_simplelist(INTERP._invoke('set', 'tcl_libPath'))
when :PLATFORM, :TCL_PLATFORM
INTERP._invoke_without_enc('global', 'tcl_platform')
Hash[*tk_split_simplelist(INTERP._invoke_without_enc('array', 'get',
'tcl_platform'))]
when :ENV
INTERP._invoke_without_enc('global', 'env')
Hash[*tk_split_simplelist(INTERP._invoke('array', 'get', 'env'))]
#when :AUTO_PATH #<===
# tk_split_simplelist(INTERP._invoke('set', 'auto_path'))
#when :AUTO_OLDPATH
# tk_split_simplelist(INTERP._invoke('set', 'auto_oldpath'))
when :AUTO_INDEX
INTERP._invoke_without_enc('global', 'auto_index')
Hash[*tk_split_simplelist(INTERP._invoke('array', 'get', 'auto_index'))]
when :PRIV, :PRIVATE, :TK_PRIV
priv = {}
if INTERP._invoke_without_enc('info', 'vars', 'tk::Priv') != ""
var_nam = 'tk::Priv'
else
var_nam = 'tkPriv'
end
INTERP._invoke_without_enc('global', var_nam)
Hash[*tk_split_simplelist(INTERP._invoke('array', 'get',
var_nam))].each{|k,v|
k.freeze
case v
when /^-?\d+$/
priv[k] = v.to_i
when /^-?\d+\.?\d*(e[-+]?\d+)?$/
priv[k] = v.to_f
else
priv[k] = v.freeze
end
}
priv
else
raise NameError, 'uninitialized constant Tk::' + sym.id2name
end
end
def Tk.errorInfo
INTERP._invoke_without_enc('global', 'errorInfo')
INTERP._invoke_without_enc('set', 'errorInfo')
end
def Tk.errorCode
INTERP._invoke_without_enc('global', 'errorCode')
code = tk_split_simplelist(INTERP._invoke_without_enc('set', 'errorCode'))
case code[0]
when 'CHILDKILLED', 'CHILDSTATUS', 'CHILDSUSP'
begin
pid = Integer(code[1])
code[1] = pid
rescue
end
end
code
end
def Tk.has_mainwindow?
INTERP.has_mainwindow?
end
def root
Tk::Root.new
end
def Tk.load_tclscript(file, enc=nil)
if enc
# TCL_VERSION >= 8.5
tk_call('source', '-encoding', enc, file)
else
tk_call('source', file)
end
end
def Tk.load_tcllibrary(file, pkg_name=None, interp=None)
tk_call('load', file, pkg_name, interp)
end
def Tk.unload_tcllibrary(*args)
if args[-1].kind_of?(Hash)
keys = _symbolkey2str(args.pop)
nocomp = (keys['nocomplain'])? '-nocomplain': None
keeplib = (keys['keeplibrary'])? '-keeplibrary': None
tk_call('unload', nocomp, keeplib, '--', *args)
else
tk_call('unload', *args)
end
end
def Tk.pkgconfig_list(mod)
# Tk8.5 feature
if mod.kind_of?(Module)
if mod.respond_to?(:package_name)
pkgname = mod.package_name
elsif mod.const_defined?(:PACKAGE_NAME)
pkgname = mod::PACKAGE_NAME
else
fail NotImplementedError, 'may not be a module for a Tcl extension'
end
else
pkgname = mod.to_s
end
pkgname = '::' << pkgname unless pkgname =~ /^::/
tk_split_list(tk_call(pkgname + '::pkgconfig', 'list'))
end
def Tk.pkgconfig_get(mod, key)
# Tk8.5 feature
if mod.kind_of?(Module)
if mod.respond_to?(:package_name)
pkgname = mod.package_name
else
fail NotImplementedError, 'may not be a module for a Tcl extension'
end
else
pkgname = mod.to_s
end
pkgname = '::' << pkgname unless pkgname =~ /^::/
tk_call(pkgname + '::pkgconfig', 'get', key)
end
def Tk.tcl_pkgconfig_list
# Tk8.5 feature
Tk.pkgconfig_list('::tcl')
end
def Tk.tcl_pkgconfig_get(key)
# Tk8.5 feature
Tk.pkgconfig_get('::tcl', key)
end
def Tk.tk_pkgconfig_list
# Tk8.5 feature
Tk.pkgconfig_list('::tk')
end
def Tk.tk_pkgconfig_get(key)
# Tk8.5 feature
Tk.pkgconfig_get('::tk', key)
end
def Tk.bell(nice = false)
if nice
tk_call_without_enc('bell', '-nice')
else
tk_call_without_enc('bell')
end
nil
end
def Tk.bell_on_display(win, nice = false)
if nice
tk_call_without_enc('bell', '-displayof', win, '-nice')
else
tk_call_without_enc('bell', '-displayof', win)
end
nil
end
def Tk.destroy(*wins)
#tk_call_without_enc('destroy', *wins)
tk_call_without_enc('destroy', *(wins.collect{|win|
if win.kind_of?(TkWindow)
win.epath
else
win
end
}))
end
def Tk.exit
TkCore::INTERP.has_mainwindow? && tk_call_without_enc('destroy', '.')
end
################################################
def Tk.sleep(ms = nil, id = nil)
if id
var = (id.kind_of?(TkVariable))? id: TkVarAccess.new(id.to_s)
else
var = TkVariable.new
end
var.value = tk_call_without_enc('after', ms, proc{ var.value = 0 }) if ms
var.thread_wait
ms
end
def Tk.wakeup(id)
((id.kind_of?(TkVariable))? id: TkVarAccess.new(id.to_s)).value = 0
nil
end
################################################
def Tk.pack(*args)
TkPack.configure(*args)
end
def Tk.pack_forget(*args)
TkPack.forget(*args)
end
def Tk.unpack(*args)
TkPack.forget(*args)
end
def Tk.grid(*args)
TkGrid.configure(*args)
end
def Tk.grid_forget(*args)
TkGrid.forget(*args)
end
def Tk.ungrid(*args)
TkGrid.forget(*args)
end
def Tk.place(*args)
TkPlace.configure(*args)
end
def Tk.place_forget(*args)
TkPlace.forget(*args)
end
def Tk.unplace(*args)
TkPlace.forget(*args)
end
def Tk.update(idle=nil)
if idle
tk_call_without_enc('update', 'idletasks')
else
tk_call_without_enc('update')
end
end
def Tk.update_idletasks
update(true)
end
def update(idle=nil)
# only for backward compatibility (This never be recommended to use)
Tk.update(idle)
self
end
# NOTE::
# If no eventloop-thread is running, "thread_update" method is same
# to "update" method. Else, "thread_update" method waits to complete
# idletask operation on the eventloop-thread.
def Tk.thread_update(idle=nil)
if idle
tk_call_without_enc('thread_update', 'idletasks')
else
tk_call_without_enc('thread_update')
end
end
def Tk.thread_update_idletasks
thread_update(true)
end
def Tk.lower_window(win, below=None)
tk_call('lower', _epath(win), _epath(below))
nil
end
def Tk.raise_window(win, above=None)
tk_call('raise', _epath(win), _epath(above))
nil
end
def Tk.current_grabs(win = nil)
if win
window(tk_call_without_enc('grab', 'current', win))
else
tk_split_list(tk_call_without_enc('grab', 'current'))
end
end
def Tk.focus(display=nil)
if display == nil
window(tk_call_without_enc('focus'))
else
window(tk_call_without_enc('focus', '-displayof', display))
end
end
def Tk.focus_to(win, force=false)
if force
tk_call_without_enc('focus', '-force', win)
else
tk_call_without_enc('focus', win)
end
end
def Tk.focus_lastfor(win)
window(tk_call_without_enc('focus', '-lastfor', win))
end
def Tk.focus_next(win)
TkManageFocus.next(win)
end
def Tk.focus_prev(win)
TkManageFocus.prev(win)
end
def Tk.strictMotif(mode=None)
bool(tk_call_without_enc('set', 'tk_strictMotif', mode))
end
def Tk.show_kinsoku(mode='both')
begin
if /^8\.*/ === TK_VERSION && JAPANIZED_TK
tk_split_simplelist(tk_call('kinsoku', 'show', mode))
end
rescue
end
end
def Tk.add_kinsoku(chars, mode='both')
begin
if /^8\.*/ === TK_VERSION && JAPANIZED_TK
tk_split_simplelist(tk_call('kinsoku', 'add', mode,
*(chars.split(''))))
else
[]
end
rescue
[]
end
end
def Tk.delete_kinsoku(chars, mode='both')
begin
if /^8\.*/ === TK_VERSION && JAPANIZED_TK
tk_split_simplelist(tk_call('kinsoku', 'delete', mode,
*(chars.split(''))))
end
rescue
end
end
def Tk.toUTF8(str, encoding = nil)
_toUTF8(str, encoding)
end
def Tk.fromUTF8(str, encoding = nil)
_fromUTF8(str, encoding)
end
end
###########################################
# string with Tcl's encoding
###########################################
module Tk
def Tk.subst_utf_backslash(str)
Tk::EncodedString.subst_utf_backslash(str)
end
def Tk.subst_tk_backslash(str)
Tk::EncodedString.subst_tk_backslash(str)
end
def Tk.utf_to_backslash_sequence(str)
Tk::EncodedString.utf_to_backslash_sequence(str)
end
def Tk.utf_to_backslash(str)
Tk::EncodedString.utf_to_backslash_sequence(str)
end
def Tk.to_backslash_sequence(str)
Tk::EncodedString.to_backslash_sequence(str)
end
end
###########################################
# convert kanji string to/from utf-8
###########################################
if (/^(8\.[1-9]|9\.|[1-9][0-9])/ =~ Tk::TCL_VERSION && !Tk::JAPANIZED_TK)
module Tk
module Encoding
extend Encoding
TkCommandNames = ['encoding'.freeze].freeze
#############################################
if TkCore::WITH_ENCODING ### Ruby 1.9
RubyEncoding = ::Encoding
# for saving GC cost
#ENCNAMES_CMD = ['encoding'.freeze, 'names'.freeze]
BINARY_NAME = 'binary'.freeze
UTF8_NAME = 'utf-8'.freeze
DEFAULT_EXTERNAL_NAME = RubyEncoding.default_external.name.freeze
DEFAULT_INTERNAL_NAME = RubyEncoding.default_internal.name.freeze rescue nil
BINARY = RubyEncoding.find(BINARY_NAME)
UNKNOWN = RubyEncoding.find('ASCII-8BIT')
### start of creating ENCODING_TABLE
ENCODING_TABLE = TkCore::INTERP.encoding_table
=begin
ENCODING_TABLE = {
'binary' => BINARY,
# 'UNKNOWN-8BIT' => UNKNOWN,
}
list = TkCore::INTERP._invoke_without_enc(ENCNAMES_CMD[0],
ENCNAMES_CMD[1])
TkCore::INTERP._split_tklist(list).each{|name|
begin
enc = RubyEncoding.find(name)
rescue ArgumentError
case name
when 'identity'
enc = BINARY
when 'shiftjis'
enc = RubyEncoding.find('Shift_JIS')
when 'unicode'
enc = RubyEncoding.find('UTF-8')
#if Tk.tk_call('set', 'tcl_platform(byteOrder)') =='littleEndian'
# enc = RubyEncoding.find('UTF-16LE')
#else
# enc = RubyEncoding.find('UTF-16BE')
#end
when 'symbol'
# single byte data
enc = RubyEncoding.find('ASCII-8BIT') ### ???
else
# unsupported on Ruby, but supported on Tk
enc = TkCore::INTERP.create_dummy_encoding_for_tk(name)
end
end
ENCODING_TABLE[name.freeze] = enc
}
=end
=begin
def ENCODING_TABLE.get_name(enc)
orig_enc = enc
# unles enc, use system default
# 1st: Ruby/Tk default encoding
# 2nd: Tcl/Tk default encoding
# 3rd: Ruby's default_external
enc ||= TkCore::INTERP.encoding
enc ||= TclTkLib.encoding_system
enc ||= DEFAULT_EXTERNAL_NAME
if enc.kind_of?(RubyEncoding)
# Ruby's Encoding object
if (name = self.key(enc))
return name
end
# Is it new ?
list = TkCore::INTERP._invoke_without_enc(ENCNAMES_CMD[0],
ENCNAMES_CMD[1])
TkComm.simplelist(list).each{|name|
if ((enc == RubyEncoding.find(name)) rescue false)
# new relation!! update table
self[name.freeze] = enc
return name
end
}
else
# String or Symbol ?
if self[name = enc.to_s]
return name
end
# Is it new ?
if (enc_obj = (RubyEncoding.find(name) rescue false))
list = TkCore::INTERP._invoke_without_enc(ENCNAMES_CMD[0],
ENCNAMES_CMD[1])
if TkComm.simplelist(list).index(name)
# Tk's encoding name ?
self[name.freeze] = enc_obj # new relation!! update table
return name
else
# Ruby's encoding name ?
if (name = self.key(enc_obj))
return name
end
end
end
end
fail ArgumentError, "unsupported Tk encoding '#{orig_enc}'"
end
def ENCODING_TABLE.get_obj(enc)
# returns the encoding object.
# If 'enc' is the encoding name on Tk only, it returns nil.
((obj = self[self.get_name(enc)]).kind_of?(RubyEncoding))? obj: nil
end
=end
### end of creating ENCODING_TABLE
end
#############################################
if TkCore::WITH_ENCODING
################################
### Ruby 1.9
################################
def force_default_encoding(mode)
TkCore::INTERP.force_default_encoding = mode
end
def force_default_encoding?
TkCore::INTERP.force_default_encoding?
end
def default_encoding=(enc)
TkCore::INTERP.default_encoding = Tk::Encoding::ENCODING_TABLE.get_name(enc)
end
def encoding=(enc)
TkCore::INTERP.encoding = Tk::Encoding::ENCODING_TABLE.get_name(enc)
end
def encoding_name
Tk::Encoding::ENCODING_TABLE.get_name(TkCore::INTERP.encoding)
end
def encoding_obj
Tk::Encoding::ENCODING_TABLE.get_obj(TkCore::INTERP.encoding)
end
alias encoding encoding_name
alias default_encoding encoding_name
def tk_encoding_names
#TkComm.simplelist(TkCore::INTERP._invoke_without_enc(Tk::Encoding::ENCNAMES_CMD[0], Tk::Encoding::ENCNAMES_CMD[1]))
TkComm.simplelist(TkCore::INTERP._invoke_without_enc('encoding', 'names'))
end
def encoding_names
self.tk_encoding_names.find_all{|name|
Tk::Encoding::ENCODING_TABLE.get_name(name) rescue false
}
end
def encoding_objs
self.tk_encoding_names.map!{|name|
Tk::Encoding::ENCODING_TABLE.get_obj(name) rescue nil
}.compact
end
def encoding_system=(enc)
TclTkLib.encoding_system = Tk::Encoding::ENCODING_TABLE.get_name(enc)
end
def encoding_system_name
Tk::Encoding::ENCODING_TABLE.get_name(TclTkLib.encoding_system)
end
def encoding_system_obj
Tk::Encoding::ENCODING_TABLE.get_obj(TclTkLib.encoding_system)
end
alias encoding_system encoding_system_name
################################
else
################################
### Ruby 1.8-
################################
def force_default_encoding=(mode)
true
end
def force_default_encoding?
true
end
def default_encoding=(enc)
TkCore::INTERP.default_encoding = enc
end
def encoding=(enc)
TkCore::INTERP.encoding = enc
end
def encoding_obj
TkCore::INTERP.encoding
end
def encoding_name
TkCore::INTERP.encoding
end
alias encoding encoding_name
alias default_encoding encoding_name
def tk_encoding_names
TkComm.simplelist(Tk.tk_call('encoding', 'names'))
end
def encoding_objs
self.tk_encoding_names
end
def encoding_names
self.tk_encoding_names
end
def encoding_system=(enc)
TclTkLib.encoding_system = enc
end
def encoding_system_name
TclTkLib.encoding_system
end
def encoding_system_obj
TclTkLib.encoding_system
end
alias encoding_system encoding_system_name
################################
end
def encoding_convertfrom(str, enc=nil)
enc = encoding_system_name unless enc
str = str.dup
if TkCore::WITH_ENCODING
if str.kind_of?(Tk::EncodedString)
str.__instance_variable_set('@encoding', nil)
else
str.instance_variable_set('@encoding', nil)
end
str.force_encoding('binary')
else
str.instance_variable_set('@encoding', 'binary')
end
ret = TkCore::INTERP._invoke_without_enc('encoding', 'convertfrom',
enc, str)
if TkCore::WITH_ENCODING
ret.force_encoding('utf-8')
else
Tk::UTF8_String.new(ret)
end
ret
end
alias encoding_convert_from encoding_convertfrom
def encoding_convertto(str, enc=nil)
# str must be a UTF-8 string
enc = encoding_system_name unless enc
ret = TkCore::INTERP._invoke_without_enc('encoding', 'convertto',
enc, str)
#ret.instance_variable_set('@encoding', 'binary')
if TkCore::WITH_ENCODING
#ret.force_encoding(Tk::Encoding::ENCODING_TABLE.get_obj('binary'))
ret.force_encoding(Tk::Encoding::ENCODING_TABLE.get_obj(enc))
end
ret
end
alias encoding_convert_to encoding_convertto
def encoding_dirs
# Tcl8.5 feature
TkComm.simplelist(Tk.tk_call_without_enc('encoding', 'dirs'))
end
def encoding_dirs=(dir_list) # an array or a Tcl's list string
# Tcl8.5 feature
Tk.tk_call_without_enc('encoding', 'dirs', dir_list)
end
end
extend Encoding
end
class TclTkIp
def force_default_encoding=(mode)
@force_default_encoding[0] = (mode)? true: false
end
def force_default_encoding?
@force_default_encoding[0] ||= false
end
def default_encoding=(name)
name = name.name if Tk::WITH_ENCODING && name.kind_of?(::Encoding)
@encoding[0] = name.to_s.dup
end
# from tkencoding.rb by ttate@jaist.ac.jp
#attr_accessor :encoding
def encoding=(name)
self.force_default_encoding = true # for comaptibility
self.default_encoding = name
end
def encoding_name
(@encoding[0])? @encoding[0].dup: nil
end
alias encoding encoding_name
alias default_encoding encoding_name
def encoding_obj
if Tk::WITH_ENCODING
Tk::Encoding.tcl2rb_encoding(@encoding[0])
else
(@encoding[0])? @encoding[0].dup: nil
end
end
alias __toUTF8 _toUTF8
alias __fromUTF8 _fromUTF8
if Object.const_defined?(:Encoding) && ::Encoding.class == Class
# with Encoding (Ruby 1.9+)
#
# use functions on Tcl as default.
# but when unsupported encoding on Tcl, use methods on Ruby.
#
def _toUTF8(str, enc = nil)
if enc
# use given encoding
begin
enc_name = Tk::Encoding::ENCODING_TABLE.get_name(enc)
rescue
# unknown encoding for Tk -> try to convert encoding on Ruby
str = str.dup.force_encoding(enc)
str.encode!(Tk::Encoding::UTF8_NAME) # modify self !!
return str # if no error, probably succeed converting
end
end
enc_name ||= str.instance_variable_get(:@encoding)
enc_name ||=
Tk::Encoding::ENCODING_TABLE.get_name(str.encoding) rescue nil
if enc_name
# str has its encoding information
encstr = __toUTF8(str, enc_name)
encstr.force_encoding(Tk::Encoding::UTF8_NAME)
return encstr
else
# str.encoding isn't supported by Tk -> try to convert on Ruby
begin
return str.encode(Tk::Encoding::UTF8_NAME) # new string
rescue
# error -> ignore, try to use default encoding of Ruby/Tk
end
end
#enc_name ||=
# Tk::Encoding::ENCODING_TABLE.get_name(Tk.encoding) rescue nil
enc_name ||= Tk::Encoding::ENCODING_TABLE.get_name(nil)
# is 'binary' encoding?
if enc_name == Tk::Encoding::BINARY_NAME
return str.dup.force_encoding(Tk::Encoding::BINARY_NAME)
end
# force default encoding?
if ! str.kind_of?(Tk::EncodedString) && self.force_default_encoding?
enc_name = Tk::Encoding::ENCODING_TABLE.get_name(Tk.default_encoding)
end
encstr = __toUTF8(str, enc_name)
encstr.force_encoding(Tk::Encoding::UTF8_NAME)
encstr
end
def _fromUTF8(str, enc = nil)
# str must be UTF-8 or binary.
enc_name = str.instance_variable_get(:@encoding)
enc_name ||=
Tk::Encoding::ENCODING_TABLE.get_name(str.encoding) rescue nil
# is 'binary' encoding?
if enc_name == Tk::Encoding::BINARY_NAME
return str.dup.force_encoding(Tk::Encoding::BINARY_NAME)
end
# get target encoding name (if enc == nil, use default encoding)
begin
enc_name = Tk::Encoding::ENCODING_TABLE.get_name(enc)
rescue
# then, enc != nil
# unknown encoding for Tk -> try to convert encoding on Ruby
str = str.dup.force_encoding(Tk::Encoding::UTF8_NAME)
str.encode!(enc) # modify self !!
return str # if no error, probably succeed converting
end
encstr = __fromUTF8(str, enc_name)
encstr.force_encoding(Tk::Encoding::ENCODING_TABLE.get_obj(enc_name))
encstr
end
###
else
# without Encoding (Ruby 1.8)
def _toUTF8(str, encoding = nil)
__toUTF8(str, encoding)
end
def _fromUTF8(str, encoding = nil)
__fromUTF8(str, encoding)
end
###
end
alias __eval _eval
alias __invoke _invoke
def _eval(cmd)
_fromUTF8(__eval(_toUTF8(cmd)))
end
def _invoke(*cmds)
_fromUTF8(__invoke(*(cmds.collect{|cmd| _toUTF8(cmd)})))
end
alias _eval_with_enc _eval
alias _invoke_with_enc _invoke
=begin
#### --> definition is moved to TclTkIp module
def _toUTF8(str, encoding = nil)
# decide encoding
if encoding
encoding = encoding.to_s
elsif str.kind_of?(Tk::EncodedString) && str.encoding != nil
encoding = str.encoding.to_s
elsif str.instance_variable_get(:@encoding)
encoding = str.instance_variable_get(:@encoding).to_s
elsif defined?(@encoding) && @encoding != nil
encoding = @encoding.to_s
else
encoding = __invoke('encoding', 'system')
end
# convert
case encoding
when 'utf-8', 'binary'
str
else
__toUTF8(str, encoding)
end
end
def _fromUTF8(str, encoding = nil)
unless encoding
if defined?(@encoding) && @encoding != nil
encoding = @encoding.to_s
else
encoding = __invoke('encoding', 'system')
end
end
if str.kind_of?(Tk::EncodedString)
if str.encoding == 'binary'
str
else
__fromUTF8(str, encoding)
end
elsif str.instance_variable_get(:@encoding).to_s == 'binary'
str
else
__fromUTF8(str, encoding)
end
end
=end
=begin
def _eval(cmd)
if defined?(@encoding) && @encoding != 'utf-8'
ret = if cmd.kind_of?(Tk::EncodedString)
case cmd.encoding
when 'utf-8', 'binary'
__eval(cmd)
else
__eval(_toUTF8(cmd, cmd.encoding))
end
elsif cmd.instance_variable_get(:@encoding) == 'binary'
__eval(cmd)
else
__eval(_toUTF8(cmd, @encoding))
end
if ret.kind_of?(String) && ret.instance_variable_get(:@encoding) == 'binary'
ret
else
_fromUTF8(ret, @encoding)
end
else
__eval(cmd)
end
end
def _invoke(*cmds)
if defined?(@encoding) && @encoding != 'utf-8'
cmds = cmds.collect{|cmd|
if cmd.kind_of?(Tk::EncodedString)
case cmd.encoding
when 'utf-8', 'binary'
cmd
else
_toUTF8(cmd, cmd.encoding)
end
elsif cmd.instance_variable_get(:@encoding) == 'binary'
cmd
else
_toUTF8(cmd, @encoding)
end
}
ret = __invoke(*cmds)
if ret.kind_of?(String) && ret.instance_variable_get(:@encoding) == 'binary'
ret
else
_fromUTF8(ret, @encoding)
end
else
__invoke(*cmds)
end
end
=end
end
module TclTkLib
class << self
def force_default_encoding=(mode)
TkCore::INTERP.force_default_encoding = mode
end
def force_default_encoding?
TkCore::INTERP.force_default_encoding?
end
def default_encoding=(name)
TkCore::INTERP.default_encoding = name
end
alias _encoding encoding
alias _encoding= encoding=
def encoding=(name)
name = name.name if name.kind_of?(::Encoding) if Tk::WITH_ENCODING
TkCore::INTERP.encoding = name
end
def encoding_name
TkCore::INTERP.encoding
end
alias encoding encoding_name
alias default_encoding encoding_name
def encoding_obj
if Tk::WITH_ENCODING
Tk::Encoding.tcl2rb_encoding(TkCore::INTERP.encoding)
else
TkCore::INTERP.encoding
end
end
end
end
# estimate encoding
unless TkCore::WITH_ENCODING
case $KCODE
when /^e/i # EUC
Tk.encoding = 'euc-jp'
Tk.encoding_system = 'euc-jp'
when /^s/i # SJIS
begin
if Tk.encoding_system == 'cp932'
Tk.encoding = 'cp932'
else
Tk.encoding = 'shiftjis'
Tk.encoding_system = 'shiftjis'
end
rescue StandardError, NameError
Tk.encoding = 'shiftjis'
Tk.encoding_system = 'shiftjis'
end
when /^u/i # UTF8
Tk.encoding = 'utf-8'
Tk.encoding_system = 'utf-8'
else # NONE
if defined? DEFAULT_TK_ENCODING
Tk.encoding_system = DEFAULT_TK_ENCODING
end
begin
Tk.encoding = Tk.encoding_system
rescue StandardError, NameError
Tk.encoding = 'utf-8'
Tk.encoding_system = 'utf-8'
end
end
else ### Ruby 1.9 !!!!!!!!!!!!
# loc_enc_obj = (::Encoding.find(::Encoding.locale_charmap) rescue Tk::Encoding::UNKNOWN)
loc_enc_obj = ::Encoding.find("locale")
ext_enc_obj = ::Encoding.default_external
int_enc_obj = ::Encoding.default_internal || ext_enc_obj
tksys_enc_name = Tk::Encoding::ENCODING_TABLE.get_name(Tk.encoding_system)
# p [Tk.encoding, Tk.encoding_system, loc_enc_obj, ext_enc_obj]
=begin
if ext_enc_obj == Tk::Encoding::UNKNOWN
if defined? DEFAULT_TK_ENCODING
if DEFAULT_TK_ENCODING.kind_of?(::Encoding)
tk_enc_name = DEFAULT_TK_ENCODING.name
tksys_enc_name = DEFAULT_TK_ENCODING.name
else
tk_enc_name = DEFAULT_TK_ENCODING
tksys_enc_name = DEFAULT_TK_ENCODING
end
else
tk_enc_name = loc_enc_obj.name
tksys_enc_name = loc_enc_obj.name
end
else
tk_enc_name = ext_enc_obj.name
tksys_enc_name = ext_enc_obj.name
end
# Tk.encoding = tk_enc_name
Tk.default_encoding = tk_enc_name
Tk.encoding_system = tksys_enc_name
=end
if ext_enc_obj == Tk::Encoding::UNKNOWN
if loc_enc_obj == Tk::Encoding::UNKNOWN
# use Tk.encoding_system
else
# use locale_charmap
begin
loc_enc_name = Tk::Encoding::ENCODING_TABLE.get_name(loc_enc_obj)
if loc_enc_name && loc_enc_name != tksys_enc_name
# use locale_charmap
Tk.encoding_system = loc_enc_name
else
# use Tk.encoding_system
end
rescue ArgumentError
# unsupported encoding on Tk -> use Tk.encoding_system
end
end
else
begin
ext_enc_name = Tk::Encoding::ENCODING_TABLE.get_name(ext_enc_obj)
if ext_enc_name && ext_enc_name != tksys_enc_name
# use default_external
Tk.encoding_system = ext_enc_name
else
# use Tk.encoding_system
end
rescue ArgumentError
# unsupported encoding on Tk -> use Tk.encoding_system
end
end
# setup Tk.encoding
enc_name = nil
begin
default_def = DEFAULT_TK_ENCODING
if ::Encoding.find(default_def.to_s) != Tk::Encoding::UNKNOWN
enc_name = Tk::Encoding::ENCODING_TABLE.get_name(default_def)
end
rescue NameError
# ignore
enc_name = nil
rescue ArgumentError
enc_name = nil
fail ArgumentError,
"DEFAULT_TK_ENCODING has an unknown encoding #{default_def}"
end
unless enc_name
#if ext_enc_obj == Tk::Encoding::UNKNOWN
if int_enc_obj == Tk::Encoding::UNKNOWN
if loc_enc_obj == Tk::Encoding::UNKNOWN
# use Tk.encoding_system
enc_name = tksys_enc_name
else
# use locale_charmap
begin
loc_enc_name = Tk::Encoding::ENCODING_TABLE.get_name(loc_enc_obj)
if loc_enc_name
# use locale_charmap
enc_name = loc_enc_name
else
# use Tk.encoding_system
enc_name = tksys_enc_name
end
rescue ArgumentError
# unsupported encoding on Tk -> use Tk.encoding_system
enc_name = tksys_enc_name
end
end
else
begin
#ext_enc_name = Tk::Encoding::ENCODING_TABLE.get_name(ext_enc_obj)
#if ext_enc_name && ext_enc_name != tksys_enc_name
int_enc_name = Tk::Encoding::ENCODING_TABLE.get_name(int_enc_obj)
if int_enc_name
# use default_internal
enc_name = int_enc_name
else
# use Tk.encoding_system
enc_name = tksys_enc_name
end
rescue ArgumentError
# unsupported encoding on Tk -> use Tk.encoding_system
enc_name = tksys_enc_name
end
end
end
Tk.default_encoding = (enc_name)? enc_name: tksys_enc_name
end
else
# dummy methods
module Tk
module Encoding
extend Encoding
def force_default_encoding=(mode)
nil
end
def force_default_encoding?
nil
end
def default_encoding=(enc)
nil
end
def default_encoding
nil
end
def encoding=(name)
nil
end
def encoding
nil
end
def encoding_names
nil
end
def encoding_system
nil
end
def encoding_system=(enc)
nil
end
def encoding_convertfrom(str, enc=None)
str
end
alias encoding_convert_from encoding_convertfrom
def encoding_convertto(str, enc=None)
str
end
alias encoding_convert_to encoding_convertto
def encoding_dirs
nil
end
def encoding_dirs=(dir_array)
nil
end
end
extend Encoding
end
class TclTkIp
attr_accessor :encoding
alias __eval _eval
alias __invoke _invoke
alias _eval_with_enc _eval
alias _invoke_with_enc _invoke
end
end
module TkBindCore
#def bind(context, cmd=Proc.new, *args)
# Tk.bind(self, context, cmd, *args)
#end
def bind(context, *args)
# if args[0].kind_of?(Proc) || args[0].kind_of?(Method)
if TkComm._callback_entry?(args[0]) || !block_given?
cmd = args.shift
else
cmd = Proc.new
end
Tk.bind(self, context, cmd, *args)
end
#def bind_append(context, cmd=Proc.new, *args)
# Tk.bind_append(self, context, cmd, *args)
#end
def bind_append(context, *args)
# if args[0].kind_of?(Proc) || args[0].kind_of?(Method)
if TkComm._callback_entry?(args[0]) || !block_given?
cmd = args.shift
else
cmd = Proc.new
end
Tk.bind_append(self, context, cmd, *args)
end
def bind_remove(context)
Tk.bind_remove(self, context)
end
def bindinfo(context=nil)
Tk.bindinfo(self, context)
end
end
module TkTreatFont
def __font_optkeys
['font']
end
private :__font_optkeys
def __pathname
self.path
end
private :__pathname
################################
def font_configinfo(key = nil)
optkeys = __font_optkeys
if key && !optkeys.find{|opt| opt.to_s == key.to_s}
fail ArgumentError, "unknown font option name `#{key}'"
end
win, tag = __pathname.split(':')
if key
pathname = [win, tag, key].join(';')
TkFont.used_on(pathname) ||
TkFont.init_widget_font(pathname, *__confinfo_cmd)
elsif optkeys.size == 1
pathname = [win, tag, optkeys[0]].join(';')
TkFont.used_on(pathname) ||
TkFont.init_widget_font(pathname, *__confinfo_cmd)
else
fonts = {}
optkeys.each{|k|
k = k.to_s
pathname = [win, tag, k].join(';')
fonts[k] =
TkFont.used_on(pathname) ||
TkFont.init_widget_font(pathname, *__confinfo_cmd)
}
fonts
end
end
alias fontobj font_configinfo
def font_configure(slot)
pathname = __pathname
slot = _symbolkey2str(slot)
__font_optkeys.each{|optkey|
optkey = optkey.to_s
l_optkey = 'latin' << optkey
a_optkey = 'ascii' << optkey
k_optkey = 'kanji' << optkey
if slot.key?(optkey)
fnt = slot.delete(optkey)
if fnt.kind_of?(TkFont)
slot.delete(l_optkey)
slot.delete(a_optkey)
slot.delete(k_optkey)
fnt.call_font_configure([pathname, optkey], *(__config_cmd << {}))
next
else
if fnt
if (slot.key?(l_optkey) ||
slot.key?(a_optkey) ||
slot.key?(k_optkey))
fnt = TkFont.new(fnt)
lfnt = slot.delete(l_optkey)
lfnt = slot.delete(a_optkey) if slot.key?(a_optkey)
kfnt = slot.delete(k_optkey)
fnt.latin_replace(lfnt) if lfnt
fnt.kanji_replace(kfnt) if kfnt
fnt.call_font_configure([pathname, optkey],
*(__config_cmd << {}))
next
else
fnt = hash_kv(fnt) if fnt.kind_of?(Hash)
unless TkConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__
tk_call(*(__config_cmd << "-#{optkey}" << fnt))
else
begin
tk_call(*(__config_cmd << "-#{optkey}" << fnt))
rescue
# ignore
end
end
end
end
next
end
end
lfnt = slot.delete(l_optkey)
lfnt = slot.delete(a_optkey) if slot.key?(a_optkey)
kfnt = slot.delete(k_optkey)
if lfnt && kfnt
TkFont.new(lfnt, kfnt).call_font_configure([pathname, optkey],
*(__config_cmd << {}))
elsif lfnt
latinfont_configure([lfnt, optkey])
elsif kfnt
kanjifont_configure([kfnt, optkey])
end
}
# configure other (without font) options
tk_call(*(__config_cmd.concat(hash_kv(slot)))) if slot != {}
self
end
def latinfont_configure(ltn, keys=nil)
if ltn.kind_of?(Array)
key = ltn[1]
ltn = ltn[0]
else
key = nil
end
optkeys = __font_optkeys
if key && !optkeys.find{|opt| opt.to_s == key.to_s}
fail ArgumentError, "unknown font option name `#{key}'"
end
win, tag = __pathname.split(':')
optkeys = [key] if key
optkeys.each{|optkey|
optkey = optkey.to_s
pathname = [win, tag, optkey].join(';')
if (fobj = TkFont.used_on(pathname))
fobj = TkFont.new(fobj) # create a new TkFont object
elsif Tk::JAPANIZED_TK
fobj = fontobj # create a new TkFont object
else
ltn = hash_kv(ltn) if ltn.kind_of?(Hash)
unless TkConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__
tk_call(*(__config_cmd << "-#{optkey}" << ltn))
else
begin
tk_call(*(__config_cmd << "-#{optkey}" << ltn))
rescue => e
# ignore
end
end
next
end
if fobj.kind_of?(TkFont)
if ltn.kind_of?(TkFont)
conf = {}
ltn.latin_configinfo.each{|k,val| conf[k] = val}
if keys
fobj.latin_configure(conf.update(keys))
else
fobj.latin_configure(conf)
end
else
fobj.latin_replace(ltn)
end
end
fobj.call_font_configure([pathname, optkey], *(__config_cmd << {}))
}
self
end
alias asciifont_configure latinfont_configure
def kanjifont_configure(knj, keys=nil)
if knj.kind_of?(Array)
key = knj[1]
knj = knj[0]
else
key = nil
end
optkeys = __font_optkeys
if key && !optkeys.find{|opt| opt.to_s == key.to_s}
fail ArgumentError, "unknown font option name `#{key}'"
end
win, tag = __pathname.split(':')
optkeys = [key] if key
optkeys.each{|optkey|
optkey = optkey.to_s
pathname = [win, tag, optkey].join(';')
if (fobj = TkFont.used_on(pathname))
fobj = TkFont.new(fobj) # create a new TkFont object
elsif Tk::JAPANIZED_TK
fobj = fontobj # create a new TkFont object
else
knj = hash_kv(knj) if knj.kind_of?(Hash)
unless TkConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__
tk_call(*(__config_cmd << "-#{optkey}" << knj))
else
begin
tk_call(*(__config_cmd << "-#{optkey}" << knj))
rescue => e
# ignore
end
end
next
end
if fobj.kind_of?(TkFont)
if knj.kind_of?(TkFont)
conf = {}
knj.kanji_configinfo.each{|k,val| conf[k] = val}
if keys
fobj.kanji_configure(conf.update(keys))
else
fobj.kanji_configure(conf)
end
else
fobj.kanji_replace(knj)
end
end
fobj.call_font_configure([pathname, optkey], *(__config_cmd << {}))
}
self
end
def font_copy(win, wintag=nil, winkey=nil, targetkey=nil)
if wintag
if winkey
fnt = win.tagfontobj(wintag, winkey).dup
else
fnt = win.tagfontobj(wintag).dup
end
else
if winkey
fnt = win.fontobj(winkey).dup
else
fnt = win.fontobj.dup
end
end
if targetkey
fnt.call_font_configure([__pathname, targetkey], *(__config_cmd << {}))
else
fnt.call_font_configure(__pathname, *(__config_cmd << {}))
end
self
end
def latinfont_copy(win, wintag=nil, winkey=nil, targetkey=nil)
if targetkey
fontobj(targetkey).dup.call_font_configure([__pathname, targetkey],
*(__config_cmd << {}))
else
fontobj.dup.call_font_configure(__pathname, *(__config_cmd << {}))
end
if wintag
if winkey
fontobj.latin_replace(win.tagfontobj(wintag, winkey).latin_font_id)
else
fontobj.latin_replace(win.tagfontobj(wintag).latin_font_id)
end
else
if winkey
fontobj.latin_replace(win.fontobj(winkey).latin_font_id)
else
fontobj.latin_replace(win.fontobj.latin_font_id)
end
end
self
end
alias asciifont_copy latinfont_copy
def kanjifont_copy(win, wintag=nil, winkey=nil, targetkey=nil)
if targetkey
fontobj(targetkey).dup.call_font_configure([__pathname, targetkey],
*(__config_cmd << {}))
else
fontobj.dup.call_font_configure(__pathname, *(__config_cmd << {}))
end
if wintag
if winkey
fontobj.kanji_replace(win.tagfontobj(wintag, winkey).kanji_font_id)
else
fontobj.kanji_replace(win.tagfontobj(wintag).kanji_font_id)
end
else
if winkey
fontobj.kanji_replace(win.fontobj(winkey).kanji_font_id)
else
fontobj.kanji_replace(win.fontobj.kanji_font_id)
end
end
self
end
end
module TkConfigMethod
include TkUtil
include TkTreatFont
def TkConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__
@mode || false
end
def TkConfigMethod.__set_IGNORE_UNKNOWN_CONFIGURE_OPTION__!(mode)
@mode = (mode)? true: false
end
def __cget_cmd
[self.path, 'cget']
end
private :__cget_cmd
def __config_cmd
[self.path, 'configure']
end
private :__config_cmd
def __confinfo_cmd
__config_cmd
end
private :__confinfo_cmd
def __configinfo_struct
{:key=>0, :alias=>1, :db_name=>1, :db_class=>2,
:default_value=>3, :current_value=>4}
end
private :__configinfo_struct
def __optkey_aliases
{}
end
private :__optkey_aliases
def __numval_optkeys
[]
end
private :__numval_optkeys
def __numstrval_optkeys
[]
end
private :__numstrval_optkeys
def __boolval_optkeys
['exportselection', 'jump', 'setgrid', 'takefocus']
end
private :__boolval_optkeys
def __strval_optkeys
[
'text', 'label', 'show', 'data', 'file',
'activebackground', 'activeforeground', 'background',
'disabledforeground', 'disabledbackground', 'foreground',
'highlightbackground', 'highlightcolor', 'insertbackground',
'selectbackground', 'selectforeground', 'troughcolor'
]
end
private :__strval_optkeys
def __listval_optkeys
[]
end
private :__listval_optkeys
def __numlistval_optkeys
[]
end
private :__numlistval_optkeys
def __tkvariable_optkeys
['variable', 'textvariable']
end
private :__tkvariable_optkeys
def __val2ruby_optkeys # { key=>proc, ... }
# The method is used to convert a opt-value to a ruby's object.
# When get the value of the option "key", "proc.call(value)" is called.
{}
end
private :__val2ruby_optkeys
def __ruby2val_optkeys # { key=>proc, ... }
# The method is used to convert a ruby's object to a opt-value.
# When set the value of the option "key", "proc.call(value)" is called.
# That is, "-#{key} #{proc.call(value)}".
{}
end
private :__ruby2val_optkeys
def __methodcall_optkeys # { key=>method, ... }
# The method is used to both of get and set.
# Usually, the 'key' will not be a widget option.
{}
end
private :__methodcall_optkeys
def __keyonly_optkeys # { def_key=>undef_key or nil, ... }
{}
end
private :__keyonly_optkeys
def __conv_keyonly_opts(keys)
return keys unless keys.kind_of?(Hash)
keyonly = __keyonly_optkeys
keys2 = {}
keys.each{|k, v|
optkey = keyonly.find{|kk,vv| kk.to_s == k.to_s}
if optkey
defkey, undefkey = optkey
if v
keys2[defkey.to_s] = None
elsif undefkey
keys2[undefkey.to_s] = None
else
# remove key
end
else
keys2[k.to_s] = v
end
}
keys2
end
private :__conv_keyonly_opts
def config_hash_kv(keys, enc_mode = nil, conf = nil)
hash_kv(__conv_keyonly_opts(keys), enc_mode, conf)
end
################################
def [](id)
cget(id)
end
def []=(id, val)
configure(id, val)
val
end
def cget_tkstring(option)
opt = option.to_s
fail ArgumentError, "Invalid option `#{option.inspect}'" if opt.length == 0
tk_call_without_enc(*(__cget_cmd << "-#{opt}"))
end
def __cget_core(slot)
orig_slot = slot
slot = slot.to_s
if slot.length == 0
fail ArgumentError, "Invalid option `#{orig_slot.inspect}'"
end
alias_name, real_name = __optkey_aliases.find{|k, v| k.to_s == slot}
if real_name
slot = real_name.to_s
end
if ( method = _symbolkey2str(__val2ruby_optkeys())[slot] )
optval = tk_call_without_enc(*(__cget_cmd << "-#{slot}"))
begin
return method.call(optval)
rescue => e
warn("Warning:: #{e.message} (when #{method}.call(#{optval.inspect})") if $DEBUG
return optval
end
end
if ( method = _symbolkey2str(__methodcall_optkeys)[slot] )
return self.__send__(method)
end
case slot
when /^(#{__numval_optkeys.join('|')})$/
begin
number(tk_call_without_enc(*(__cget_cmd << "-#{slot}")))
rescue
nil
end
when /^(#{__numstrval_optkeys.join('|')})$/
num_or_str(tk_call_without_enc(*(__cget_cmd << "-#{slot}")))
when /^(#{__boolval_optkeys.join('|')})$/
begin
bool(tk_call_without_enc(*(__cget_cmd << "-#{slot}")))
rescue
nil
end
when /^(#{__listval_optkeys.join('|')})$/
simplelist(tk_call_without_enc(*(__cget_cmd << "-#{slot}")))
when /^(#{__numlistval_optkeys.join('|')})$/
conf = tk_call_without_enc(*(__cget_cmd << "-#{slot}"))
if conf =~ /^[0-9+-]/
list(conf)
else
conf
end
when /^(#{__strval_optkeys.join('|')})$/
_fromUTF8(tk_call_without_enc(*(__cget_cmd << "-#{slot}")))
when /^(|latin|ascii|kanji)(#{__font_optkeys.join('|')})$/
fontcode = $1
fontkey = $2
fnt = tk_tcl2ruby(tk_call_without_enc(*(__cget_cmd << "-#{fontkey}")), true)
unless fnt.kind_of?(TkFont)
fnt = fontobj(fontkey)
end
if fontcode == 'kanji' && JAPANIZED_TK && TK_VERSION =~ /^4\.*/
# obsolete; just for compatibility
fnt.kanji_font
else
fnt
end
when /^(#{__tkvariable_optkeys.join('|')})$/
v = tk_call_without_enc(*(__cget_cmd << "-#{slot}"))
(v.empty?)? nil: TkVarAccess.new(v)
else
tk_tcl2ruby(tk_call_without_enc(*(__cget_cmd << "-#{slot}")), true)
end
end
private :__cget_core
def cget(slot)
unless TkConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__
__cget_core(slot)
else
begin
__cget_core(slot)
rescue => e
if current_configinfo.has_key?(slot.to_s)
# error on known option
fail e
else
# unknown option
nil
end
end
end
end
def cget_strict(slot)
# never use TkConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__
__cget_core(slot)
end
def __configure_core(slot, value=None)
if slot.kind_of? Hash
slot = _symbolkey2str(slot)
__optkey_aliases.each{|alias_name, real_name|
alias_name = alias_name.to_s
if slot.has_key?(alias_name)
slot[real_name.to_s] = slot.delete(alias_name)
end
}
__methodcall_optkeys.each{|key, method|
value = slot.delete(key.to_s)
self.__send__(method, value) if value
}
__ruby2val_optkeys.each{|key, method|
key = key.to_s
slot[key] = method.call(slot[key]) if slot.has_key?(key)
}
__keyonly_optkeys.each{|defkey, undefkey|
conf = slot.find{|kk, vv| kk == defkey.to_s}
if conf
k, v = conf
if v
slot[k] = None
else
slot[undefkey.to_s] = None if undefkey
slot.delete(k)
end
end
}
if (slot.find{|k, v| k =~ /^(|latin|ascii|kanji)(#{__font_optkeys.join('|')})$/})
font_configure(slot)
elsif slot.size > 0
tk_call(*(__config_cmd.concat(hash_kv(slot))))
end
else
orig_slot = slot
slot = slot.to_s
if slot.length == 0
fail ArgumentError, "Invalid option `#{orig_slot.inspect}'"
end
alias_name, real_name = __optkey_aliases.find{|k, v| k.to_s == slot}
if real_name
slot = real_name.to_s
end
if ( conf = __keyonly_optkeys.find{|k, v| k.to_s == slot} )
defkey, undefkey = conf
if value
tk_call(*(__config_cmd << "-#{defkey}"))
elsif undefkey
tk_call(*(__config_cmd << "-#{undefkey}"))
end
elsif ( method = _symbolkey2str(__ruby2val_optkeys)[slot] )
tk_call(*(__config_cmd << "-#{slot}" << method.call(value)))
elsif ( method = _symbolkey2str(__methodcall_optkeys)[slot] )
self.__send__(method, value)
elsif (slot =~ /^(|latin|ascii|kanji)(#{__font_optkeys.join('|')})$/)
if value == None
fontobj($2)
else
font_configure({slot=>value})
end
else
tk_call(*(__config_cmd << "-#{slot}" << value))
end
end
self
end
private :__configure_core
def __check_available_configure_options(keys)
availables = self.current_configinfo.keys
# add non-standard keys
availables |= __font_optkeys.map{|k|
[k.to_s, "latin#{k}", "ascii#{k}", "kanji#{k}"]
}.flatten
availables |= __methodcall_optkeys.keys.map{|k| k.to_s}
availables |= __keyonly_optkeys.keys.map{|k| k.to_s}
keys = _symbolkey2str(keys)
keys.delete_if{|k, v| !(availables.include?(k))}
end
def configure(slot, value=None)
unless TkConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__
__configure_core(slot, value)
else
if slot.kind_of?(Hash)
begin
__configure_core(slot)
rescue
slot = __check_available_configure_options(slot)
__configure_core(slot) unless slot.empty?
end
else
begin
__configure_core(slot, value)
rescue => e
if current_configinfo.has_key?(slot.to_s)
# error on known option
fail e
else
# unknown option
nil
end
end
end
end
self
end
def configure_cmd(slot, value)
configure(slot, install_cmd(value))
end
def __configinfo_core(slot = nil)
if TkComm::GET_CONFIGINFO_AS_ARRAY
if (slot &&
slot.to_s =~ /^(|latin|ascii|kanji)(#{__font_optkeys.join('|')})$/)
fontkey = $2
# conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__confinfo_cmd << "-#{fontkey}"))))
conf = tk_split_simplelist(tk_call_without_enc(*(__confinfo_cmd << "-#{fontkey}")), false, true)
conf[__configinfo_struct[:key]] =
conf[__configinfo_struct[:key]][1..-1]
if ( ! __configinfo_struct[:alias] \
|| conf.size > __configinfo_struct[:alias] + 1 )
fnt = conf[__configinfo_struct[:default_value]]
if TkFont.is_system_font?(fnt)
conf[__configinfo_struct[:default_value]] = TkNamedFont.new(fnt)
end
conf[__configinfo_struct[:current_value]] = fontobj(fontkey)
elsif ( __configinfo_struct[:alias] \
&& conf.size == __configinfo_struct[:alias] + 1 \
&& conf[__configinfo_struct[:alias]][0] == ?- )
conf[__configinfo_struct[:alias]] =
conf[__configinfo_struct[:alias]][1..-1]
end
conf
else
if slot
slot = slot.to_s
alias_name, real_name = __optkey_aliases.find{|k, v| k.to_s == slot}
if real_name
slot = real_name.to_s
end
case slot
when /^(#{__val2ruby_optkeys().keys.join('|')})$/
method = _symbolkey2str(__val2ruby_optkeys())[slot]
conf = tk_split_simplelist(tk_call_without_enc(*(__confinfo_cmd() << "-#{slot}")), false, true)
if ( __configinfo_struct[:default_value] \
&& conf[__configinfo_struct[:default_value]] )
optval = conf[__configinfo_struct[:default_value]]
begin
val = method.call(optval)
rescue => e
warn("Warning:: #{e.message} (when #{method}.call(#{optval.inspect})") if $DEBUG
val = optval
end
conf[__configinfo_struct[:default_value]] = val
end
if ( conf[__configinfo_struct[:current_value]] )
optval = conf[__configinfo_struct[:current_value]]
begin
val = method.call(optval)
rescue => e
warn("Warning:: #{e.message} (when #{method}.call(#{optval.inspect})") if $DEBUG
val = optval
end
conf[__configinfo_struct[:current_value]] = val
end
when /^(#{__methodcall_optkeys.keys.join('|')})$/
method = _symbolkey2str(__methodcall_optkeys)[slot]
return [slot, '', '', '', self.__send__(method)]
when /^(#{__numval_optkeys.join('|')})$/
# conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}"))))
conf = tk_split_simplelist(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")), false, true)
if ( __configinfo_struct[:default_value] \
&& conf[__configinfo_struct[:default_value]])
begin
conf[__configinfo_struct[:default_value]] =
number(conf[__configinfo_struct[:default_value]])
rescue
conf[__configinfo_struct[:default_value]] = nil
end
end
if ( conf[__configinfo_struct[:current_value]] )
begin
conf[__configinfo_struct[:current_value]] =
number(conf[__configinfo_struct[:current_value]])
rescue
conf[__configinfo_struct[:current_value]] = nil
end
end
when /^(#{__numstrval_optkeys.join('|')})$/
# conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}"))))
conf = tk_split_simplelist(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")), false, true)
if ( __configinfo_struct[:default_value] \
&& conf[__configinfo_struct[:default_value]])
conf[__configinfo_struct[:default_value]] =
num_or_str(conf[__configinfo_struct[:default_value]])
end
if ( conf[__configinfo_struct[:current_value]] )
conf[__configinfo_struct[:current_value]] =
num_or_str(conf[__configinfo_struct[:current_value]])
end
when /^(#{__boolval_optkeys.join('|')})$/
# conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}"))))
conf = tk_split_simplelist(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")), false, true)
if ( __configinfo_struct[:default_value] \
&& conf[__configinfo_struct[:default_value]])
begin
conf[__configinfo_struct[:default_value]] =
bool(conf[__configinfo_struct[:default_value]])
rescue
conf[__configinfo_struct[:default_value]] = nil
end
end
if ( conf[__configinfo_struct[:current_value]] )
begin
conf[__configinfo_struct[:current_value]] =
bool(conf[__configinfo_struct[:current_value]])
rescue
conf[__configinfo_struct[:current_value]] = nil
end
end
when /^(#{__listval_optkeys.join('|')})$/
# conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}"))))
conf = tk_split_simplelist(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")), false, true)
if ( __configinfo_struct[:default_value] \
&& conf[__configinfo_struct[:default_value]])
conf[__configinfo_struct[:default_value]] =
simplelist(conf[__configinfo_struct[:default_value]])
end
if ( conf[__configinfo_struct[:current_value]] )
conf[__configinfo_struct[:current_value]] =
simplelist(conf[__configinfo_struct[:current_value]])
end
when /^(#{__numlistval_optkeys.join('|')})$/
# conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}"))))
conf = tk_split_simplelist(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")), false, true)
if ( __configinfo_struct[:default_value] \
&& conf[__configinfo_struct[:default_value]] \
&& conf[__configinfo_struct[:default_value]] =~ /^[0-9]/ )
conf[__configinfo_struct[:default_value]] =
list(conf[__configinfo_struct[:default_value]])
end
if ( conf[__configinfo_struct[:current_value]] \
&& conf[__configinfo_struct[:current_value]] =~ /^[0-9]/ )
conf[__configinfo_struct[:current_value]] =
list(conf[__configinfo_struct[:current_value]])
end
when /^(#{__strval_optkeys.join('|')})$/
# conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}"))))
conf = tk_split_simplelist(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")), false, true)
when /^(#{__tkvariable_optkeys.join('|')})$/
conf = tk_split_simplelist(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")), false, true)
if ( __configinfo_struct[:default_value] \
&& conf[__configinfo_struct[:default_value]])
v = conf[__configinfo_struct[:default_value]]
if v.empty?
conf[__configinfo_struct[:default_value]] = nil
else
conf[__configinfo_struct[:default_value]] = TkVarAccess.new(v)
end
end
if ( conf[__configinfo_struct[:current_value]] )
v = conf[__configinfo_struct[:current_value]]
if v.empty?
conf[__configinfo_struct[:current_value]] = nil
else
conf[__configinfo_struct[:current_value]] = TkVarAccess.new(v)
end
end
else
# conf = tk_split_list(_fromUTF8(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}"))))
# conf = tk_split_list(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")), 0, false, true)
conf = tk_split_list(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")), 1, false, true)
end
conf[__configinfo_struct[:key]] =
conf[__configinfo_struct[:key]][1..-1]
if ( __configinfo_struct[:alias] \
&& conf.size == __configinfo_struct[:alias] + 1 \
&& conf[__configinfo_struct[:alias]][0] == ?- )
conf[__configinfo_struct[:alias]] =
conf[__configinfo_struct[:alias]][1..-1]
end
conf
else
# ret = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*__confinfo_cmd))).collect{|conflist|
# conf = tk_split_simplelist(conflist)
ret = tk_split_simplelist(tk_call_without_enc(*__confinfo_cmd), false, false).collect{|conflist|
conf = tk_split_simplelist(conflist, false, true)
conf[__configinfo_struct[:key]] =
conf[__configinfo_struct[:key]][1..-1]
optkey = conf[__configinfo_struct[:key]]
case optkey
when /^(#{__val2ruby_optkeys().keys.join('|')})$/
method = _symbolkey2str(__val2ruby_optkeys())[optkey]
if ( __configinfo_struct[:default_value] \
&& conf[__configinfo_struct[:default_value]] )
optval = conf[__configinfo_struct[:default_value]]
begin
val = method.call(optval)
rescue => e
warn("Warning:: #{e.message} (when #{method}.call(#{optval.inspect})") if $DEBUG
val = optval
end
conf[__configinfo_struct[:default_value]] = val
end
if ( conf[__configinfo_struct[:current_value]] )
optval = conf[__configinfo_struct[:current_value]]
begin
val = method.call(optval)
rescue => e
warn("Warning:: #{e.message} (when #{method}.call(#{optval.inspect})") if $DEBUG
val = optval
end
conf[__configinfo_struct[:current_value]] = val
end
when /^(#{__strval_optkeys.join('|')})$/
# do nothing
when /^(#{__numval_optkeys.join('|')})$/
if ( __configinfo_struct[:default_value] \
&& conf[__configinfo_struct[:default_value]] )
begin
conf[__configinfo_struct[:default_value]] =
number(conf[__configinfo_struct[:default_value]])
rescue
conf[__configinfo_struct[:default_value]] = nil
end
end
if ( conf[__configinfo_struct[:current_value]] )
begin
conf[__configinfo_struct[:current_value]] =
number(conf[__configinfo_struct[:current_value]])
rescue
conf[__configinfo_struct[:current_value]] = nil
end
end
when /^(#{__numstrval_optkeys.join('|')})$/
if ( __configinfo_struct[:default_value] \
&& conf[__configinfo_struct[:default_value]] )
conf[__configinfo_struct[:default_value]] =
num_or_str(conf[__configinfo_struct[:default_value]])
end
if ( conf[__configinfo_struct[:current_value]] )
conf[__configinfo_struct[:current_value]] =
num_or_str(conf[__configinfo_struct[:current_value]])
end
when /^(#{__boolval_optkeys.join('|')})$/
if ( __configinfo_struct[:default_value] \
&& conf[__configinfo_struct[:default_value]] )
begin
conf[__configinfo_struct[:default_value]] =
bool(conf[__configinfo_struct[:default_value]])
rescue
conf[__configinfo_struct[:default_value]] = nil
end
end
if ( conf[__configinfo_struct[:current_value]] )
begin
conf[__configinfo_struct[:current_value]] =
bool(conf[__configinfo_struct[:current_value]])
rescue
conf[__configinfo_struct[:current_value]] = nil
end
end
when /^(#{__listval_optkeys.join('|')})$/
if ( __configinfo_struct[:default_value] \
&& conf[__configinfo_struct[:default_value]] )
conf[__configinfo_struct[:default_value]] =
simplelist(conf[__configinfo_struct[:default_value]])
end
if ( conf[__configinfo_struct[:current_value]] )
conf[__configinfo_struct[:current_value]] =
simplelist(conf[__configinfo_struct[:current_value]])
end
when /^(#{__numlistval_optkeys.join('|')})$/
if ( __configinfo_struct[:default_value] \
&& conf[__configinfo_struct[:default_value]] \
&& conf[__configinfo_struct[:default_value]] =~ /^[0-9]/ )
conf[__configinfo_struct[:default_value]] =
list(conf[__configinfo_struct[:default_value]])
end
if ( conf[__configinfo_struct[:current_value]] \
&& conf[__configinfo_struct[:current_value]] =~ /^[0-9]/ )
conf[__configinfo_struct[:current_value]] =
list(conf[__configinfo_struct[:current_value]])
end
when /^(#{__tkvariable_optkeys.join('|')})$/
if ( __configinfo_struct[:default_value] \
&& conf[__configinfo_struct[:default_value]] )
v = conf[__configinfo_struct[:default_value]]
if v.empty?
conf[__configinfo_struct[:default_value]] = nil
else
conf[__configinfo_struct[:default_value]] = TkVarAccess.new(v)
end
end
if ( conf[__configinfo_struct[:current_value]] )
v = conf[__configinfo_struct[:current_value]]
if v.empty?
conf[__configinfo_struct[:current_value]] = nil
else
conf[__configinfo_struct[:current_value]] = TkVarAccess.new(v)
end
end
else
if ( __configinfo_struct[:default_value] \
&& conf[__configinfo_struct[:default_value]] )
if conf[__configinfo_struct[:default_value]].index('{')
conf[__configinfo_struct[:default_value]] =
tk_split_list(conf[__configinfo_struct[:default_value]])
else
conf[__configinfo_struct[:default_value]] =
tk_tcl2ruby(conf[__configinfo_struct[:default_value]])
end
end
if conf[__configinfo_struct[:current_value]]
if conf[__configinfo_struct[:current_value]].index('{')
conf[__configinfo_struct[:current_value]] =
tk_split_list(conf[__configinfo_struct[:current_value]])
else
conf[__configinfo_struct[:current_value]] =
tk_tcl2ruby(conf[__configinfo_struct[:current_value]])
end
end
end
if ( __configinfo_struct[:alias] \
&& conf.size == __configinfo_struct[:alias] + 1 \
&& conf[__configinfo_struct[:alias]][0] == ?- )
conf[__configinfo_struct[:alias]] =
conf[__configinfo_struct[:alias]][1..-1]
end
conf
}
__font_optkeys.each{|optkey|
optkey = optkey.to_s
fontconf = ret.assoc(optkey)
if fontconf && fontconf.size > 2
ret.delete_if{|inf| inf[0] =~ /^(|latin|ascii|kanji)#{optkey}$/}
fnt = fontconf[__configinfo_struct[:default_value]]
if TkFont.is_system_font?(fnt)
fontconf[__configinfo_struct[:default_value]] \
= TkNamedFont.new(fnt)
end
fontconf[__configinfo_struct[:current_value]] = fontobj(optkey)
ret.push(fontconf)
end
}
__methodcall_optkeys.each{|optkey, m|
ret << [optkey.to_s, '', '', '', self.__send__(m)]
}
ret
end
end
else # ! TkComm::GET_CONFIGINFO_AS_ARRAY
if (slot &&
slot.to_s =~ /^(|latin|ascii|kanji)(#{__font_optkeys.join('|')})$/)
fontkey = $2
# conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__confinfo_cmd << "-#{fontkey}"))))
conf = tk_split_simplelist(tk_call_without_enc(*(__confinfo_cmd << "-#{fontkey}")), false, true)
conf[__configinfo_struct[:key]] =
conf[__configinfo_struct[:key]][1..-1]
if ( ! __configinfo_struct[:alias] \
|| conf.size > __configinfo_struct[:alias] + 1 )
fnt = conf[__configinfo_struct[:default_value]]
if TkFont.is_system_font?(fnt)
conf[__configinfo_struct[:default_value]] = TkNamedFont.new(fnt)
end
conf[__configinfo_struct[:current_value]] = fontobj(fontkey)
{ conf.shift => conf }
elsif ( __configinfo_struct[:alias] \
&& conf.size == __configinfo_struct[:alias] + 1 )
if conf[__configinfo_struct[:alias]][0] == ?-
conf[__configinfo_struct[:alias]] =
conf[__configinfo_struct[:alias]][1..-1]
end
{ conf[0] => conf[1] }
else
{ conf.shift => conf }
end
else
if slot
slot = slot.to_s
alias_name, real_name = __optkey_aliases.find{|k,var| k.to_s == slot}
if real_name
slot = real_name.to_s
end
case slot
when /^(#{__val2ruby_optkeys().keys.join('|')})$/
method = _symbolkey2str(__val2ruby_optkeys())[slot]
conf = tk_split_simplelist(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")), false, true)
if ( __configinfo_struct[:default_value] \
&& conf[__configinfo_struct[:default_value]] )
optval = conf[__configinfo_struct[:default_value]]
begin
val = method.call(optval)
rescue => e
warn("Warning:: #{e.message} (when #{method}.call(#{optval.inspect})") if $DEBUG
val = optval
end
conf[__configinfo_struct[:default_value]] = val
end
if ( conf[__configinfo_struct[:current_value]] )
optval = conf[__configinfo_struct[:current_value]]
begin
val = method.call(optval)
rescue => e
warn("Warning:: #{e.message} (when #{method}.call(#{optval.inspect})") if $DEBUG
val = optval
end
conf[__configinfo_struct[:current_value]] = val
end
when /^(#{__methodcall_optkeys.keys.join('|')})$/
method = _symbolkey2str(__methodcall_optkeys)[slot]
return {slot => ['', '', '', self.__send__(method)]}
when /^(#{__numval_optkeys.join('|')})$/
# conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}"))))
conf = tk_split_simplelist(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")), false, true)
if ( __configinfo_struct[:default_value] \
&& conf[__configinfo_struct[:default_value]] )
begin
conf[__configinfo_struct[:default_value]] =
number(conf[__configinfo_struct[:default_value]])
rescue
conf[__configinfo_struct[:default_value]] = nil
end
end
if ( conf[__configinfo_struct[:current_value]] )
begin
conf[__configinfo_struct[:current_value]] =
number(conf[__configinfo_struct[:current_value]])
rescue
conf[__configinfo_struct[:current_value]] = nil
end
end
when /^(#{__numstrval_optkeys.join('|')})$/
# conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}"))))
conf = tk_split_simplelist(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")), false, true)
if ( __configinfo_struct[:default_value] \
&& conf[__configinfo_struct[:default_value]] )
conf[__configinfo_struct[:default_value]] =
num_or_str(conf[__configinfo_struct[:default_value]])
end
if ( conf[__configinfo_struct[:current_value]] )
conf[__configinfo_struct[:current_value]] =
num_or_str(conf[__configinfo_struct[:current_value]])
end
when /^(#{__boolval_optkeys.join('|')})$/
# conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}"))))
conf = tk_split_simplelist(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")), false, true)
if ( __configinfo_struct[:default_value] \
&& conf[__configinfo_struct[:default_value]] )
begin
conf[__configinfo_struct[:default_value]] =
bool(conf[__configinfo_struct[:default_value]])
rescue
conf[__configinfo_struct[:default_value]] = nil
end
end
if ( conf[__configinfo_struct[:current_value]] )
begin
conf[__configinfo_struct[:current_value]] =
bool(conf[__configinfo_struct[:current_value]])
rescue
conf[__configinfo_struct[:current_value]] = nil
end
end
when /^(#{__listval_optkeys.join('|')})$/
# conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}"))))
conf = tk_split_simplelist(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")), false, true)
if ( __configinfo_struct[:default_value] \
&& conf[__configinfo_struct[:default_value]] )
conf[__configinfo_struct[:default_value]] =
simplelist(conf[__configinfo_struct[:default_value]])
end
if ( conf[__configinfo_struct[:current_value]] )
conf[__configinfo_struct[:current_value]] =
simplelist(conf[__configinfo_struct[:current_value]])
end
when /^(#{__numlistval_optkeys.join('|')})$/
# conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}"))))
conf = tk_split_simplelist(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")), false, true)
if ( __configinfo_struct[:default_value] \
&& conf[__configinfo_struct[:default_value]] \
&& conf[__configinfo_struct[:default_value]] =~ /^[0-9]/ )
conf[__configinfo_struct[:default_value]] =
list(conf[__configinfo_struct[:default_value]])
end
if ( conf[__configinfo_struct[:current_value]] \
&& conf[__configinfo_struct[:current_value]] =~ /^[0-9]/ )
conf[__configinfo_struct[:current_value]] =
list(conf[__configinfo_struct[:current_value]])
end
when /^(#{__tkvariable_optkeys.join('|')})$/
conf = tk_split_simplelist(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")), false, true)
if ( __configinfo_struct[:default_value] \
&& conf[__configinfo_struct[:default_value]] )
v = conf[__configinfo_struct[:default_value]]
if v.empty?
conf[__configinfo_struct[:default_value]] = nil
else
conf[__configinfo_struct[:default_value]] = TkVarAccess.new(v)
end
end
if ( conf[__configinfo_struct[:current_value]] )
v = conf[__configinfo_struct[:current_value]]
if v.empty?
conf[__configinfo_struct[:current_value]] = nil
else
conf[__configinfo_struct[:current_value]] = TkVarAccess.new(v)
end
end
when /^(#{__strval_optkeys.join('|')})$/
# conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}"))))
conf = tk_split_simplelist(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")), false, true)
else
# conf = tk_split_list(_fromUTF8(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}"))))
conf = tk_split_list(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")), 0, false, true)
end
conf[__configinfo_struct[:key]] =
conf[__configinfo_struct[:key]][1..-1]
if ( __configinfo_struct[:alias] \
&& conf.size == __configinfo_struct[:alias] + 1 )
if conf[__configinfo_struct[:alias]][0] == ?-
conf[__configinfo_struct[:alias]] =
conf[__configinfo_struct[:alias]][1..-1]
end
{ conf[0] => conf[1] }
else
{ conf.shift => conf }
end
else
ret = {}
# tk_split_simplelist(_fromUTF8(tk_call_without_enc(*__confinfo_cmd))).each{|conflist|
# conf = tk_split_simplelist(conflist)
tk_split_simplelist(tk_call_without_enc(*__confinfo_cmd), false, false).each{|conflist|
conf = tk_split_simplelist(conflist, false, true)
conf[__configinfo_struct[:key]] =
conf[__configinfo_struct[:key]][1..-1]
optkey = conf[__configinfo_struct[:key]]
case optkey
when /^(#{__val2ruby_optkeys().keys.join('|')})$/
method = _symbolkey2str(__val2ruby_optkeys())[optkey]
if ( __configinfo_struct[:default_value] \
&& conf[__configinfo_struct[:default_value]] )
optval = conf[__configinfo_struct[:default_value]]
begin
val = method.call(optval)
rescue => e
warn("Warning:: #{e.message} (when #{method}.call(#{optval.inspect})") if $DEBUG
val = optval
end
conf[__configinfo_struct[:default_value]] = val
end
if ( conf[__configinfo_struct[:current_value]] )
optval = conf[__configinfo_struct[:current_value]]
begin
val = method.call(optval)
rescue => e
warn("Warning:: #{e.message} (when #{method}.call(#{optval.inspect})") if $DEBUG
val = optval
end
conf[__configinfo_struct[:current_value]] = val
end
when /^(#{__strval_optkeys.join('|')})$/
# do nothing
when /^(#{__numval_optkeys.join('|')})$/
if ( __configinfo_struct[:default_value] \
&& conf[__configinfo_struct[:default_value]] )
begin
conf[__configinfo_struct[:default_value]] =
number(conf[__configinfo_struct[:default_value]])
rescue
conf[__configinfo_struct[:default_value]] = nil
end
end
if ( conf[__configinfo_struct[:current_value]] )
begin
conf[__configinfo_struct[:current_value]] =
number(conf[__configinfo_struct[:current_value]])
rescue
conf[__configinfo_struct[:current_value]] = nil
end
end
when /^(#{__numstrval_optkeys.join('|')})$/
if ( __configinfo_struct[:default_value] \
&& conf[__configinfo_struct[:default_value]] )
conf[__configinfo_struct[:default_value]] =
num_or_str(conf[__configinfo_struct[:default_value]])
end
if ( conf[__configinfo_struct[:current_value]] )
conf[__configinfo_struct[:current_value]] =
num_or_str(conf[__configinfo_struct[:current_value]])
end
when /^(#{__boolval_optkeys.join('|')})$/
if ( __configinfo_struct[:default_value] \
&& conf[__configinfo_struct[:default_value]] )
begin
conf[__configinfo_struct[:default_value]] =
bool(conf[__configinfo_struct[:default_value]])
rescue
conf[__configinfo_struct[:default_value]] = nil
end
end
if ( conf[__configinfo_struct[:current_value]] )
begin
conf[__configinfo_struct[:current_value]] =
bool(conf[__configinfo_struct[:current_value]])
rescue
conf[__configinfo_struct[:current_value]] = nil
end
end
when /^(#{__listval_optkeys.join('|')})$/
if ( __configinfo_struct[:default_value] \
&& conf[__configinfo_struct[:default_value]] )
conf[__configinfo_struct[:default_value]] =
simplelist(conf[__configinfo_struct[:default_value]])
end
if ( conf[__configinfo_struct[:current_value]] )
conf[__configinfo_struct[:current_value]] =
simplelist(conf[__configinfo_struct[:current_value]])
end
when /^(#{__numlistval_optkeys.join('|')})$/
if ( __configinfo_struct[:default_value] \
&& conf[__configinfo_struct[:default_value]] \
&& conf[__configinfo_struct[:default_value]] =~ /^[0-9]/ )
conf[__configinfo_struct[:default_value]] =
list(conf[__configinfo_struct[:default_value]])
end
if ( conf[__configinfo_struct[:current_value]] \
&& conf[__configinfo_struct[:current_value]] =~ /^[0-9]/ )
conf[__configinfo_struct[:current_value]] =
list(conf[__configinfo_struct[:current_value]])
end
when /^(#{__tkvariable_optkeys.join('|')})$/
if ( __configinfo_struct[:default_value] \
&& conf[__configinfo_struct[:default_value]] )
v = conf[__configinfo_struct[:default_value]]
if v.empty?
conf[__configinfo_struct[:default_value]] = nil
else
conf[__configinfo_struct[:default_value]] = TkVarAccess.new
end
end
if ( conf[__configinfo_struct[:current_value]] )
v = conf[__configinfo_struct[:current_value]]
if v.empty?
conf[__configinfo_struct[:current_value]] = nil
else
conf[__configinfo_struct[:current_value]] = TkVarAccess.new
end
end
else
if ( __configinfo_struct[:default_value] \
&& conf[__configinfo_struct[:default_value]] )
if conf[__configinfo_struct[:default_value]].index('{')
conf[__configinfo_struct[:default_value]] =
tk_split_list(conf[__configinfo_struct[:default_value]])
else
conf[__configinfo_struct[:default_value]] =
tk_tcl2ruby(conf[__configinfo_struct[:default_value]])
end
end
if conf[__configinfo_struct[:current_value]]
if conf[__configinfo_struct[:current_value]].index('{')
conf[__configinfo_struct[:current_value]] =
tk_split_list(conf[__configinfo_struct[:current_value]])
else
conf[__configinfo_struct[:current_value]] =
tk_tcl2ruby(conf[__configinfo_struct[:current_value]])
end
end
end
if ( __configinfo_struct[:alias] \
&& conf.size == __configinfo_struct[:alias] + 1 )
if conf[__configinfo_struct[:alias]][0] == ?-
conf[__configinfo_struct[:alias]] =
conf[__configinfo_struct[:alias]][1..-1]
end
ret[conf[0]] = conf[1]
else
ret[conf.shift] = conf
end
}
__font_optkeys.each{|optkey|
optkey = optkey.to_s
fontconf = ret[optkey]
if fontconf.kind_of?(Array)
ret.delete(optkey)
ret.delete('latin' << optkey)
ret.delete('ascii' << optkey)
ret.delete('kanji' << optkey)
fnt = fontconf[__configinfo_struct[:default_value]]
if TkFont.is_system_font?(fnt)
fontconf[__configinfo_struct[:default_value]] \
= TkNamedFont.new(fnt)
end
fontconf[__configinfo_struct[:current_value]] = fontobj(optkey)
ret[optkey] = fontconf
end
}
__methodcall_optkeys.each{|optkey, m|
ret[optkey.to_s] = ['', '', '', self.__send__(m)]
}
ret
end
end
end
end
private :__configinfo_core
def configinfo(slot = nil)
if slot && TkConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__
begin
__configinfo_core(slot)
rescue
Array.new(__configinfo_struct.values.max).unshift(slot.to_s)
end
else
__configinfo_core(slot)
end
end
def current_configinfo(slot = nil)
if TkComm::GET_CONFIGINFO_AS_ARRAY
if slot
org_slot = slot
begin
conf = configinfo(slot)
if ( ! __configinfo_struct[:alias] \
|| conf.size > __configinfo_struct[:alias] + 1 )
return {conf[0] => conf[-1]}
end
slot = conf[__configinfo_struct[:alias]]
end while(org_slot != slot)
fail RuntimeError,
"there is a configure alias loop about '#{org_slot}'"
else
ret = {}
configinfo().each{|cnf|
if ( ! __configinfo_struct[:alias] \
|| cnf.size > __configinfo_struct[:alias] + 1 )
ret[cnf[0]] = cnf[-1]
end
}
ret
end
else # ! TkComm::GET_CONFIGINFO_AS_ARRAY
ret = {}
configinfo(slot).each{|key, cnf|
ret[key] = cnf[-1] if cnf.kind_of?(Array)
}
ret
end
end
end
class TkObject<TkKernel
extend TkCore
include Tk
include TkConfigMethod
include TkBindCore
### --> definition is moved to TkUtil module
# def path
# @path
# end
def epath
@path
end
def to_eval
@path
end
def tk_send(cmd, *rest)
tk_call(path, cmd, *rest)
end
def tk_send_without_enc(cmd, *rest)
tk_call_without_enc(path, cmd, *rest)
end
def tk_send_with_enc(cmd, *rest)
tk_call_with_enc(path, cmd, *rest)
end
# private :tk_send, :tk_send_without_enc, :tk_send_with_enc
def tk_send_to_list(cmd, *rest)
tk_call_to_list(path, cmd, *rest)
end
def tk_send_to_list_without_enc(cmd, *rest)
tk_call_to_list_without_enc(path, cmd, *rest)
end
def tk_send_to_list_with_enc(cmd, *rest)
tk_call_to_list_with_enc(path, cmd, *rest)
end
def tk_send_to_simplelist(cmd, *rest)
tk_call_to_simplelist(path, cmd, *rest)
end
def tk_send_to_simplelist_without_enc(cmd, *rest)
tk_call_to_simplelist_without_enc(path, cmd, *rest)
end
def tk_send_to_simplelist_with_enc(cmd, *rest)
tk_call_to_simplelist_with_enc(path, cmd, *rest)
end
def method_missing(id, *args)
name = id.id2name
case args.length
when 1
if name[-1] == ?=
configure name[0..-2], args[0]
args[0]
else
configure name, args[0]
self
end
when 0
begin
cget(name)
rescue
if self.kind_of?(TkWindow) && name != "to_ary" && name != "to_str"
fail NameError,
"unknown option '#{id}' for #{self.inspect} (deleted widget?)"
else
super(id, *args)
end
# fail NameError,
# "undefined local variable or method `#{name}' for #{self.to_s}",
# error_at
end
else
super(id, *args)
# fail NameError, "undefined method `#{name}' for #{self.to_s}", error_at
end
end
=begin
def [](id)
cget(id)
end
def []=(id, val)
configure(id, val)
val
end
=end
def event_generate(context, keys=nil)
if context.kind_of?(TkEvent::Event)
context.generate(self, ((keys)? keys: {}))
elsif keys
#tk_call('event', 'generate', path,
# "<#{tk_event_sequence(context)}>", *hash_kv(keys))
tk_call_without_enc('event', 'generate', path,
"<#{tk_event_sequence(context)}>",
*hash_kv(keys, true))
else
#tk_call('event', 'generate', path, "<#{tk_event_sequence(context)}>")
tk_call_without_enc('event', 'generate', path,
"<#{tk_event_sequence(context)}>")
end
end
def tk_trace_variable(v)
#unless v.kind_of?(TkVariable)
# fail(ArgumentError, "type error (#{v.class}); must be TkVariable object")
#end
v
end
private :tk_trace_variable
def destroy
#tk_call 'trace', 'vdelete', @tk_vn, 'w', @var_id if @var_id
end
end
class TkWindow<TkObject
include TkWinfo
extend TkBindCore
include Tk::Wm_for_General
include Tk::Busy
@@WIDGET_INSPECT_FULL = false
def TkWindow._widget_inspect_full_?
@@WIDGET_INSPECT_FULL
end
def TkWindow._widget_inspect_full_=(mode)
@@WIDGET_INSPECT_FULL = (mode && true) || false
end
TkCommandNames = [].freeze
## ==> If TkCommandNames[0] is a string (not a null string),
## assume the string is a Tcl/Tk's create command of the widget class.
WidgetClassName = ''.freeze
# WidgetClassNames[WidgetClassName] = self
## ==> If self is a widget class, entry to the WidgetClassNames table.
def self.to_eval
self::WidgetClassName
end
def initialize(parent=nil, keys=nil)
if parent.kind_of? Hash
keys = _symbolkey2str(parent)
parent = keys.delete('parent')
widgetname = keys.delete('widgetname')
install_win(if parent then parent.path end, widgetname)
without_creating = keys.delete('without_creating')
# if without_creating && !widgetname
# fail ArgumentError,
# "if set 'without_creating' to true, need to define 'widgetname'"
# end
elsif keys
keys = _symbolkey2str(keys)
widgetname = keys.delete('widgetname')
install_win(if parent then parent.path end, widgetname)
without_creating = keys.delete('without_creating')
# if without_creating && !widgetname
# fail ArgumentError,
# "if set 'without_creating' to true, need to define 'widgetname'"
# end
else
install_win(if parent then parent.path end)
end
if self.method(:create_self).arity == 0
p 'create_self has no arg' if $DEBUG
create_self unless without_creating
if keys
# tk_call @path, 'configure', *hash_kv(keys)
configure(keys)
end
else
p 'create_self has args' if $DEBUG
fontkeys = {}
methodkeys = {}
if keys
#['font', 'kanjifont', 'latinfont', 'asciifont'].each{|key|
# fontkeys[key] = keys.delete(key) if keys.key?(key)
#}
__font_optkeys.each{|key|
fkey = key.to_s
fontkeys[fkey] = keys.delete(fkey) if keys.key?(fkey)
fkey = "kanji#{key}"
fontkeys[fkey] = keys.delete(fkey) if keys.key?(fkey)
fkey = "latin#{key}"
fontkeys[fkey] = keys.delete(fkey) if keys.key?(fkey)
fkey = "ascii#{key}"
fontkeys[fkey] = keys.delete(fkey) if keys.key?(fkey)
}
__optkey_aliases.each{|alias_name, real_name|
alias_name = alias_name.to_s
if keys.has_key?(alias_name)
keys[real_name.to_s] = keys.delete(alias_name)
end
}
__methodcall_optkeys.each{|key|
key = key.to_s
methodkeys[key] = keys.delete(key) if keys.key?(key)
}
__ruby2val_optkeys.each{|key, method|
key = key.to_s
keys[key] = method.call(keys[key]) if keys.has_key?(key)
}
end
if without_creating && keys
#configure(keys)
configure(__conv_keyonly_opts(keys))
else
#create_self(keys)
create_self(__conv_keyonly_opts(keys))
end
font_configure(fontkeys) unless fontkeys.empty?
configure(methodkeys) unless methodkeys.empty?
end
end
def create_self(keys)
# may need to override
begin
cmd = self.class::TkCommandNames[0]
fail unless (cmd.kind_of?(String) && cmd.length > 0)
rescue
fail RuntimeError, "class #{self.class} may be an abstract class"
end
if keys and keys != None
unless TkConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__
tk_call_without_enc(cmd, @path, *hash_kv(keys, true))
else
begin
tk_call_without_enc(cmd, @path, *hash_kv(keys, true))
rescue => e
tk_call_without_enc(cmd, @path)
keys = __check_available_configure_options(keys)
unless keys.empty?
begin
# try to configure
configure(keys)
rescue
# fail => includes options adaptable when creattion only?
begin
tk_call_without_enc('destroy', @path)
rescue
# cannot rescue options error
fail e
else
# re-create widget
tk_call_without_enc(cmd, @path, *hash_kv(keys, true))
end
end
end
end
end
else
tk_call_without_enc(cmd, @path)
end
end
private :create_self
def inspect
if @@WIDGET_INSPECT_FULL
super
else
str = super
str[0..(str.index(' '))] << '@path=' << @path.inspect << '>'
end
end
def exist?
TkWinfo.exist?(self)
end
alias subcommand tk_send
def bind_class
@db_class || self.class()
end
def database_classname
TkWinfo.classname(self)
end
def database_class
name = database_classname()
if WidgetClassNames[name]
WidgetClassNames[name]
else
TkDatabaseClass.new(name)
end
end
def self.database_classname
self::WidgetClassName
end
def self.database_class
WidgetClassNames[self::WidgetClassName]
end
def pack(keys = nil)
#tk_call_without_enc('pack', epath, *hash_kv(keys, true))
if keys
TkPack.configure(self, keys)
else
TkPack.configure(self)
end
self
end
def pack_in(target, keys = nil)
if keys
keys = keys.dup
keys['in'] = target
else
keys = {'in'=>target}
end
#tk_call 'pack', epath, *hash_kv(keys)
TkPack.configure(self, keys)
self
end
def pack_forget
#tk_call_without_enc('pack', 'forget', epath)
TkPack.forget(self)
self
end
alias unpack pack_forget
def pack_config(slot, value=None)
#if slot.kind_of? Hash
# tk_call 'pack', 'configure', epath, *hash_kv(slot)
#else
# tk_call 'pack', 'configure', epath, "-#{slot}", value
#end
if slot.kind_of? Hash
TkPack.configure(self, slot)
else
TkPack.configure(self, slot=>value)
end
end
alias pack_configure pack_config
def pack_info()
#ilist = list(tk_call('pack', 'info', epath))
#info = {}
#while key = ilist.shift
# info[key[1..-1]] = ilist.shift
#end
#return info
TkPack.info(self)
end
def pack_propagate(mode=None)
#if mode == None
# bool(tk_call('pack', 'propagate', epath))
#else
# tk_call('pack', 'propagate', epath, mode)
# self
#end
if mode == None
TkPack.propagate(self)
else
TkPack.propagate(self, mode)
self
end
end
def pack_slaves()
#list(tk_call('pack', 'slaves', epath))
TkPack.slaves(self)
end
def grid(keys = nil)
#tk_call 'grid', epath, *hash_kv(keys)
if keys
TkGrid.configure(self, keys)
else
TkGrid.configure(self)
end
self
end
def grid_in(target, keys = nil)
if keys
keys = keys.dup
keys['in'] = target
else
keys = {'in'=>target}
end
#tk_call 'grid', epath, *hash_kv(keys)
TkGrid.configure(self, keys)
self
end
def grid_anchor(anchor=None)
if anchor == None
TkGrid.anchor(self)
else
TkGrid.anchor(self, anchor)
self
end
end
def grid_forget
#tk_call('grid', 'forget', epath)
TkGrid.forget(self)
self
end
alias ungrid grid_forget
def grid_bbox(*args)
#list(tk_call('grid', 'bbox', epath, *args))
TkGrid.bbox(self, *args)
end
def grid_config(slot, value=None)
#if slot.kind_of? Hash
# tk_call 'grid', 'configure', epath, *hash_kv(slot)
#else
# tk_call 'grid', 'configure', epath, "-#{slot}", value
#end
if slot.kind_of? Hash
TkGrid.configure(self, slot)
else
TkGrid.configure(self, slot=>value)
end
end
alias grid_configure grid_config
def grid_columnconfig(index, keys)
#tk_call('grid', 'columnconfigure', epath, index, *hash_kv(keys))
TkGrid.columnconfigure(self, index, keys)
end
alias grid_columnconfigure grid_columnconfig
def grid_rowconfig(index, keys)
#tk_call('grid', 'rowconfigure', epath, index, *hash_kv(keys))
TkGrid.rowconfigure(self, index, keys)
end
alias grid_rowconfigure grid_rowconfig
def grid_columnconfiginfo(index, slot=nil)
#if slot
# tk_call('grid', 'columnconfigure', epath, index, "-#{slot}").to_i
#else
# ilist = list(tk_call('grid', 'columnconfigure', epath, index))
# info = {}
# while key = ilist.shift
# info[key[1..-1]] = ilist.shift
# end
# info
#end
TkGrid.columnconfiginfo(self, index, slot)
end
def grid_rowconfiginfo(index, slot=nil)
#if slot
# tk_call('grid', 'rowconfigure', epath, index, "-#{slot}").to_i
#else
# ilist = list(tk_call('grid', 'rowconfigure', epath, index))
# info = {}
# while key = ilist.shift
# info[key[1..-1]] = ilist.shift
# end
# info
#end
TkGrid.rowconfiginfo(self, index, slot)
end
def grid_column(index, keys=nil)
if keys.kind_of?(Hash)
grid_columnconfigure(index, keys)
else
grid_columnconfiginfo(index, keys)
end
end
def grid_row(index, keys=nil)
if keys.kind_of?(Hash)
grid_rowconfigure(index, keys)
else
grid_rowconfiginfo(index, keys)
end
end
def grid_info()
#list(tk_call('grid', 'info', epath))
TkGrid.info(self)
end
def grid_location(x, y)
#list(tk_call('grid', 'location', epath, x, y))
TkGrid.location(self, x, y)
end
def grid_propagate(mode=None)
#if mode == None
# bool(tk_call('grid', 'propagate', epath))
#else
# tk_call('grid', 'propagate', epath, mode)
# self
#end
if mode == None
TkGrid.propagate(self)
else
TkGrid.propagate(self, mode)
self
end
end
def grid_remove()
#tk_call 'grid', 'remove', epath
TkGrid.remove(self)
self
end
def grid_size()
#list(tk_call('grid', 'size', epath))
TkGrid.size(self)
end
def grid_slaves(keys = nil)
#list(tk_call('grid', 'slaves', epath, *hash_kv(args)))
TkGrid.slaves(self, keys)
end
def place(keys)
#tk_call 'place', epath, *hash_kv(keys)
TkPlace.configure(self, keys)
self
end
def place_in(target, keys = nil)
if keys
keys = keys.dup
keys['in'] = target
else
keys = {'in'=>target}
end
#tk_call 'place', epath, *hash_kv(keys)
TkPlace.configure(self, keys)
self
end
def place_forget
#tk_call 'place', 'forget', epath
TkPlace.forget(self)
self
end
alias unplace place_forget
def place_config(slot, value=None)
#if slot.kind_of? Hash
# tk_call 'place', 'configure', epath, *hash_kv(slot)
#else
# tk_call 'place', 'configure', epath, "-#{slot}", value
#end
TkPlace.configure(self, slot, value)
end
alias place_configure place_config
def place_configinfo(slot = nil)
# for >= Tk8.4a2 ?
#if slot
# conf = tk_split_list(tk_call('place', 'configure', epath, "-#{slot}") )
# conf[0] = conf[0][1..-1]
# conf
#else
# tk_split_simplelist(tk_call('place',
# 'configure', epath)).collect{|conflist|
# conf = tk_split_simplelist(conflist)
# conf[0] = conf[0][1..-1]
# conf
# }
#end
TkPlace.configinfo(self, slot)
end
def place_info()
#ilist = list(tk_call('place', 'info', epath))
#info = {}
#while key = ilist.shift
# info[key[1..-1]] = ilist.shift
#end
#return info
TkPlace.info(self)
end
def place_slaves()
#list(tk_call('place', 'slaves', epath))
TkPlace.slaves(self)
end
def set_focus(force=false)
if force
tk_call_without_enc('focus', '-force', path)
else
tk_call_without_enc('focus', path)
end
self
end
alias focus set_focus
def grab(opt = nil)
unless opt
tk_call_without_enc('grab', 'set', path)
return self
end
case opt
when 'set', :set
tk_call_without_enc('grab', 'set', path)
return self
when 'global', :global
#return(tk_call('grab', 'set', '-global', path))
tk_call_without_enc('grab', 'set', '-global', path)
return self
when 'release', :release
#return tk_call('grab', 'release', path)
tk_call_without_enc('grab', 'release', path)
return self
when 'current', :current
return window(tk_call_without_enc('grab', 'current', path))
when 'status', :status
return tk_call_without_enc('grab', 'status', path)
else
return tk_call_without_enc('grab', opt, path)
end
end
def grab_current
grab('current')
end
alias current_grab grab_current
def grab_release
grab('release')
end
alias release_grab grab_release
def grab_set
grab('set')
end
alias set_grab grab_set
def grab_set_global
grab('global')
end
alias set_global_grab grab_set_global
def grab_status
grab('status')
end
def lower(below=None)
# below = below.epath if below.kind_of?(TkObject)
below = _epath(below)
tk_call 'lower', epath, below
self
end
alias lower_window lower
def raise(above=None)
#above = above.epath if above.kind_of?(TkObject)
above = _epath(above)
tk_call 'raise', epath, above
self
end
alias raise_window raise
def command(cmd=nil, &b)
if cmd
configure_cmd('command', cmd)
elsif b
configure_cmd('command', Proc.new(&b))
else
cget('command')
end
end
def colormodel(model=None)
tk_call('tk', 'colormodel', path, model)
self
end
def caret(keys=nil)
TkXIM.caret(path, keys)
end
def destroy
super
children = []
rexp = /^#{self.path}\.[^.]+$/
TkCore::INTERP.tk_windows.each{|path, obj|
children << [path, obj] if path =~ rexp
}
if defined?(@cmdtbl)
for id in @cmdtbl
uninstall_cmd id
end
end
children.each{|path, obj|
obj.instance_eval{
if defined?(@cmdtbl)
for id in @cmdtbl
uninstall_cmd id
end
end
}
TkCore::INTERP.tk_windows.delete(path)
}
begin
tk_call_without_enc('destroy', epath)
rescue
end
uninstall_win
end
def wait_visibility(on_thread = true)
on_thread &= (Thread.list.size != 1)
if on_thread
INTERP._thread_tkwait('visibility', path)
else
INTERP._invoke('tkwait', 'visibility', path)
end
end
def eventloop_wait_visibility
wait_visibility(false)
end
def thread_wait_visibility
wait_visibility(true)
end
alias wait wait_visibility
alias tkwait wait_visibility
alias eventloop_wait eventloop_wait_visibility
alias eventloop_tkwait eventloop_wait_visibility
alias eventloop_tkwait_visibility eventloop_wait_visibility
alias thread_wait thread_wait_visibility
alias thread_tkwait thread_wait_visibility
alias thread_tkwait_visibility thread_wait_visibility
def wait_destroy(on_thread = true)
on_thread &= (Thread.list.size != 1)
if on_thread
INTERP._thread_tkwait('window', epath)
else
INTERP._invoke('tkwait', 'window', epath)
end
end
alias wait_window wait_destroy
def eventloop_wait_destroy
wait_destroy(false)
end
alias eventloop_wait_window eventloop_wait_destroy
def thread_wait_destroy
wait_destroy(true)
end
alias thread_wait_window thread_wait_destroy
alias tkwait_destroy wait_destroy
alias tkwait_window wait_destroy
alias eventloop_tkwait_destroy eventloop_wait_destroy
alias eventloop_tkwait_window eventloop_wait_destroy
alias thread_tkwait_destroy thread_wait_destroy
alias thread_tkwait_window thread_wait_destroy
def bindtags(taglist=nil)
if taglist
fail ArgumentError, "taglist must be Array" unless taglist.kind_of? Array
tk_call('bindtags', path, taglist)
taglist
else
list(tk_call('bindtags', path)).collect{|tag|
if tag.kind_of?(String)
if cls = WidgetClassNames[tag]
cls
elsif btag = TkBindTag.id2obj(tag)
btag
else
tag
end
else
tag
end
}
end
end
def bindtags=(taglist)
bindtags(taglist)
taglist
end
def bindtags_shift
taglist = bindtags
tag = taglist.shift
bindtags(taglist)
tag
end
def bindtags_unshift(tag)
bindtags(bindtags().unshift(tag))
end
end
TkWidget = TkWindow
# freeze core modules
#TclTkLib.freeze
#TclTkIp.freeze
#TkUtil.freeze
#TkKernel.freeze
#TkComm.freeze
#TkComm::Event.freeze
#TkCore.freeze
#Tk.freeze
module Tk
RELEASE_DATE = '2014-10-19'.freeze
autoload :AUTO_PATH, 'tk/variable'
autoload :TCL_PACKAGE_PATH, 'tk/variable'
autoload :PACKAGE_PATH, 'tk/variable'
autoload :TCL_LIBRARY_PATH, 'tk/variable'
autoload :LIBRARY_PATH, 'tk/variable'
autoload :TCL_PRECISION, 'tk/variable'
end
# call setup script for Tk extension libraries (base configuration)
begin
require 'tkextlib/version.rb'
require 'tkextlib/setup.rb'
rescue LoadError
# ignore
end