# # tk.rb - Tk interface module using tcltklib # by Yukihiro Matsumoto # 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 _invoke_without_enc _invoke def _ip_id_ # for RemoteTkIp '' end alias __initialize__ initialize private :__initialize__ def initialize(*args) __initialize__(*args) @force_default_encoding ||= [false].taint @encoding ||= [nil].taint def @encoding.to_s; self.join(nil); end end end # define TkComm module (step 1: basic functions) module TkComm include TkUtil extend TkUtil WidgetClassNames = {}.taint TkExtlibAutoloadModule = [].taint # None = Object.new ### --> definition is moved to TkUtil module # def None.to_s # 'None' # end # None.freeze #Tk_CMDTBL = {} #Tk_WINDOWS = {} Tk_IDs = ["00000".taint, "00000".taint] # [0]-cmdid, [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 = [].taint } 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 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 } 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 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, :string, :num_or_str private :list, :simplelist, :window, :procedure module_function :bool, :number, :num_or_str, :string module_function :list, :simplelist, :window, :image_obj, :procedure 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 @cmdtbl.taint 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 if WITH_RUBY_VM ### check Ruby 1.9 !!!!!!! # *** NEED TO FIX *** ip = TclTkIp.new(name, opts) if ip._invoke_without_enc('tk', 'windowingsystem') == 'aqua' && (TclTkLib.get_version <=> [8,4,TclTkLib::RELEASE_TYPE::FINAL,9]) > 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. RUN_EVENTLOOP_ON_MAIN_THREAD = true INTERP = ip else unless self.const_defined? :RUN_EVENTLOOP_ON_MAIN_THREAD RUN_EVENTLOOP_ON_MAIN_THREAD = false end if RUN_EVENTLOOP_ON_MAIN_THREAD INTERP = ip else ip.delete end end ip = nil else unless self.const_defined? :RUN_EVENTLOOP_ON_MAIN_THREAD 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) rescue => e Thread.current[:interp] = e raise e end status = [nil] def status.value self[0] end def status.value=(val) self[0] = val end Thread.current[:status] = status #sleep begin Thread.current[:status].value = TclTkLib.mainloop(true) rescue Exception=>e Thread.current[:status].value = e ensure INTERP_MUTEX.synchronize{ INTERP_ROOT_CHECK.broadcast } end Thread.current[:status].value = TclTkLib.mainloop(false) } until INTERP_THREAD[:interp] Thread.pass end # INTERP_THREAD.run raise INTERP_THREAD[:interp] if INTERP_THREAD[:interp].kind_of? Exception INTERP = INTERP_THREAD[:interp] INTERP_THREAD_STATUS = INTERP_THREAD[:status] end def INTERP.__getip self end def INTERP.default_master? true end INTERP.instance_eval{ # @tk_cmd_tbl = {}.taint @tk_cmd_tbl = Hash.new{|hash, key| fail IndexError, "unknown command ID '#{key}'" }.taint 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 = {}.taint @tk_table_list = [].taint @init_ip_env = [].taint # table of Procs @add_tk_procs = [].taint # table of [name, args, body] @force_default_encoding ||= [false].taint @encoding ||= [nil].taint def @encoding.to_s; self.join(nil); end @cb_entry_class = Class.new(TkCallbackEntry){ class << self def inspect sprintf("#", 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("#", 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? || tbl.taint @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, '') } 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 = '' INTERP._invoke_without_enc('event', 'add', "<#{WIDGET_DESTROY_HOOK}>", '') 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 at_exit{ INTERP.remove_tk_procs(TclTkLib::FINALIZE_PROC_NAME) } 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 >= 4 fail SecurityError, "cannot send Tk commands at level 4" elsif $SAFE >= 1 && args.find{|obj| obj.tainted?} fail SecurityError, "cannot send tainted Tk commands at level #{$SAFE}" end if async != true && async != false && async != nil args.unshift(async) async = false end if async tk_call('send', '-async', '--', interp, *args) else tk_call('send', '--', interp, *args) end end def rb_appsend(interp, async, *args) if $SAFE >= 4 fail SecurityError, "cannot send Ruby commands at level 4" elsif $SAFE >= 1 && args.find{|obj| obj.tainted?} fail SecurityError, "cannot send tainted Ruby commands at level #{$SAFE}" end if async != true && async != false && async != nil args.unshift(async) async = false end #args = args.collect!{|c| _get_eval_string(c).gsub(/[\[\]$"]/, '\\\\\&')} args = args.collect!{|c| _get_eval_string(c).gsub(/[\[\]$"\\]/, '\\\\\&')} # args.push(').to_s"') # appsend(interp, async, 'ruby "(', *args) args.push('}.call)"') appsend(interp, async, 'ruby "TkComm._get_eval_string(proc{', *args) end def appsend_displayof(interp, win, async, *args) if $SAFE >= 4 fail SecurityError, "cannot send Tk commands at level 4" elsif $SAFE >= 1 && args.find{|obj| obj.tainted?} fail SecurityError, "cannot send tainted Tk commands at level #{$SAFE}" end win = '.' if win == nil if async != true && async != false && async != nil args.unshift(async) async = false end if async tk_call('send', '-async', '-displayof', win, '--', interp, *args) else tk_call('send', '-displayor', win, '--', interp, *args) end end def rb_appsend_displayof(interp, win, async, *args) if $SAFE >= 4 fail SecurityError, "cannot send Ruby commands at level 4" elsif $SAFE >= 1 && args.find{|obj| obj.tainted?} fail SecurityError, "cannot send tainted Ruby commands at level #{$SAFE}" end win = '.' if win == nil if async != true && async != false && async != nil args.unshift(async) async = false end #args = args.collect!{|c| _get_eval_string(c).gsub(/[\[\]$"]/, '\\\\\&')} args = args.collect!{|c| _get_eval_string(c).gsub(/[\[\]$"\\]/, '\\\\\&')} # args.push(').to_s"') # appsend_displayof(interp, win, async, 'ruby "(', *args) args.push('}.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 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 begin TclTkLib.set_eventloop_window_mode(true) 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 if $SAFE < 4 raise status if status.kind_of?(Exception) end } else INTERP_THREAD.value end 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 = INTERP._invoke(*args).taint # 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 = INTERP._invoke(*args).taint #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 if $SAFE >= 4 fail SecurityError, "can't get #{sym} when $SAFE >= 4" end 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 defind? 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_external 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{|key| key = key.to_s pathname = [win, tag, key].join(';') fonts[key] = 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{|key,val| conf[key] = 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{|key,val| conf[key] = 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) fail SecurityError, "can't change the mode" if $SAFE>=4 @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_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) 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, method| ret << [optkey.to_s, '', '', '', self.__send__(method)] } 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, 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 /^(#{__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, method| ret[optkey.to_s] = ['', '', '', self.__send__(method)] } 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{|conf| if ( ! __configinfo_struct[:alias] \ || conf.size > __configinfo_struct[:alias] + 1 ) ret[conf[0]] = conf[-1] end } ret end else # ! TkComm::GET_CONFIGINFO_AS_ARRAY ret = {} configinfo(slot).each{|key, conf| ret[key] = conf[-1] if conf.kind_of?(Array) } ret end end end class TkObject 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) 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 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 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) if $SAFE >= 4 fail SecurityError, "can't wait visibility at $SAFE >= 4" end 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) if $SAFE >= 4 fail SecurityError, "can't wait destroy at $SAFE >= 4" end 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 = '2009-01-13'.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