diff options
Diffstat (limited to 'ext/tk/lib')
343 files changed, 0 insertions, 65032 deletions
diff --git a/ext/tk/lib/README b/ext/tk/lib/README deleted file mode 100644 index df1c7906ea..0000000000 --- a/ext/tk/lib/README +++ /dev/null @@ -1,30 +0,0 @@ -README this file -multi-tk.rb multiple Tk interpreter (included safe-Tk) support -remotei-tk.rb control remote Tk interpreter on the other process support -tk.rb Tk interface - -tk/ library files construct Ruby/Tk - -tkextlib/ non-standard Tcl/Tk extension support libraries - -********************************************************************* -*** The followings exists for backward compatibility only. -*** The only thing which they work is that requires current -*** library files ( tk/*.rb ). -********************************************************************* -tkafter.rb handles Tcl after -tkbgerror.rb Tk error module -tkcanvas.rb Tk canvas interface -tkclass.rb provides generic names for Tk classes -tkconsole.rb console command support -tkdialog.rb Tk dialog class -tkentry.rb Tk entry class -tkfont.rb Tk font support -tkmacpkg.rb Mac resource support -tkmenubar.rb TK menubar utility -tkmngfocus.rb focus manager -tkpalette.rb palette support -tkscrollbox.rb scroll box, also example of compound widget -tktext.rb text classes -tkvirtevent.rb virtual event support -tkwinpkg.rb Win DDE and registry support diff --git a/ext/tk/lib/multi-tk.rb b/ext/tk/lib/multi-tk.rb deleted file mode 100644 index 0fe766c049..0000000000 --- a/ext/tk/lib/multi-tk.rb +++ /dev/null @@ -1,3743 +0,0 @@ -# frozen_string_literal: false -# -# multi-tk.rb - supports multi Tk interpreters -# by Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp> - -require 'tcltklib' -require 'tkutil' -require 'thread' - -if defined? Tk - fail RuntimeError,"'multi-tk' library must be required before requiring 'tk'" -end - -################################################ -# ignore exception on the mainloop? - -TclTkLib.mainloop_abort_on_exception = true -# TclTkLib.mainloop_abort_on_exception = false -# TclTkLib.mainloop_abort_on_exception = nil - - -################################################ -# add ThreadGroup check to TclTkIp.new -class << TclTkIp - alias __new__ new - private :__new__ - - def new(*args) - if Thread.current.group != ThreadGroup::Default - raise SecurityError, 'only ThreadGroup::Default can call TclTkIp.new' - end - obj = __new__(*args) - obj.instance_eval{ - @force_default_encoding ||= TkUtil.untrust([false]) - @encoding ||= TkUtil.untrust([nil]) - def @encoding.to_s; self.join(nil); end - } - obj - end -end - - -################################################ -# exception to treat the return value from IP -class MultiTkIp_OK < Exception - def self.send(thread, ret=nil) - thread.raise self.new(ret) - end - - def initialize(ret=nil) - super('succeed') - @return_value = ret - end - - attr_reader :return_value - alias value return_value -end -MultiTkIp_OK.freeze - - -################################################ -# methods for construction -class MultiTkIp - class Command_Queue < Queue - def initialize(interp) - @interp = interp - super() - end - - def push(value) - if !@interp || @interp.deleted? - fail RuntimeError, "Tk interpreter is already deleted" - end - super(value) - end - alias << push - alias enq push - - def close - @interp = nil - end - end - Command_Queue.freeze - - BASE_DIR = File.dirname(__FILE__) - - WITH_RUBY_VM = Object.const_defined?(:RubyVM) && ::RubyVM.class == Class - WITH_ENCODING = defined?(::Encoding.default_external) - #WITH_ENCODING = Object.const_defined?(:Encoding) && ::Encoding.class == Class - - (@@SLAVE_IP_ID = ['slave'.freeze, TkUtil.untrust('0')]).instance_eval{ - @mutex = Mutex.new - def mutex; @mutex; end - freeze - } - - @@IP_TABLE = TkUtil.untrust({}) unless defined?(@@IP_TABLE) - - @@INIT_IP_ENV = TkUtil.untrust([]) unless defined?(@@INIT_IP_ENV) # table of Procs - @@ADD_TK_PROCS = TkUtil.untrust([]) unless defined?(@@ADD_TK_PROCS) # table of [name, args, body] - - @@TK_TABLE_LIST = TkUtil.untrust([]) unless defined?(@@TK_TABLE_LIST) - - unless defined?(@@TK_CMD_TBL) - @@TK_CMD_TBL = TkUtil.untrust(Object.new) - - # @@TK_CMD_TBL.instance_variable_set('@tbl', {}.taint) - tbl_obj = TkUtil.untrust(Hash.new{|hash,key| - fail IndexError, "unknown command ID '#{key}'" - }) - @@TK_CMD_TBL.instance_variable_set('@tbl', tbl_obj) - - class << @@TK_CMD_TBL - allow = [ - '__send__', '__id__', 'freeze', 'inspect', 'kind_of?', 'object_id', - '[]', '[]=', 'delete', 'each', 'has_key?' - ] - instance_methods.each{|m| undef_method(m) unless allow.index(m.to_s)} - - def kind_of?(klass) - @tbl.kind_of?(klass) - end - - def inspect - if Thread.current.group == ThreadGroup::Default - @tbl.inspect - else - ip = MultiTkIp.__getip - @tbl.reject{|idx, ent| ent.respond_to?(:ip) && ent.ip != ip}.inspect - end - end - - def [](idx) - return unless (ent = @tbl[idx]) - if Thread.current.group == ThreadGroup::Default - ent - elsif ent.respond_to?(:ip) - (ent.ip == MultiTkIp.__getip)? ent: nil - else - ent - end - end - - def []=(idx,val) - if self.has_key?(idx) && Thread.current.group != ThreadGroup::Default - fail SecurityError,"cannot change the entried command" - end - @tbl[idx] = val - end - - def delete(idx, &blk) - # if gets an entry, is permitted to delete - if self[idx] - @tbl.delete(idx) - elsif blk - blk.call(idx) - else - nil - end - end - - def each(&blk) - if Thread.current.group == ThreadGroup::Default - @tbl.each(&blk) - else - ip = MultiTkIp.__getip - @tbl.each{|idx, ent| - blk.call(idx, ent) unless ent.respond_to?(:ip) && ent.ip != ip - } - end - self - end - - def has_key?(k) - @tbl.has_key?(k) - end - alias include? has_key? - alias key? has_key? - alias member? has_key? - end - - @@TK_CMD_TBL.freeze - end - - ###################################### - - @@CB_ENTRY_CLASS = Class.new(TkCallbackEntry){ - def initialize(ip, cmd) - @ip = ip - @safe = safe = $SAFE - # @cmd = cmd - cmd = MultiTkIp._proc_on_safelevel(&cmd) - @cmd = proc{|*args| cmd.call(safe, *args)} - self.freeze - end - attr_reader :ip, :cmd - def inspect - cmd.inspect - end - def call(*args) - unless @ip.deleted? - current = Thread.current - backup_ip = current[:callback_ip] - current[:callback_ip] = @ip - begin - ret = @ip.cb_eval(@cmd, *args) - fail ret if ret.kind_of?(Exception) - ret - rescue TkCallbackBreak, TkCallbackContinue => e - fail e - rescue SecurityError => e - # in 'exit', 'exit!', and 'abort' : security error --> delete IP - if e.backtrace[0] =~ /^(.+?):(\d+):in `(exit|exit!|abort)'/ - @ip.delete - elsif @ip.safe? - if @ip.respond_to?(:cb_error) - @ip.cb_error(e) - else - nil # ignore - end - else - fail e - end - rescue Exception => e - fail e if e.message =~ /^TkCallback/ - - if @ip.safe? - if @ip.respond_to?(:cb_error) - @ip.cb_error(e) - else - nil # ignore - end - else - fail e - end - ensure - current[:callback_ip] = backup_ip - end - end - end - }.freeze - - ###################################### - - def _keys2opts(src_keys) - return nil if src_keys == nil - keys = {}; src_keys.each{|k, v| keys[k.to_s] = v} - #keys.collect{|k,v| "-#{k} #{v}"}.join(' ') - keys.collect{|k,v| "-#{k} #{TclTkLib._conv_listelement(TkComm::_get_eval_string(v))}"}.join(' ') - end - private :_keys2opts - - def _check_and_return(thread, exception, wait=0) - unless thread - unless exception.kind_of?(MultiTkIp_OK) - msg = "#{exception.class}: #{exception.message}" - - if @interp.deleted? - warn("Warning (#{self}): " + msg) - return nil - end - - if safe? - warn("Warning (#{self}): " + msg) if $DEBUG - return nil - end - - begin - @interp._eval_without_enc(@interp._merge_tklist('bgerror', msg)) - rescue Exception => e - warn("Warning (#{self}): " + msg) - end - end - return nil - end - - if wait == 0 - # no wait - Thread.pass - if thread.stop? - thread.raise exception - end - return thread - end - - # wait to stop the caller thread - wait.times{ - if thread.stop? - # ready to send exception - thread.raise exception - return thread - end - - # wait - Thread.pass - } - - # unexpected error - thread.raise RuntimeError, "the thread may not wait for the return value" - return thread - end - - ###################################### - - def set_cb_error(cmd = Proc.new) - @cb_error_proc[0] = cmd - end - - def cb_error(e) - if @cb_error_proc[0].respond_to?(:call) - @cb_error_proc[0].call(e) - end - end - - ###################################### - - def set_safe_level(safe) - if safe > @safe_level[0] - @safe_level[0] = safe - @cmd_queue.enq([@system, 'set_safe_level', safe]) - end - @safe_level[0] - end - def safe_level=(safe) - set_safe_level(safe) - end - def self.set_safe_level(safe) - __getip.set_safe_level(safe) - end - def self.safe_level=(safe) - self.set_safe_level(safe) - end - def safe_level - @safe_level[0] - end - def self.safe_level - __getip.safe_level - end - - def wait_on_mainloop? - @wait_on_mainloop[0] - end - def wait_on_mainloop=(bool) - @wait_on_mainloop[0] = bool - end - - def running_mainloop? - @wait_on_mainloop[1] > 0 - end - - def _destroy_slaves_of_slaveIP(ip) - unless ip.deleted? - # ip._split_tklist(ip._invoke('interp', 'slaves')).each{|name| - ip._split_tklist(ip._invoke_without_enc('interp', 'slaves')).each{|name| - name = _fromUTF8(name) - begin - # ip._eval_without_enc("#{name} eval {foreach i [after info] {after cancel $i}}") - after_ids = ip._eval_without_enc("#{name} eval {after info}") - ip._eval_without_enc("#{name} eval {foreach i {#{after_ids}} {after cancel $i}}") - rescue Exception - end - begin - # ip._invoke('interp', 'eval', name, 'destroy', '.') - ip._invoke(name, 'eval', 'destroy', '.') - rescue Exception - end - - # safe_base? - if ip._eval_without_enc("catch {::safe::interpConfigure #{name}}") == '0' - begin - ip._eval_without_enc("::safe::interpDelete #{name}") - rescue Exception - end - end -=begin - if ip._invoke('interp', 'exists', name) == '1' - begin - ip._invoke(name, 'eval', 'exit') - rescue Exception - end - end -=end - unless ip.deleted? - if ip._invoke('interp', 'exists', name) == '1' - begin - ip._invoke('interp', 'delete', name) - rescue Exception - end - end - end - } - end - end - - def _receiver_eval_proc_core(safe_level, thread, cmd, *args) - begin - #ret = proc{$SAFE = safe_level; cmd.call(*args)}.call - #ret = cmd.call(safe_level, *args) - normal_ret = false - ret = catch(:IRB_EXIT) do # IRB hack - retval = cmd.call(safe_level, *args) - normal_ret = true - retval - end - unless normal_ret - # catch IRB_EXIT - exit(ret) - end - ret - rescue SystemExit => e - # delete IP - unless @interp.deleted? - @slave_ip_tbl.each{|name, subip| - _destroy_slaves_of_slaveIP(subip) - begin - # subip._eval_without_enc("foreach i [after info] {after cancel $i}") - after_ids = subip._eval_without_enc("after info") - subip._eval_without_enc("foreach i {#{after_ids}} {after cancel $i}") - rescue Exception - end -=begin - begin - subip._invoke('destroy', '.') unless subip.deleted? - rescue Exception - end -=end - # safe_base? - if @interp._eval_without_enc("catch {::safe::interpConfigure #{name}}") == '0' - begin - @interp._eval_without_enc("::safe::interpDelete #{name}") - rescue Exception - else - next if subip.deleted? - end - end - if subip.respond_to?(:safe_base?) && subip.safe_base? && - !subip.deleted? - # do 'exit' to call the delete_hook procedure - begin - subip._eval_without_enc('exit') - rescue Exception - end - else - begin - subip.delete unless subip.deleted? - rescue Exception - end - end - } - - begin - # @interp._eval_without_enc("foreach i [after info] {after cancel $i}") - after_ids = @interp._eval_without_enc("after info") - @interp._eval_without_enc("foreach i {#{after_ids}} {after cancel $i}") - rescue Exception - end - begin - @interp._invoke('destroy', '.') unless @interp.deleted? - rescue Exception - end - if @safe_base && !@interp.deleted? - # do 'exit' to call the delete_hook procedure - @interp._eval_without_enc('exit') - else - @interp.delete unless @interp.deleted? - end - end - - if e.backtrace[0] =~ /^(.+?):(\d+):in `(exit|exit!|abort)'/ - _check_and_return(thread, MultiTkIp_OK.new($3 == 'exit')) - else - _check_and_return(thread, MultiTkIp_OK.new(nil)) - end - - # if master? && !safe? && allow_ruby_exit? - if !@interp.deleted? && master? && !safe? && allow_ruby_exit? -=begin - ObjectSpace.each_object(TclTkIp){|obj| - obj.delete unless obj.deleted? - } -=end - #exit(e.status) - fail e - end - # break - - rescue SecurityError => e - # in 'exit', 'exit!', and 'abort' : security error --> delete IP - if e.backtrace[0] =~ /^(.+?):(\d+):in `(exit|exit!|abort)'/ - ret = ($3 == 'exit') - unless @interp.deleted? - @slave_ip_tbl.each{|name, subip| - _destroy_slaves_of_slaveIP(subip) - begin - # subip._eval_without_enc("foreach i [after info] {after cancel $i}") - after_ids = subip._eval_without_enc("after info") - subip._eval_without_enc("foreach i {#{after_ids}} {after cancel $i}") - rescue Exception - end -=begin - begin - subip._invoke('destroy', '.') unless subip.deleted? - rescue Exception - end -=end - # safe_base? - if @interp._eval_without_enc("catch {::safe::interpConfigure #{name}}") == '0' - begin - @interp._eval_without_enc("::safe::interpDelete #{name}") - rescue Exception - else - next if subip.deleted? - end - end - if subip.respond_to?(:safe_base?) && subip.safe_base? && - !subip.deleted? - # do 'exit' to call the delete_hook procedure - begin - subip._eval_without_enc('exit') - rescue Exception - end - else - begin - subip.delete unless subip.deleted? - rescue Exception - end - end - } - - begin - # @interp._eval_without_enc("foreach i [after info] {after cancel $i}") - after_ids = @interp._eval_without_enc("after info") - @interp._eval_without_enc("foreach i {#{after_ids}} {after cancel $i}") - rescue Exception - end -=begin - begin - @interp._invoke('destroy', '.') unless @interp.deleted? - rescue Exception - end -=end - if @safe_base && !@interp.deleted? - # do 'exit' to call the delete_hook procedure - @interp._eval_without_enc('exit') - else - @interp.delete unless @interp.deleted? - end - end - _check_and_return(thread, MultiTkIp_OK.new(ret)) - # break - - else - # raise security error - _check_and_return(thread, e) - end - - rescue Exception => e - # raise exception - begin - bt = _toUTF8(e.backtrace.join("\n")) - if MultiTkIp::WITH_ENCODING - bt.force_encoding('utf-8') - else - bt.instance_variable_set(:@encoding, 'utf-8') - end - rescue Exception - bt = e.backtrace.join("\n") - end - begin - @interp._set_global_var('errorInfo', bt) - rescue Exception - end - _check_and_return(thread, e) - - else - # no exception - _check_and_return(thread, MultiTkIp_OK.new(ret)) - end - end - - def _receiver_eval_proc(last_thread, safe_level, thread, cmd, *args) - if thread - Thread.new{ - last_thread.join if last_thread - unless @interp.deleted? - _receiver_eval_proc_core(safe_level, thread, cmd, *args) - end - } - else - Thread.new{ - unless @interp.deleted? - _receiver_eval_proc_core(safe_level, thread, cmd, *args) - end - } - last_thread - end - end - - private :_receiver_eval_proc, :_receiver_eval_proc_core - - def _receiver_mainloop(check_root) - if @evloop_thread[0] && @evloop_thread[0].alive? - @evloop_thread[0] - else - @evloop_thread[0] = Thread.new{ - while !@interp.deleted? - #if check_root - # inf = @interp._invoke_without_enc('info', 'command', '.') - # break if !inf.kind_of?(String) || inf != '.' - #end - break if check_root && !@interp.has_mainwindow? - sleep 0.5 - end - } - @evloop_thread[0] - end - end - - def _create_receiver_and_watchdog(lvl = $SAFE) - lvl = $SAFE if lvl < $SAFE - - # command-procedures receiver - receiver = Thread.new(lvl){|safe_level| - last_thread = {} - - loop do - break if @interp.deleted? - thread, cmd, *args = @cmd_queue.deq - if thread == @system - # control command - case cmd - when 'set_safe_level' - begin - safe_level = args[0] if safe_level < args[0] - rescue Exception - end - when 'call_mainloop' - thread = args.shift - _check_and_return(thread, - MultiTkIp_OK.new(_receiver_mainloop(*args))) - else - # ignore - end - - else - # procedure - last_thread[thread] = _receiver_eval_proc(last_thread[thread], - safe_level, thread, - cmd, *args) - end - end - } - - # watchdog of receiver - watchdog = Thread.new{ - begin - loop do - sleep 1 - if @interp.deleted? - receiver.kill - @cmd_queue.close - end - break unless receiver.alive? - end - rescue Exception - # ignore all kind of Exception - end - - # receiver is dead - retry_count = 3 - loop do - Thread.pass - begin - thread, cmd, *args = @cmd_queue.deq(true) # non-block - rescue ThreadError - # queue is empty - retry_count -= 1 - break if retry_count <= 0 - sleep 0.5 - retry - end - next unless thread - if thread.alive? - if @interp.deleted? - thread.raise RuntimeError, 'the interpreter is already deleted' - else - thread.raise RuntimeError, - 'the interpreter no longer receives command procedures' - end - end - end - } - - # return threads - [receiver, watchdog] - end - private :_check_and_return, :_create_receiver_and_watchdog - - ###################################### - - unless self.const_defined? :RUN_EVENTLOOP_ON_MAIN_THREAD - ### Ruby 1.9 !!!!!!!!!!!!!!!!!!!!!!!!!! - RUN_EVENTLOOP_ON_MAIN_THREAD = false - end - - if self.const_defined? :DEFAULT_MASTER_NAME - name = DEFAULT_MASTER_NAME.to_s - else - name = nil - end - if self.const_defined?(:DEFAULT_MASTER_OPTS) && - DEFAULT_MASTER_OPTS.kind_of?(Hash) - keys = DEFAULT_MASTER_OPTS - else - keys = {} - end - - @@DEFAULT_MASTER = self.allocate - @@DEFAULT_MASTER.instance_eval{ - @tk_windows = TkUtil.untrust({}) - - @tk_table_list = TkUtil.untrust([]) - - @slave_ip_tbl = TkUtil.untrust({}) - - @slave_ip_top = TkUtil.untrust({}) - - @evloop_thread = TkUtil.untrust([]) - - unless keys.kind_of? Hash - fail ArgumentError, "expecting a Hash object for the 2nd argument" - end - - if !WITH_RUBY_VM || RUN_EVENTLOOP_ON_MAIN_THREAD ### check Ruby 1.9 !!!!!!! - @interp = TclTkIp.new(name, _keys2opts(keys)) - else ### Ruby 1.9 !!!!!!!!!!! - @interp_thread = Thread.new{ - current = Thread.current - begin - current[:interp] = interp = TclTkIp.new(name, _keys2opts(keys)) - rescue e - current[:interp] = e - raise e - end - #sleep - current[:mutex] = mutex = Mutex.new - current[:root_check] = cond_var = ConditionVariable.new - - status = [nil] - def status.value - self[0] - end - def status.value=(val) - self[0] = val - end - current[:status] = status - - begin - begin - #TclTkLib.mainloop_abort_on_exception = false - #Thread.current[:status].value = TclTkLib.mainloop(true) - interp.mainloop_abort_on_exception = true - current[:status].value = interp.mainloop(true) - rescue SystemExit=>e - current[:status].value = e - rescue Exception=>e - current[:status].value = e - retry if interp.has_mainwindow? - ensure - mutex.synchronize{ cond_var.broadcast } - end - - #Thread.current[:status].value = TclTkLib.mainloop(false) - current[:status].value = interp.mainloop(false) - - ensure - # interp must be deleted before the thread for interp is dead. - # If not, raise Tcl_Panic on Tcl_AsyncDelete because async handler - # deleted by the wrong thread. - interp.delete - end - } - 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] - - # delete the interpreter and kill the eventloop thread at exit - interp = @interp - interp_thread = @interp_thread - END{ - if interp_thread.alive? - interp.delete - interp_thread.kill - end - } - - def self.mainloop(check_root = true) - begin - TclTkLib.set_eventloop_window_mode(true) - @interp_thread.value - ensure - TclTkLib.set_eventloop_window_mode(false) - end - end - end - - @interp.instance_eval{ - @force_default_encoding ||= TkUtil.untrust([false]) - @encoding ||= TkUtil.untrust([nil]) - def @encoding.to_s; self.join(nil); end - } - - @ip_name = nil - - @callback_status = TkUtil.untrust([]) - - @system = Object.new - - @wait_on_mainloop = TkUtil.untrust([true, 0]) - - @threadgroup = Thread.current.group - - @safe_base = false - - @safe_level = [$SAFE] - - @cmd_queue = MultiTkIp::Command_Queue.new(@interp) - - @cmd_receiver, @receiver_watchdog = _create_receiver_and_watchdog(@safe_level[0]) - - @threadgroup.add @cmd_receiver - @threadgroup.add @receiver_watchdog - - # NOT enclose @threadgroup for @@DEFAULT_MASTER - - @@IP_TABLE[ThreadGroup::Default] = self - @@IP_TABLE[@threadgroup] = self - - ################################# - - @pseudo_toplevel = [false, nil] - - def self.__pseudo_toplevel - Thread.current.group == ThreadGroup::Default && - MultiTkIp.__getip == @@DEFAULT_MASTER && - self.__pseudo_toplevel_evaluable? && @pseudo_toplevel[1] - end - - def self.__pseudo_toplevel=(m) - unless (Thread.current.group == ThreadGroup::Default && - MultiTkIp.__getip == @@DEFAULT_MASTER) - fail SecurityError, "no permission to manipulate" - end - - # if m.kind_of?(Module) && m.respond_to?(:pseudo_toplevel_evaluable?) - if m.respond_to?(:pseudo_toplevel_evaluable?) - @pseudo_toplevel[0] = true - @pseudo_toplevel[1] = m - else - fail ArgumentError, 'fail to set pseudo-toplevel' - end - self - end - - def self.__pseudo_toplevel_evaluable? - begin - @pseudo_toplevel[0] && @pseudo_toplevel[1].pseudo_toplevel_evaluable? - rescue Exception - false - end - end - - def self.__pseudo_toplevel_evaluable=(mode) - unless (Thread.current.group == ThreadGroup::Default && - MultiTkIp.__getip == @@DEFAULT_MASTER) - fail SecurityError, "no permission to manipulate" - end - - @pseudo_toplevel[0] = (mode)? true: false - end - - ################################# - - @assign_request = Class.new(Exception){ - def self.new(target, ret) - obj = super() - obj.target = target - obj.ret = ret - obj - end - attr_accessor :target, :ret - } - - @assign_thread = Thread.new{ - loop do - begin - Thread.stop - rescue @assign_request=>req - begin - req.ret[0] = req.target.instance_eval{ - @cmd_receiver, @receiver_watchdog = - _create_receiver_and_watchdog(@safe_level[0]) - @threadgroup.add @cmd_receiver - @threadgroup.add @receiver_watchdog - @threadgroup.enclose - true - } - rescue Exception=>e - begin - req.ret[0] = e - rescue Exception - # ignore - end - end - rescue Exception - # ignore - end - end - } - - def self.assign_receiver_and_watchdog(target) - ret = [nil] - @assign_thread.raise(@assign_request.new(target, ret)) - while ret[0] == nil - unless @assign_thread.alive? - raise RuntimeError, 'lost the thread to assign a receiver and a watchdog thread' - end - end - if ret[0].kind_of?(Exception) - raise ret[0] - else - ret[0] - end - end - - ################################# - - @init_ip_env_queue = Queue.new - Thread.new{ - current = Thread.current - loop { - mtx, cond, ret, table, script = @init_ip_env_queue.deq - begin - ret[0] = table.each{|tg, ip| ip._init_ip_env(script) } - rescue Exception => e - ret[0] = e - ensure - mtx.synchronize{ cond.signal } - end - mtx = cond = ret = table = script = nil # clear variables for GC - } - } - - def self.__init_ip_env__(table, script) - ret = [] - mtx = (Thread.current[:MultiTk_ip_Mutex] ||= Mutex.new) - cond = (Thread.current[:MultiTk_ip_CondVar] ||= ConditionVariable.new) - mtx.synchronize{ - @init_ip_env_queue.enq([mtx, cond, ret, table, script]) - cond.wait(mtx) - } - if ret[0].kind_of?(Exception) - raise ret[0] - else - ret[0] - end - end - - ################################# - - class << self - undef :instance_eval - end - } - - @@DEFAULT_MASTER.freeze # defend against modification - - ###################################### - - def self.inherited(subclass) - # trust if on ThreadGroup::Default or @@DEFAULT_MASTER's ThreadGroup - if @@IP_TABLE[Thread.current.group] == @@DEFAULT_MASTER - begin - class << subclass - self.methods.each{|m| - name = m.to_s - begin - unless name == '__id__' || name == '__send__' || name == 'freeze' - undef_method(m) - end - rescue Exception - # ignore all exceptions - end - } - end - ensure - subclass.freeze - fail SecurityError, - "cannot create subclass of MultiTkIp on a untrusted ThreadGroup" - end - end - end - - ###################################### - - @@SAFE_OPT_LIST = [ - 'accessPath'.freeze, - 'statics'.freeze, - 'nested'.freeze, - 'deleteHook'.freeze - ].freeze - - def _parse_slaveopts(keys) - name = nil - safe = false - safe_opts = {} - tk_opts = {} - - keys.each{|k,v| - k_str = k.to_s - if k_str == 'name' - name = v - elsif k_str == 'safe' - safe = v - elsif @@SAFE_OPT_LIST.member?(k_str) - safe_opts[k_str] = v - else - tk_opts[k_str] = v - end - } - - if keys['without_tk'] || keys[:without_tk] - [name, safe, safe_opts, nil] - else - [name, safe, safe_opts, tk_opts] - end - end - private :_parse_slaveopts - - def _create_slave_ip_name - @@SLAVE_IP_ID.mutex.synchronize{ - name = @@SLAVE_IP_ID.join('') - @@SLAVE_IP_ID[1].succ! - name.freeze - } - end - private :_create_slave_ip_name - - ###################################### - - def __check_safetk_optkeys(optkeys) - # based on 'safetk.tcl' - new_keys = {} - optkeys.each{|k,v| new_keys[k.to_s] = v} - - # check 'display' - if !new_keys.key?('display') - begin - #new_keys['display'] = @interp._invoke('winfo screen .') - new_keys['display'] = @interp._invoke('winfo', 'screen', '.') - rescue - if ENV[DISPLAY] - new_keys['display'] = ENV[DISPLAY] - elsif !new_keys.key?('use') - warn "Warning: no screen info or ENV[DISPLAY], so use ':0.0'" - new_keys['display'] = ':0.0' - end - end - end - - # check 'use' - if new_keys.key?('use') - # given 'use' - case new_keys['use'] - when TkWindow - new_keys['use'] = TkWinfo.id(new_keys['use']) - #assoc_display = @interp._eval('winfo screen .') - assoc_display = @interp._invoke('winfo', 'screen', '.') - when /^\..*/ - new_keys['use'] = @interp._invoke('winfo', 'id', new_keys['use']) - assoc_display = @interp._invoke('winfo', 'screen', new_keys['use']) - else - begin - pathname = @interp._invoke('winfo', 'pathname', new_keys['use']) - assoc_display = @interp._invoke('winfo', 'screen', pathname) - rescue - assoc_display = new_keys['display'] - end - end - - # match display? - if assoc_display != new_keys['display'] - if optkeys.key?(:display) || optkeys.key?('display') - fail RuntimeError, - "conflicting 'display'=>#{new_keys['display']} " + - "and display '#{assoc_display}' on 'use'=>#{new_keys['use']}" - else - new_keys['display'] = assoc_display - end - end - end - - # return - new_keys - end - private :__check_safetk_optkeys - - def __create_safetk_frame(slave_ip, slave_name, app_name, keys) - # display option is used by ::safe::loadTk - loadTk_keys = {} - loadTk_keys['display'] = keys['display'] - dup_keys = keys.dup - - # keys for toplevel : allow followings - toplevel_keys = {} - ['height', 'width', 'background', 'menu'].each{|k| - toplevel_keys[k] = dup_keys.delete(k) if dup_keys.key?(k) - } - toplevel_keys['classname'] = 'SafeTk' - toplevel_keys['screen'] = dup_keys.delete('display') - - # other keys used by pack option of container frame - - # create toplevel widget - begin - top = TkToplevel.new(toplevel_keys) - rescue NameError => e - fail e unless @interp.safe? - fail SecurityError, "unable create toplevel on the safe interpreter" - end - msg = "Untrusted Ruby/Tk applet (#{slave_name})" - if app_name.kind_of?(String) - top.title "#{app_name} (#{slave_name})" - else - top.title msg - end - - # procedure to delete slave interpreter - slave_delete_proc = proc{ - unless slave_ip.deleted? - #if slave_ip._invoke('info', 'command', '.') != "" - # slave_ip._invoke('destroy', '.') - #end - #slave_ip.delete - slave_ip._eval_without_enc('exit') - end - begin - top.destroy if top.winfo_exist? - rescue - # ignore - end - } - tag = TkBindTag.new.bind('Destroy', slave_delete_proc) - - top.bindtags = top.bindtags.unshift(tag) - - # create control frame - TkFrame.new(top, :bg=>'red', :borderwidth=>3, :relief=>'ridge') {|fc| - fc.bindtags = fc.bindtags.unshift(tag) - - TkFrame.new(fc, :bd=>0){|f| - TkButton.new(f, - :text=>'Delete', :bd=>1, :padx=>2, :pady=>0, - :highlightthickness=>0, :command=>slave_delete_proc - ).pack(:side=>:right, :fill=>:both) - f.pack(:side=>:right, :fill=>:both, :expand=>true) - } - - TkLabel.new(fc, :text=>msg, :padx=>2, :pady=>0, - :anchor=>:w).pack(:side=>:left, :fill=>:both, :expand=>true) - - fc.pack(:side=>:bottom, :fill=>:x) - } - - # container frame for slave interpreter - dup_keys['fill'] = :both unless dup_keys.key?('fill') - dup_keys['expand'] = true unless dup_keys.key?('expand') - c = TkFrame.new(top, :container=>true).pack(dup_keys) - c.bind('Destroy', proc{top.destroy}) - - # return keys - loadTk_keys['use'] = TkWinfo.id(c) - [loadTk_keys, top.path] - end - private :__create_safetk_frame - - def __create_safe_slave_obj(safe_opts, app_name, tk_opts) - raise SecurityError, "no permission to manipulate" unless self.manipulable? - - # safe interpreter - ip_name = _create_slave_ip_name - slave_ip = @interp.create_slave(ip_name, true) - slave_ip.instance_eval{ - @force_default_encoding ||= TkUtil.untrust([false]) - @encoding ||= TkUtil.untrust([nil]) - def @encoding.to_s; self.join(nil); end - } - @slave_ip_tbl[ip_name] = slave_ip - def slave_ip.safe_base? - true - end - - @interp._eval("::safe::interpInit #{ip_name}") - - slave_ip._invoke('set', 'argv0', app_name) if app_name.kind_of?(String) - - if tk_opts - tk_opts = __check_safetk_optkeys(tk_opts) - if tk_opts.key?('use') - @slave_ip_top[ip_name] = '' - else - tk_opts, top_path = __create_safetk_frame(slave_ip, ip_name, app_name, - tk_opts) - @slave_ip_top[ip_name] = top_path - end - @interp._eval("::safe::loadTk #{ip_name} #{_keys2opts(tk_opts)}") - @interp._invoke('__replace_slave_tk_commands__', ip_name) - else - @slave_ip_top[ip_name] = nil - end - - if safe_opts.key?('deleteHook') || safe_opts.key?(:deleteHook) - @interp._eval("::safe::interpConfigure #{ip_name} " + - _keys2opts(safe_opts)) - else - @interp._eval("::safe::interpConfigure #{ip_name} " + - _keys2opts(safe_opts) + '-deleteHook {' + - TkComm._get_eval_string(proc{|slave| - self._default_delete_hook(slave) - }) + '}') - end - - [slave_ip, ip_name] - end - - def __create_trusted_slave_obj(name, keys) - raise SecurityError, "no permission to manipulate" unless self.manipulable? - - ip_name = _create_slave_ip_name - slave_ip = @interp.create_slave(ip_name, false) - slave_ip.instance_eval{ - @force_default_encoding ||= TkUtil.untrust([false]) - @encoding ||= TkUtil.untrust([nil]) - def @encoding.to_s; self.join(nil); end - } - slave_ip._invoke('set', 'argv0', name) if name.kind_of?(String) - slave_ip._invoke('set', 'argv', _keys2opts(keys)) - @interp._invoke('load', '', 'Tk', ip_name) - @interp._invoke('__replace_slave_tk_commands__', ip_name) - @slave_ip_tbl[ip_name] = slave_ip - [slave_ip, ip_name] - end - - ###################################### - - def _create_slave_object(keys={}) - raise SecurityError, "no permission to manipulate" unless self.manipulable? - - ip = MultiTkIp.new_slave(self, keys={}) - @slave_ip_tbl[ip.name] = ip - end - - ###################################### - - def initialize(master, safeip=true, keys={}) - if master.deleted? && safeip == nil - fail RuntimeError, "cannot create a slave of a deleted interpreter" - end - - if !master.deleted? && !master.master? && master.safe? - fail SecurityError, "safe-slave-ip cannot create a new interpreter" - end - - if safeip == nil && !master.master? - fail SecurityError, "slave-ip cannot create a master-ip" - end - - unless keys.kind_of? Hash - fail ArgumentError, "expecting a Hash object for the 2nd argument" - end - - @tk_windows = {} - @tk_table_list = [] - @slave_ip_tbl = {} - @slave_ip_top = {} - @cb_error_proc = [] - @evloop_thread = [] - - TkUtil.untrust(@tk_windows) unless @tk_windows.tainted? - TkUtil.untrust(@tk_table_list) unless @tk_table_list.tainted? - TkUtil.untrust(@slave_ip_tbl) unless @slave_ip_tbl.tainted? - TkUtil.untrust(@slave_ip_top) unless @slave_ip_top.tainted? - TkUtil.untrust(@cb_error_proc) unless @cb_error_proc.tainted? - TkUtil.untrust(@evloop_thread) unless @evloop_thread.tainted? - - @callback_status = [] - - name, safe, safe_opts, tk_opts = _parse_slaveopts(keys) - - safe = 1 if safe && !safe.kind_of?(Fixnum) - - @safe_base = false - - if safeip == nil - # create master-ip - unless WITH_RUBY_VM - @interp = TclTkIp.new(name, _keys2opts(tk_opts)) - @interp.instance_eval{ - @force_default_encoding ||= TkUtil.untrust([false]) - @encoding ||= TkUtil.untrust([nil]) - def @encoding.to_s; self.join(nil); end - } - - else ### Ruby 1.9 !!!!!!!!!!! -=begin - @interp_thread = Thread.new{ - Thread.current[:interp] = interp = TclTkIp.new(name, _keys2opts(tk_opts)) - interp.instance_eval{ - @force_default_encoding ||= TkUtil.untrust([false]) - @encoding ||= TkUtil.untrust([nil]) - def @encoding.to_s; self.join(nil); end - } - - #sleep - TclTkLib.mainloop(true) - } - until @interp_thread[:interp] - Thread.pass - end - # INTERP_THREAD.run - @interp = @interp_thread[:interp] -=end - @interp_thread = Thread.new{ - current = Thread.current - begin - current[:interp] = interp = TclTkIp.new(name, _keys2opts(tk_opts)) - rescue e - current[:interp] = e - raise e - end - #sleep - #TclTkLib.mainloop(true) - current[:mutex] = mutex = Mutex.new - current[:root_check] = cond_ver = ConditionVariable.new - - status = [nil] - def status.value - self[0] - end - def status.value=(val) - self[0] = val - end - current[:status] = status - - begin - begin - current[:status].value = interp.mainloop(true) - rescue SystemExit=>e - current[:status].value = e - rescue Exception=>e - current[:status].value = e - retry if interp.has_mainwindow? - ensure - mutex.synchronize{ cond_var.broadcast } - end - current[:status].value = interp.mainloop(false) - ensure - interp.delete - end - } - until @interp_thread[:interp] - Thread.pass - end - # INTERP_THREAD.run - @interp = @interp_thread[:interp] - - @evloop_thread[0] = @interp_thread - - def self.mainloop(check_root = true) - begin - TclTkLib.set_eventloop_window_mode(true) - @interp_thread.value - ensure - TclTkLib.set_eventloop_window_mode(false) - end - end - end - - @interp.instance_eval{ - @force_default_encoding ||= TkUtil.untrust([false]) - @encoding ||= TkUtil.untrust([nil]) - def @encoding.to_s; self.join(nil); end - } - - @ip_name = nil - - if safe - safe = $SAFE if safe < $SAFE - @safe_level = [safe] - else - @safe_level = [$SAFE] - end - - else - # create slave-ip - if safeip || master.safe? - @safe_base = true - @interp, @ip_name = master.__create_safe_slave_obj(safe_opts, - name, tk_opts) - # @interp_thread = nil if RUBY_VERSION < '1.9.0' ### !!!!!!!!!!! - @interp_thread = nil unless WITH_RUBY_VM ### Ruby 1.9 !!!!!!!!!!! - if safe - safe = master.safe_level if safe < master.safe_level - @safe_level = [safe] - else - @safe_level = [1] - end - else - @interp, @ip_name = master.__create_trusted_slave_obj(name, tk_opts) - # @interp_thread = nil if RUBY_VERSION < '1.9.0' ### !!!!!!!!!!! - @interp_thread = nil unless WITH_RUBY_VM ### Ruby 1.9 !!!!!!!!!!! - if safe - safe = master.safe_level if safe < master.safe_level - @safe_level = [safe] - else - @safe_level = [master.safe_level] - end - end - @set_alias_proc = proc{|name| - master._invoke('interp', 'alias', @ip_name, name, '', name) - }.freeze - end - - @system = Object.new - - @wait_on_mainloop = TkUtil.untrust([true, 0]) - # @wait_on_mainloop = TkUtil.untrust([false, 0]) - - @threadgroup = ThreadGroup.new - - @pseudo_toplevel = [false, nil] - - @cmd_queue = MultiTkIp::Command_Queue.new(@interp) - -=begin - @cmd_receiver, @receiver_watchdog = _create_receiver_and_watchdog(@safe_level[0]) - - @threadgroup.add @cmd_receiver - @threadgroup.add @receiver_watchdog - - @threadgroup.enclose -=end - @@DEFAULT_MASTER.assign_receiver_and_watchdog(self) - - @@IP_TABLE[@threadgroup] = self - @@TK_TABLE_LIST.size.times{ - @tk_table_list << TkUtil.untrust({}) - } - _init_ip_internal(@@INIT_IP_ENV, @@ADD_TK_PROCS) - - class << self - undef :instance_eval - end - - # dummy call for initialization - self.eval_proc{ Tk.tk_call('set', 'tcl_patchLevel') } - - self.freeze # defend against modification - end - - ###################################### - - def _default_delete_hook(slave) - raise SecurityError, "no permission to manipulate" unless self.manipulable? - @slave_ip_tbl.delete(slave) - top = @slave_ip_top.delete(slave) - if top.kind_of?(String) - # call default hook of safetk.tcl (ignore exceptions) - if top == '' - begin - @interp._eval("::safe::disallowTk #{slave}") - rescue - warn("Warning: fail to call '::safe::disallowTk'") if $DEBUG - end - else # toplevel path - begin - @interp._eval("::safe::tkDelete {} #{top} #{slave}") - rescue - warn("Warning: fail to call '::safe::tkDelete'") if $DEBUG - begin - @interp._eval("destroy #{top}") - rescue - warn("Warning: fail to destroy toplevel") if $DEBUG - end - end - end - end - end - -end - - -# get target IP -class MultiTkIp - @@CALLBACK_SUBTHREAD = Class.new(Thread){ - def self.new(interp, &blk) - super(interp){|ip| Thread.current[:callback_ip] = ip; blk.call} - end - - @table = TkUtil.untrust(Hash.new{|h,k| h[k] = TkUtil.untrust([])}) - def self.table - @table - end - } - - def self._ip_id_ - __getip._ip_id_ - end - def _ip_id_ - # for RemoteTkIp - '' - end - - def self.__getip - current = Thread.current - if current.kind_of?(@@CALLBACK_SUBTHREAD) - return current[:callback_ip] - end - if TclTkLib.mainloop_thread? != false && current[:callback_ip] - return current[:callback_ip] - end - if current.group == ThreadGroup::Default - @@DEFAULT_MASTER - else - ip = @@IP_TABLE[current.group] - unless ip - fail SecurityError, - "cannot call Tk methods on #{Thread.current.inspect}" - end - ip - end - end -end - - -# aliases of constructor -class << MultiTkIp - alias __new new - private :__new - - def new_master(safe=nil, keys={}, &blk) - if MultiTkIp::WITH_RUBY_VM - #### TODO !!!!!! - fail RuntimeError, - 'sorry, still not support multiple master-interpreters on RubyVM' - end - - if safe.kind_of?(Hash) - keys = safe - elsif safe.kind_of?(Integer) - raise ArgumentError, "unexpected argument(s)" unless keys.kind_of?(Hash) - if !keys.key?(:safe) && !keys.key?('safe') - keys[:safe] = safe - end - elsif safe == nil - # do nothing - else - raise ArgumentError, "unexpected argument(s)" - end - - ip = __new(__getip, nil, keys) - #ip.eval_proc(proc{$SAFE=ip.safe_level; Proc.new}.call) if block_given? - if block_given? - #Thread.new{ip.eval_proc(proc{$SAFE=ip.safe_level; Proc.new}.call)} - #Thread.new{ip.eval_proc(proc{$SAFE=ip.safe_level; yield}.call)} - ip._proc_on_safelevel(&blk).call(ip.safe_level) - end - ip - end - - alias new new_master - - def new_slave(safe=nil, keys={}, &blk) - if safe.kind_of?(Hash) - keys = safe - elsif safe.kind_of?(Integer) - raise ArgumentError, "unexpected argument(s)" unless keys.kind_of?(Hash) - if !keys.key?(:safe) && !keys.key?('safe') - keys[:safe] = safe - end - elsif safe == nil - # do nothing - else - raise ArgumentError, "unexpected argument(s)" - end - - ip = __new(__getip, false, keys) - # ip.eval_proc(proc{$SAFE=ip.safe_level; Proc.new}.call) if block_given? - if block_given? - #Thread.new{ip.eval_proc(proc{$SAFE=ip.safe_level; Proc.new}.call)} - #Thread.new{ip.eval_proc(proc{$SAFE=ip.safe_level; yield}.call)} - ip._proc_on_safelevel(&blk).call(ip.safe_level) - end - ip - end - alias new_trusted_slave new_slave - - def new_safe_slave(safe=1, keys={}, &blk) - if safe.kind_of?(Hash) - keys = safe - elsif safe.kind_of?(Integer) - raise ArgumentError, "unexpected argument(s)" unless keys.kind_of?(Hash) - if !keys.key?(:safe) && !keys.key?('safe') - keys[:safe] = safe - end - else - raise ArgumentError, "unexpected argument(s)" - end - - ip = __new(__getip, true, keys) - # ip.eval_proc(proc{$SAFE=ip.safe_level; Proc.new}.call) if block_given? - if block_given? - #Thread.new{ip.eval_proc(proc{$SAFE=ip.safe_level; Proc.new}.call)} - #Thread.new{ip.eval_proc(proc{$SAFE=ip.safe_level; yield}.call)} - ip._proc_on_safelevel(&blk).call(ip.safe_level) - end - ip - end - alias new_safeTk new_safe_slave -end - - -# get info -class MultiTkIp - def inspect - s = self.to_s.chop! - if self.manipulable? - if master? - if @interp.deleted? - s << ':deleted-master' - else - s << ':master' - end - else - if @interp.deleted? - s << ':deleted-slave' - elsif @interp.safe? - s << ':safe-slave' - else - s << ':trusted-slave' - end - end - end - s << '>' - end - - def master? - if @ip_name - false - else - true - end - end - def self.master? - __getip.master? - end - - def slave? - not master? - end - def self.slave? - not self.master? - end - - def alive? - raise SecurityError, "no permission to manipulate" unless self.manipulable? - begin - return false unless @cmd_receiver.alive? - return false if @interp.deleted? - return false if @interp._invoke('interp', 'exists', '') == '0' - rescue Exception - return false - end - true - end - def self.alive? - __getip.alive? - end - - def path - @ip_name || '' - end - def self.path - __getip.path - end - def ip_name - @ip_name || '' - end - def self.ip_name - __getip.ip_name - end - def to_eval - @ip_name || '' - end - def self.to_eval - __getip.to_eval - end - - def slaves(all = false) - raise SecurityError, "no permission to manipulate" unless self.manipulable? - @interp._invoke('interp','slaves').split.map!{|name| - if @slave_ip_tbl.key?(name) - @slave_ip_tbl[name] - elsif all - name - else - nil - end - }.compact! - end - def self.slaves(all = false) - __getip.slaves(all) - end - - def manipulable? - return true if (Thread.current.group == ThreadGroup::Default) - ip = MultiTkIp.__getip - (ip == self) || ip._is_master_of?(@interp) - end - def self.manipulable? - true - end - - def _is_master_of?(tcltkip_obj) - tcltkip_obj.slave_of?(@interp) - end - protected :_is_master_of? -end - - -# instance methods to treat tables -class MultiTkIp - def _tk_cmd_tbl - tbl = {} - MultiTkIp.tk_cmd_tbl.each{|id, ent| tbl[id] = ent if ent.ip == self } - tbl - end - - def _tk_windows - @tk_windows - end - - def _tk_table_list - @tk_table_list - end - - def _add_new_tables - (@@TK_TABLE_LIST.size - @tk_table_list.size).times{ - @tk_table_list << TkUtil.untrust({}) - } - end - - def _init_ip_env(script) - self.eval_proc{script.call(self)} - end - - def _add_tk_procs(name, args, body) - return if slave? - @interp._invoke('proc', name, args, body) if args && body - @interp._invoke('interp', 'slaves').split.each{|slave| - @interp._invoke('interp', 'alias', slave, name, '', name) - } - end - - def _remove_tk_procs(*names) - return if slave? - names.each{|name| - name = name.to_s - - return if @interp.deleted? - @interp._invoke('rename', name, '') - - return if @interp.deleted? - @interp._invoke('interp', 'slaves').split.each{|slave| - return if @interp.deleted? - @interp._invoke('interp', 'alias', slave, name, '') rescue nil - } - } - end - - def _init_ip_internal(init_ip_env, add_tk_procs) - #init_ip_env.each{|script| self.eval_proc{script.call(self)}} - init_ip_env.each{|script| self._init_ip_env(script)} - add_tk_procs.each{|name, args, body| - if master? - @interp._invoke('proc', name, args, body) if args && body - else - @set_alias_proc.call(name) - end - } - end -end - - -# class methods to treat tables -class MultiTkIp - def self.tk_cmd_tbl - @@TK_CMD_TBL - end - def self.tk_windows - __getip._tk_windows - end - def self.tk_object_table(id) - __getip._tk_table_list[id] - end - def self.create_table - if __getip.slave? - begin - raise SecurityError, "slave-IP has no permission creating a new table" - rescue SecurityError => e - #p e.backtrace - # Is called on a Ruby/Tk library? - caller_info = e.backtrace[1] - if caller_info =~ %r{^#{MultiTkIp::BASE_DIR}/(tk|tkextlib)/[^:]+\.rb:} - # Probably, caller is a Ruby/Tk library --> allow creating - else - raise e - end - end - end - - id = @@TK_TABLE_LIST.size - obj = Object.new - @@TK_TABLE_LIST << obj - obj.instance_variable_set(:@id, id) - obj.instance_variable_set(:@mutex, Mutex.new) - obj.instance_eval{ - def self.mutex - @mutex - end - def self.method_missing(m, *args) - MultiTkIp.tk_object_table(@id).__send__(m, *args) - end - } - obj.freeze - @@IP_TABLE.each{|tg, ip| ip._add_new_tables } - return obj - end - - def self.init_ip_env(script = Proc.new) - @@INIT_IP_ENV << script - if __getip.slave? - begin - raise SecurityError, "slave-IP has no permission initializing IP env" - rescue SecurityError => e - #p e.backtrace - # Is called on a Ruby/Tk library? - caller_info = e.backtrace[1] - if caller_info =~ %r{^#{MultiTkIp::BASE_DIR}/(tk|tkextlib)/[^:]+\.rb:} - # Probably, caller is a Ruby/Tk library --> allow creating - else - raise e - end - end - end - - # @@IP_TABLE.each{|tg, ip| - # ip._init_ip_env(script) - # } - @@DEFAULT_MASTER.__init_ip_env__(@@IP_TABLE, script) - end - - def self.add_tk_procs(name, args=nil, body=nil) - if name.kind_of?(Array) # => an array of [name, args, body] - name.each{|param| self.add_tk_procs(*param)} - else - name = name.to_s - @@ADD_TK_PROCS << [name, args, body] - @@IP_TABLE.each{|tg, ip| - ip._add_tk_procs(name, args, body) - } - end - end - - def self.remove_tk_procs(*names) - names.each{|name| - name = name.to_s - @@ADD_TK_PROCS.delete_if{|elem| - elem.kind_of?(Array) && elem[0].to_s == name - } - } - @@IP_TABLE.each{|tg, ip| - ip._remove_tk_procs(*names) - } - end - - def self.init_ip_internal - __getip._init_ip_internal(@@INIT_IP_ENV, @@ADD_TK_PROCS) - end -end - -# for callback operation -class MultiTkIp - def self.cb_entry_class - @@CB_ENTRY_CLASS - end - def self.get_cb_entry(cmd) - @@CB_ENTRY_CLASS.new(__getip, cmd).freeze - end - -=begin - def cb_eval(cmd, *args) - #self.eval_callback{ TkComm._get_eval_string(TkUtil.eval_cmd(cmd, *args)) } - #ret = self.eval_callback{ TkComm._get_eval_string(TkUtil.eval_cmd(cmd, *args)) } - ret = self.eval_callback(*args){|safe, *params| - $SAFE=safe if $SAFE < safe - TkComm._get_eval_string(TkUtil.eval_cmd(cmd, *params)) - } - if ret.kind_of?(Exception) - raise ret - end - ret - end -=end - def cb_eval(cmd, *args) - self.eval_callback(*args, - &_proc_on_safelevel{|*params| - TkComm._get_eval_string(TkUtil.eval_cmd(cmd, *params)) - }) - end -=begin - def cb_eval(cmd, *args) - self.eval_callback(*args){|safe, *params| - $SAFE=safe if $SAFE < safe - # TkUtil.eval_cmd(cmd, *params) - TkComm._get_eval_string(TkUtil.eval_cmd(cmd, *params)) - } - end -=end -=begin - def cb_eval(cmd, *args) - @callback_status[0] ||= TkVariable.new - @callback_status[1] ||= TkVariable.new - st, val = @callback_status - th = Thread.new{ - self.eval_callback(*args){|safe, *params| - #p [status, val, safe, *params] - $SAFE=safe if $SAFE < safe - begin - TkComm._get_eval_string(TkUtil.eval_cmd(cmd, *params)) - rescue TkCallbackContinue - st.value = 4 - rescue TkCallbackBreak - st.value = 3 - rescue TkCallbackReturn - st.value = 2 - rescue Exception => e - val.value = e.message - st.value = 1 - else - st.value = 0 - end - } - } - begin - st.wait - status = st.numeric - retval = val.value - rescue => e - fail e - end - - if status == 1 - fail RuntimeError, retval - elsif status == 2 - fail TkCallbackReturn, "Tk callback returns 'return' status" - elsif status == 3 - fail TkCallbackBreak, "Tk callback returns 'break' status" - elsif status == 4 - fail TkCallbackContinue, "Tk callback returns 'continue' status" - else - '' - end - end -=end - -end - -# pseudo-toplevel operation support -class MultiTkIp - # instance method - def __pseudo_toplevel - ip = MultiTkIp.__getip - (ip == @@DEFAULT_MASTER || ip == self) && - self.__pseudo_toplevel_evaluable? && @pseudo_toplevel[1] - end - - def __pseudo_toplevel=(m) - unless (Thread.current.group == ThreadGroup::Default && - MultiTkIp.__getip == @@DEFAULT_MASTER) - fail SecurityError, "no permission to manipulate" - end - - # if m.kind_of?(Module) && m.respond_to?(:pseudo_toplevel_evaluable?) - if m.respond_to?(:pseudo_toplevel_evaluable?) - @pseudo_toplevel[0] = true - @pseudo_toplevel[1] = m - else - fail ArgumentError, 'fail to set pseudo-toplevel' - end - self - end - - def __pseudo_toplevel_evaluable? - begin - @pseudo_toplevel[0] && @pseudo_toplevel[1].pseudo_toplevel_evaluable? - rescue Exception - false - end - end - - def __pseudo_toplevel_evaluable=(mode) - unless (Thread.current.group == ThreadGroup::Default && - MultiTkIp.__getip == @@DEFAULT_MASTER) - fail SecurityError, "no permission to manipulate" - end - - @pseudo_toplevel[0] = (mode)? true: false - end -end - - -################################################ -# use pseudo-toplevel feature of MultiTkIp ? -if (!defined?(Use_PseudoToplevel_Feature_of_MultiTkIp) || - Use_PseudoToplevel_Feature_of_MultiTkIp) - module MultiTkIp_PseudoToplevel_Evaluable - #def pseudo_toplevel_eval(body = Proc.new) - # Thread.current[:TOPLEVEL] = self - # begin - # body.call - # ensure - # Thread.current[:TOPLEVEL] = nil - # end - #end - - def pseudo_toplevel_evaluable? - @pseudo_toplevel_evaluable - end - - def pseudo_toplevel_evaluable=(mode) - @pseudo_toplevel_evaluable = (mode)? true: false - end - - def self.extended(mod) - mod.__send__(:extend_object, mod) - mod.instance_variable_set('@pseudo_toplevel_evaluable', true) - end - end - - class Object - alias __method_missing_alias_for_MultiTkIp__ method_missing - private :__method_missing_alias_for_MultiTkIp__ - - def method_missing(id, *args) - begin - has_top = (top = MultiTkIp.__getip.__pseudo_toplevel) && - top.respond_to?(:pseudo_toplevel_evaluable?) && - top.pseudo_toplevel_evaluable? && - top.respond_to?(id) - rescue Exception => e - has_top = false - end - - if has_top - top.__send__(id, *args) - else - __method_missing_alias_for_MultiTkIp__(id, *args) - end - end - end -else - # dummy - module MultiTkIp_PseudoToplevel_Evaluable - def pseudo_toplevel_evaluable? - false - end - end -end - - -################################################ -# evaluate a procedure on the proper interpreter -class MultiTkIp - # instance & class method - def _proc_on_safelevel(cmd=nil) # require a block for eval - if cmd - if cmd.kind_of?(Method) - _proc_on_safelevel{|*args| cmd.call(*args)} - else - _proc_on_safelevel(&cmd) - end - else - #Proc.new{|safe, *args| $SAFE=safe if $SAFE < safe; yield(*args)} - Proc.new{|safe, *args| - # avoid security error on Exception objects - untrust_proc = proc{|err| - begin - err.untrust if err.respond_to?(:untrust) - rescue SecurityError - end - err - } - $SAFE=safe if $SAFE < safe; - begin - yield(*args) - rescue Exception => e - fail untrust_proc.call(e) - end - } - end - end - def MultiTkIp._proc_on_safelevel(cmd=nil, &blk) - MultiTkIp.__getip._proc_on_safelevel(cmd, &blk) - end - - def _proc_on_current_safelevel(cmd=nil, &blk) # require a block for eval - safe = $SAFE - cmd = _proc_on_safelevel(cmd, &blk) - Proc.new{|*args| cmd.call(safe, *args)} - end - def MultiTkIp._proc_on_current_safelevel(cmd=nil, &blk) - MultiTkIp.__getip._proc_on_current_safelevel(cmd, &blk) - end - - ###################################### - # instance method - def eval_proc_core(req_val, cmd, *args) - # check - raise SecurityError, "no permission to manipulate" unless self.manipulable? - unless cmd.kind_of?(Proc) || cmd.kind_of?(Method) - raise RuntimeError, "A Proc/Method object is expected for the 'cmd' argument" - end - - # on IP thread - if @cmd_receiver == Thread.current || - (!req_val && TclTkLib.mainloop_thread? != false) # callback - begin - ret = cmd.call(safe_level, *args) - rescue SystemExit => e - # exit IP - warn("Warning: "+ e.inspect + " on " + self.inspect) if $DEBUG - begin - self._eval_without_enc('exit') - rescue Exception => e - end - self.delete - ret = nil - rescue Exception => e - if $DEBUG - warn("Warning: " + e.class.inspect + - ((e.message.length > 0)? ' "' + e.message + '"': '') + - " on " + self.inspect) - end -=begin - begin - bt = _toUTF8(e.backtrace.join("\n")) - bt.instance_variable_set(:@encoding, 'utf-8') - rescue Exception - bt = e.backtrace.join("\n") - end - begin - @interp._set_global_var('errorInfo', bt) - rescue Exception - end -=end - ret = e - end - return ret - end - - # send cmd to the proc-queue - unless req_val - begin - @cmd_queue.enq([nil, cmd, *args]) - rescue Exception => e - # ignore - if $DEBUG - warn("Warning: " + e.class.inspect + - ((e.message.length > 0)? ' "' + e.message + '"': '') + - " on " + self.inspect) - end - return e - end - return nil - end - - # send and get return value by exception - begin - @cmd_queue.enq([Thread.current, cmd, *args]) - Thread.stop - rescue MultiTkIp_OK => ret - # return value - return ret.value - rescue SystemExit => e - # exit IP - warn("Warning: " + e.inspect + " on " + self.inspect) if $DEBUG - begin - self._eval_without_enc('exit') - rescue Exception - end - if !self.deleted? && !safe? && allow_ruby_exit? - self.delete - fail e - else - self.delete - end - rescue Exception => e - if $DEBUG - warn("Warning: " + e.class.inspect + - ((e.message.length > 0)? ' "' + e.message + '"': '') + - " on " + self.inspect) - end - return e - end - return nil - end - private :eval_proc_core - -if false && WITH_RUBY_VM ### Ruby 1.9 - # Not stable, so disable this feature - def eval_callback(*args) - if block_given? - cmd = Proc.new - else - cmd = args.shift - end - begin - if @@CALLBACK_SUBTHREAD.table[self].index(Thread.current) - last_th = nil - else - last_th = @@CALLBACK_SUBTHREAD.table[self][-1] - end - @@CALLBACK_SUBTHREAD.new(self){ - @@CALLBACK_SUBTHREAD.table[self] << Thread.current - begin - last_th.join if last_th - eval_proc_core(false, cmd, *args) - rescue Exception=>e - e - ensure - @@CALLBACK_SUBTHREAD.table[self].delete(Thread.current) - end - } - end - end -else ### Ruby 1.8 - def eval_callback(*args) - if block_given? - cmd = Proc.new - else - cmd = args.shift - end - begin - eval_proc_core(false, cmd, *args) - rescue Exception=>e - e - ensure - end - end -end - - def eval_proc(*args, &blk) - if block_given? - cmd = _proc_on_safelevel(&blk) - else - unless (cmd = args.shift) - fail ArgumentError, "A Proc or Method object is expected for 1st argument" - end - cmd = _proc_on_safelevel(&cmd) - end - if TclTkLib.mainloop_thread? == true - # call from eventloop - current = Thread.current - backup_ip = current[:callback_ip] - current[:callback_ip] = self - begin - eval_proc_core(false, cmd, *args) - ensure - current[:callback_ip] = backup_ip - end - else - eval_proc_core(true, - proc{|safe, *params| - Thread.new{cmd.call(safe, *params)}.value - }, - *args) - end - end -=begin - def eval_proc(*args) - # The scope of the eval-block of 'eval_proc' method is different from - # the external. If you want to pass local values to the eval-block, - # use arguments of eval_proc method. They are passed to block-arguments. - if block_given? - cmd = Proc.new - else - unless (cmd = args.shift) - fail ArgumentError, "A Proc or Method object is expected for 1st argument" - end - end - if TclTkLib.mainloop_thread? == true - # call from eventloop - current = Thread.current - backup_ip = current[:callback_ip] - current[:callback_ip] = self - begin - eval_proc_core(false, - proc{|safe, *params| - $SAFE=safe if $SAFE < safe - cmd.call(*params) - }, *args) - ensure - current[:callback_ip] = backup_ip - end - else - eval_proc_core(true, - proc{|safe, *params| - $SAFE=safe if $SAFE < safe - Thread.new(*params, &cmd).value - }, - *args) - end - end -=end - alias call eval_proc - - def bg_eval_proc(*args) - if block_given? - cmd = Proc.new - else - unless (cmd = args.shift) - fail ArgumentError, "A Proc or Method object is expected for 1st argument" - end - end - Thread.new{ - eval_proc(cmd, *args) -=begin - eval_proc_core(false, - proc{|safe, *params| - $SAFE=safe if $SAFE < safe - Thread.new(*params, &cmd).value - }, - safe_level, *args) -=end - } - end - alias background_eval_proc bg_eval_proc - alias thread_eval_proc bg_eval_proc - alias bg_call bg_eval_proc - alias background_call bg_eval_proc - - def eval_string(cmd, *eval_args) - # cmd string ==> proc - unless cmd.kind_of?(String) - raise RuntimeError, "A String object is expected for the 'cmd' argument" - end - - eval_proc_core(true, - proc{|safe| - Kernel.eval("$SAFE=#{safe} if $SAFE < #{safe};" << cmd, - *eval_args) - }) - end - alias eval_str eval_string - - def bg_eval_string(cmd, *eval_args) - # cmd string ==> proc - unless cmd.kind_of?(String) - raise RuntimeError, "A String object is expected for the 'cmd' argument" - end - Thread.new{ - eval_proc_core(true, - proc{|safe| - Kernel.eval("$SAFE=#{safe} if $SAFE < #{safe};" << cmd, - *eval_args) - }) - } - end - alias background_eval_string bg_eval_string - alias bg_eval_str bg_eval_string - alias background_eval_str bg_eval_string - - def eval(*args, &blk) - if block_given? - eval_proc(*args, &blk) - elsif args[0] - if args[0].respond_to?(:call) - eval_proc(*args) - else - eval_string(*args) - end - else - fail ArgumentError, "no argument to eval" - end - end - - def bg_eval(*args, &blk) - if block_given? - bg_eval_proc(*args, &blk) - elsif args[0] - if args[0].respond_to?(:call) - bg_eval_proc(*args) - else - bg_eval_string(*args) - end - else - fail ArgumentError, "no argument to eval" - end - end - alias background_eval bg_eval -end - -class << MultiTkIp - # class method - def eval_proc(*args, &blk) - # class ==> interp object - __getip.eval_proc(*args, &blk) - end - alias call eval_proc - - def bg_eval_proc(*args, &blk) - # class ==> interp object - __getip.bg_eval_proc(*args, &blk) - end - alias background_eval_proc bg_eval_proc - alias thread_eval_proc bg_eval_proc - alias bg_call bg_eval_proc - alias background_call bg_eval_proc - - def eval_string(cmd, *eval_args) - # class ==> interp object - __getip.eval_string(cmd, *eval_args) - end - alias eval_str eval_string - - def bg_eval_string(cmd, *eval_args) - # class ==> interp object - __getip.bg_eval_string(cmd, *eval_args) - end - alias background_eval_string bg_eval_string - alias bg_eval_str bg_eval_string - alias background_eval_str bg_eval_string - - def eval(*args, &blk) - # class ==> interp object - __getip.eval(*args, &blk) - end - def bg_eval(*args, &blk) - # class ==> interp object - __getip.bg_eval(*args, &blk) - end - alias background_eval bg_eval -end - - -# event loop -# all master/slave IPs are controlled by only one event-loop -class MultiTkIp - def self.default_master? - __getip == @@DEFAULT_MASTER - end -end -class << MultiTkIp - def mainloop(check_root = true) - __getip.mainloop(check_root) - end - def mainloop_watchdog(check_root = true) - __getip.mainloop_watchdog(check_root) - end - def do_one_event(flag = TclTkLib::EventFlag::ALL) - __getip.do_one_event(flag) - end - def mainloop_abort_on_exception - # __getip.mainloop_abort_on_exception - TclTkLib.mainloop_abort_on_exception - end - def mainloop_abort_on_exception=(mode) - # __getip.mainloop_abort_on_exception=(mode) - TclTkLib.mainloop_abort_on_exception=(mode) - end - def set_eventloop_tick(tick) - __getip.set_eventloop_tick(tick) - end - def get_eventloop_tick - __getip.get_eventloop_tick - end - def set_no_event_wait(tick) - __getip.set_no_event_wait(tick) - end - def get_no_event_wait - __getip.get_no_event_wait - end - def set_eventloop_weight(loop_max, no_event_tick) - __getip.set_eventloop_weight(loop_max, no_event_tick) - end - def get_eventloop_weight - __getip.get_eventloop_weight - end -end - -# class methods to delegate to TclTkIp -class << MultiTkIp - def method_missing(id, *args) - __getip.__send__(id, *args) - end - - def make_safe - __getip.make_safe - end - - def safe? - __getip.safe? - end - - def safe_base? - begin - __getip.safe_base? - rescue - false - end - end - - def allow_ruby_exit? - __getip.allow_ruby_exit? - end - - def allow_ruby_exit= (mode) - __getip.allow_ruby_exit = mode - end - - def delete - __getip.delete - end - - def deleted? - __getip.deleted? - end - - def has_mainwindow? - __getip.has_mainwindow? - end - - def invalid_namespace? - __getip.invalid_namespace? - end - - def abort(msg = nil) - __getip.abort(msg) - end - - def exit(st = true) - __getip.exit(st) - end - - def exit!(st = false) - __getip.exit!(st) - end - - def restart(app_name = nil, keys = {}) - init_ip_internal - - __getip._invoke('set', 'argv0', app_name) if app_name - if keys.kind_of?(Hash) - __getip._invoke('set', 'argv', _keys2opts(keys)) - end - - __getip.restart - end - - def _eval(str) - __getip._eval(str) - end - - def _invoke(*args) - __getip._invoke(*args) - end - - def _eval_without_enc(str) - __getip._eval_without_enc(str) - end - - def _invoke_without_enc(*args) - __getip._invoke_without_enc(*args) - end - - def _eval_with_enc(str) - __getip._eval_with_enc(str) - end - - def _invoke_with_enc(*args) - __getip._invoke_with_enc(*args) - end - - def _toUTF8(str, encoding=nil) - __getip._toUTF8(str, encoding) - end - - def _fromUTF8(str, encoding=nil) - __getip._fromUTF8(str, encoding) - end - - def _thread_vwait(var) - __getip._thread_vwait(var) - end - - def _thread_tkwait(mode, target) - __getip._thread_tkwait(mode, target) - end - - def _return_value - __getip._return_value - end - - def _get_variable(var, flag) - __getip._get_variable(var, flag) - end - def _get_variable2(var, idx, flag) - __getip._get_variable2(var, idx, flag) - end - def _set_variable(var, value, flag) - __getip._set_variable(var, value, flag) - end - def _set_variable2(var, idx, value, flag) - __getip._set_variable2(var, idx, value, flag) - end - def _unset_variable(var, flag) - __getip._unset_variable(var, flag) - end - def _unset_variable2(var, idx, flag) - __getip._unset_variable2(var, idx, flag) - end - - def _get_global_var(var) - __getip._get_global_var(var) - end - def _get_global_var2(var, idx) - __getip._get_global_var2(var, idx) - end - def _set_global_var(var, value) - __getip._set_global_var(var, value) - end - def _set_global_var2(var, idx, value) - __getip._set_global_var2(var, idx, value) - end - def _unset_global_var(var) - __getip._unset_global_var(var) - end - def _unset_global_var2(var, idx) - __getip._unset_global_var2(var, idx) - end - - def _make_menu_embeddable(menu_path) - __getip._make_menu_embeddable(menu_path) - end - - def _split_tklist(str) - __getip._split_tklist(str) - end - def _merge_tklist(*args) - __getip._merge_tklist(*args) - end - def _conv_listelement(arg) - __getip._conv_listelement(arg) - end - - def _create_console - __getip._create_console - end -end - - -# wrap methods on TclTkLib : not permit calling TclTkLib module methods -class << TclTkLib - def mainloop(check_root = true) - MultiTkIp.mainloop(check_root) - end - def mainloop_watchdog(check_root = true) - MultiTkIp.mainloop_watchdog(check_root) - end - def do_one_event(flag = TclTkLib::EventFlag::ALL) - MultiTkIp.do_one_event(flag) - end - #def mainloop_abort_on_exception - # MultiTkIp.mainloop_abort_on_exception - #end - #def mainloop_abort_on_exception=(mode) - # MultiTkIp.mainloop_abort_on_exception=(mode) - #end - def set_eventloop_tick(tick) - MultiTkIp.set_eventloop_tick(tick) - end - def get_eventloop_tick - MultiTkIp.get_eventloop_tick - end - def set_no_event_wait(tick) - MultiTkIp.set_no_event_wait(tick) - end - def get_no_event_wait - MultiTkIp.get_no_event_wait - end - def set_eventloop_weight(loop_max, no_event_tick) - MultiTkIp.set_eventloop_weight(loop_max, no_event_tick) - end - def get_eventloop_weight - MultiTkIp.get_eventloop_weight - end - def restart(*args) - MultiTkIp.restart(*args) - end - - def _merge_tklist(*args) - MultiTkIp._merge_tklist(*args) - end - def _conv_listelement(arg) - MultiTkIp._conv_listelement(arg) - end -end - - -# depend on TclTkIp -class MultiTkIp -# def mainloop(check_root = true, restart_on_dead = true) - def mainloop(check_root = true, restart_on_dead = false) - raise SecurityError, "no permission to manipulate" unless self.manipulable? - - if WITH_RUBY_VM ### Ruby 1.9 !!!!!!!!!!! - return @interp_thread.value if @interp_thread - end - - #return self if self.slave? - #return self if self != @@DEFAULT_MASTER - if self != @@DEFAULT_MASTER - if @wait_on_mainloop[0] - begin - @wait_on_mainloop[1] += 1 - @cmd_queue.enq([@system, 'call_mainloop', - Thread.current, check_root]) - Thread.stop - rescue MultiTkIp_OK => ret - # return value - if ret.value.kind_of?(Thread) - return ret.value.value - else - return ret.value - end - rescue SystemExit => e - # exit IP - warn("Warning: " + e.inspect + " on " + self.inspect) if $DEBUG - begin - self._eval_without_enc('exit') - rescue Exception - end - self.delete - rescue StandardError => e - if $DEBUG - warn("Warning: " + e.class.inspect + - ((e.message.length > 0)? ' "' + e.message + '"': '') + - " on " + self.inspect) - end - return e - rescue Exception => e - return e - ensure - @wait_on_mainloop[1] -= 1 - end - end - return - end - - unless restart_on_dead - @wait_on_mainloop[1] += 1 -=begin - begin - @interp.mainloop(check_root) - rescue StandardError => e - if $DEBUG - warn("Warning: " + e.class.inspect + - ((e.message.length > 0)? ' "' + e.message + '"': '') + - " on " + self.inspect) - end - end -=end - begin - @interp.mainloop(check_root) - ensure - @wait_on_mainloop[1] -= 1 - end - else - loop do - break unless self.alive? - if check_root - begin - break if TclTkLib.num_of_mainwindows == 0 - rescue StandardError - break - end - end - break if @interp.deleted? - begin - @wait_on_mainloop[1] += 1 - @interp.mainloop(check_root) - rescue StandardError => e - if TclTkLib.mainloop_abort_on_exception != nil - #STDERR.print("Warning: Tk mainloop receives ", $!.class.inspect, - # " exception (ignore) : ", $!.message, "\n"); - if $DEBUG - warn("Warning: Tk mainloop receives " << e.class.inspect << - " exception (ignore) : " << e.message); - end - end - #raise e - rescue Exception => e -=begin - if TclTkLib.mainloop_abort_on_exception != nil - #STDERR.print("Warning: Tk mainloop receives ", $!.class.inspect, - # " exception (ignore) : ", $!.message, "\n"); - if $DEBUG - warn("Warning: Tk mainloop receives " << e.class.inspect << - " exception (ignore) : " << e.message); - end - end -=end - raise e - ensure - @wait_on_mainloop[1] -= 1 - Thread.pass # avoid eventloop conflict - end - end - end - self - end - - def make_safe - raise SecurityError, "no permission to manipulate" unless self.manipulable? - @interp.make_safe - end - - def safe? - raise SecurityError, "no permission to manipulate" unless self.manipulable? - @interp.safe? - end - - def safe_base? - raise SecurityError, "no permission to manipulate" unless self.manipulable? - @safe_base - end - - def allow_ruby_exit? - raise SecurityError, "no permission to manipulate" unless self.manipulable? - @interp.allow_ruby_exit? - end - - def allow_ruby_exit= (mode) - raise SecurityError, "no permission to manipulate" unless self.manipulable? - @interp.allow_ruby_exit = mode - end - - def delete - raise SecurityError, "no permission to manipulate" unless self.manipulable? - @slave_ip_tbl.each{|name, subip| - _destroy_slaves_of_slaveIP(subip) -=begin - begin - subip._invoke('destroy', '.') unless subip.deleted? - rescue Exception - end -=end - begin - # subip._eval_without_enc("foreach i [after info] {after cancel $i}") - unless subip.deleted? - after_ids = subip._eval_without_enc("after info") - subip._eval_without_enc("foreach i {#{after_ids}} {after cancel $i}") - end - rescue Exception - end - - # safe_base? - if @interp._eval_without_enc("catch {::safe::interpConfigure #{name}}") == '0' - begin - @interp._eval_without_enc("::safe::interpDelete #{name}") - rescue Exception - else - next if subip.deleted? - end - end - if subip.respond_to?(:safe_base?) && subip.safe_base? && - !subip.deleted? - # do 'exit' to call the delete_hook procedure - begin - subip._eval_without_enc('exit') - rescue Exception - end - else - begin - subip.delete unless subip.deleted? - rescue Exception - end - end - } - - begin - # @interp._eval_without_enc("foreach i [after info] {after cancel $i}") - after_ids = @interp._eval_without_enc("after info") - @interp._eval_without_enc("foreach i {#{after_ids}} {after cancel $i}") - rescue Exception - end - - begin - @interp._invoke('destroy', '.') unless @interp.deleted? - rescue Exception - end - - if @safe_base && !@interp.deleted? - # do 'exit' to call the delete_hook procedure - @interp._eval_without_enc('exit') - end - @interp.delete - self - end - - def deleted? - raise SecurityError, "no permission to manipulate" unless self.manipulable? - @interp.deleted? - end - - def has_mainwindow? - raise SecurityError, "no permission to manipulate" unless self.manipulable? - @interp.has_mainwindow? - end - - def invalid_namespace? - raise SecurityError, "no permission to manipulate" unless self.manipulable? - @interp.invalid_namespace? - end - - def abort(msg = nil) - raise SecurityError, "no permission to manipulate" unless self.manipulable? - if master? && !safe? && allow_ruby_exit? - if msg - Kernel.abort(msg) - else - Kernel.abort - end - else - # ignore msg - delete - 1 - end - end - - def exit(st = true) - raise SecurityError, "no permission to manipulate" unless self.manipulable? - if master? && !safe? && allow_ruby_exit? - Kernel.exit(st) - else - delete - st - end - end - - def exit!(st = false) - raise SecurityError, "no permission to manipulate" unless self.manipulable? - if master? && !safe? && allow_ruby_exit? - Kernel.exit!(st) - else - delete - st - end - end - - def restart(app_name = nil, keys = {}) - raise SecurityError, "no permission to manipulate" unless self.manipulable? - - _init_ip_internal(@@INIT_IP_ENV, @@ADD_TK_PROCS) - - @interp._invoke('set', 'argv0', app_name) if app_name - if keys.kind_of?(Hash) - @interp._invoke('set', 'argv', _keys2opts(keys)) - end - - @interp.restart - end - - def __eval(str) - raise SecurityError, "no permission to manipulate" unless self.manipulable? - @interp.__eval(str) - end - - def __invoke(*args) - raise SecurityError, "no permission to manipulate" unless self.manipulable? - @interp.__invoke(*args) - end - - def _eval(str) - raise SecurityError, "no permission to manipulate" unless self.manipulable? - @interp._eval(str) - end - - def _invoke(*args) - raise SecurityError, "no permission to manipulate" unless self.manipulable? - @interp._invoke(*args) - end - - def _eval_without_enc(str) - raise SecurityError, "no permission to manipulate" unless self.manipulable? - @interp._eval_without_enc(str) - end - - def _invoke_without_enc(*args) - raise SecurityError, "no permission to manipulate" unless self.manipulable? - @interp._invoke_without_enc(*args) - end - - def _eval_with_enc(str) - raise SecurityError, "no permission to manipulate" unless self.manipulable? - @interp._eval_with_enc(str) - end - - def _invoke_with_enc(*args) - raise SecurityError, "no permission to manipulate" unless self.manipulable? - @interp._invoke_with_enc(*args) - end - - def _toUTF8(str, encoding=nil) - raise SecurityError, "no permission to manipulate" unless self.manipulable? - @interp._toUTF8(str, encoding) - end - - def _fromUTF8(str, encoding=nil) - raise SecurityError, "no permission to manipulate" unless self.manipulable? - @interp._fromUTF8(str, encoding) - end - - def _thread_vwait(var) - raise SecurityError, "no permission to manipulate" unless self.manipulable? - @interp._thread_vwait(var) - end - - def _thread_tkwait(mode, target) - raise SecurityError, "no permission to manipulate" unless self.manipulable? - @interp._thread_tkwait(mode, target) - end - - def _return_value - raise SecurityError, "no permission to manipulate" unless self.manipulable? - @interp._return_value - end - - def _get_variable(var, flag) - raise SecurityError, "no permission to manipulate" unless self.manipulable? - @interp._get_variable(var, flag) - end - def _get_variable2(var, idx, flag) - raise SecurityError, "no permission to manipulate" unless self.manipulable? - @interp._get_variable2(var, idx, flag) - end - def _set_variable(var, value, flag) - raise SecurityError, "no permission to manipulate" unless self.manipulable? - @interp._set_variable(var, value, flag) - end - def _set_variable2(var, idx, value, flag) - raise SecurityError, "no permission to manipulate" unless self.manipulable? - @interp._set_variable2(var, idx, value, flag) - end - def _unset_variable(var, flag) - raise SecurityError, "no permission to manipulate" unless self.manipulable? - @interp._unset_variable(var, flag) - end - def _unset_variable2(var, idx, flag) - raise SecurityError, "no permission to manipulate" unless self.manipulable? - @interp._unset_variable2(var, idx, flag) - end - - def _get_global_var(var) - raise SecurityError, "no permission to manipulate" unless self.manipulable? - @interp._get_global_var(var) - end - def _get_global_var2(var, idx) - raise SecurityError, "no permission to manipulate" unless self.manipulable? - @interp._get_global_var2(var, idx) - end - def _set_global_var(var, value) - raise SecurityError, "no permission to manipulate" unless self.manipulable? - @interp._set_global_var(var, value) - end - def _set_global_var2(var, idx, value) - raise SecurityError, "no permission to manipulate" unless self.manipulable? - @interp._set_global_var2(var, idx, value) - end - def _unset_global_var(var) - raise SecurityError, "no permission to manipulate" unless self.manipulable? - @interp._unset_global_var(var) - end - def _unset_global_var2(var, idx) - raise SecurityError, "no permission to manipulate" unless self.manipulable? - @interp._unset_global_var2(var, idx) - end - - def _make_menu_embeddable(menu_path) - raise SecurityError, "no permission to manipulate" unless self.manipulable? - @interp._make_menu_embeddable(menu_path) - end - - def _split_tklist(str) - raise SecurityError, "no permission to manipulate" unless self.manipulable? - @interp._split_tklist(str) - end - def _merge_tklist(*args) - raise SecurityError, "no permission to manipulate" unless self.manipulable? - @interp._merge_tklist(*args) - end - def _conv_listelement(arg) - raise SecurityError, "no permission to manipulate" unless self.manipulable? - @interp._conv_listelement(arg) - end -end - - -# interp command support -class MultiTkIp - def _lst2ary(str) - return [] if str == "" - idx = str.index('{') - while idx and idx > 0 and str[idx-1] == ?\\ - idx = str.index('{', idx+1) - end - return str.split unless idx - - list = str[0,idx].split - str = str[idx+1..-1] - i = -1 - brace = 1 - str.each_byte {|c| - c = c.chr - i += 1 - brace += 1 if c == '{' - brace -= 1 if c == '}' - break if brace == 0 - } - if i == 0 - list.push '' - elsif str[0, i] == ' ' - list.push ' ' - else - list.push str[0..i-1] - end - #list += _lst2ary(str[i+1..-1]) - list.concat(_lst2ary(str[i+1..-1])) - list - end - private :_lst2ary - - def _slavearg(slave) - if slave.kind_of?(MultiTkIp) - slave.path - elsif slave.kind_of?(String) - slave - else - slave.to_s - end - end - private :_slavearg - - def alias_info(slave, cmd_name) - raise SecurityError, "no permission to manipulate" unless self.manipulable? - _lst2ary(@interp._invoke('interp', 'alias', _slavearg(slave), cmd_name)) - end - def self.alias_info(slave, cmd_name) - __getip.alias_info(slave, cmd_name) - end - - def alias_delete(slave, cmd_name) - raise SecurityError, "no permission to manipulate" unless self.manipulable? - @interp._invoke('interp', 'alias', _slavearg(slave), cmd_name, '') - self - end - def self.alias_delete(slave, cmd_name) - __getip.alias_delete(slave, cmd_name) - self - end - - def def_alias(slave, new_cmd, org_cmd, *args) - raise SecurityError, "no permission to manipulate" unless self.manipulable? - ret = @interp._invoke('interp', 'alias', _slavearg(slave), new_cmd, - '', org_cmd, *args) - (ret == new_cmd)? self: nil - end - def self.def_alias(slave, new_cmd, org_cmd, *args) - ret = __getip.def_alias(slave, new_cmd, org_cmd, *args) - (ret == new_cmd)? self: nil - end - - def aliases(slave = '') - raise SecurityError, "no permission to manipulate" unless self.manipulable? - _lst2ary(@interp._invoke('interp', 'aliases', _slavearg(slave))) - end - def self.aliases(slave = '') - __getip.aliases(slave) - end - - def delete_slaves(*args) - raise SecurityError, "no permission to manipulate" unless self.manipulable? - slaves = args.collect{|s| _slavearg(s)} - @interp._invoke('interp', 'delete', *slaves) if slaves.size > 0 - self - end - def self.delete_slaves(*args) - __getip.delete_slaves(*args) - self - end - - def exist?(slave = '') - raise SecurityError, "no permission to manipulate" unless self.manipulable? - ret = @interp._invoke('interp', 'exists', _slavearg(slave)) - (ret == '1')? true: false - end - def self.exist?(slave = '') - __getip.exist?(slave) - end - - def delete_cmd(slave, cmd) - raise SecurityError, "no permission to manipulate" unless self.manipulable? - slave_invoke = @interp._invoke('list', 'rename', cmd, '') - @interp._invoke('interp', 'eval', _slavearg(slave), slave_invoke) - self - end - def self.delete_cmd(slave, cmd) - __getip.delete_cmd(slave, cmd) - self - end - - def expose_cmd(slave, cmd, aliasname = nil) - raise SecurityError, "no permission to manipulate" unless self.manipulable? - if aliasname - @interp._invoke('interp', 'expose', _slavearg(slave), cmd, aliasname) - else - @interp._invoke('interp', 'expose', _slavearg(slave), cmd) - end - self - end - def self.expose_cmd(slave, cmd, aliasname = nil) - __getip.expose_cmd(slave, cmd, aliasname) - self - end - - def hide_cmd(slave, cmd, aliasname = nil) - raise SecurityError, "no permission to manipulate" unless self.manipulable? - if aliasname - @interp._invoke('interp', 'hide', _slavearg(slave), cmd, aliasname) - else - @interp._invoke('interp', 'hide', _slavearg(slave), cmd) - end - self - end - def self.hide_cmd(slave, cmd, aliasname = nil) - __getip.hide_cmd(slave, cmd, aliasname) - self - end - - def hidden_cmds(slave = '') - raise SecurityError, "no permission to manipulate" unless self.manipulable? - _lst2ary(@interp._invoke('interp', 'hidden', _slavearg(slave))) - end - def self.hidden_cmds(slave = '') - __getip.hidden_cmds(slave) - end - - def invoke_hidden(slave, cmd, *args) - raise SecurityError, "no permission to manipulate" unless self.manipulable? - if args[-1].kind_of?(Hash) - keys = _symbolkey2str(args.pop) - else - keys = [] - end - keys << _slavearg(slave) - if Tk::TCL_MAJOR_VERSION > 8 || - (Tk::TCL_MAJOR_VERSION == 8 && Tk::TCL_MINOR_VERSION >= 5) - keys << '--' - end - keys << cmd - keys.concat(args) - @interp._invoke('interp', 'invokehidden', *keys) - end - def self.invoke_hidden(slave, cmd, *args) - __getip.invoke_hidden(slave, cmd, *args) - end - - def invoke_hidden_on_global(slave, cmd, *args) - raise SecurityError, "no permission to manipulate" unless self.manipulable? - if args[-1].kind_of?(Hash) - keys = _symbolkey2str(args.pop) - else - keys = [] - end - keys << _slavearg(slave) - keys << '-global' - if Tk::TCL_MAJOR_VERSION > 8 || - (Tk::TCL_MAJOR_VERSION == 8 && Tk::TCL_MINOR_VERSION >= 5) - keys << '--' - end - keys << cmd - keys.concat(args) - @interp._invoke('interp', 'invokehidden', *keys) - end - def self.invoke_hidden_on_global(slave, cmd, *args) - __getip.invoke_hidden_on_global(slave, cmd, *args) - end - - def invoke_hidden_on_namespace(slave, ns, cmd, *args) - # for Tcl8.5 or later - raise SecurityError, "no permission to manipulate" unless self.manipulable? - if args[-1].kind_of?(Hash) - keys = _symbolkey2str(args.pop) - else - keys = [] - end - keys << _slavearg(slave) - keys << '-namespace' << TkComm._get_eval_string(ns) - keys << '--' << cmd - keys.concat(args) - @interp._invoke('interp', 'invokehidden', *keys) - end - def self.invoke_hidden_on_namespace(slave, ns, cmd, *args) - __getip.invoke_hidden_on_namespace(slave, ns, cmd, *args) - end - - def mark_trusted(slave = '') - raise SecurityError, "no permission to manipulate" unless self.manipulable? - @interp._invoke('interp', 'marktrusted', _slavearg(slave)) - self - end - def self.mark_trusted(slave = '') - __getip.mark_trusted(slave) - self - end - - def set_bgerror_handler(cmd = Proc.new, slave = nil, &b) - raise SecurityError, "no permission to manipulate" unless self.manipulable? - - unless TkComm._callback_entry?(cmd) - if !slave && b - slave = cmd - cmd = Proc.new(&b) - end - end - slave = '' unless slave - - @interp._invoke('interp', 'bgerror', _slavearg(slave), cmd) - end - def self.bgerror(cmd = Proc.new, slave = nil, &b) - __getip.bgerror(cmd, slave, &b) - end - - def get_bgerror_handler(slave = '') - raise SecurityError, "no permission to manipulate" unless self.manipulable? - procedure(@interp._invoke('interp', 'bgerror', _slavearg(slave))) - end - def self.bgerror(slave = '') - __getip.bgerror(slave) - end - - def set_limit(limit_type, slave = '', opts = {}) - raise SecurityError, "no permission to manipulate" unless self.manipulable? - @interp._invoke('interp', 'limit', _slavearg(slave), limit_type, opts) - end - def self.set_limit(limit_type, slave = '', opts = {}) - __getip.set_limit(limit_type, slave, opts) - end - - def get_limit(limit_type, slave = '', slot = nil) - raise SecurityError, "no permission to manipulate" unless self.manipulable? - - if slot - num_or_str(@interp._invoke('interp', 'limit', _slavearg(slave), - limit_type, slot)) - else - l = @interp._split_tklist(@interp._invoke_without_enc('interp', 'limit', - _slavearg(slave), - limit_type)) - l.map!{|s| _fromUTF8(s)} - r = {} - until l.empty? - key = l.shift[1..-1] - val = l.shift - val = num_or_str(val) if val - r[key] = val - end - r - end - end - def self.get_limit(limit_type, slave = '', slot = nil) - __getip.get_limit(limit_type, slave, slot) - end - - def recursion_limit(slave = '', limit = None) - raise SecurityError, "no permission to manipulate" unless self.manipulable? - number(@interp._invoke('interp', 'recursionlimit', - _slavearg(slave), limit)) - end - def self.recursion_limit(slave = '', limit = None) - __getip.recursion_limit(slave) - end - - def alias_target(aliascmd, slave = '') - raise SecurityError, "no permission to manipulate" unless self.manipulable? - @interp._invoke('interp', 'target', _slavearg(slave), aliascmd) - end - def self.alias_target(aliascmd, slave = '') - __getip.alias_target(aliascmd, slave) - end - - def share_stdin(dist, src = '') - raise SecurityError, "no permission to manipulate" unless self.manipulable? - @interp._invoke('interp', 'share', src, 'stdin', dist) - self - end - def self.share_stdin(dist, src = '') - __getip.share_stdin(dist, src) - self - end - - def share_stdout(dist, src = '') - raise SecurityError, "no permission to manipulate" unless self.manipulable? - @interp._invoke('interp', 'share', src, 'stdout', dist) - self - end - def self.share_stdout(dist, src = '') - __getip.share_stdout(dist, src) - self - end - - def share_stderr(dist, src = '') - raise SecurityError, "no permission to manipulate" unless self.manipulable? - @interp._invoke('interp', 'share', src, 'stderr', dist) - self - end - def self.share_stderr(dist, src = '') - __getip.share_stderr(dist, src) - self - end - - def transfer_stdin(dist, src = '') - raise SecurityError, "no permission to manipulate" unless self.manipulable? - @interp._invoke('interp', 'transfer', src, 'stdin', dist) - self - end - def self.transfer_stdin(dist, src = '') - __getip.transfer_stdin(dist, src) - self - end - - def transfer_stdout(dist, src = '') - raise SecurityError, "no permission to manipulate" unless self.manipulable? - @interp._invoke('interp', 'transfer', src, 'stdout', dist) - self - end - def self.transfer_stdout(dist, src = '') - __getip.transfer_stdout(dist, src) - self - end - - def transfer_stderr(dist, src = '') - raise SecurityError, "no permission to manipulate" unless self.manipulable? - @interp._invoke('interp', 'transfer', src, 'stderr', dist) - self - end - def self.transfer_stderr(dist, src = '') - __getip.transfer_stderr(dist, src) - self - end - - def share_stdio(dist, src = '') - raise SecurityError, "no permission to manipulate" unless self.manipulable? - @interp._invoke('interp', 'share', src, 'stdin', dist) - @interp._invoke('interp', 'share', src, 'stdout', dist) - @interp._invoke('interp', 'share', src, 'stderr', dist) - self - end - def self.share_stdio(dist, src = '') - __getip.share_stdio(dist, src) - self - end - - def transfer_stdio(dist, src = '') - raise SecurityError, "no permission to manipulate" unless self.manipulable? - @interp._invoke('interp', 'transfer', src, 'stdin', dist) - @interp._invoke('interp', 'transfer', src, 'stdout', dist) - @interp._invoke('interp', 'transfer', src, 'stderr', dist) - self - end - def self.transfer_stdio(dist, src = '') - __getip.transfer_stdio(dist, src) - self - end -end - - -# Safe Base :: manipulating safe interpreter -class MultiTkIp - def safeip_configure(slot, value=None) - # use for '-noStatics' option ==> {statics=>false} - # for '-nestedLoadOk' option ==> {nested=>true} - if slot.kind_of?(Hash) - ip = MultiTkIp.__getip - ip._eval('::safe::interpConfigure ' + @ip_name + ' ' + _keys2opts(slot)) - else - ip._eval('::safe::interpConfigure ' + @ip_name + ' ' + - "-#{slot} #{_get_eval_string(value)}") - end - self - end - - def safeip_configinfo(slot = nil) - ip = MultiTkIp.__getip - ret = {} - if slot - conf = _lst2ary(ip._eval("::safe::interpConfigure " + - @ip_name + " -#{slot}")) - if conf[0] == '-deleteHook' -=begin - if conf[1] =~ /^rb_out\S* (c(_\d+_)?\d+)/ - ret[conf[0][1..-1]] = MultiTkIp._tk_cmd_tbl[$1] -=end - if conf[1] =~ /rb_out\S*(?:\s+(::\S*|[{](::.*)[}]|["](::.*)["]))? (c(_\d+_)?(\d+))/ - ret[conf[0][1..-1]] = MultiTkIp._tk_cmd_tbl[$4] - else - ret[conf[0][1..-1]] = conf[1] - end - else - ret[conf[0][1..-1]] = conf[1] - end - else - Hash[*_lst2ary(ip._eval("::safe::interpConfigure " + - @ip_name))].each{|k, v| - if k == '-deleteHook' -=begin - if v =~ /^rb_out\S* (c(_\d+_)?\d+)/ - ret[k[1..-1]] = MultiTkIp._tk_cmd_tbl[$1] -=end - if v =~ /rb_out\S*(?:\s+(::\S*|[{](::.*)[}]|["](::.*)["]))? (c(_\d+_)?(\d+))/ - ret[k[1..-1]] = MultiTkIp._tk_cmd_tbl[$4] - else - ret[k[1..-1]] = v - end - else - ret[k[1..-1]] = v - end - } - end - ret - end - - def safeip_delete - ip = MultiTkIp.__getip - ip._eval("::safe::interpDelete " + @ip_name) - end - - def safeip_add_to_access_path(dir) - ip = MultiTkIp.__getip - ip._eval("::safe::interpAddToAccessPath #{@ip_name} #{dir}") - end - - def safeip_find_in_access_path(dir) - ip = MultiTkIp.__getip - ip._eval("::safe::interpFindInAccessPath #{@ip_name} #{dir}") - end - - def safeip_set_log_cmd(cmd = Proc.new) - ip = MultiTkIp.__getip - ip._eval("::safe::setLogCmd #{@ip_name} #{_get_eval_string(cmd)}") - end -end - - -# encoding convert -class << MultiTkIp - def encoding_table - __getip.encoding_table - end - - def force_default_encoding=(mode) - __getip.force_default_encoding=(mode) - end - - def force_default_encoding? - __getip.force_default_encoding? - end - - def default_encoding=(enc) - __getip.default_encoding=(enc) - end - - def encoding=(enc) - __getip.encoding=(enc) - end - - def encoding_name - __getip.encoding_name - end - - def encoding_obj - __getip.encoding_obj - end - alias encoding encoding_name - alias default_encoding encoding_name - - def encoding_convertfrom(str, enc=None) - __getip.encoding_convertfrom(str, enc) - end - alias encoding_convert_from encoding_convertfrom - - def encoding_convertto(str, enc=None) - __getip.encoding_convertto(str, enc) - end - alias encoding_convert_to encoding_convertto -end -class MultiTkIp - def encoding_table - @interp.encoding_table - end - - def force_default_encoding=(mode) - raise SecurityError, "no permission to manipulate" unless self.manipulable? - @interp.force_default_encoding = mode - end - def force_default_encoding? - raise SecurityError, "no permission to manipulate" unless self.manipulable? - @interp.force_default_encoding? - end - - def default_encoding=(enc) - raise SecurityError, "no permission to manipulate" unless self.manipulable? - @interp.default_encoding = enc - end - - def encoding=(enc) - raise SecurityError, "no permission to manipulate" unless self.manipulable? - @interp.encoding = enc - end - def encoding_name - raise SecurityError, "no permission to manipulate" unless self.manipulable? - @interp.encoding_name - end - def encoding_obj - raise SecurityError, "no permission to manipulate" unless self.manipulable? - @interp.encoding_obj - end - alias encoding encoding_name - alias default_encoding encoding_name - - def encoding_convertfrom(str, enc=None) - raise SecurityError, "no permission to manipulate" unless self.manipulable? - @interp.encoding_convertfrom(str, enc) - end - alias encoding_convert_from encoding_convertfrom - - def encoding_convertto(str, enc=None) - raise SecurityError, "no permission to manipulate" unless self.manipulable? - @interp.encoding_convertto(str, enc) - end - alias encoding_convert_to encoding_convertto -end - - -# remove methods for security -=begin -class MultiTkIp - INTERP_THREAD = @@DEFAULT_MASTER.instance_variable_get('@interp_thread') - INTERP_MUTEX = INTERP_THREAD[:mutex] - INTERP_ROOT_CHECK = INTERP_THREAD[:root_check] - - # undef_method :instance_eval - undef_method :instance_variable_get - undef_method :instance_variable_set -end - -module TkCore - if MultiTkIp::WITH_RUBY_VM && - ! MultiTkIp::RUN_EVENTLOOP_ON_MAIN_THREAD ### check Ruby 1.9 !!!!!!! - INTERP_THREAD = MultiTkIp::INTERP_THREAD - INTERP_MUTEX = MultiTkIp::INTERP_MUTEX - INTERP_ROOT_CHECK = MultiTkIp::INTERP_ROOT_CHECK - end -end -class MultiTkIp - remove_const(:INTERP_THREAD) - remove_const(:INTERP_MUTEX) - remove_const(:INTERP_ROOT_CHECK) -end -=end -if MultiTkIp::WITH_RUBY_VM && - ! MultiTkIp::RUN_EVENTLOOP_ON_MAIN_THREAD ### check Ruby 1.9 !!!!!!! - class MultiTkIp - INTERP_THREAD = @@DEFAULT_MASTER.instance_variable_get('@interp_thread') - INTERP_THREAD_STATUS = INTERP_THREAD[:status] - INTERP_MUTEX = INTERP_THREAD[:mutex] - INTERP_ROOT_CHECK = INTERP_THREAD[:root_check] - end - module TkCore - INTERP_THREAD = MultiTkIp::INTERP_THREAD - INTERP_THREAD_STATUS = MultiTkIp::INTERP_THREAD_STATUS - INTERP_MUTEX = MultiTkIp::INTERP_MUTEX - INTERP_ROOT_CHECK = MultiTkIp::INTERP_ROOT_CHECK - end - class MultiTkIp - remove_const(:INTERP_THREAD) - remove_const(:INTERP_THREAD_STATUS) - remove_const(:INTERP_MUTEX) - remove_const(:INTERP_ROOT_CHECK) - end -end - -class MultiTkIp - # undef_method :instance_eval - undef_method :instance_variable_get - undef_method :instance_variable_set -end -# end of MultiTkIp definition - -# defend against modification -#MultiTkIp.freeze -#TclTkLib.freeze - -######################################## -# start Tk which depends on MultiTkIp -module TkCore - INTERP = MultiTkIp -end -require 'tk' diff --git a/ext/tk/lib/remote-tk.rb b/ext/tk/lib/remote-tk.rb deleted file mode 100644 index 4d33637c30..0000000000 --- a/ext/tk/lib/remote-tk.rb +++ /dev/null @@ -1,527 +0,0 @@ -# frozen_string_literal: false -# -# remote-tk.rb - supports to control remote Tk interpreters -# by Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp> - -if defined? MultiTkIp - fail RuntimeError, "'remote-tk' library must be required before requiring 'multi-tk'" -end - -require 'tkutil' - -class MultiTkIp; end -class RemoteTkIp < MultiTkIp; end - -class MultiTkIp - @@IP_TABLE = TkUtil.untrust({}) unless defined?(@@IP_TABLE) - @@TK_TABLE_LIST = TkUtil.untrust([]) unless defined?(@@TK_TABLE_LIST) - def self._IP_TABLE; @@IP_TABLE; end - def self._TK_TABLE_LIST; @@TK_TABLE_LIST; end - - @flag = true - def self._DEFAULT_MASTER - # work only once - if @flag - @flag = nil - @@DEFAULT_MASTER - else - nil - end - end -end -class RemoteTkIp - @@IP_TABLE = MultiTkIp._IP_TABLE unless defined?(@@IP_TABLE) - @@TK_TABLE_LIST = MultiTkIp._TK_TABLE_LIST unless defined?(@@TK_TABLE_LIST) -end -class << MultiTkIp - undef _IP_TABLE - undef _TK_TABLE_LIST -end - -require 'multi-tk' - -class RemoteTkIp - if defined?(@@DEFAULT_MASTER) - MultiTkIp._DEFAULT_MASTER - else - @@DEFAULT_MASTER = MultiTkIp._DEFAULT_MASTER - end -end - - -############################### - -class << RemoteTkIp - undef new_master, new_slave, new_safe_slave - undef new_trusted_slave, new_safeTk - - def new(*args, &b) - ip = __new(*args) - ip.eval_proc(&b) if b - ip - end -end - -class RemoteTkIp - def initialize(remote_ip, displayof=nil, timeout=5) - @interp = MultiTkIp.__getip - if @interp.safe? - fail SecurityError, "safe-IP cannot create RemoteTkIp" - end - - - @interp.allow_ruby_exit = false - @appname = @interp._invoke('tk', 'appname') - @remote = remote_ip.to_s.dup.freeze - if displayof.kind_of?(TkWindow) - @displayof = displayof.path.dup.freeze - else - @displayof = nil - end - if self.deleted? - fail RuntimeError, "no Tk application named \"#{@remote}\"" - end - - @tk_windows = {} - @tk_table_list = [] - @slave_ip_tbl = {} - @slave_ip_top = {} - - @force_default_encoding ||= TkUtil.untrust([false]) - @encoding ||= TkUtil.untrust([nil]) - def @encoding.to_s; self.join(nil); end - - TkUtil.untrust(@tk_windows) unless @tk_windows.tainted? - TkUtil.untrust(@tk_table_list) unless @tk_table_list.tainted? - TkUtil.untrust(@slave_ip_tbl) unless @slave_ip_tbl.tainted? - TkUtil.untrust(@slave_ip_top) unless @slave_ip_top.tainted? - - @system = Object.new - - @threadgroup = ThreadGroup.new - - @safe_level = [$SAFE] - - @wait_on_mainloop = [true, 0] - - @cmd_queue = Queue.new - -=begin - @cmd_receiver, @receiver_watchdog = _create_receiver_and_watchdog() - - @threadgroup.add @cmd_receiver - @threadgroup.add @receiver_watchdog - - @threadgroup.enclose -=end - @@DEFAULT_MASTER.assign_receiver_and_watchdog(self) - - @@IP_TABLE[@threadgroup] = self - @@TK_TABLE_LIST.size.times{ - (tbl = {}).tainted? || TkUtil.untrust(tbl) - @tk_table_list << tbl - } - - @ret_val = TkVariable.new - if timeout > 0 && ! _available_check(timeout) - fail RuntimeError, "cannot create connection" - end - @ip_id = _create_connection - - class << self - undef :instance_eval - end - - self.freeze # defend against modification - end - - def manipulable? - return true if (Thread.current.group == ThreadGroup::Default) - MultiTkIp.__getip == @interp && ! @interp.safe? - end - def self.manipulable? - true - end - - def _is_master_of?(tcltkip_obj) - tcltkip_obj == @interp - end - protected :_is_master_of? - - def _ip_id_ - @ip_id - end - - def _available_check(timeout = 5) - raise SecurityError, "no permission to manipulate" unless self.manipulable? - - return nil if timeout < 1 - @ret_val.value = '' - @interp._invoke('send', '-async', @remote, - 'send', '-async', Tk.appname, - "set #{@ret_val.id} ready") - Tk.update - if @ret_val != 'ready' - (1..(timeout*5)).each{ - sleep 0.2 - Tk.update - break if @ret_val == 'ready' - } - end - @ret_val.value == 'ready' - end - private :_available_check - - def _create_connection - raise SecurityError, "no permission to manipulate" unless self.manipulable? - - ip_id = '_' + @interp._invoke('send', @remote, <<-'EOS') + '_' - if {[catch {set _rubytk_control_ip_id_} ret] != 0} { - set _rubytk_control_ip_id_ 0 - } else { - set _rubytk_control_ip_id_ [expr $ret + 1] - } - return $_rubytk_control_ip_id_ - EOS - - @interp._invoke('send', @remote, <<-EOS) - proc rb_out#{ip_id} args { - send #{@appname} rb_out \$args - } - EOS - - ip_id - end - private :_create_connection - - def _appsend(enc_mode, async, *cmds) - raise SecurityError, "no permission to manipulate" unless self.manipulable? - - p ['_appsend', [@remote, @displayof], enc_mode, async, cmds] if $DEBUG - if $SAFE >= 1 && cmds.find{|obj| obj.tainted?} - fail SecurityError, "cannot send tainted commands at level #{$SAFE}" - end - - cmds = @interp._merge_tklist(*TkUtil::_conv_args([], enc_mode, *cmds)) - if @displayof - if async - @interp.__invoke('send', '-async', '-displayof', @displayof, - '--', @remote, *cmds) - else - @interp.__invoke('send', '-displayof', @displayof, - '--', @remote, *cmds) - end - else - if async - @interp.__invoke('send', '-async', '--', @remote, *cmds) - else - @interp.__invoke('send', '--', @remote, *cmds) - end - end - end - private :_appsend - - def ready?(timeout=5) - if timeout < 0 - fail ArgumentError, "timeout must be positive number" - end - _available_check(timeout) - end - - def is_rubytk? - return false if _appsend(false, false, 'info', 'command', 'ruby') == "" - [ _appsend(false, false, 'ruby', 'RUBY_VERSION'), - _appsend(false, false, 'set', 'tk_patchLevel') ] - end - - def appsend(async, *args) - raise SecurityError, "no permission to manipulate" unless self.manipulable? - - if async != true && async != false && async != nil - args.unshift(async) - async = false - end - if @displayof - Tk.appsend_displayof(@remote, @displayof, async, *args) - else - Tk.appsend(@remote, async, *args) - end - end - - def rb_appsend(async, *args) - raise SecurityError, "no permission to manipulate" unless self.manipulable? - - if async != true && async != false && async != nil - args.unshift(async) - async = false - end - if @displayof - Tk.rb_appsend_displayof(@remote, @displayof, async, *args) - else - Tk.rb_appsend(@remote, async, *args) - end - end - - def create_slave(name, safe=false) - if safe - safe_opt = '' - else - safe_opt = '-safe' - end - _appsend(false, false, "interp create #{safe_opt} -- #{name}") - end - - def make_safe - fail RuntimeError, 'cannot change safe mode of the remote interpreter' - end - - def safe? - _appsend(false, false, 'interp issafe') - end - - def safe_base? - false - end - - def allow_ruby_exit? - false - end - - def allow_ruby_exit= (mode) - fail RuntimeError, 'cannot change mode of the remote interpreter' - end - - def delete - _appsend(false, true, 'exit') - end - - def deleted? - raise SecurityError, "no permission to manipulate" unless self.manipulable? - - if @displayof - lst = @interp._invoke_without_enc('winfo', 'interps', - '-displayof', @displayof) - else - lst = @interp._invoke_without_enc('winfo', 'interps') - end - # unless @interp._split_tklist(lst).index(@remote) - unless @interp._split_tklist(lst).index(_toUTF8(@remote)) - true - else - false - end - end - - def has_mainwindow? - raise SecurityError, "no permission to manipulate" unless self.manipulable? - - begin - inf = @interp._invoke_without_enc('info', 'command', '.') - rescue Exception - return nil - end - if !inf.kind_of?(String) || inf != '.' - false - else - true - end - end - - def invalid_namespace? - false - end - - def restart - fail RuntimeError, 'cannot restart the remote interpreter' - end - - def __eval(str) - _appsend(false, false, str) - end - def _eval(str) - _appsend(nil, false, str) - end - def _eval_without_enc(str) - _appsend(false, false, str) - end - def _eval_with_enc(str) - _appsend(true, false, str) - end - - def _invoke(*args) - _appsend(nil, false, *args) - end - - def __invoke(*args) - _appsend(false, false, *args) - end - def _invoke(*args) - _appsend(nil, false, *args) - end - def _invoke_without_enc(*args) - _appsend(false, false, *args) - end - def _invoke_with_enc(*args) - _appsend(true, false, *args) - end - - def _toUTF8(str, encoding=nil) - raise SecurityError, "no permission to manipulate" unless self.manipulable? - @interp._toUTF8(str, encoding) - end - - def _fromUTF8(str, encoding=nil) - raise SecurityError, "no permission to manipulate" unless self.manipulable? - @interp._fromUTF8(str, encoding) - end - - def _thread_vwait(var_name) - _appsend(false, 'thread_vwait', varname) - end - - def _thread_tkwait(mode, target) - _appsend(false, 'thread_tkwait', mode, target) - end - - def _return_value - raise SecurityError, "no permission to manipulate" unless self.manipulable? - @interp._return_value - end - - def _get_variable(var_name, flag) - # ignore flag - _appsend(false, 'set', TkComm::_get_eval_string(var_name)) - end - def _get_variable2(var_name, index_name, flag) - # ignore flag - _appsend(false, 'set', "#{TkComm::_get_eval_string(var_name)}(#{TkComm::_get_eval_string(index_name)})") - end - - def _set_variable(var_name, value, flag) - # ignore flag - _appsend(false, 'set', TkComm::_get_eval_string(var_name), TkComm::_get_eval_string(value)) - end - def _set_variable2(var_name, index_name, value, flag) - # ignore flag - _appsend(false, 'set', "#{TkComm::_get_eval_string(var_name)}(#{TkComm::_get_eval_string(index_name)})", TkComm::_get_eval_string(value)) - end - - def _unset_variable(var_name, flag) - # ignore flag - _appsend(false, 'unset', TkComm::_get_eval_string(var_name)) - end - def _unset_variable2(var_name, index_name, flag) - # ignore flag - _appsend(false, 'unset', "#{var_name}(#{index_name})") - end - - def _get_global_var(var_name) - _appsend(false, 'set', TkComm::_get_eval_string(var_name)) - end - def _get_global_var2(var_name, index_name) - _appsend(false, 'set', "#{TkComm::_get_eval_string(var_name)}(#{TkComm::_get_eval_string(index_name)})") - end - - def _set_global_var(var_name, value) - _appsend(false, 'set', TkComm::_get_eval_string(var_name), TkComm::_get_eval_string(value)) - end - def _set_global_var2(var_name, index_name, value) - _appsend(false, 'set', "#{TkComm::_get_eval_string(var_name)}(#{TkComm::_get_eval_string(index_name)})", TkComm::_get_eval_string(value)) - end - - def _unset_global_var(var_name) - _appsend(false, 'unset', TkComm::_get_eval_string(var_name)) - end - def _unset_global_var2(var_name, index_name) - _appsend(false, 'unset', "#{var_name}(#{index_name})") - end - - def _split_tklist(str) - raise SecurityError, "no permission to manipulate" unless self.manipulable? - @interp._split_tklist(str) - end - - def _merge_tklist(*args) - raise SecurityError, "no permission to manipulate" unless self.manipulable? - @interp._merge_tklist(*args) - end - - def _conv_listelement(str) - raise SecurityError, "no permission to manipulate" unless self.manipulable? - @interp._conv_listelement(str) - end - - def _create_console - fail RuntimeError, 'not support "_create_console" on the remote interpreter' - end - - def mainloop - fail RuntimeError, 'not support "mainloop" on the remote interpreter' - end - def mainloop_watchdog - fail RuntimeError, 'not support "mainloop_watchdog" on the remote interpreter' - end - def do_one_event(flag = nil) - fail RuntimeError, 'not support "do_one_event" on the remote interpreter' - end - def mainloop_abort_on_exception - fail RuntimeError, 'not support "mainloop_abort_on_exception" on the remote interpreter' - end - def mainloop_abort_on_exception=(mode) - fail RuntimeError, 'not support "mainloop_abort_on_exception=" on the remote interpreter' - end - def set_eventloop_tick(*args) - fail RuntimeError, 'not support "set_eventloop_tick" on the remote interpreter' - end - def get_eventloop_tick - fail RuntimeError, 'not support "get_eventloop_tick" on the remote interpreter' - end - def set_no_event_wait(*args) - fail RuntimeError, 'not support "set_no_event_wait" on the remote interpreter' - end - def get_no_event_wait - fail RuntimeError, 'not support "get_no_event_wait" on the remote interpreter' - end - def set_eventloop_weight(*args) - fail RuntimeError, 'not support "set_eventloop_weight" on the remote interpreter' - end - def get_eventloop_weight - fail RuntimeError, 'not support "get_eventloop_weight" on the remote interpreter' - end -end - -class << RemoteTkIp - def mainloop(*args) - fail RuntimeError, 'not support "mainloop" on the remote interpreter' - end - def mainloop_watchdog(*args) - fail RuntimeError, 'not support "mainloop_watchdog" on the remote interpreter' - end - def do_one_event(flag = nil) - fail RuntimeError, 'not support "do_one_event" on the remote interpreter' - end - def mainloop_abort_on_exception - fail RuntimeError, 'not support "mainloop_abort_on_exception" on the remote interpreter' - end - def mainloop_abort_on_exception=(mode) - fail RuntimeError, 'not support "mainloop_abort_on_exception=" on the remote interpreter' - end - def set_eventloop_tick(*args) - fail RuntimeError, 'not support "set_eventloop_tick" on the remote interpreter' - end - def get_eventloop_tick - fail RuntimeError, 'not support "get_eventloop_tick" on the remote interpreter' - end - def set_no_event_wait(*args) - fail RuntimeError, 'not support "set_no_event_wait" on the remote interpreter' - end - def get_no_event_wait - fail RuntimeError, 'not support "get_no_event_wait" on the remote interpreter' - end - def set_eventloop_weight(*args) - fail RuntimeError, 'not support "set_eventloop_weight" on the remote interpreter' - end - def get_eventloop_weight - fail RuntimeError, 'not support "get_eventloop_weight" on the remote interpreter' - end -end diff --git a/ext/tk/lib/tcltk.rb b/ext/tk/lib/tcltk.rb deleted file mode 100644 index 121f42c26e..0000000000 --- a/ext/tk/lib/tcltk.rb +++ /dev/null @@ -1,369 +0,0 @@ -# frozen_string_literal: false -# tof - -#### tcltk library, more direct manipulation of tcl/tk -#### Sep. 5, 1997 Y. Shigehiro - -require "tcltklib" - -################ - -# module TclTk: collection of tcl/tk utilities (supplies namespace.) -module TclTk - - # initialize Hash to hold unique symbols and such - @namecnt = {} - - # initialize Hash to hold callbacks - @callback = {} -end - -# TclTk.mainloop(): call TclTkLib.mainloop() -def TclTk.mainloop() - print("mainloop: start\n") if $DEBUG - TclTkLib.mainloop() - print("mainloop: end\n") if $DEBUG -end - -# TclTk.deletecallbackkey(ca): remove callback from TclTk module -# this does not remove callbacks from tcl/tk interpreter -# without calling this method, TclTkInterpreter will not be GCed -# ca: callback(TclTkCallback) -def TclTk.deletecallbackkey(ca) - print("deletecallbackkey: ", ca.to_s(), "\n") if $DEBUG - @callback.delete(ca.to_s) -end - -# TclTk.dcb(ca, wid, W): call TclTk.deletecallbackkey() for each callbacks -# in an array. -# this is for callback for top-level <Destroy> -# ca: array of callbacks(TclTkCallback) -# wid: top-level widget(TclTkWidget) -# w: information about window given by %W(String) -def TclTk.dcb(ca, wid, w) - if wid.to_s() == w - ca.each{|i| - TclTk.deletecallbackkey(i) - } - end -end - -# TclTk._addcallback(ca): register callback -# ca: callback(TclTkCallback) -def TclTk._addcallback(ca) - print("_addcallback: ", ca.to_s(), "\n") if $DEBUG - @callback[ca.to_s()] = ca -end - -# TclTk._callcallback(key, arg): invoke registered callback -# key: key to select callback (to_s value of the TclTkCallback) -# arg: parameter from tcl/tk interpreter -def TclTk._callcallback(key, arg) - print("_callcallback: ", @callback[key].inspect, "\n") if $DEBUG - @callback[key]._call(arg) - # throw out callback value - # should return String to satisfy rb_eval_string() - return "" -end - -# TclTk._newname(prefix): generate unique name(String) -# prefix: prefix of the unique name -def TclTk._newname(prefix) - # generated name counter is stored in @namecnt - if !@namecnt.key?(prefix) - # first appearing prefix, initialize - @namecnt[prefix] = 1 - else - # already appeared prefix, generate next name - @namecnt[prefix] += 1 - end - return "#{prefix}#{@namecnt[prefix]}" -end - -################ - -# class TclTkInterpreter: tcl/tk interpreter -class TclTkInterpreter - - # initialize(): - def initialize() - # generate interpreter object - @ip = TclTkIp.new() - - # add ruby_fmt command to tcl interpreter - # ruby_fmt command format arguments by `format' and call `ruby' command - # (notice ruby command receives only one argument) - if $DEBUG - @ip._eval("proc ruby_fmt {fmt args} { puts \"ruby_fmt: $fmt $args\" ; set cmd [list ruby [format $fmt $args]] ; uplevel $cmd }") - else - @ip._eval("proc ruby_fmt {fmt args} { set cmd [list ruby [format $fmt $args]] ; uplevel $cmd }") - end - - # @ip._get_eval_string(*args): generate string to evaluate in tcl interpreter - # *args: script which is going to be evaluated under tcl/tk - def @ip._get_eval_string(*args) - argstr = "" - args.each{|arg| - argstr += " " if argstr != "" - # call to_eval if it is defined - if (arg.respond_to?(:to_eval)) - argstr += arg.to_eval() - else - # call to_s unless defined - argstr += arg.to_s() - end - } - return argstr - end - - # @ip._eval_args(*args): evaluate string under tcl/tk interpreter - # returns result string. - # *args: script which is going to be evaluated under tcl/tk - def @ip._eval_args(*args) - # calculate the string to eval in the interpreter - argstr = _get_eval_string(*args) - - # evaluate under the interpreter - print("_eval: \"", argstr, "\"") if $DEBUG - res = _eval(argstr) - if $DEBUG - print(" -> \"", res, "\"\n") - elsif _return_value() != 0 - print(res, "\n") - end - fail(%Q/can't eval "#{argstr}"/) if _return_value() != 0 #' - return res - end - - # generate tcl/tk command object and register in the hash - @commands = {} - # for all commands registered in tcl/tk interpreter: - @ip._eval("info command").split(/ /).each{|comname| - if comname =~ /^[.]/ - # if command is a widget (path), generate TclTkWidget, - # and register it in the hash - @commands[comname] = TclTkWidget.new(@ip, comname) - else - # otherwise, generate TclTkCommand - @commands[comname] = TclTkCommand.new(@ip, comname) - end - } - end - - # commands(): returns hash of the tcl/tk commands - def commands() - return @commands - end - - # rootwidget(): returns root widget(TclTkWidget) - def rootwidget() - return @commands["."] - end - - # _tcltkip(): returns @ip(TclTkIp) - def _tcltkip() - return @ip - end - - # method_missing(id, *args): execute undefined method as tcl/tk command - # id: method symbol - # *args: method arguments - def method_missing(id, *args) - # if command named by id registered, then execute it - if @commands.key?(id.id2name) - return @commands[id.id2name].e(*args) - else - # otherwise, exception - super - end - end -end - -# class TclTkObject: base class of the tcl/tk objects -class TclTkObject - - # initialize(ip, exp): - # ip: interpreter(TclTkIp) - # exp: tcl/tk representation - def initialize(ip, exp) - fail("type is not TclTkIp") if !ip.kind_of?(TclTkIp) - @ip = ip - @exp = exp - end - - # to_s(): returns tcl/tk representation - def to_s() - return @exp - end -end - -# class TclTkCommand: tcl/tk commands -# you should not call TclTkCommand.new() -# commands are created by TclTkInterpreter:initialize() -class TclTkCommand < TclTkObject - - # e(*args): execute command. returns String (e is for exec or eval) - # *args: command arguments - def e(*args) - return @ip._eval_args(to_s(), *args) - end -end - -# class TclTkLibCommand: tcl/tk commands in the library -class TclTkLibCommand < TclTkCommand - - # initialize(ip, name): - # ip: interpreter(TclTkInterpreter) - # name: command name (String) - def initialize(ip, name) - super(ip._tcltkip, name) - end -end - -# class TclTkVariable: tcl/tk variable -class TclTkVariable < TclTkObject - - # initialize(interp, dat): - # interp: interpreter(TclTkInterpreter) - # dat: the value to set(String) - # if nil, not initialize variable - def initialize(interp, dat) - # auto-generate tcl/tk representation (variable name) - exp = TclTk._newname("v_") - # initialize TclTkObject - super(interp._tcltkip(), exp) - # safe this for `set' command - @set = interp.commands()["set"] - # set value - set(dat) if dat - end - - # although you can set/read variables by using set in tcl/tk, - # we provide the method for accessing variables - - # set(data): set tcl/tk variable using `set' - # data: new value - def set(data) - @set.e(to_s(), data.to_s()) - end - - # get(): read tcl/tk variable(String) using `set' - def get() - return @set.e(to_s()) - end -end - -# class TclTkWidget: tcl/tk widget -class TclTkWidget < TclTkCommand - - # initialize(*args): - # *args: parameters - def initialize(*args) - if args[0].kind_of?(TclTkIp) - # in case the 1st argument is TclTkIp: - - # Wrap tcl/tk widget by TclTkWidget - # (used in TclTkInterpreter#initialize()) - - # need two arguments - fail("invalid # of parameter") if args.size != 2 - - # ip: interpreter(TclTkIp) - # exp: tcl/tk representation - ip, exp = args - - # initialize TclTkObject - super(ip, exp) - elsif args[0].kind_of?(TclTkInterpreter) - # in case 1st parameter is TclTkInterpreter: - - # generate new widget from parent widget - - # interp: interpreter(TclTkInterpreter) - # parent: parent widget - # command: widget generating tk command(label ç‰) - # *args: argument to the command - interp, parent, command, *args = args - - # generate widget name - exp = parent.to_s() - exp += "." if exp !~ /[.]$/ - exp += TclTk._newname("w_") - # initialize TclTkObject - super(interp._tcltkip(), exp) - # generate widget - res = @ip._eval_args(command, exp, *args) -# fail("can't create Widget") if res != exp - # for tk_optionMenu, it is legal res != exp - return res - else - fail("first parameter is not TclTkInterpreter") - end - end -end - -# class TclTkCallback: tcl/tk callbacks -class TclTkCallback < TclTkObject - - # initialize(interp, pr, arg): - # interp: interpreter(TclTkInterpreter) - # pr: callback procedure(Proc) - # arg: string to pass as block parameters of pr - # bind command of tcl/tk uses % replacement for parameters - # pr can receive replaced data using block parameter - # its format is specified by arg string - # You should not specify arg for the command like - # scrollbar with -command option, which receives parameters - # without specifying any replacement - def initialize(interp, pr, arg = nil) - # auto-generate tcl/tk representation (variable name) - exp = TclTk._newname("c_") - # initialize TclTkObject - super(interp._tcltkip(), exp) - # save parameters - @pr = pr - @arg = arg - # register in the module - TclTk._addcallback(self) - end - - # to_eval(): returns string representation for @ip._eval_args - def to_eval() - if @arg - # bind replaces %s before calling ruby_fmt, so %%s is used - s = %Q/{ruby_fmt {TclTk._callcallback("#{to_s()}", "%%s")} #{@arg}}/ - else - s = %Q/{ruby_fmt {TclTk._callcallback("#{to_s()}", "%s")}}/ - end - - return s - end - - # _call(arg): invoke callback - # arg: callback parameter - def _call(arg) - @pr.call(arg) - end -end - -# class TclTkImage: tcl/tk images -class TclTkImage < TclTkCommand - - # initialize(interp, t, *args): - # generating image is done by TclTkImage.new() - # destroying is done by image delete (inconsistent, sigh) - # interp: interpreter(TclTkInterpreter) - # t: image type (photo, bitmap, etc.) - # *args: command argument - def initialize(interp, t, *args) - # auto-generate tcl/tk representation - exp = TclTk._newname("i_") - # initialize TclTkObject - super(interp._tcltkip(), exp) - # generate image - res = @ip._eval_args("image create", t, exp, *args) - fail("can't create Image") if res != exp - end -end - -# eof diff --git a/ext/tk/lib/tk.rb b/ext/tk/lib/tk.rb deleted file mode 100644 index 956313b54e..0000000000 --- a/ext/tk/lib/tk.rb +++ /dev/null @@ -1,5758 +0,0 @@ -# frozen_string_literal: false -# -# tk.rb - Tk interface module using tcltklib -# by Yukihiro Matsumoto <matz@netlab.jp> - -# use Shigehiro's tcltklib -require 'tcltklib' -require 'tkutil' - -# autoload -require 'tk/autoload' - -# for Mutex -require 'thread' - -class TclTkIp - # backup original (without encoding) _eval and _invoke - alias _eval_without_enc _eval - alias __eval__ _eval - alias _invoke_without_enc _invoke - alias __invoke__ _invoke - - def _ip_id_ - # for RemoteTkIp - '' - end - - alias __initialize__ initialize - private :__initialize__ - - def initialize(*args) - __initialize__(*args) - - @force_default_encoding ||= TkUtil.untrust([false]) - @encoding ||= TkUtil.untrust([nil]) - def @encoding.to_s; self.join(nil); end - end -end - -# define TkComm module (step 1: basic functions) -module TkComm - include TkUtil - extend TkUtil - - WidgetClassNames = TkUtil.untrust({}) - TkExtlibAutoloadModule = TkUtil.untrust([]) - - # None = Object.new ### --> definition is moved to TkUtil module - # def None.to_s - # 'None' - # end - # None.freeze - - #Tk_CMDTBL = {} - #Tk_WINDOWS = {} - Tk_IDs = [ - TkUtil.untrust("00000"), # [0]-cmdid - TkUtil.untrust("00000") # [1]-winid - ] - Tk_IDs.instance_eval{ - @mutex = Mutex.new - def mutex; @mutex; end - freeze - } - - # for backward compatibility - Tk_CMDTBL = Object.new - def Tk_CMDTBL.method_missing(id, *args) - TkCore::INTERP.tk_cmd_tbl.__send__(id, *args) - end - Tk_CMDTBL.freeze - Tk_WINDOWS = Object.new - def Tk_WINDOWS.method_missing(id, *args) - TkCore::INTERP.tk_windows.__send__(id, *args) - end - Tk_WINDOWS.freeze - - self.instance_eval{ - @cmdtbl = TkUtil.untrust([]) - } - - unless const_defined?(:GET_CONFIGINFO_AS_ARRAY) - # GET_CONFIGINFO_AS_ARRAY = false => returns a Hash { opt =>val, ... } - # true => returns an Array [[opt,val], ... ] - # val is a list which includes resource info. - GET_CONFIGINFO_AS_ARRAY = true - end - unless const_defined?(:GET_CONFIGINFOwoRES_AS_ARRAY) - # for configinfo without resource info; list of [opt, value] pair - # false => returns a Hash { opt=>val, ... } - # true => returns an Array [[opt,val], ... ] - GET_CONFIGINFOwoRES_AS_ARRAY = true - end - # *** ATTENTION *** - # 'current_configinfo' method always returns a Hash under all cases of above. - - def error_at - frames = caller() - frames.delete_if do |c| - c =~ %r!/tk(|core|thcore|canvas|text|entry|scrollbox)\.rb:\d+! - end - frames - end - private :error_at - - def _genobj_for_tkwidget(path) - return TkRoot.new if path == '.' - - begin - #tk_class = TkCore::INTERP._invoke('winfo', 'class', path) - tk_class = Tk.ip_invoke_without_enc('winfo', 'class', path) - rescue - return path - end - - if ruby_class = WidgetClassNames[tk_class] - ruby_class_name = ruby_class.name - # gen_class_name = ruby_class_name + 'GeneratedOnTk' - gen_class_name = ruby_class_name - classname_def = '' - else # ruby_class == nil - if Tk.const_defined?(tk_class) - Tk.const_get(tk_class) # auto_load - ruby_class = WidgetClassNames[tk_class] - end - - unless ruby_class - mods = TkExtlibAutoloadModule.find_all{|m| m.const_defined?(tk_class)} - mods.each{|mod| - begin - mod.const_get(tk_class) # auto_load - break if (ruby_class = WidgetClassNames[tk_class]) - rescue LoadError - # ignore load error - end - } - end - - unless ruby_class - std_class = 'Tk' << tk_class - if Object.const_defined?(std_class) - Object.const_get(std_class) # auto_load - ruby_class = WidgetClassNames[tk_class] - end - end - - unless ruby_class - if Tk.const_defined?('TOPLEVEL_ALIASES') && - Tk::TOPLEVEL_ALIASES.const_defined?(std_class) - Tk::TOPLEVEL_ALIASES.const_get(std_class) # auto_load - ruby_class = WidgetClassNames[tk_class] - end - end - - if ruby_class - # found - ruby_class_name = ruby_class.name - gen_class_name = ruby_class_name - classname_def = '' - else - # unknown - ruby_class_name = 'TkWindow' - gen_class_name = 'TkWidget_' + tk_class - classname_def = "WidgetClassName = '#{tk_class}'.freeze" - end - end - -################################### -=begin - if ruby_class = WidgetClassNames[tk_class] - ruby_class_name = ruby_class.name - # gen_class_name = ruby_class_name + 'GeneratedOnTk' - gen_class_name = ruby_class_name - classname_def = '' - else - mod = TkExtlibAutoloadModule.find{|m| m.const_defined?(tk_class)} - if mod - ruby_class_name = mod.name + '::' + tk_class - gen_class_name = ruby_class_name - classname_def = '' - elsif Object.const_defined?('Tk' + tk_class) - ruby_class_name = 'Tk' + tk_class - # gen_class_name = ruby_class_name + 'GeneratedOnTk' - gen_class_name = ruby_class_name - classname_def = '' - else - ruby_class_name = 'TkWindow' - # gen_class_name = ruby_class_name + tk_class + 'GeneratedOnTk' - gen_class_name = 'TkWidget_' + tk_class - classname_def = "WidgetClassName = '#{tk_class}'.freeze" - end - end -=end - -=begin - unless Object.const_defined? gen_class_name - Object.class_eval "class #{gen_class_name}<#{ruby_class_name} - #{classname_def} - end" - end - Object.class_eval "#{gen_class_name}.new('widgetname'=>'#{path}', - 'without_creating'=>true)" -=end - base = Object - gen_class_name.split('::').each{|klass| - next if klass == '' - if base.const_defined?(klass) - base = base.class_eval klass - else - base = base.class_eval "class #{klass}<#{ruby_class_name} - #{classname_def} - end - #{klass}" - end - } - base.class_eval "#{gen_class_name}.new('widgetname'=>'#{path}', - 'without_creating'=>true)" - end - private :_genobj_for_tkwidget - module_function :_genobj_for_tkwidget - - def _at(x,y=nil) - if y - "@#{Integer(x)},#{Integer(y)}" - else - "@#{Integer(x)}" - end - end - module_function :_at - - def tk_tcl2ruby(val, enc_mode = false, listobj = true) -=begin - if val =~ /^rb_out\S* (c(_\d+_)?\d+)/ - #return Tk_CMDTBL[$1] - return TkCore::INTERP.tk_cmd_tbl[$1] - #cmd_obj = TkCore::INTERP.tk_cmd_tbl[$1] - #if cmd_obj.kind_of?(Proc) || cmd_obj.kind_of?(Method) - # cmd_obj - #else - # cmd_obj.cmd - #end - end -=end - if val =~ /rb_out\S*(?:\s+(::\S*|[{](::.*)[}]|["](::.*)["]))? (c(_\d+_)?(\d+))/ - return TkCore::INTERP.tk_cmd_tbl[$4] - end - #if val.include? ?\s - # return val.split.collect{|v| tk_tcl2ruby(v)} - #end - case val - when /\A@font\S+\z/ - TkFont.get_obj(val) - when /\A-?\d+\z/ - val.to_i - when /\A\.\S*\z/ - #Tk_WINDOWS[val] ? Tk_WINDOWS[val] : _genobj_for_tkwidget(val) - TkCore::INTERP.tk_windows[val]? - TkCore::INTERP.tk_windows[val] : _genobj_for_tkwidget(val) - when /\Ai(_\d+_)?\d+\z/ - TkImage::Tk_IMGTBL.mutex.synchronize{ - TkImage::Tk_IMGTBL[val]? TkImage::Tk_IMGTBL[val] : val - } - when /\A-?\d+\.?\d*(e[-+]?\d+)?\z/ - val.to_f - when /\\ / - val.gsub(/\\ /, ' ') - when /[^\\] / - if listobj - #tk_split_escstr(val).collect{|elt| - # tk_tcl2ruby(elt, enc_mode, listobj) - #} - val = _toUTF8(val) unless enc_mode - tk_split_escstr(val, false, false).collect{|elt| - tk_tcl2ruby(elt, true, listobj) - } - elsif enc_mode - _fromUTF8(val) - else - val - end - else - if enc_mode - _fromUTF8(val) - else - val - end - end - end - - private :tk_tcl2ruby - module_function :tk_tcl2ruby - #private_class_method :tk_tcl2ruby - -unless const_defined?(:USE_TCLs_LIST_FUNCTIONS) - USE_TCLs_LIST_FUNCTIONS = true -end - -if USE_TCLs_LIST_FUNCTIONS - ########################################################################### - # use Tcl function version of split_list - ########################################################################### - - def tk_split_escstr(str, src_enc=true, dst_enc=true) - str = _toUTF8(str) if src_enc - if dst_enc - TkCore::INTERP._split_tklist(str).map!{|s| _fromUTF8(s)} - else - TkCore::INTERP._split_tklist(str) - end - end - - def tk_split_sublist(str, depth=-1, src_enc=true, dst_enc=true) - # return [] if str == "" - # list = TkCore::INTERP._split_tklist(str) - str = _toUTF8(str) if src_enc - - if depth == 0 - return "" if str == "" - list = [str] - else - return [] if str == "" - list = TkCore::INTERP._split_tklist(str) - end - if list.size == 1 - # tk_tcl2ruby(list[0], nil, false) - tk_tcl2ruby(list[0], dst_enc, false) - else - list.collect{|token| tk_split_sublist(token, depth - 1, false, dst_enc)} - end - end - - def tk_split_list(str, depth=0, src_enc=true, dst_enc=true) - return [] if str == "" - str = _toUTF8(str) if src_enc - TkCore::INTERP._split_tklist(str).map!{|token| - tk_split_sublist(token, depth - 1, false, dst_enc) - } - end - - def tk_split_simplelist(str, src_enc=true, dst_enc=true) - #lst = TkCore::INTERP._split_tklist(str) - #if (lst.size == 1 && lst =~ /^\{.*\}$/) - # TkCore::INTERP._split_tklist(str[1..-2]) - #else - # lst - #end - - str = _toUTF8(str) if src_enc - if dst_enc - TkCore::INTERP._split_tklist(str).map!{|s| _fromUTF8(s)} - else - TkCore::INTERP._split_tklist(str) - end - end - - def array2tk_list(ary, enc=nil) - return "" if ary.size == 0 - - sys_enc = TkCore::INTERP.encoding - sys_enc = TclTkLib.encoding_system unless sys_enc - - dst_enc = (enc == nil)? sys_enc: enc - - dst = ary.collect{|e| - if e.kind_of? Array - s = array2tk_list(e, enc) - elsif e.kind_of? Hash - tmp_ary = [] - #e.each{|k,v| tmp_ary << k << v } - e.each{|k,v| tmp_ary << "-#{_get_eval_string(k)}" << v } - s = array2tk_list(tmp_ary, enc) - else - s = _get_eval_string(e, enc) - end - - if dst_enc != true && dst_enc != false - if (s_enc = s.instance_variable_get(:@encoding)) - s_enc = s_enc.to_s - elsif TkCore::WITH_ENCODING - s_enc = s.encoding.name - else - s_enc = sys_enc - end - dst_enc = true if s_enc != dst_enc - end - - s - } - - if sys_enc && dst_enc - dst.map!{|s| _toUTF8(s)} - ret = TkCore::INTERP._merge_tklist(*dst) - if TkCore::WITH_ENCODING - if dst_enc.kind_of?(String) - ret = _fromUTF8(ret, dst_enc) - ret.force_encoding(dst_enc) - else - ret.force_encoding('utf-8') - end - else # without encoding - if dst_enc.kind_of?(String) - ret = _fromUTF8(ret, dst_enc) - ret.instance_variable_set(:@encoding, dst_enc) - else - ret.instance_variable_set(:@encoding, 'utf-8') - end - end - ret - else - TkCore::INTERP._merge_tklist(*dst) - end - end - -else - ########################################################################### - # use Ruby script version of split_list (traditional methods) - ########################################################################### - - def tk_split_escstr(str, src_enc=true, dst_enc=true) - return [] if str == "" - list = [] - token = nil - escape = false - brace = 0 - str.split('').each {|c| - brace += 1 if c == '{' && !escape - brace -= 1 if c == '}' && !escape - if brace == 0 && c == ' ' && !escape - list << token.gsub(/^\{(.*)\}$/, '\1') if token - token = nil - else - token = (token || "") << c - end - escape = (c == '\\' && !escape) - } - list << token.gsub(/^\{(.*)\}$/, '\1') if token - list - end - - def tk_split_sublist(str, depth=-1, src_enc=true, dst_enc=true) - #return [] if str == "" - #return [tk_split_sublist(str[1..-2])] if str =~ /^\{.*\}$/ - #list = tk_split_escstr(str) - if depth == 0 - return "" if str == "" - str = str[1..-2] if str =~ /^\{.*\}$/ - list = [str] - else - return [] if str == [] - return [tk_split_sublist(str[1..-2], depth - 1)] if str =~ /^\{.*\}$/ - list = tk_split_escstr(str) - end - if list.size == 1 - tk_tcl2ruby(list[0], nil, false) - else - list.collect{|token| tk_split_sublist(token, depth - 1)} - end - end - - def tk_split_list(str, depth=0, src_enc=true, dst_enc=true) - return [] if str == "" - tk_split_escstr(str).collect{|token| - tk_split_sublist(token, depth - 1) - } - end - - def tk_split_simplelist(str, src_enc=true, dst_enc=true) - return [] if str == "" - list = [] - token = nil - escape = false - brace = 0 - str.split('').each {|c| - if c == '\\' && !escape - escape = true - token = (token || "") << c if brace > 0 - next - end - brace += 1 if c == '{' && !escape - brace -= 1 if c == '}' && !escape - if brace == 0 && c == ' ' && !escape - list << token.gsub(/^\{(.*)\}$/, '\1') if token - token = nil - else - token = (token || "") << c - end - escape = false - } - list << token.gsub(/^\{(.*)\}$/, '\1') if token - list - end - - def array2tk_list(ary, enc=nil) - ary.collect{|e| - if e.kind_of? Array - "{#{array2tk_list(e, enc)}}" - elsif e.kind_of? Hash - # "{#{e.to_a.collect{|ee| array2tk_list(ee)}.join(' ')}}" - e.each{|k,v| tmp_ary << "-#{_get_eval_string(k)}" << v } - array2tk_list(tmp_ary, enc) - else - s = _get_eval_string(e, enc) - (s.index(/\s/) || s.size == 0)? "{#{s}}": s - end - }.join(" ") - end -end - - private :tk_split_escstr, :tk_split_sublist - private :tk_split_list, :tk_split_simplelist - private :array2tk_list - - module_function :tk_split_escstr, :tk_split_sublist - module_function :tk_split_list, :tk_split_simplelist - module_function :array2tk_list - - private_class_method :tk_split_escstr, :tk_split_sublist - private_class_method :tk_split_list, :tk_split_simplelist -# private_class_method :array2tk_list - -=begin - ### --> definition is moved to TkUtil module - def _symbolkey2str(keys) - h = {} - keys.each{|key,value| h[key.to_s] = value} - h - end - private :_symbolkey2str - module_function :_symbolkey2str -=end - -=begin - ### --> definition is moved to TkUtil module - # def hash_kv(keys, enc_mode = nil, conf = [], flat = false) - def hash_kv(keys, enc_mode = nil, conf = nil) - # Hash {key=>val, key=>val, ... } or Array [ [key, val], [key, val], ... ] - # ==> Array ['-key', val, '-key', val, ... ] - dst = [] - if keys and keys != None - keys.each{|k, v| - #dst.push("-#{k}") - dst.push('-' + k.to_s) - if v != None - # v = _get_eval_string(v, enc_mode) if (enc_mode || flat) - v = _get_eval_string(v, enc_mode) if enc_mode - dst.push(v) - end - } - end - if conf - conf + dst - else - dst - end - end - private :hash_kv - module_function :hash_kv -=end - -=begin - ### --> definition is moved to TkUtil module - def bool(val) - case val - when "1", 1, 'yes', 'true' - true - else - false - end - end - - def number(val) - case val - when /^-?\d+$/ - val.to_i - when /^-?\d+\.?\d*(e[-+]?\d+)?$/ - val.to_f - else - fail(ArgumentError, "invalid value for Number:'#{val}'") - end - end - def string(val) - if val == "{}" - '' - elsif val[0] == ?{ && val[-1] == ?} - val[1..-2] - else - val - end - end - def num_or_str(val) - begin - number(val) - rescue ArgumentError - string(val) - end - end -=end - - def list(val, depth=0, enc=true) - tk_split_list(val, depth, enc, enc) - end - def simplelist(val, src_enc=true, dst_enc=true) - tk_split_simplelist(val, src_enc, dst_enc) - end - def window(val) - if val =~ /^\./ - #Tk_WINDOWS[val]? Tk_WINDOWS[val] : _genobj_for_tkwidget(val) - TkCore::INTERP.tk_windows[val]? - TkCore::INTERP.tk_windows[val] : _genobj_for_tkwidget(val) - else - nil - end - end - def image_obj(val) - if val =~ /^i(_\d+_)?\d+$/ - TkImage::Tk_IMGTBL.mutex.synchronize{ - TkImage::Tk_IMGTBL[val]? TkImage::Tk_IMGTBL[val] : val - } - else - val - end - end - def procedure(val) -=begin - if val =~ /^rb_out\S* (c(_\d+_)?\d+)/ - #Tk_CMDTBL[$1] - #TkCore::INTERP.tk_cmd_tbl[$1] - TkCore::INTERP.tk_cmd_tbl[$1].cmd -=end - if val =~ /rb_out\S*(?:\s+(::\S*|[{](::.*)[}]|["](::.*)["]))? (c(_\d+_)?(\d+))/ - return TkCore::INTERP.tk_cmd_tbl[$4].cmd - else - #nil - val - end - end - private :bool, :number, :num_or_str, :num_or_nil, :string - private :list, :simplelist, :window, :image_obj, :procedure - module_function :bool, :number, :num_or_str, :num_or_nil, :string - module_function :list, :simplelist, :window, :image_obj, :procedure - - if (RUBY_VERSION.split('.').map{|n| n.to_i} <=> [1,8,7]) < 0 - def slice_ary(ary, size) - sliced = [] - wk_ary = ary.dup - until wk_ary.size.zero? - sub_ary = [] - size.times{ sub_ary << wk_ary.shift } - yield(sub_ary) if block_given? - sliced << sub_ary - end - (block_given?)? ary: sliced - end - else - def slice_ary(ary, size, &b) - if b - ary.each_slice(size, &b) - else - ary.each_slice(size).to_a - end - end - end - private :slice_ary - module_function :slice_ary - - def subst(str, *opts) - # opts := :nobackslashes | :nocommands | novariables - tk_call('subst', - *(opts.collect{|opt| - opt = opt.to_s - (opt[0] == ?-)? opt: '-' << opt - } << str)) - end - - def _toUTF8(str, encoding = nil) - TkCore::INTERP._toUTF8(str, encoding) - end - def _fromUTF8(str, encoding = nil) - TkCore::INTERP._fromUTF8(str, encoding) - end - private :_toUTF8, :_fromUTF8 - module_function :_toUTF8, :_fromUTF8 - - def _callback_entry_class?(cls) - cls <= Proc || cls <= Method || cls <= TkCallbackEntry - end - private :_callback_entry_class? - module_function :_callback_entry_class? - - def _callback_entry?(obj) - obj.kind_of?(Proc) || obj.kind_of?(Method) || obj.kind_of?(TkCallbackEntry) - end - private :_callback_entry? - module_function :_callback_entry? - -=begin - ### --> definition is moved to TkUtil module - def _get_eval_string(str, enc_mode = nil) - return nil if str == None - if str.kind_of?(TkObject) - str = str.path - elsif str.kind_of?(String) - str = _toUTF8(str) if enc_mode - elsif str.kind_of?(Symbol) - str = str.id2name - str = _toUTF8(str) if enc_mode - elsif str.kind_of?(Hash) - str = hash_kv(str, enc_mode).join(" ") - elsif str.kind_of?(Array) - str = array2tk_list(str) - str = _toUTF8(str) if enc_mode - elsif str.kind_of?(Proc) - str = install_cmd(str) - elsif str == nil - str = "" - elsif str == false - str = "0" - elsif str == true - str = "1" - elsif (str.respond_to?(:to_eval)) - str = str.to_eval() - str = _toUTF8(str) if enc_mode - else - str = str.to_s() || '' - unless str.kind_of? String - fail RuntimeError, "fail to convert the object to a string" - end - str = _toUTF8(str) if enc_mode - end - return str - end -=end -=begin - def _get_eval_string(obj, enc_mode = nil) - case obj - when Numeric - obj.to_s - when String - (enc_mode)? _toUTF8(obj): obj - when Symbol - (enc_mode)? _toUTF8(obj.id2name): obj.id2name - when TkObject - obj.path - when Hash - hash_kv(obj, enc_mode).join(' ') - when Array - (enc_mode)? _toUTF8(array2tk_list(obj)): array2tk_list(obj) - when Proc, Method, TkCallbackEntry - install_cmd(obj) - when false - '0' - when true - '1' - when nil - '' - when None - nil - else - if (obj.respond_to?(:to_eval)) - (enc_mode)? _toUTF8(obj.to_eval): obj.to_eval - else - begin - obj = obj.to_s || '' - rescue - fail RuntimeError, "fail to convert object '#{obj}' to string" - end - (enc_mode)? _toUTF8(obj): obj - end - end - end - private :_get_eval_string - module_function :_get_eval_string -=end - -=begin - ### --> definition is moved to TkUtil module - def _get_eval_enc_str(obj) - return obj if obj == None - _get_eval_string(obj, true) - end - private :_get_eval_enc_str - module_function :_get_eval_enc_str -=end - -=begin - ### --> obsolete - def ruby2tcl(v, enc_mode = nil) - if v.kind_of?(Hash) - v = hash_kv(v) - v.flatten! - v.collect{|e|ruby2tcl(e, enc_mode)} - else - _get_eval_string(v, enc_mode) - end - end - private :ruby2tcl -=end - -=begin - ### --> definition is moved to TkUtil module - def _conv_args(args, enc_mode, *src_args) - conv_args = [] - src_args.each{|arg| - conv_args << _get_eval_string(arg, enc_mode) unless arg == None - # if arg.kind_of?(Hash) - # arg.each{|k, v| - # args << '-' + k.to_s - # args << _get_eval_string(v, enc_mode) - # } - # elsif arg != None - # args << _get_eval_string(arg, enc_mode) - # end - } - args + conv_args - end - private :_conv_args -=end - - def _curr_cmd_id - #id = format("c%.4d", Tk_IDs[0]) - id = "c" + TkCore::INTERP._ip_id_ + TkComm::Tk_IDs[0] - end - def _next_cmd_id - TkComm::Tk_IDs.mutex.synchronize{ - id = _curr_cmd_id - #Tk_IDs[0] += 1 - TkComm::Tk_IDs[0].succ! - id - } - end - private :_curr_cmd_id, :_next_cmd_id - module_function :_curr_cmd_id, :_next_cmd_id - - def TkComm.install_cmd(cmd, local_cmdtbl=nil) - return '' if cmd == '' - begin - ns = TkCore::INTERP._invoke_without_enc('namespace', 'current') - ns = nil if ns == '::' # for backward compatibility - rescue - # probably, Tcl7.6 - ns = nil - end - id = _next_cmd_id - #Tk_CMDTBL[id] = cmd - if cmd.kind_of?(TkCallbackEntry) - TkCore::INTERP.tk_cmd_tbl[id] = cmd - else - TkCore::INTERP.tk_cmd_tbl[id] = TkCore::INTERP.get_cb_entry(cmd) - end - @cmdtbl = [] unless defined? @cmdtbl - TkUtil.untrust(@cmdtbl) unless @cmdtbl.tainted? - @cmdtbl.push id - - if local_cmdtbl && local_cmdtbl.kind_of?(Array) - begin - local_cmdtbl << id - rescue Exception - # ignore - end - end - - #return Kernel.format("rb_out %s", id); - if ns - 'rb_out' << TkCore::INTERP._ip_id_ << ' ' << ns << ' ' << id - else - 'rb_out' << TkCore::INTERP._ip_id_ << ' ' << id - end - end - def TkComm.uninstall_cmd(id, local_cmdtbl=nil) - #id = $1 if /rb_out\S* (c(_\d+_)?\d+)/ =~ id - id = $4 if id =~ /rb_out\S*(?:\s+(::\S*|[{](::.*)[}]|["](::.*)["]))? (c(_\d+_)?(\d+))/ - - if local_cmdtbl && local_cmdtbl.kind_of?(Array) - begin - local_cmdtbl.delete(id) - rescue Exception - # ignore - end - end - @cmdtbl.delete(id) - - #Tk_CMDTBL.delete(id) - TkCore::INTERP.tk_cmd_tbl.delete(id) - end - # private :install_cmd, :uninstall_cmd - # module_function :install_cmd, :uninstall_cmd - def install_cmd(cmd) - TkComm.install_cmd(cmd, @cmdtbl) - end - def uninstall_cmd(id) - TkComm.uninstall_cmd(id, @cmdtbl) - end - -=begin - def install_win(ppath,name=nil) - if !name or name == '' - #name = format("w%.4d", Tk_IDs[1]) - #Tk_IDs[1] += 1 - name = "w" + Tk_IDs[1] - Tk_IDs[1].succ! - end - if name[0] == ?. - @path = name.dup - elsif !ppath or ppath == "." - @path = Kernel.format(".%s", name); - else - @path = Kernel.format("%s.%s", ppath, name) - end - #Tk_WINDOWS[@path] = self - TkCore::INTERP.tk_windows[@path] = self - end -=end - def install_win(ppath,name=nil) - if name - if name == '' - raise ArgumentError, "invalid widget-name '#{name}'" - end - if name[0] == ?. - @path = '' + name - @path.freeze - return TkCore::INTERP.tk_windows[@path] = self - end - else - Tk_IDs.mutex.synchronize{ - name = "w" + TkCore::INTERP._ip_id_ + Tk_IDs[1] - Tk_IDs[1].succ! - } - end - if !ppath or ppath == '.' - @path = '.' + name - else - @path = ppath + '.' + name - end - @path.freeze - TkCore::INTERP.tk_windows[@path] = self - end - - def uninstall_win() - #Tk_WINDOWS.delete(@path) - TkCore::INTERP.tk_windows.delete(@path) - end - private :install_win, :uninstall_win - - def _epath(win) - if win.kind_of?(TkObject) - win.epath - elsif win.respond_to?(:epath) - win.epath - else - win - end - end - private :_epath -end - -# define TkComm module (step 2: event binding) -module TkComm - include TkEvent - extend TkEvent - - def tk_event_sequence(context) - if context.kind_of? TkVirtualEvent - context = context.path - end - if context.kind_of? Array - context = context.collect{|ev| - if ev.kind_of? TkVirtualEvent - ev.path - else - ev - end - }.join("><") - end - if /,/ =~ context - context = context.split(/\s*,\s*/).join("><") - else - context - end - end - - def _bind_core(mode, what, context, cmd, *args) - id = install_bind(cmd, *args) if cmd - begin - tk_call_without_enc(*(what + ["<#{tk_event_sequence(context)}>", - mode + id])) - rescue - uninstall_cmd(id) if cmd - fail - end - end - - def _bind(what, context, cmd, *args) - _bind_core('', what, context, cmd, *args) - end - - def _bind_append(what, context, cmd, *args) - _bind_core('+', what, context, cmd, *args) - end - - def _bind_remove(what, context) - tk_call_without_enc(*(what + ["<#{tk_event_sequence(context)}>", ''])) - end - - def _bindinfo(what, context=nil) - if context - if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!! - enum_obj = tk_call_without_enc(*what+["<#{tk_event_sequence(context)}>"]).each_line - else - enum_obj = tk_call_without_enc(*what+["<#{tk_event_sequence(context)}>"]) - end - enum_obj.collect {|cmdline| -=begin - if cmdline =~ /^rb_out\S* (c(?:_\d+_)?\d+)\s+(.*)$/ - #[Tk_CMDTBL[$1], $2] - [TkCore::INTERP.tk_cmd_tbl[$1], $2] -=end - if cmdline =~ /rb_out\S*(?:\s+(::\S*|[{](::.*)[}]|["](::.*)["]))? (c(_\d+_)?(\d+))/ - [TkCore::INTERP.tk_cmd_tbl[$4], $5] - else - cmdline - end - } - else - tk_split_simplelist(tk_call_without_enc(*what)).collect!{|seq| - l = seq.scan(/<*[^<>]+>*/).collect!{|subseq| - case (subseq) - when /^<<[^<>]+>>$/ - TkVirtualEvent.getobj(subseq[1..-2]) - when /^<[^<>]+>$/ - subseq[1..-2] - else - subseq.split('') - end - }.flatten - (l.size == 1) ? l[0] : l - } - end - end - - def _bind_core_for_event_class(klass, mode, what, context, cmd, *args) - id = install_bind_for_event_class(klass, cmd, *args) if cmd - begin - tk_call_without_enc(*(what + ["<#{tk_event_sequence(context)}>", - mode + id])) - rescue - uninstall_cmd(id) if cmd - fail - end - end - - def _bind_for_event_class(klass, what, context, cmd, *args) - _bind_core_for_event_class(klass, '', what, context, cmd, *args) - end - - def _bind_append_for_event_class(klass, what, context, cmd, *args) - _bind_core_for_event_class(klass, '+', what, context, cmd, *args) - end - - def _bind_remove_for_event_class(klass, what, context) - _bind_remove(what, context) - end - - def _bindinfo_for_event_class(klass, what, context=nil) - _bindinfo(what, context) - end - - private :tk_event_sequence - private :_bind_core, :_bind, :_bind_append, :_bind_remove, :_bindinfo - private :_bind_core_for_event_class, :_bind_for_event_class, - :_bind_append_for_event_class, :_bind_remove_for_event_class, - :_bindinfo_for_event_class - - #def bind(tagOrClass, context, cmd=Proc.new, *args) - # _bind(["bind", tagOrClass], context, cmd, *args) - # tagOrClass - #end - def bind(tagOrClass, context, *args) - # if args[0].kind_of?(Proc) || args[0].kind_of?(Method) - if TkComm._callback_entry?(args[0]) || !block_given? - cmd = args.shift - else - cmd = Proc.new - end - _bind(["bind", tagOrClass], context, cmd, *args) - tagOrClass - end - - #def bind_append(tagOrClass, context, cmd=Proc.new, *args) - # _bind_append(["bind", tagOrClass], context, cmd, *args) - # tagOrClass - #end - def bind_append(tagOrClass, context, *args) - # if args[0].kind_of?(Proc) || args[0].kind_of?(Method) - if TkComm._callback_entry?(args[0]) || !block_given? - cmd = args.shift - else - cmd = Proc.new - end - _bind_append(["bind", tagOrClass], context, cmd, *args) - tagOrClass - end - - def bind_remove(tagOrClass, context) - _bind_remove(['bind', tagOrClass], context) - tagOrClass - end - - def bindinfo(tagOrClass, context=nil) - _bindinfo(['bind', tagOrClass], context) - end - - #def bind_all(context, cmd=Proc.new, *args) - # _bind(['bind', 'all'], context, cmd, *args) - # TkBindTag::ALL - #end - def bind_all(context, *args) - # if args[0].kind_of?(Proc) || args[0].kind_of?(Method) - if TkComm._callback_entry?(args[0]) || !block_given? - cmd = args.shift - else - cmd = Proc.new - end - _bind(['bind', 'all'], context, cmd, *args) - TkBindTag::ALL - end - - #def bind_append_all(context, cmd=Proc.new, *args) - # _bind_append(['bind', 'all'], context, cmd, *args) - # TkBindTag::ALL - #end - def bind_append_all(context, *args) - # if args[0].kind_of?(Proc) || args[0].kind_of?(Method) - if TkComm._callback_entry?(args[0]) || !block_given? - cmd = args.shift - else - cmd = Proc.new - end - _bind_append(['bind', 'all'], context, cmd, *args) - TkBindTag::ALL - end - - def bind_remove_all(context) - _bind_remove(['bind', 'all'], context) - TkBindTag::ALL - end - - def bindinfo_all(context=nil) - _bindinfo(['bind', 'all'], context) - end -end - - -module TkCore - include TkComm - extend TkComm - - WITH_RUBY_VM = Object.const_defined?(:RubyVM) && ::RubyVM.class == Class - WITH_ENCODING = defined?(::Encoding.default_external) && true - #WITH_ENCODING = Object.const_defined?(:Encoding) && ::Encoding.class == Class - - unless self.const_defined? :INTERP - if self.const_defined? :IP_NAME - name = IP_NAME.to_s - else - #name = nil - name = $0 - end - if self.const_defined? :IP_OPTS - if IP_OPTS.kind_of?(Hash) - opts = hash_kv(IP_OPTS).join(' ') - else - opts = IP_OPTS.to_s - end - else - opts = '' - end - - # RUN_EVENTLOOP_ON_MAIN_THREAD = true - - unless self.const_defined? :RUN_EVENTLOOP_ON_MAIN_THREAD - if WITH_RUBY_VM ### check Ruby 1.9 !!!!!!! - # *** NEED TO FIX *** - case RUBY_PLATFORM - when /cygwin/ - RUN_EVENTLOOP_ON_MAIN_THREAD = true - when /darwin/ # MacOS X -=begin - ip = TclTkIp.new(name, opts) - if ip._invoke_without_enc('tk', 'windowingsystem') == 'aqua' && - (TclTkLib.get_version<=>[8,4,TclTkLib::RELEASE_TYPE::FINAL,6]) > 0 -=end - if TclTkLib::WINDOWING_SYSTEM == 'aqua' && - (TclTkLib.get_version<=>[8,4,TclTkLib::RELEASE_TYPE::FINAL,6]) > 0 - # *** KNOWN BUG *** - # Main event loop thread of TkAqua (> Tk8.4.9) must be the main - # application thread. So, ruby1.9 users must call Tk.mainloop on - # the main application thread. - # - # *** ADD (2009/05/10) *** - # In some cases (I don't know the description of conditions), - # TkAqua 8.4.7 has a same kind of hang-up trouble. - # So, if 8.4.7 or later, set RUN_EVENTLOOP_ON_MAIN_THREAD to true. - # When you want to control this mode, please call the following - # (set true/false as you want) before "require 'tk'". - # ---------------------------------------------------------- - # module TkCore; RUN_EVENTLOOP_ON_MAIN_THREAD = true; end - # ---------------------------------------------------------- - # - # *** ADD (2010/07/05) *** - # The value of TclTkLib::WINDOWING_SYSTEM is defined at compiling. - # If it is inconsistent with linked DLL, please call the following - # before "require 'tk'". - # ---------------------------------------------------------- - # require 'tcltklib' - # module TclTkLib - # remove_const :WINDOWING_SYSTEM - # WINDOWING_SYSTEM = 'x11' # or 'aqua' - # end - # ---------------------------------------------------------- - # - RUN_EVENTLOOP_ON_MAIN_THREAD = true - else - RUN_EVENTLOOP_ON_MAIN_THREAD = false -=begin - ip.delete - ip = nil -=end - end - else - RUN_EVENTLOOP_ON_MAIN_THREAD = false - end - - else # Ruby 1.8.x - RUN_EVENTLOOP_ON_MAIN_THREAD = false - end - end - - if !WITH_RUBY_VM || RUN_EVENTLOOP_ON_MAIN_THREAD ### check Ruby 1.9 !!!!!!! - INTERP = TclTkIp.new(name, opts) unless self.const_defined? :INTERP - else - INTERP_MUTEX = Mutex.new - INTERP_ROOT_CHECK = ConditionVariable.new - INTERP_THREAD = Thread.new{ - begin - #Thread.current[:interp] = interp = TclTkIp.new(name, opts) - interp = TclTkIp.new(name, opts) - rescue => e - Thread.current[:interp] = e - raise e - end - - interp.mainloop_abort_on_exception = true - Thread.current.instance_variable_set("@interp", interp) - - status = [nil] - def status.value - self[0] - end - def status.value=(val) - self[0] = val - end - - Thread.current[:status] = status - #sleep - - # like as 1.8, withdraw a root widget before calling Tk.mainloop - interp._eval <<EOS -wm withdraw . -rename wm __wm_orig__ -proc wm {subcmd win args} { - set val [eval [list __wm_orig__ $subcmd $win] $args] - if {[string equal $subcmd withdraw] && [string equal $win .]} { - rename wm {} - rename __wm_orig__ wm - } - return $val -} -proc __startup_rbtk_mainloop__ {args} { - rename __startup_rbtk_mainloop__ {} - if {[info command __wm_orig__] == "__wm_orig__"} { - rename wm {} - rename __wm_orig__ wm - if [string equal [wm state .] withdrawn] { - wm deiconify . - } - } -} -set __initial_state_of_rubytk__ 1 -trace add variable __initial_state_of_rubytk__ unset __startup_rbtk_mainloop__ - -# complete initializing -ruby {TkCore::INTERP_THREAD[:interp] = TkCore::INTERP_THREAD.instance_variable_get('@interp')} -EOS - - begin - begin - #TclTkLib.mainloop_abort_on_exception = false - #interp.mainloop_abort_on_exception = true - #Thread.current[:interp] = interp - #Thread.current[:status].value = TclTkLib.mainloop(true) - Thread.current[:status].value = interp.mainloop(true) - rescue SystemExit=>e - Thread.current[:status].value = e - rescue Exception=>e - Thread.current[:status].value = e - p e if $DEBUG - retry if interp.has_mainwindow? - ensure - INTERP_MUTEX.synchronize{ INTERP_ROOT_CHECK.broadcast } - end - - unless interp.deleted? - begin - #Thread.current[:status].value = TclTkLib.mainloop(false) - Thread.current[:status].value = interp.mainloop(false) - rescue Exception=>e - puts "ignore exception on interp: #{e.inspect}\n" if $DEBUG - end - end - - ensure - # interp must be deleted before the thread for interp is dead. - # If not, raise Tcl_Panic on Tcl_AsyncDelete because async handler - # deleted by the wrong thread. - interp.delete - end - } - - # check a Tcl/Tk interpreter is initialized - until INTERP_THREAD[:interp] - # Thread.pass - INTERP_THREAD.run - end - - # INTERP_THREAD.run - raise INTERP_THREAD[:interp] if INTERP_THREAD[:interp].kind_of? Exception - - # check an eventloop is running - while INTERP_THREAD.alive? && TclTkLib.mainloop_thread?.nil? - INTERP_THREAD.run - end - - INTERP = INTERP_THREAD[:interp] - INTERP_THREAD_STATUS = INTERP_THREAD[:status] - - # delete the interpreter and kill the eventloop thread at exit - END{ - if INTERP_THREAD.alive? - INTERP.delete - INTERP_THREAD.kill - end - } - - # (for safety's sake) force the eventloop to run - INTERP_THREAD.run - end - - def INTERP.__getip - self - end - def INTERP.default_master? - true - end - - INTERP.instance_eval{ - # @tk_cmd_tbl = TkUtil.untrust({}) - @tk_cmd_tbl = - TkUtil.untrust(Hash.new{|hash, key| - fail IndexError, "unknown command ID '#{key}'" - }) - def @tk_cmd_tbl.[]=(idx,val) - if self.has_key?(idx) && Thread.current.group != ThreadGroup::Default - fail SecurityError,"cannot change the entried command" - end - super(idx,val) - end - - @tk_windows = TkUtil.untrust({}) - - @tk_table_list = TkUtil.untrust([]) - - @init_ip_env = TkUtil.untrust([]) # table of Procs - @add_tk_procs = TkUtil.untrust([]) # table of [name, args, body] - - @force_default_encoding ||= TkUtil.untrust([false]) - @encoding ||= TkUtil.untrust([nil]) - def @encoding.to_s; self.join(nil); end - - @cb_entry_class = Class.new(TkCallbackEntry){ - class << self - def inspect - sprintf("#<Class(TkCallbackEntry):%0x>", self.__id__) - end - alias to_s inspect - end - - def initialize(ip, cmd) - @ip = ip - @cmd = cmd - end - attr_reader :ip, :cmd - def call(*args) - @ip.cb_eval(@cmd, *args) - end - def inspect - sprintf("#<cb_entry:%0x>", self.__id__) - end - alias to_s inspect - }.freeze - } - - def INTERP.cb_entry_class - @cb_entry_class - end - def INTERP.tk_cmd_tbl - @tk_cmd_tbl - end - def INTERP.tk_windows - @tk_windows - end - - class Tk_OBJECT_TABLE - def initialize(id) - @id = id - @mutex = Mutex.new - end - def mutex - @mutex - end - def method_missing(m, *args, &b) - TkCore::INTERP.tk_object_table(@id).__send__(m, *args, &b) - end - end - - def INTERP.tk_object_table(id) - @tk_table_list[id] - end - def INTERP.create_table - id = @tk_table_list.size - (tbl = {}).tainted? || TkUtil.untrust(tbl) - @tk_table_list << tbl -# obj = Object.new -# obj.instance_eval <<-EOD -# def self.method_missing(m, *args) -# TkCore::INTERP.tk_object_table(#{id}).send(m, *args) -# end -# EOD -# return obj - Tk_OBJECT_TABLE.new(id) - end - - def INTERP.get_cb_entry(cmd) - @cb_entry_class.new(__getip, cmd).freeze - end - def INTERP.cb_eval(cmd, *args) - TkUtil._get_eval_string(TkUtil.eval_cmd(cmd, *args)) - end - - def INTERP.init_ip_env(script = Proc.new) - @init_ip_env << script - script.call(self) - end - def INTERP.add_tk_procs(name, args = nil, body = nil) - if name.kind_of?(Array) - name.each{|param| self.add_tk_procs(*param)} - else - name = name.to_s - @add_tk_procs << [name, args, body] - self._invoke('proc', name, args, body) if args && body - end - end - def INTERP.remove_tk_procs(*names) - names.each{|name| - name = name.to_s - @add_tk_procs.delete_if{|elem| - elem.kind_of?(Array) && elem[0].to_s == name - } - #self._invoke('rename', name, '') - self.__invoke__('rename', name, '') - } - end - def INTERP.init_ip_internal - ip = self - @init_ip_env.each{|script| script.call(ip)} - @add_tk_procs.each{|name,args,body| ip._invoke('proc',name,args,body)} - end - end - - unless self.const_defined? :RUN_EVENTLOOP_ON_MAIN_THREAD - ### Ruby 1.9 !!!!!!!!!!!!!!!!!!!!!!!!!! - RUN_EVENTLOOP_ON_MAIN_THREAD = false - end - - WIDGET_DESTROY_HOOK = '<WIDGET_DESTROY_HOOK>' - INTERP._invoke_without_enc('event', 'add', - "<#{WIDGET_DESTROY_HOOK}>", '<Destroy>') - INTERP._invoke_without_enc('bind', 'all', "<#{WIDGET_DESTROY_HOOK}>", - install_cmd(proc{|path| - unless TkCore::INTERP.deleted? - begin - if (widget=TkCore::INTERP.tk_windows[path]) - if widget.respond_to?(:__destroy_hook__) - widget.__destroy_hook__ - end - end - rescue Exception=>e - p e if $DEBUG - end - end - }) << ' %W') - - INTERP.add_tk_procs(TclTkLib::FINALIZE_PROC_NAME, '', - "catch { bind all <#{WIDGET_DESTROY_HOOK}> {} }") - - INTERP.add_tk_procs('rb_out', 'ns args', <<-'EOL') - if [regexp {^::} $ns] { - set cmd {namespace eval $ns {ruby_cmd TkCore callback} $args} - } else { - set cmd {eval {ruby_cmd TkCore callback} $ns $args} - } - if {[set st [catch $cmd ret]] != 0} { - #return -code $st $ret - set idx [string first "\n\n" $ret] - if {$idx > 0} { - return -code $st \ - -errorinfo [string range $ret [expr $idx + 2] \ - [string length $ret]] \ - [string range $ret 0 [expr $idx - 1]] - } else { - return -code $st $ret - } - } else { - return $ret - } - EOL -=begin - INTERP.add_tk_procs('rb_out', 'args', <<-'EOL') - if {[set st [catch {eval {ruby_cmd TkCore callback} $args} ret]] != 0} { - #return -code $st $ret - set idx [string first "\n\n" $ret] - if {$idx > 0} { - return -code $st \ - -errorinfo [string range $ret [expr $idx + 2] \ - [string length $ret]] \ - [string range $ret 0 [expr $idx - 1]] - } else { - return -code $st $ret - } - } else { - return $ret - } - EOL -=end -=begin - INTERP.add_tk_procs('rb_out', 'args', <<-'EOL') - #regsub -all {\\} $args {\\\\} args - #regsub -all {!} $args {\\!} args - #regsub -all "{" $args "\\{" args - regsub -all {(\\|!|\{|\})} $args {\\\1} args - if {[set st [catch {ruby [format "TkCore.callback %%Q!%s!" $args]} ret]] != 0} { - #return -code $st $ret - set idx [string first "\n\n" $ret] - if {$idx > 0} { - return -code $st \ - -errorinfo [string range $ret [expr $idx + 2] \ - [string length $ret]] \ - [string range $ret 0 [expr $idx - 1]] - } else { - return -code $st $ret - } - } else { - return $ret - } - EOL -=end - - if !WITH_RUBY_VM || RUN_EVENTLOOP_ON_MAIN_THREAD ### check Ruby 1.9 !!!!!!! - at_exit{ INTERP.remove_tk_procs(TclTkLib::FINALIZE_PROC_NAME) } - else - at_exit{ - Tk.root.destroy - INTERP.remove_tk_procs(TclTkLib::FINALIZE_PROC_NAME) - INTERP_THREAD.kill.join - } - end - - EventFlag = TclTkLib::EventFlag - - def callback_break - fail TkCallbackBreak, "Tk callback returns 'break' status" - end - - def callback_continue - fail TkCallbackContinue, "Tk callback returns 'continue' status" - end - - def callback_return - fail TkCallbackReturn, "Tk callback returns 'return' status" - end - - def TkCore.callback(*arg) - begin - if TkCore::INTERP.tk_cmd_tbl.kind_of?(Hash) - #TkCore::INTERP.tk_cmd_tbl[arg.shift].call(*arg) - normal_ret = false - ret = catch(:IRB_EXIT) do # IRB hack - retval = TkCore::INTERP.tk_cmd_tbl[arg.shift].call(*arg) - normal_ret = true - retval - end - unless normal_ret - # catch IRB_EXIT - exit(ret) - end - ret - end - rescue SystemExit=>e - exit(e.status) - rescue Interrupt=>e - fail(e) - rescue Exception => e - begin - msg = _toUTF8(e.class.inspect) + ': ' + - _toUTF8(e.message) + "\n" + - "\n---< backtrace of Ruby side >-----\n" + - _toUTF8(e.backtrace.join("\n")) + - "\n---< backtrace of Tk side >-------" - if TkCore::WITH_ENCODING - msg.force_encoding('utf-8') - else - msg.instance_variable_set(:@encoding, 'utf-8') - end - rescue Exception - msg = e.class.inspect + ': ' + e.message + "\n" + - "\n---< backtrace of Ruby side >-----\n" + - e.backtrace.join("\n") + - "\n---< backtrace of Tk side >-------" - end - # TkCore::INTERP._set_global_var('errorInfo', msg) - # fail(e) - fail(e, msg) - end - end -=begin - def TkCore.callback(arg_str) - # arg = tk_split_list(arg_str) - arg = tk_split_simplelist(arg_str) - #_get_eval_string(TkUtil.eval_cmd(Tk_CMDTBL[arg.shift], *arg)) - #_get_eval_string(TkUtil.eval_cmd(TkCore::INTERP.tk_cmd_tbl[arg.shift], - # *arg)) - # TkCore::INTERP.tk_cmd_tbl[arg.shift].call(*arg) - begin - TkCore::INTERP.tk_cmd_tbl[arg.shift].call(*arg) - rescue Exception => e - raise(e, e.class.inspect + ': ' + e.message + "\n" + - "\n---< backtrace of Ruby side >-----\n" + - e.backtrace.join("\n") + - "\n---< backtrace of Tk side >-------") - end -#=begin -# cb_obj = TkCore::INTERP.tk_cmd_tbl[arg.shift] -# unless $DEBUG -# cb_obj.call(*arg) -# else -# begin -# raise 'check backtrace' -# rescue -# # ignore backtrace before 'callback' -# pos = -($!.backtrace.size) -# end -# begin -# cb_obj.call(*arg) -# rescue -# trace = $!.backtrace -# raise $!, "\n#{trace[0]}: #{$!.message} (#{$!.class})\n" + -# "\tfrom #{trace[1..pos].join("\n\tfrom ")}" -# end -# end -#=end - end -=end - - def load_cmd_on_ip(tk_cmd) - bool(tk_call('auto_load', tk_cmd)) - end - - def after(ms, cmd=Proc.new) - cmdid = install_cmd(proc{ret = cmd.call;uninstall_cmd(cmdid); ret}) - after_id = tk_call_without_enc("after",ms,cmdid) - after_id.instance_variable_set('@cmdid', cmdid) - after_id - end -=begin - def after(ms, cmd=Proc.new) - crit_bup = Thread.critical - Thread.critical = true - - myid = _curr_cmd_id - cmdid = install_cmd(proc{ret = cmd.call;uninstall_cmd(myid); ret}) - - Thread.critical = crit_bup - - tk_call_without_enc("after",ms,cmdid) # return id -# return -# if false #defined? Thread -# Thread.start do -# ms = Float(ms)/1000 -# ms = 10 if ms == 0 -# sleep ms/1000 -# cmd.call -# end -# else -# cmdid = install_cmd(cmd) -# tk_call("after",ms,cmdid) -# end - end -=end - - def after_idle(cmd=Proc.new) - cmdid = install_cmd(proc{ret = cmd.call;uninstall_cmd(cmdid); ret}) - after_id = tk_call_without_enc('after','idle',cmdid) - after_id.instance_variable_set('@cmdid', cmdid) - after_id - end -=begin - def after_idle(cmd=Proc.new) - crit_bup = Thread.critical - Thread.critical = true - - myid = _curr_cmd_id - cmdid = install_cmd(proc{ret = cmd.call;uninstall_cmd(myid); ret}) - - Thread.critical = crit_bup - - tk_call_without_enc('after','idle',cmdid) - end -=end - - def after_cancel(afterId) - tk_call_without_enc('after','cancel',afterId) - if (cmdid = afterId.instance_variable_get('@cmdid')) - afterId.instance_variable_set('@cmdid', nil) - uninstall_cmd(cmdid) - end - afterId - end - - def windowingsystem - tk_call_without_enc('tk', 'windowingsystem') - end - - def scaling(scale=nil) - if scale - tk_call_without_enc('tk', 'scaling', scale) - else - Float(number(tk_call_without_enc('tk', 'scaling'))) - end - end - def scaling_displayof(win, scale=nil) - if scale - tk_call_without_enc('tk', 'scaling', '-displayof', win, scale) - else - Float(number(tk_call_without_enc('tk', '-displayof', win, 'scaling'))) - end - end - - def inactive - Integer(tk_call_without_enc('tk', 'inactive')) - end - def inactive_displayof(win) - Integer(tk_call_without_enc('tk', 'inactive', '-displayof', win)) - end - def reset_inactive - tk_call_without_enc('tk', 'inactive', 'reset') - end - def reset_inactive_displayof(win) - tk_call_without_enc('tk', 'inactive', '-displayof', win, 'reset') - end - - def appname(name=None) - tk_call('tk', 'appname', name) - end - - def appsend_deny - tk_call('rename', 'send', '') - end - - def appsend(interp, async, *args) - if $SAFE >= 1 && args.find{|obj| obj.tainted?} - fail SecurityError, "cannot send tainted Tk commands at level #{$SAFE}" - end - if async != true && async != false && async != nil - args.unshift(async) - async = false - end - if async - tk_call('send', '-async', '--', interp, *args) - else - tk_call('send', '--', interp, *args) - end - end - - def rb_appsend(interp, async, *args) - if $SAFE >= 1 && args.find{|obj| obj.tainted?} - fail SecurityError, "cannot send tainted Ruby commands at level #{$SAFE}" - end - if async != true && async != false && async != nil - args.unshift(async) - async = false - end - #args = args.collect!{|c| _get_eval_string(c).gsub(/[\[\]$"]/, '\\\\\&')} - args = args.collect!{|c| _get_eval_string(c).gsub(/[\[\]$"\\]/, '\\\\\&')} - # args.push(').to_s"') - # appsend(interp, async, 'ruby "(', *args) - args.push('}.call)"') - appsend(interp, async, 'ruby "TkComm._get_eval_string(proc{', *args) - end - - def appsend_displayof(interp, win, async, *args) - if $SAFE >= 1 && args.find{|obj| obj.tainted?} - fail SecurityError, "cannot send tainted Tk commands at level #{$SAFE}" - end - win = '.' if win == nil - if async != true && async != false && async != nil - args.unshift(async) - async = false - end - if async - tk_call('send', '-async', '-displayof', win, '--', interp, *args) - else - tk_call('send', '-displayor', win, '--', interp, *args) - end - end - - def rb_appsend_displayof(interp, win, async, *args) - if $SAFE >= 1 && args.find{|obj| obj.tainted?} - fail SecurityError, "cannot send tainted Ruby commands at level #{$SAFE}" - end - win = '.' if win == nil - if async != true && async != false && async != nil - args.unshift(async) - async = false - end - #args = args.collect!{|c| _get_eval_string(c).gsub(/[\[\]$"]/, '\\\\\&')} - args = args.collect!{|c| _get_eval_string(c).gsub(/[\[\]$"\\]/, '\\\\\&')} - # args.push(').to_s"') - # appsend_displayof(interp, win, async, 'ruby "(', *args) - args.push('}.call)"') - appsend(interp, win, async, 'ruby "TkComm._get_eval_string(proc{', *args) - end - - def info(*args) - tk_call('info', *args) - end - - def mainloop(check_root = true) - if !TkCore::WITH_RUBY_VM - TclTkLib.mainloop(check_root) - - elsif TkCore::RUN_EVENTLOOP_ON_MAIN_THREAD - # if TclTkLib::WINDOWING_SYSTEM == 'aqua' && - #if TkCore::INTERP._invoke_without_enc('tk','windowingsystem')=='aqua' && - # Thread.current != Thread.main && - # (TclTkLib.get_version <=> [8,4,TclTkLib::RELEASE_TYPE::FINAL,9]) > 0 - # raise RuntimeError, - # "eventloop on TkAqua ( > Tk8.4.9 ) works on the main thread only" - #end - if Thread.current != Thread.main - raise RuntimeError, "Tk.mainloop is allowed on the main thread only" - end - TclTkLib.mainloop(check_root) - - else ### Ruby 1.9 !!!!! - unless TkCore::INTERP.default_master? - # [MultiTkIp] slave interp ? - return TkCore::INTERP._thread_tkwait('window', '.') if check_root - end - - # like as 1.8, withdraw a root widget before calling Tk.mainloop - TkCore::INTERP._eval_without_enc('catch {unset __initial_state_of_rubytk__}') - INTERP_THREAD.run - - begin - TclTkLib.set_eventloop_window_mode(true) - - # force run the eventloop - TkCore::INTERP._eval_without_enc('update') - TkCore::INTERP._eval_without_enc('catch {set __initial_state_of_rubytk__}') - INTERP_THREAD.run - if check_root - INTERP_MUTEX.synchronize{ - INTERP_ROOT_CHECK.wait(INTERP_MUTEX) - status = INTERP_THREAD_STATUS.value - if status && TkCore::INTERP.default_master? - INTERP_THREAD_STATUS.value = nil - raise status if status.kind_of?(Exception) - end - } - else - # INTERP_THREAD.value - begin - INTERP_THREAD.value - rescue Exception => e - raise e - end - end - rescue Exception => e - raise e - ensure - TclTkLib.set_eventloop_window_mode(false) - end - end - end - - def mainloop_thread? - # true : current thread is mainloop - # nil : there is no mainloop - # false : mainloop is running on the other thread - # ( At then, it is dangerous to call Tk interpreter directly. ) - if !TkCore::WITH_RUBY_VM || TkCore::RUN_EVENTLOOP_ON_MAIN_THREAD - ### Ruby 1.9 !!!!!!!!!!! - TclTkLib.mainloop_thread? - else - Thread.current == INTERP_THREAD - end - end - - def mainloop_exist? - TclTkLib.mainloop_thread? != nil - end - - def is_mainloop? - TclTkLib.mainloop_thread? == true - end - - def mainloop_watchdog(check_root = true) - # watchdog restarts mainloop when mainloop is dead - TclTkLib.mainloop_watchdog(check_root) - end - - def do_one_event(flag = TclTkLib::EventFlag::ALL) - TclTkLib.do_one_event(flag) - end - - def set_eventloop_tick(timer_tick) - TclTkLib.set_eventloop_tick(timer_tick) - end - - def get_eventloop_tick() - TclTkLib.get_eventloop_tick - end - - def set_no_event_wait(wait) - TclTkLib.set_no_even_wait(wait) - end - - def get_no_event_wait() - TclTkLib.get_no_eventloop_wait - end - - def set_eventloop_weight(loop_max, no_event_tick) - TclTkLib.set_eventloop_weight(loop_max, no_event_tick) - end - - def get_eventloop_weight() - TclTkLib.get_eventloop_weight - end - - def restart(app_name = nil, keys = {}) - TkCore::INTERP.init_ip_internal - - tk_call('set', 'argv0', app_name) if app_name - if keys.kind_of?(Hash) - # tk_call('set', 'argc', keys.size * 2) - tk_call('set', 'argv', hash_kv(keys).join(' ')) - end - - INTERP.restart - nil - end - - def event_generate(win, context, keys=nil) - #win = win.path if win.kind_of?(TkObject) - if context.kind_of?(TkEvent::Event) - context.generate(win, ((keys)? keys: {})) - elsif keys - tk_call_without_enc('event', 'generate', win, - "<#{tk_event_sequence(context)}>", - *hash_kv(keys, true)) - else - tk_call_without_enc('event', 'generate', win, - "<#{tk_event_sequence(context)}>") - end - nil - end - - def messageBox(keys) - tk_call('tk_messageBox', *hash_kv(keys)) - end - - def getOpenFile(keys = nil) - tk_call('tk_getOpenFile', *hash_kv(keys)) - end - def getMultipleOpenFile(keys = nil) - simplelist(tk_call('tk_getOpenFile', '-multiple', '1', *hash_kv(keys))) - end - - def getSaveFile(keys = nil) - tk_call('tk_getSaveFile', *hash_kv(keys)) - end - def getMultipleSaveFile(keys = nil) - simplelist(tk_call('tk_getSaveFile', '-multiple', '1', *hash_kv(keys))) - end - - def chooseColor(keys = nil) - tk_call('tk_chooseColor', *hash_kv(keys)) - end - - def chooseDirectory(keys = nil) - tk_call('tk_chooseDirectory', *hash_kv(keys)) - end - - def _ip_eval_core(enc_mode, cmd_string) - case enc_mode - when nil - res = INTERP._eval(cmd_string) - when false - res = INTERP._eval_without_enc(cmd_string) - when true - res = INTERP._eval_with_enc(cmd_string) - end - if INTERP._return_value() != 0 - fail RuntimeError, res, error_at - end - return res - end - private :_ip_eval_core - - def ip_eval(cmd_string) - _ip_eval_core(nil, cmd_string) - end - - def ip_eval_without_enc(cmd_string) - _ip_eval_core(false, cmd_string) - end - - def ip_eval_with_enc(cmd_string) - _ip_eval_core(true, cmd_string) - end - - def _ip_invoke_core(enc_mode, *args) - case enc_mode - when false - res = INTERP._invoke_without_enc(*args) - when nil - res = INTERP._invoke(*args) - when true - res = INTERP._invoke_with_enc(*args) - end - if INTERP._return_value() != 0 - fail RuntimeError, res, error_at - end - return res - end - private :_ip_invoke_core - - def ip_invoke(*args) - _ip_invoke_core(nil, *args) - end - - def ip_invoke_without_enc(*args) - _ip_invoke_core(false, *args) - end - - def ip_invoke_with_enc(*args) - _ip_invoke_core(true, *args) - end - - def _tk_call_core(enc_mode, *args) - ### puts args.inspect if $DEBUG - #args.collect! {|x|ruby2tcl(x, enc_mode)} - #args.compact! - #args.flatten! - args = _conv_args([], enc_mode, *args) - puts 'invoke args => ' + args.inspect if $DEBUG - ### print "=> ", args.join(" ").inspect, "\n" if $DEBUG - begin - # res = TkUtil.untrust(INTERP._invoke(*args)) - # res = INTERP._invoke(enc_mode, *args) - res = _ip_invoke_core(enc_mode, *args) - # >>>>> _invoke returns a TAINTED string <<<<< - rescue NameError => err - # err = $! - begin - args.unshift "unknown" - #res = TkUtil.untrust(INTERP._invoke(*args)) - #res = INTERP._invoke(enc_mode, *args) - res = _ip_invoke_core(enc_mode, *args) - # >>>>> _invoke returns a TAINTED string <<<<< - rescue StandardError => err2 - fail err2 unless /^invalid command/ =~ err2.message - fail err - end - end - if INTERP._return_value() != 0 - fail RuntimeError, res, error_at - end - ### print "==> ", res.inspect, "\n" if $DEBUG - return res - end - private :_tk_call_core - - def tk_call(*args) - _tk_call_core(nil, *args) - end - - def tk_call_without_enc(*args) - _tk_call_core(false, *args) - end - - def tk_call_with_enc(*args) - _tk_call_core(true, *args) - end - - def _tk_call_to_list_core(depth, arg_enc, val_enc, *args) - args = _conv_args([], arg_enc, *args) - val = _tk_call_core(false, *args) - if !depth.kind_of?(Integer) || depth == 0 - tk_split_simplelist(val, false, val_enc) - else - tk_split_list(val, depth, false, val_enc) - end - end - #private :_tk_call_to_list_core - - def tk_call_to_list(*args) - _tk_call_to_list_core(-1, nil, true, *args) - end - - def tk_call_to_list_without_enc(*args) - _tk_call_to_list_core(-1, false, false, *args) - end - - def tk_call_to_list_with_enc(*args) - _tk_call_to_list_core(-1, true, true, *args) - end - - def tk_call_to_simplelist(*args) - _tk_call_to_list_core(0, nil, true, *args) - end - - def tk_call_to_simplelist_without_enc(*args) - _tk_call_to_list_core(0, false, false, *args) - end - - def tk_call_to_simplelist_with_enc(*args) - _tk_call_to_list_core(0, true, true, *args) - end -end - - -module Tk - include TkCore - extend Tk - - TCL_VERSION = INTERP._invoke_without_enc("info", "tclversion").freeze - TCL_PATCHLEVEL = INTERP._invoke_without_enc("info", "patchlevel").freeze - - major, minor = TCL_VERSION.split('.') - TCL_MAJOR_VERSION = major.to_i - TCL_MINOR_VERSION = minor.to_i - - TK_VERSION = INTERP._invoke_without_enc("set", "tk_version").freeze - TK_PATCHLEVEL = INTERP._invoke_without_enc("set", "tk_patchLevel").freeze - - major, minor = TK_VERSION.split('.') - TK_MAJOR_VERSION = major.to_i - TK_MINOR_VERSION = minor.to_i - - JAPANIZED_TK = (INTERP._invoke_without_enc("info", "commands", - "kanji") != "").freeze - - def Tk.const_missing(sym) - case(sym) - when :TCL_LIBRARY - INTERP._invoke_without_enc('global', 'tcl_library') - INTERP._invoke("set", "tcl_library").freeze - - when :TK_LIBRARY - INTERP._invoke_without_enc('global', 'tk_library') - INTERP._invoke("set", "tk_library").freeze - - when :LIBRARY - INTERP._invoke("info", "library").freeze - - #when :PKG_PATH, :PACKAGE_PATH, :TCL_PACKAGE_PATH - # INTERP._invoke_without_enc('global', 'tcl_pkgPath') - # tk_split_simplelist(INTERP._invoke('set', 'tcl_pkgPath')) - - #when :LIB_PATH, :LIBRARY_PATH, :TCL_LIBRARY_PATH - # INTERP._invoke_without_enc('global', 'tcl_libPath') - # tk_split_simplelist(INTERP._invoke('set', 'tcl_libPath')) - - when :PLATFORM, :TCL_PLATFORM - INTERP._invoke_without_enc('global', 'tcl_platform') - Hash[*tk_split_simplelist(INTERP._invoke_without_enc('array', 'get', - 'tcl_platform'))] - - when :ENV - INTERP._invoke_without_enc('global', 'env') - Hash[*tk_split_simplelist(INTERP._invoke('array', 'get', 'env'))] - - #when :AUTO_PATH #<=== - # tk_split_simplelist(INTERP._invoke('set', 'auto_path')) - - #when :AUTO_OLDPATH - # tk_split_simplelist(INTERP._invoke('set', 'auto_oldpath')) - - when :AUTO_INDEX - INTERP._invoke_without_enc('global', 'auto_index') - Hash[*tk_split_simplelist(INTERP._invoke('array', 'get', 'auto_index'))] - - when :PRIV, :PRIVATE, :TK_PRIV - priv = {} - if INTERP._invoke_without_enc('info', 'vars', 'tk::Priv') != "" - var_nam = 'tk::Priv' - else - var_nam = 'tkPriv' - end - INTERP._invoke_without_enc('global', var_nam) - Hash[*tk_split_simplelist(INTERP._invoke('array', 'get', - var_nam))].each{|k,v| - k.freeze - case v - when /^-?\d+$/ - priv[k] = v.to_i - when /^-?\d+\.?\d*(e[-+]?\d+)?$/ - priv[k] = v.to_f - else - priv[k] = v.freeze - end - } - priv - - else - raise NameError, 'uninitialized constant Tk::' + sym.id2name - end - end - - def Tk.errorInfo - INTERP._invoke_without_enc('global', 'errorInfo') - INTERP._invoke_without_enc('set', 'errorInfo') - end - - def Tk.errorCode - INTERP._invoke_without_enc('global', 'errorCode') - code = tk_split_simplelist(INTERP._invoke_without_enc('set', 'errorCode')) - case code[0] - when 'CHILDKILLED', 'CHILDSTATUS', 'CHILDSUSP' - begin - pid = Integer(code[1]) - code[1] = pid - rescue - end - end - code - end - - def Tk.has_mainwindow? - INTERP.has_mainwindow? - end - - def root - Tk::Root.new - end - - def Tk.load_tclscript(file, enc=nil) - if enc - # TCL_VERSION >= 8.5 - tk_call('source', '-encoding', enc, file) - else - tk_call('source', file) - end - end - - def Tk.load_tcllibrary(file, pkg_name=None, interp=None) - tk_call('load', file, pkg_name, interp) - end - - def Tk.unload_tcllibrary(*args) - if args[-1].kind_of?(Hash) - keys = _symbolkey2str(args.pop) - nocomp = (keys['nocomplain'])? '-nocomplain': None - keeplib = (keys['keeplibrary'])? '-keeplibrary': None - tk_call('unload', nocomp, keeplib, '--', *args) - else - tk_call('unload', *args) - end - end - - def Tk.pkgconfig_list(mod) - # Tk8.5 feature - if mod.kind_of?(Module) - if mod.respond_to?(:package_name) - pkgname = mod.package_name - elsif mod.const_defined?(:PACKAGE_NAME) - pkgname = mod::PACKAGE_NAME - else - fail NotImplementedError, 'may not be a module for a Tcl extension' - end - else - pkgname = mod.to_s - end - - pkgname = '::' << pkgname unless pkgname =~ /^::/ - - tk_split_list(tk_call(pkgname + '::pkgconfig', 'list')) - end - - def Tk.pkgconfig_get(mod, key) - # Tk8.5 feature - if mod.kind_of?(Module) - if mod.respond_to?(:package_name) - pkgname = mod.package_name - else - fail NotImplementedError, 'may not be a module for a Tcl extension' - end - else - pkgname = mod.to_s - end - - pkgname = '::' << pkgname unless pkgname =~ /^::/ - - tk_call(pkgname + '::pkgconfig', 'get', key) - end - - def Tk.tcl_pkgconfig_list - # Tk8.5 feature - Tk.pkgconfig_list('::tcl') - end - - def Tk.tcl_pkgconfig_get(key) - # Tk8.5 feature - Tk.pkgconfig_get('::tcl', key) - end - - def Tk.tk_pkgconfig_list - # Tk8.5 feature - Tk.pkgconfig_list('::tk') - end - - def Tk.tk_pkgconfig_get(key) - # Tk8.5 feature - Tk.pkgconfig_get('::tk', key) - end - - def Tk.bell(nice = false) - if nice - tk_call_without_enc('bell', '-nice') - else - tk_call_without_enc('bell') - end - nil - end - - def Tk.bell_on_display(win, nice = false) - if nice - tk_call_without_enc('bell', '-displayof', win, '-nice') - else - tk_call_without_enc('bell', '-displayof', win) - end - nil - end - - def Tk.destroy(*wins) - #tk_call_without_enc('destroy', *wins) - tk_call_without_enc('destroy', *(wins.collect{|win| - if win.kind_of?(TkWindow) - win.epath - else - win - end - })) - end - - def Tk.exit - TkCore::INTERP.has_mainwindow? && tk_call_without_enc('destroy', '.') - end - - ################################################ - - def Tk.sleep(ms = nil, id = nil) - if id - var = (id.kind_of?(TkVariable))? id: TkVarAccess.new(id.to_s) - else - var = TkVariable.new - end - - var.value = tk_call_without_enc('after', ms, proc{ var.value = 0 }) if ms - var.thread_wait - ms - end - - def Tk.wakeup(id) - ((id.kind_of?(TkVariable))? id: TkVarAccess.new(id.to_s)).value = 0 - nil - end - - ################################################ - - def Tk.pack(*args) - TkPack.configure(*args) - end - def Tk.pack_forget(*args) - TkPack.forget(*args) - end - def Tk.unpack(*args) - TkPack.forget(*args) - end - - def Tk.grid(*args) - TkGrid.configure(*args) - end - def Tk.grid_forget(*args) - TkGrid.forget(*args) - end - def Tk.ungrid(*args) - TkGrid.forget(*args) - end - - def Tk.place(*args) - TkPlace.configure(*args) - end - def Tk.place_forget(*args) - TkPlace.forget(*args) - end - def Tk.unplace(*args) - TkPlace.forget(*args) - end - - def Tk.update(idle=nil) - if idle - tk_call_without_enc('update', 'idletasks') - else - tk_call_without_enc('update') - end - end - def Tk.update_idletasks - update(true) - end - def update(idle=nil) - # only for backward compatibility (This never be recommended to use) - Tk.update(idle) - self - end - - # NOTE:: - # If no eventloop-thread is running, "thread_update" method is same - # to "update" method. Else, "thread_update" method waits to complete - # idletask operation on the eventloop-thread. - def Tk.thread_update(idle=nil) - if idle - tk_call_without_enc('thread_update', 'idletasks') - else - tk_call_without_enc('thread_update') - end - end - def Tk.thread_update_idletasks - thread_update(true) - end - - def Tk.lower_window(win, below=None) - tk_call('lower', _epath(win), _epath(below)) - nil - end - def Tk.raise_window(win, above=None) - tk_call('raise', _epath(win), _epath(above)) - nil - end - - def Tk.current_grabs(win = nil) - if win - window(tk_call_without_enc('grab', 'current', win)) - else - tk_split_list(tk_call_without_enc('grab', 'current')) - end - end - - def Tk.focus(display=nil) - if display == nil - window(tk_call_without_enc('focus')) - else - window(tk_call_without_enc('focus', '-displayof', display)) - end - end - - def Tk.focus_to(win, force=false) - if force - tk_call_without_enc('focus', '-force', win) - else - tk_call_without_enc('focus', win) - end - end - - def Tk.focus_lastfor(win) - window(tk_call_without_enc('focus', '-lastfor', win)) - end - - def Tk.focus_next(win) - TkManageFocus.next(win) - end - - def Tk.focus_prev(win) - TkManageFocus.prev(win) - end - - def Tk.strictMotif(mode=None) - bool(tk_call_without_enc('set', 'tk_strictMotif', mode)) - end - - def Tk.show_kinsoku(mode='both') - begin - if /^8\.*/ === TK_VERSION && JAPANIZED_TK - tk_split_simplelist(tk_call('kinsoku', 'show', mode)) - end - rescue - end - end - def Tk.add_kinsoku(chars, mode='both') - begin - if /^8\.*/ === TK_VERSION && JAPANIZED_TK - tk_split_simplelist(tk_call('kinsoku', 'add', mode, - *(chars.split('')))) - else - [] - end - rescue - [] - end - end - def Tk.delete_kinsoku(chars, mode='both') - begin - if /^8\.*/ === TK_VERSION && JAPANIZED_TK - tk_split_simplelist(tk_call('kinsoku', 'delete', mode, - *(chars.split('')))) - end - rescue - end - end - - def Tk.toUTF8(str, encoding = nil) - _toUTF8(str, encoding) - end - - def Tk.fromUTF8(str, encoding = nil) - _fromUTF8(str, encoding) - end -end - -########################################### -# string with Tcl's encoding -########################################### -module Tk - def Tk.subst_utf_backslash(str) - Tk::EncodedString.subst_utf_backslash(str) - end - def Tk.subst_tk_backslash(str) - Tk::EncodedString.subst_tk_backslash(str) - end - def Tk.utf_to_backslash_sequence(str) - Tk::EncodedString.utf_to_backslash_sequence(str) - end - def Tk.utf_to_backslash(str) - Tk::EncodedString.utf_to_backslash_sequence(str) - end - def Tk.to_backslash_sequence(str) - Tk::EncodedString.to_backslash_sequence(str) - end -end - - -########################################### -# convert kanji string to/from utf-8 -########################################### -if (/^(8\.[1-9]|9\.|[1-9][0-9])/ =~ Tk::TCL_VERSION && !Tk::JAPANIZED_TK) - module Tk - module Encoding - extend Encoding - - TkCommandNames = ['encoding'.freeze].freeze - - ############################################# - - if TkCore::WITH_ENCODING ### Ruby 1.9 - RubyEncoding = ::Encoding - - # for saving GC cost - #ENCNAMES_CMD = ['encoding'.freeze, 'names'.freeze] - BINARY_NAME = 'binary'.freeze - UTF8_NAME = 'utf-8'.freeze - DEFAULT_EXTERNAL_NAME = RubyEncoding.default_external.name.freeze - DEFAULT_INTERNAL_NAME = RubyEncoding.default_internal.name.freeze rescue nil - - BINARY = RubyEncoding.find(BINARY_NAME) - UNKNOWN = RubyEncoding.find('ASCII-8BIT') - - ### start of creating ENCODING_TABLE - ENCODING_TABLE = TkCore::INTERP.encoding_table -=begin - ENCODING_TABLE = { - 'binary' => BINARY, - # 'UNKNOWN-8BIT' => UNKNOWN, - } - - list = TkCore::INTERP._invoke_without_enc(ENCNAMES_CMD[0], - ENCNAMES_CMD[1]) - TkCore::INTERP._split_tklist(list).each{|name| - begin - enc = RubyEncoding.find(name) - rescue ArgumentError - case name - when 'identity' - enc = BINARY - when 'shiftjis' - enc = RubyEncoding.find('Shift_JIS') - when 'unicode' - enc = RubyEncoding.find('UTF-8') - #if Tk.tk_call('set', 'tcl_platform(byteOrder)') =='littleEndian' - # enc = RubyEncoding.find('UTF-16LE') - #else - # enc = RubyEncoding.find('UTF-16BE') - #end - when 'symbol' - # single byte data - enc = RubyEncoding.find('ASCII-8BIT') ### ??? - else - # unsupported on Ruby, but supported on Tk - enc = TkCore::INTERP.create_dummy_encoding_for_tk(name) - end - end - ENCODING_TABLE[name.freeze] = enc - } -=end -=begin - def ENCODING_TABLE.get_name(enc) - orig_enc = enc - - # unless 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 compatibility - self.default_encoding = name - end - - def encoding_name - (@encoding[0])? @encoding[0].dup: nil - end - alias encoding encoding_name - alias default_encoding encoding_name - - def encoding_obj - if Tk::WITH_ENCODING - Tk::Encoding.tcl2rb_encoding(@encoding[0]) - else - (@encoding[0])? @encoding[0].dup: nil - end - end - - alias __toUTF8 _toUTF8 - alias __fromUTF8 _fromUTF8 - - if Object.const_defined?(:Encoding) && ::Encoding.class == Class - # with Encoding (Ruby 1.9+) - # - # use functions on Tcl as default. - # but when unsupported encoding on Tcl, use methods on Ruby. - # - def _toUTF8(str, enc = nil) - if enc - # use given encoding - begin - enc_name = Tk::Encoding::ENCODING_TABLE.get_name(enc) - rescue - # unknown encoding for Tk -> try to convert encoding on Ruby - str = str.dup.force_encoding(enc) - str.encode!(Tk::Encoding::UTF8_NAME) # modify self !! - return str # if no error, probably succeed converting - end - end - - enc_name ||= str.instance_variable_get(:@encoding) - - enc_name ||= - Tk::Encoding::ENCODING_TABLE.get_name(str.encoding) rescue nil - - if enc_name - # str has its encoding information - encstr = __toUTF8(str, enc_name) - encstr.force_encoding(Tk::Encoding::UTF8_NAME) - return encstr - else - # str.encoding isn't supported by Tk -> try to convert on Ruby - begin - return str.encode(Tk::Encoding::UTF8_NAME) # new string - rescue - # error -> ignore, try to use default encoding of Ruby/Tk - end - end - - #enc_name ||= - # Tk::Encoding::ENCODING_TABLE.get_name(Tk.encoding) rescue nil - enc_name ||= Tk::Encoding::ENCODING_TABLE.get_name(nil) - - # is 'binary' encoding? - if enc_name == Tk::Encoding::BINARY_NAME - return str.dup.force_encoding(Tk::Encoding::BINARY_NAME) - end - - # force default encoding? - if ! str.kind_of?(Tk::EncodedString) && self.force_default_encoding? - enc_name = Tk::Encoding::ENCODING_TABLE.get_name(Tk.default_encoding) - end - - encstr = __toUTF8(str, enc_name) - encstr.force_encoding(Tk::Encoding::UTF8_NAME) - encstr - end - def _fromUTF8(str, enc = nil) - # str must be UTF-8 or binary. - enc_name = str.instance_variable_get(:@encoding) - enc_name ||= - Tk::Encoding::ENCODING_TABLE.get_name(str.encoding) rescue nil - - # is 'binary' encoding? - if enc_name == Tk::Encoding::BINARY_NAME - return str.dup.force_encoding(Tk::Encoding::BINARY_NAME) - end - - # get target encoding name (if enc == nil, use default encoding) - begin - enc_name = Tk::Encoding::ENCODING_TABLE.get_name(enc) - rescue - # then, enc != nil - # unknown encoding for Tk -> try to convert encoding on Ruby - str = str.dup.force_encoding(Tk::Encoding::UTF8_NAME) - str.encode!(enc) # modify self !! - return str # if no error, probably succeed converting - end - - encstr = __fromUTF8(str, enc_name) - encstr.force_encoding(Tk::Encoding::ENCODING_TABLE.get_obj(enc_name)) - encstr - end - ### - else - # without Encoding (Ruby 1.8) - def _toUTF8(str, encoding = nil) - __toUTF8(str, encoding) - end - def _fromUTF8(str, encoding = nil) - __fromUTF8(str, encoding) - end - ### - end - - alias __eval _eval - alias __invoke _invoke - - def _eval(cmd) - _fromUTF8(__eval(_toUTF8(cmd))) - end - - def _invoke(*cmds) - _fromUTF8(__invoke(*(cmds.collect{|cmd| _toUTF8(cmd)}))) - end - - alias _eval_with_enc _eval - alias _invoke_with_enc _invoke - -=begin - #### --> definition is moved to TclTkIp module - - def _toUTF8(str, encoding = nil) - # decide encoding - if encoding - encoding = encoding.to_s - elsif str.kind_of?(Tk::EncodedString) && str.encoding != nil - encoding = str.encoding.to_s - elsif str.instance_variable_get(:@encoding) - encoding = str.instance_variable_get(:@encoding).to_s - elsif defined?(@encoding) && @encoding != nil - encoding = @encoding.to_s - else - encoding = __invoke('encoding', 'system') - end - - # convert - case encoding - when 'utf-8', 'binary' - str - else - __toUTF8(str, encoding) - end - end - - def _fromUTF8(str, encoding = nil) - unless encoding - if defined?(@encoding) && @encoding != nil - encoding = @encoding.to_s - else - encoding = __invoke('encoding', 'system') - end - end - - if str.kind_of?(Tk::EncodedString) - if str.encoding == 'binary' - str - else - __fromUTF8(str, encoding) - end - elsif str.instance_variable_get(:@encoding).to_s == 'binary' - str - else - __fromUTF8(str, encoding) - end - end -=end - -=begin - def _eval(cmd) - if defined?(@encoding) && @encoding != 'utf-8' - ret = if cmd.kind_of?(Tk::EncodedString) - case cmd.encoding - when 'utf-8', 'binary' - __eval(cmd) - else - __eval(_toUTF8(cmd, cmd.encoding)) - end - elsif cmd.instance_variable_get(:@encoding) == 'binary' - __eval(cmd) - else - __eval(_toUTF8(cmd, @encoding)) - end - if ret.kind_of?(String) && ret.instance_variable_get(:@encoding) == 'binary' - ret - else - _fromUTF8(ret, @encoding) - end - else - __eval(cmd) - end - end - - def _invoke(*cmds) - if defined?(@encoding) && @encoding != 'utf-8' - cmds = cmds.collect{|cmd| - if cmd.kind_of?(Tk::EncodedString) - case cmd.encoding - when 'utf-8', 'binary' - cmd - else - _toUTF8(cmd, cmd.encoding) - end - elsif cmd.instance_variable_get(:@encoding) == 'binary' - cmd - else - _toUTF8(cmd, @encoding) - end - } - ret = __invoke(*cmds) - if ret.kind_of?(String) && ret.instance_variable_get(:@encoding) == 'binary' - ret - else - _fromUTF8(ret, @encoding) - end - else - __invoke(*cmds) - end - end -=end - end - - module TclTkLib - class << self - def force_default_encoding=(mode) - TkCore::INTERP.force_default_encoding = mode - end - - def force_default_encoding? - TkCore::INTERP.force_default_encoding? - end - - def default_encoding=(name) - TkCore::INTERP.default_encoding = name - end - - alias _encoding encoding - alias _encoding= encoding= - def encoding=(name) - name = name.name if name.kind_of?(::Encoding) if Tk::WITH_ENCODING - TkCore::INTERP.encoding = name - end - - def encoding_name - TkCore::INTERP.encoding - end - alias encoding encoding_name - alias default_encoding encoding_name - - def encoding_obj - if Tk::WITH_ENCODING - Tk::Encoding.tcl2rb_encoding(TkCore::INTERP.encoding) - else - TkCore::INTERP.encoding - end - end - end - end - - # estimate encoding - unless TkCore::WITH_ENCODING - case $KCODE - when /^e/i # EUC - Tk.encoding = 'euc-jp' - Tk.encoding_system = 'euc-jp' - when /^s/i # SJIS - begin - if Tk.encoding_system == 'cp932' - Tk.encoding = 'cp932' - else - Tk.encoding = 'shiftjis' - Tk.encoding_system = 'shiftjis' - end - rescue StandardError, NameError - Tk.encoding = 'shiftjis' - Tk.encoding_system = 'shiftjis' - end - when /^u/i # UTF8 - Tk.encoding = 'utf-8' - Tk.encoding_system = 'utf-8' - else # NONE - if defined? DEFAULT_TK_ENCODING - Tk.encoding_system = DEFAULT_TK_ENCODING - end - begin - Tk.encoding = Tk.encoding_system - rescue StandardError, NameError - Tk.encoding = 'utf-8' - Tk.encoding_system = 'utf-8' - end - end - - else ### Ruby 1.9 !!!!!!!!!!!! - # loc_enc_obj = (::Encoding.find(::Encoding.locale_charmap) rescue Tk::Encoding::UNKNOWN) - loc_enc_obj = ::Encoding.find("locale") - ext_enc_obj = ::Encoding.default_external - int_enc_obj = ::Encoding.default_internal || ext_enc_obj - tksys_enc_name = Tk::Encoding::ENCODING_TABLE.get_name(Tk.encoding_system) - # p [Tk.encoding, Tk.encoding_system, loc_enc_obj, ext_enc_obj] - -=begin - if ext_enc_obj == Tk::Encoding::UNKNOWN - if defined? DEFAULT_TK_ENCODING - if DEFAULT_TK_ENCODING.kind_of?(::Encoding) - tk_enc_name = DEFAULT_TK_ENCODING.name - tksys_enc_name = DEFAULT_TK_ENCODING.name - else - tk_enc_name = DEFAULT_TK_ENCODING - tksys_enc_name = DEFAULT_TK_ENCODING - end - else - tk_enc_name = loc_enc_obj.name - tksys_enc_name = loc_enc_obj.name - end - else - tk_enc_name = ext_enc_obj.name - tksys_enc_name = ext_enc_obj.name - end - - # Tk.encoding = tk_enc_name - Tk.default_encoding = tk_enc_name - Tk.encoding_system = tksys_enc_name -=end - - if ext_enc_obj == Tk::Encoding::UNKNOWN - if loc_enc_obj == Tk::Encoding::UNKNOWN - # use Tk.encoding_system - else - # use locale_charmap - begin - loc_enc_name = Tk::Encoding::ENCODING_TABLE.get_name(loc_enc_obj) - if loc_enc_name && loc_enc_name != tksys_enc_name - # use locale_charmap - Tk.encoding_system = loc_enc_name - else - # use Tk.encoding_system - end - rescue ArgumentError - # unsupported encoding on Tk -> use Tk.encoding_system - end - end - else - begin - ext_enc_name = Tk::Encoding::ENCODING_TABLE.get_name(ext_enc_obj) - if ext_enc_name && ext_enc_name != tksys_enc_name - # use default_external - Tk.encoding_system = ext_enc_name - else - # use Tk.encoding_system - end - rescue ArgumentError - # unsupported encoding on Tk -> use Tk.encoding_system - end - end - - # setup Tk.encoding - enc_name = nil - - begin - default_def = DEFAULT_TK_ENCODING - if ::Encoding.find(default_def.to_s) != Tk::Encoding::UNKNOWN - enc_name = Tk::Encoding::ENCODING_TABLE.get_name(default_def) - end - rescue NameError - # ignore - enc_name = nil - rescue ArgumentError - enc_name = nil - fail ArgumentError, - "DEFAULT_TK_ENCODING has an unknown encoding #{default_def}" - end - - unless enc_name - #if ext_enc_obj == Tk::Encoding::UNKNOWN - if int_enc_obj == Tk::Encoding::UNKNOWN - if loc_enc_obj == Tk::Encoding::UNKNOWN - # use Tk.encoding_system - enc_name = tksys_enc_name - else - # use locale_charmap - begin - loc_enc_name = Tk::Encoding::ENCODING_TABLE.get_name(loc_enc_obj) - if loc_enc_name - # use locale_charmap - enc_name = loc_enc_name - else - # use Tk.encoding_system - enc_name = tksys_enc_name - end - rescue ArgumentError - # unsupported encoding on Tk -> use Tk.encoding_system - enc_name = tksys_enc_name - end - end - else - begin - #ext_enc_name = Tk::Encoding::ENCODING_TABLE.get_name(ext_enc_obj) - #if ext_enc_name && ext_enc_name != tksys_enc_name - int_enc_name = Tk::Encoding::ENCODING_TABLE.get_name(int_enc_obj) - if int_enc_name - # use default_internal - enc_name = int_enc_name - else - # use Tk.encoding_system - enc_name = tksys_enc_name - end - rescue ArgumentError - # unsupported encoding on Tk -> use Tk.encoding_system - enc_name = tksys_enc_name - end - end - end - - Tk.default_encoding = (enc_name)? enc_name: tksys_enc_name - end - -else - # dummy methods - module Tk - module Encoding - extend Encoding - - def force_default_encoding=(mode) - nil - end - - def force_default_encoding? - nil - end - - def default_encoding=(enc) - nil - end - def default_encoding - nil - end - - def encoding=(name) - nil - end - def encoding - nil - end - def encoding_names - nil - end - def encoding_system - nil - end - def encoding_system=(enc) - nil - end - - def encoding_convertfrom(str, enc=None) - str - end - alias encoding_convert_from encoding_convertfrom - - def encoding_convertto(str, enc=None) - str - end - alias encoding_convert_to encoding_convertto - def encoding_dirs - nil - end - def encoding_dirs=(dir_array) - nil - end - end - - extend Encoding - end - - class TclTkIp - attr_accessor :encoding - - alias __eval _eval - alias __invoke _invoke - - alias _eval_with_enc _eval - alias _invoke_with_enc _invoke - end -end - - -module TkBindCore - #def bind(context, cmd=Proc.new, *args) - # Tk.bind(self, context, cmd, *args) - #end - def bind(context, *args) - # if args[0].kind_of?(Proc) || args[0].kind_of?(Method) - if TkComm._callback_entry?(args[0]) || !block_given? - cmd = args.shift - else - cmd = Proc.new - end - Tk.bind(self, context, cmd, *args) - end - - #def bind_append(context, cmd=Proc.new, *args) - # Tk.bind_append(self, context, cmd, *args) - #end - def bind_append(context, *args) - # if args[0].kind_of?(Proc) || args[0].kind_of?(Method) - if TkComm._callback_entry?(args[0]) || !block_given? - cmd = args.shift - else - cmd = Proc.new - end - Tk.bind_append(self, context, cmd, *args) - end - - def bind_remove(context) - Tk.bind_remove(self, context) - end - - def bindinfo(context=nil) - Tk.bindinfo(self, context) - end -end - - -module TkTreatFont - def __font_optkeys - ['font'] - end - private :__font_optkeys - - def __pathname - self.path - end - private :__pathname - - ################################ - - def font_configinfo(key = nil) - optkeys = __font_optkeys - if key && !optkeys.find{|opt| opt.to_s == key.to_s} - fail ArgumentError, "unknown font option name `#{key}'" - end - - win, tag = __pathname.split(':') - - if key - pathname = [win, tag, key].join(';') - TkFont.used_on(pathname) || - TkFont.init_widget_font(pathname, *__confinfo_cmd) - elsif optkeys.size == 1 - pathname = [win, tag, optkeys[0]].join(';') - TkFont.used_on(pathname) || - TkFont.init_widget_font(pathname, *__confinfo_cmd) - else - fonts = {} - optkeys.each{|k| - k = k.to_s - pathname = [win, tag, k].join(';') - fonts[k] = - TkFont.used_on(pathname) || - TkFont.init_widget_font(pathname, *__confinfo_cmd) - } - fonts - end - end - alias fontobj font_configinfo - - def font_configure(slot) - pathname = __pathname - - slot = _symbolkey2str(slot) - - __font_optkeys.each{|optkey| - optkey = optkey.to_s - l_optkey = 'latin' << optkey - a_optkey = 'ascii' << optkey - k_optkey = 'kanji' << optkey - - if slot.key?(optkey) - fnt = slot.delete(optkey) - if fnt.kind_of?(TkFont) - slot.delete(l_optkey) - slot.delete(a_optkey) - slot.delete(k_optkey) - - fnt.call_font_configure([pathname, optkey], *(__config_cmd << {})) - next - else - if fnt - if (slot.key?(l_optkey) || - slot.key?(a_optkey) || - slot.key?(k_optkey)) - fnt = TkFont.new(fnt) - - lfnt = slot.delete(l_optkey) - lfnt = slot.delete(a_optkey) if slot.key?(a_optkey) - kfnt = slot.delete(k_optkey) - - fnt.latin_replace(lfnt) if lfnt - fnt.kanji_replace(kfnt) if kfnt - - fnt.call_font_configure([pathname, optkey], - *(__config_cmd << {})) - next - else - fnt = hash_kv(fnt) if fnt.kind_of?(Hash) - unless TkConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__ - tk_call(*(__config_cmd << "-#{optkey}" << fnt)) - else - begin - tk_call(*(__config_cmd << "-#{optkey}" << fnt)) - rescue - # ignore - end - end - end - end - next - end - end - - lfnt = slot.delete(l_optkey) - lfnt = slot.delete(a_optkey) if slot.key?(a_optkey) - kfnt = slot.delete(k_optkey) - - if lfnt && kfnt - TkFont.new(lfnt, kfnt).call_font_configure([pathname, optkey], - *(__config_cmd << {})) - elsif lfnt - latinfont_configure([lfnt, optkey]) - elsif kfnt - kanjifont_configure([kfnt, optkey]) - end - } - - # configure other (without font) options - tk_call(*(__config_cmd.concat(hash_kv(slot)))) if slot != {} - self - end - - def latinfont_configure(ltn, keys=nil) - if ltn.kind_of?(Array) - key = ltn[1] - ltn = ltn[0] - else - key = nil - end - - optkeys = __font_optkeys - if key && !optkeys.find{|opt| opt.to_s == key.to_s} - fail ArgumentError, "unknown font option name `#{key}'" - end - - win, tag = __pathname.split(':') - - optkeys = [key] if key - - optkeys.each{|optkey| - optkey = optkey.to_s - - pathname = [win, tag, optkey].join(';') - - if (fobj = TkFont.used_on(pathname)) - fobj = TkFont.new(fobj) # create a new TkFont object - elsif Tk::JAPANIZED_TK - fobj = fontobj # create a new TkFont object - else - ltn = hash_kv(ltn) if ltn.kind_of?(Hash) - unless TkConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__ - tk_call(*(__config_cmd << "-#{optkey}" << ltn)) - else - begin - tk_call(*(__config_cmd << "-#{optkey}" << ltn)) - rescue => e - # ignore - end - end - next - end - - if fobj.kind_of?(TkFont) - if ltn.kind_of?(TkFont) - conf = {} - ltn.latin_configinfo.each{|k,val| conf[k] = val} - if keys - fobj.latin_configure(conf.update(keys)) - else - fobj.latin_configure(conf) - end - else - fobj.latin_replace(ltn) - end - end - - fobj.call_font_configure([pathname, optkey], *(__config_cmd << {})) - } - self - end - alias asciifont_configure latinfont_configure - - def kanjifont_configure(knj, keys=nil) - if knj.kind_of?(Array) - key = knj[1] - knj = knj[0] - else - key = nil - end - - optkeys = __font_optkeys - if key && !optkeys.find{|opt| opt.to_s == key.to_s} - fail ArgumentError, "unknown font option name `#{key}'" - end - - win, tag = __pathname.split(':') - - optkeys = [key] if key - - optkeys.each{|optkey| - optkey = optkey.to_s - - pathname = [win, tag, optkey].join(';') - - if (fobj = TkFont.used_on(pathname)) - fobj = TkFont.new(fobj) # create a new TkFont object - elsif Tk::JAPANIZED_TK - fobj = fontobj # create a new TkFont object - else - knj = hash_kv(knj) if knj.kind_of?(Hash) - unless TkConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__ - tk_call(*(__config_cmd << "-#{optkey}" << knj)) - else - begin - tk_call(*(__config_cmd << "-#{optkey}" << knj)) - rescue => e - # ignore - end - end - next - end - - if fobj.kind_of?(TkFont) - if knj.kind_of?(TkFont) - conf = {} - knj.kanji_configinfo.each{|k,val| conf[k] = val} - if keys - fobj.kanji_configure(conf.update(keys)) - else - fobj.kanji_configure(conf) - end - else - fobj.kanji_replace(knj) - end - end - - fobj.call_font_configure([pathname, optkey], *(__config_cmd << {})) - } - self - end - - def font_copy(win, wintag=nil, winkey=nil, targetkey=nil) - if wintag - if winkey - fnt = win.tagfontobj(wintag, winkey).dup - else - fnt = win.tagfontobj(wintag).dup - end - else - if winkey - fnt = win.fontobj(winkey).dup - else - fnt = win.fontobj.dup - end - end - - if targetkey - fnt.call_font_configure([__pathname, targetkey], *(__config_cmd << {})) - else - fnt.call_font_configure(__pathname, *(__config_cmd << {})) - end - self - end - - def latinfont_copy(win, wintag=nil, winkey=nil, targetkey=nil) - if targetkey - fontobj(targetkey).dup.call_font_configure([__pathname, targetkey], - *(__config_cmd << {})) - else - fontobj.dup.call_font_configure(__pathname, *(__config_cmd << {})) - end - - if wintag - if winkey - fontobj.latin_replace(win.tagfontobj(wintag, winkey).latin_font_id) - else - fontobj.latin_replace(win.tagfontobj(wintag).latin_font_id) - end - else - if winkey - fontobj.latin_replace(win.fontobj(winkey).latin_font_id) - else - fontobj.latin_replace(win.fontobj.latin_font_id) - end - end - self - end - alias asciifont_copy latinfont_copy - - def kanjifont_copy(win, wintag=nil, winkey=nil, targetkey=nil) - if targetkey - fontobj(targetkey).dup.call_font_configure([__pathname, targetkey], - *(__config_cmd << {})) - else - fontobj.dup.call_font_configure(__pathname, *(__config_cmd << {})) - end - - if wintag - if winkey - fontobj.kanji_replace(win.tagfontobj(wintag, winkey).kanji_font_id) - else - fontobj.kanji_replace(win.tagfontobj(wintag).kanji_font_id) - end - else - if winkey - fontobj.kanji_replace(win.fontobj(winkey).kanji_font_id) - else - fontobj.kanji_replace(win.fontobj.kanji_font_id) - end - end - self - end -end - - -module TkConfigMethod - include TkUtil - include TkTreatFont - - def TkConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__ - @mode || false - end - def TkConfigMethod.__set_IGNORE_UNKNOWN_CONFIGURE_OPTION__!(mode) - @mode = (mode)? true: false - end - - def __cget_cmd - [self.path, 'cget'] - end - private :__cget_cmd - - def __config_cmd - [self.path, 'configure'] - end - private :__config_cmd - - def __confinfo_cmd - __config_cmd - end - private :__confinfo_cmd - - def __configinfo_struct - {:key=>0, :alias=>1, :db_name=>1, :db_class=>2, - :default_value=>3, :current_value=>4} - end - private :__configinfo_struct - - def __optkey_aliases - {} - end - private :__optkey_aliases - - def __numval_optkeys - [] - end - private :__numval_optkeys - - def __numstrval_optkeys - [] - end - private :__numstrval_optkeys - - def __boolval_optkeys - ['exportselection', 'jump', 'setgrid', 'takefocus'] - end - private :__boolval_optkeys - - def __strval_optkeys - [ - 'text', 'label', 'show', 'data', 'file', - 'activebackground', 'activeforeground', 'background', - 'disabledforeground', 'disabledbackground', 'foreground', - 'highlightbackground', 'highlightcolor', 'insertbackground', - 'selectbackground', 'selectforeground', 'troughcolor' - ] - end - private :__strval_optkeys - - def __listval_optkeys - [] - end - private :__listval_optkeys - - def __numlistval_optkeys - [] - end - private :__numlistval_optkeys - - def __tkvariable_optkeys - ['variable', 'textvariable'] - end - private :__tkvariable_optkeys - - def __val2ruby_optkeys # { key=>proc, ... } - # The method is used to convert a opt-value to a ruby's object. - # When get the value of the option "key", "proc.call(value)" is called. - {} - end - private :__val2ruby_optkeys - - def __ruby2val_optkeys # { key=>proc, ... } - # The method is used to convert a ruby's object to a opt-value. - # When set the value of the option "key", "proc.call(value)" is called. - # That is, "-#{key} #{proc.call(value)}". - {} - end - private :__ruby2val_optkeys - - def __methodcall_optkeys # { key=>method, ... } - # The method is used to both of get and set. - # Usually, the 'key' will not be a widget option. - {} - end - private :__methodcall_optkeys - - def __keyonly_optkeys # { def_key=>undef_key or nil, ... } - {} - end - private :__keyonly_optkeys - - def __conv_keyonly_opts(keys) - return keys unless keys.kind_of?(Hash) - keyonly = __keyonly_optkeys - keys2 = {} - keys.each{|k, v| - optkey = keyonly.find{|kk,vv| kk.to_s == k.to_s} - if optkey - defkey, undefkey = optkey - if v - keys2[defkey.to_s] = None - elsif undefkey - keys2[undefkey.to_s] = None - else - # remove key - end - else - keys2[k.to_s] = v - end - } - keys2 - end - private :__conv_keyonly_opts - - def config_hash_kv(keys, enc_mode = nil, conf = nil) - hash_kv(__conv_keyonly_opts(keys), enc_mode, conf) - end - - ################################ - - def [](id) - cget(id) - end - - def []=(id, val) - configure(id, val) - val - end - - def cget_tkstring(option) - opt = option.to_s - fail ArgumentError, "Invalid option `#{option.inspect}'" if opt.length == 0 - tk_call_without_enc(*(__cget_cmd << "-#{opt}")) - end - - def __cget_core(slot) - orig_slot = slot - slot = slot.to_s - - if slot.length == 0 - fail ArgumentError, "Invalid option `#{orig_slot.inspect}'" - end - - alias_name, real_name = __optkey_aliases.find{|k, v| k.to_s == slot} - if real_name - slot = real_name.to_s - end - - if ( method = _symbolkey2str(__val2ruby_optkeys())[slot] ) - optval = tk_call_without_enc(*(__cget_cmd << "-#{slot}")) - begin - return method.call(optval) - rescue => e - warn("Warning:: #{e.message} (when #{method}.call(#{optval.inspect})") if $DEBUG - return optval - end - end - - if ( method = _symbolkey2str(__methodcall_optkeys)[slot] ) - return self.__send__(method) - end - - case slot - when /^(#{__numval_optkeys.join('|')})$/ - begin - number(tk_call_without_enc(*(__cget_cmd << "-#{slot}"))) - rescue - nil - end - - when /^(#{__numstrval_optkeys.join('|')})$/ - num_or_str(tk_call_without_enc(*(__cget_cmd << "-#{slot}"))) - - when /^(#{__boolval_optkeys.join('|')})$/ - begin - bool(tk_call_without_enc(*(__cget_cmd << "-#{slot}"))) - rescue - nil - end - - when /^(#{__listval_optkeys.join('|')})$/ - simplelist(tk_call_without_enc(*(__cget_cmd << "-#{slot}"))) - - when /^(#{__numlistval_optkeys.join('|')})$/ - conf = tk_call_without_enc(*(__cget_cmd << "-#{slot}")) - if conf =~ /^[0-9+-]/ - list(conf) - else - conf - end - - when /^(#{__strval_optkeys.join('|')})$/ - _fromUTF8(tk_call_without_enc(*(__cget_cmd << "-#{slot}"))) - - when /^(|latin|ascii|kanji)(#{__font_optkeys.join('|')})$/ - fontcode = $1 - fontkey = $2 - fnt = tk_tcl2ruby(tk_call_without_enc(*(__cget_cmd << "-#{fontkey}")), true) - unless fnt.kind_of?(TkFont) - fnt = fontobj(fontkey) - end - if fontcode == 'kanji' && JAPANIZED_TK && TK_VERSION =~ /^4\.*/ - # obsolete; just for compatibility - fnt.kanji_font - else - fnt - end - - when /^(#{__tkvariable_optkeys.join('|')})$/ - v = tk_call_without_enc(*(__cget_cmd << "-#{slot}")) - (v.empty?)? nil: TkVarAccess.new(v) - - else - tk_tcl2ruby(tk_call_without_enc(*(__cget_cmd << "-#{slot}")), true) - end - end - private :__cget_core - - def cget(slot) - unless TkConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__ - __cget_core(slot) - else - begin - __cget_core(slot) - rescue => e - if current_configinfo.has_key?(slot.to_s) - # error on known option - fail e - else - # unknown option - nil - end - end - end - end - def cget_strict(slot) - # never use TkConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__ - __cget_core(slot) - end - - def __configure_core(slot, value=None) - if slot.kind_of? Hash - slot = _symbolkey2str(slot) - - __optkey_aliases.each{|alias_name, real_name| - alias_name = alias_name.to_s - if slot.has_key?(alias_name) - slot[real_name.to_s] = slot.delete(alias_name) - end - } - - __methodcall_optkeys.each{|key, method| - value = slot.delete(key.to_s) - self.__send__(method, value) if value - } - - __ruby2val_optkeys.each{|key, method| - key = key.to_s - slot[key] = method.call(slot[key]) if slot.has_key?(key) - } - - __keyonly_optkeys.each{|defkey, undefkey| - conf = slot.find{|kk, vv| kk == defkey.to_s} - if conf - k, v = conf - if v - slot[k] = None - else - slot[undefkey.to_s] = None if undefkey - slot.delete(k) - end - end - } - - if (slot.find{|k, v| k =~ /^(|latin|ascii|kanji)(#{__font_optkeys.join('|')})$/}) - font_configure(slot) - elsif slot.size > 0 - tk_call(*(__config_cmd.concat(hash_kv(slot)))) - end - - else - orig_slot = slot - slot = slot.to_s - if slot.length == 0 - fail ArgumentError, "Invalid option `#{orig_slot.inspect}'" - end - - alias_name, real_name = __optkey_aliases.find{|k, v| k.to_s == slot} - if real_name - slot = real_name.to_s - end - - if ( conf = __keyonly_optkeys.find{|k, v| k.to_s == slot} ) - defkey, undefkey = conf - if value - tk_call(*(__config_cmd << "-#{defkey}")) - elsif undefkey - tk_call(*(__config_cmd << "-#{undefkey}")) - end - elsif ( method = _symbolkey2str(__ruby2val_optkeys)[slot] ) - tk_call(*(__config_cmd << "-#{slot}" << method.call(value))) - elsif ( method = _symbolkey2str(__methodcall_optkeys)[slot] ) - self.__send__(method, value) - elsif (slot =~ /^(|latin|ascii|kanji)(#{__font_optkeys.join('|')})$/) - if value == None - fontobj($2) - else - font_configure({slot=>value}) - end - else - tk_call(*(__config_cmd << "-#{slot}" << value)) - end - end - self - end - private :__configure_core - - def __check_available_configure_options(keys) - availables = self.current_configinfo.keys - - # add non-standard keys - availables |= __font_optkeys.map{|k| - [k.to_s, "latin#{k}", "ascii#{k}", "kanji#{k}"] - }.flatten - availables |= __methodcall_optkeys.keys.map{|k| k.to_s} - availables |= __keyonly_optkeys.keys.map{|k| k.to_s} - - keys = _symbolkey2str(keys) - keys.delete_if{|k, v| !(availables.include?(k))} - end - - def configure(slot, value=None) - unless TkConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__ - __configure_core(slot, value) - else - if slot.kind_of?(Hash) - begin - __configure_core(slot) - rescue - slot = __check_available_configure_options(slot) - __configure_core(slot) unless slot.empty? - end - else - begin - __configure_core(slot, value) - rescue => e - if current_configinfo.has_key?(slot.to_s) - # error on known option - fail e - else - # unknown option - nil - end - end - end - end - self - end - - def configure_cmd(slot, value) - configure(slot, install_cmd(value)) - end - - def __configinfo_core(slot = nil) - if TkComm::GET_CONFIGINFO_AS_ARRAY - if (slot && - slot.to_s =~ /^(|latin|ascii|kanji)(#{__font_optkeys.join('|')})$/) - fontkey = $2 - # conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__confinfo_cmd << "-#{fontkey}")))) - conf = tk_split_simplelist(tk_call_without_enc(*(__confinfo_cmd << "-#{fontkey}")), false, true) - conf[__configinfo_struct[:key]] = - conf[__configinfo_struct[:key]][1..-1] - if ( ! __configinfo_struct[:alias] \ - || conf.size > __configinfo_struct[:alias] + 1 ) - fnt = conf[__configinfo_struct[:default_value]] - if TkFont.is_system_font?(fnt) - conf[__configinfo_struct[:default_value]] = TkNamedFont.new(fnt) - end - conf[__configinfo_struct[:current_value]] = fontobj(fontkey) - elsif ( __configinfo_struct[:alias] \ - && conf.size == __configinfo_struct[:alias] + 1 \ - && conf[__configinfo_struct[:alias]][0] == ?- ) - conf[__configinfo_struct[:alias]] = - conf[__configinfo_struct[:alias]][1..-1] - end - conf - else - if slot - slot = slot.to_s - - alias_name, real_name = __optkey_aliases.find{|k, v| k.to_s == slot} - if real_name - slot = real_name.to_s - end - - case slot - when /^(#{__val2ruby_optkeys().keys.join('|')})$/ - method = _symbolkey2str(__val2ruby_optkeys())[slot] - conf = tk_split_simplelist(tk_call_without_enc(*(__confinfo_cmd() << "-#{slot}")), false, true) - if ( __configinfo_struct[:default_value] \ - && conf[__configinfo_struct[:default_value]] ) - optval = conf[__configinfo_struct[:default_value]] - begin - val = method.call(optval) - rescue => e - warn("Warning:: #{e.message} (when #{method}.call(#{optval.inspect})") if $DEBUG - val = optval - end - conf[__configinfo_struct[:default_value]] = val - end - if ( conf[__configinfo_struct[:current_value]] ) - optval = conf[__configinfo_struct[:current_value]] - begin - val = method.call(optval) - rescue => e - warn("Warning:: #{e.message} (when #{method}.call(#{optval.inspect})") if $DEBUG - val = optval - end - conf[__configinfo_struct[:current_value]] = val - end - - when /^(#{__methodcall_optkeys.keys.join('|')})$/ - method = _symbolkey2str(__methodcall_optkeys)[slot] - return [slot, '', '', '', self.__send__(method)] - - when /^(#{__numval_optkeys.join('|')})$/ - # conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")))) - conf = tk_split_simplelist(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")), false, true) - - if ( __configinfo_struct[:default_value] \ - && conf[__configinfo_struct[:default_value]]) - begin - conf[__configinfo_struct[:default_value]] = - number(conf[__configinfo_struct[:default_value]]) - rescue - conf[__configinfo_struct[:default_value]] = nil - end - end - if ( conf[__configinfo_struct[:current_value]] ) - begin - conf[__configinfo_struct[:current_value]] = - number(conf[__configinfo_struct[:current_value]]) - rescue - conf[__configinfo_struct[:current_value]] = nil - end - end - - when /^(#{__numstrval_optkeys.join('|')})$/ - # conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")))) - conf = tk_split_simplelist(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")), false, true) - - if ( __configinfo_struct[:default_value] \ - && conf[__configinfo_struct[:default_value]]) - conf[__configinfo_struct[:default_value]] = - num_or_str(conf[__configinfo_struct[:default_value]]) - end - if ( conf[__configinfo_struct[:current_value]] ) - conf[__configinfo_struct[:current_value]] = - num_or_str(conf[__configinfo_struct[:current_value]]) - end - - when /^(#{__boolval_optkeys.join('|')})$/ - # conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")))) - conf = tk_split_simplelist(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")), false, true) - - if ( __configinfo_struct[:default_value] \ - && conf[__configinfo_struct[:default_value]]) - begin - conf[__configinfo_struct[:default_value]] = - bool(conf[__configinfo_struct[:default_value]]) - rescue - conf[__configinfo_struct[:default_value]] = nil - end - end - if ( conf[__configinfo_struct[:current_value]] ) - begin - conf[__configinfo_struct[:current_value]] = - bool(conf[__configinfo_struct[:current_value]]) - rescue - conf[__configinfo_struct[:current_value]] = nil - end - end - - when /^(#{__listval_optkeys.join('|')})$/ - # conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")))) - conf = tk_split_simplelist(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")), false, true) - - if ( __configinfo_struct[:default_value] \ - && conf[__configinfo_struct[:default_value]]) - conf[__configinfo_struct[:default_value]] = - simplelist(conf[__configinfo_struct[:default_value]]) - end - if ( conf[__configinfo_struct[:current_value]] ) - conf[__configinfo_struct[:current_value]] = - simplelist(conf[__configinfo_struct[:current_value]]) - end - - when /^(#{__numlistval_optkeys.join('|')})$/ - # conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")))) - conf = tk_split_simplelist(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")), false, true) - - if ( __configinfo_struct[:default_value] \ - && conf[__configinfo_struct[:default_value]] \ - && conf[__configinfo_struct[:default_value]] =~ /^[0-9]/ ) - conf[__configinfo_struct[:default_value]] = - list(conf[__configinfo_struct[:default_value]]) - end - if ( conf[__configinfo_struct[:current_value]] \ - && conf[__configinfo_struct[:current_value]] =~ /^[0-9]/ ) - conf[__configinfo_struct[:current_value]] = - list(conf[__configinfo_struct[:current_value]]) - end - - when /^(#{__strval_optkeys.join('|')})$/ - # conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")))) - conf = tk_split_simplelist(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")), false, true) - - when /^(#{__tkvariable_optkeys.join('|')})$/ - conf = tk_split_simplelist(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")), false, true) - - if ( __configinfo_struct[:default_value] \ - && conf[__configinfo_struct[:default_value]]) - v = conf[__configinfo_struct[:default_value]] - if v.empty? - conf[__configinfo_struct[:default_value]] = nil - else - conf[__configinfo_struct[:default_value]] = TkVarAccess.new(v) - end - end - if ( conf[__configinfo_struct[:current_value]] ) - v = conf[__configinfo_struct[:current_value]] - if v.empty? - conf[__configinfo_struct[:current_value]] = nil - else - conf[__configinfo_struct[:current_value]] = TkVarAccess.new(v) - end - end - - else - # conf = tk_split_list(_fromUTF8(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")))) - # conf = tk_split_list(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")), 0, false, true) - conf = tk_split_list(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")), 1, false, true) - end - conf[__configinfo_struct[:key]] = - conf[__configinfo_struct[:key]][1..-1] - - if ( __configinfo_struct[:alias] \ - && conf.size == __configinfo_struct[:alias] + 1 \ - && conf[__configinfo_struct[:alias]][0] == ?- ) - conf[__configinfo_struct[:alias]] = - conf[__configinfo_struct[:alias]][1..-1] - end - - conf - - else - # ret = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*__confinfo_cmd))).collect{|conflist| - # conf = tk_split_simplelist(conflist) - ret = tk_split_simplelist(tk_call_without_enc(*__confinfo_cmd), false, false).collect{|conflist| - conf = tk_split_simplelist(conflist, false, true) - conf[__configinfo_struct[:key]] = - conf[__configinfo_struct[:key]][1..-1] - - optkey = conf[__configinfo_struct[:key]] - case optkey - when /^(#{__val2ruby_optkeys().keys.join('|')})$/ - method = _symbolkey2str(__val2ruby_optkeys())[optkey] - if ( __configinfo_struct[:default_value] \ - && conf[__configinfo_struct[:default_value]] ) - optval = conf[__configinfo_struct[:default_value]] - begin - val = method.call(optval) - rescue => e - warn("Warning:: #{e.message} (when #{method}.call(#{optval.inspect})") if $DEBUG - val = optval - end - conf[__configinfo_struct[:default_value]] = val - end - if ( conf[__configinfo_struct[:current_value]] ) - optval = conf[__configinfo_struct[:current_value]] - begin - val = method.call(optval) - rescue => e - warn("Warning:: #{e.message} (when #{method}.call(#{optval.inspect})") if $DEBUG - val = optval - end - conf[__configinfo_struct[:current_value]] = val - end - - when /^(#{__strval_optkeys.join('|')})$/ - # do nothing - - when /^(#{__numval_optkeys.join('|')})$/ - if ( __configinfo_struct[:default_value] \ - && conf[__configinfo_struct[:default_value]] ) - begin - conf[__configinfo_struct[:default_value]] = - number(conf[__configinfo_struct[:default_value]]) - rescue - conf[__configinfo_struct[:default_value]] = nil - end - end - if ( conf[__configinfo_struct[:current_value]] ) - begin - conf[__configinfo_struct[:current_value]] = - number(conf[__configinfo_struct[:current_value]]) - rescue - conf[__configinfo_struct[:current_value]] = nil - end - end - - when /^(#{__numstrval_optkeys.join('|')})$/ - if ( __configinfo_struct[:default_value] \ - && conf[__configinfo_struct[:default_value]] ) - conf[__configinfo_struct[:default_value]] = - num_or_str(conf[__configinfo_struct[:default_value]]) - end - if ( conf[__configinfo_struct[:current_value]] ) - conf[__configinfo_struct[:current_value]] = - num_or_str(conf[__configinfo_struct[:current_value]]) - end - - when /^(#{__boolval_optkeys.join('|')})$/ - if ( __configinfo_struct[:default_value] \ - && conf[__configinfo_struct[:default_value]] ) - begin - conf[__configinfo_struct[:default_value]] = - bool(conf[__configinfo_struct[:default_value]]) - rescue - conf[__configinfo_struct[:default_value]] = nil - end - end - if ( conf[__configinfo_struct[:current_value]] ) - begin - conf[__configinfo_struct[:current_value]] = - bool(conf[__configinfo_struct[:current_value]]) - rescue - conf[__configinfo_struct[:current_value]] = nil - end - end - - when /^(#{__listval_optkeys.join('|')})$/ - if ( __configinfo_struct[:default_value] \ - && conf[__configinfo_struct[:default_value]] ) - conf[__configinfo_struct[:default_value]] = - simplelist(conf[__configinfo_struct[:default_value]]) - end - if ( conf[__configinfo_struct[:current_value]] ) - conf[__configinfo_struct[:current_value]] = - simplelist(conf[__configinfo_struct[:current_value]]) - end - - when /^(#{__numlistval_optkeys.join('|')})$/ - if ( __configinfo_struct[:default_value] \ - && conf[__configinfo_struct[:default_value]] \ - && conf[__configinfo_struct[:default_value]] =~ /^[0-9]/ ) - conf[__configinfo_struct[:default_value]] = - list(conf[__configinfo_struct[:default_value]]) - end - if ( conf[__configinfo_struct[:current_value]] \ - && conf[__configinfo_struct[:current_value]] =~ /^[0-9]/ ) - conf[__configinfo_struct[:current_value]] = - list(conf[__configinfo_struct[:current_value]]) - end - - when /^(#{__tkvariable_optkeys.join('|')})$/ - if ( __configinfo_struct[:default_value] \ - && conf[__configinfo_struct[:default_value]] ) - v = conf[__configinfo_struct[:default_value]] - if v.empty? - conf[__configinfo_struct[:default_value]] = nil - else - conf[__configinfo_struct[:default_value]] = TkVarAccess.new(v) - end - end - if ( conf[__configinfo_struct[:current_value]] ) - v = conf[__configinfo_struct[:current_value]] - if v.empty? - conf[__configinfo_struct[:current_value]] = nil - else - conf[__configinfo_struct[:current_value]] = TkVarAccess.new(v) - end - end - - else - if ( __configinfo_struct[:default_value] \ - && conf[__configinfo_struct[:default_value]] ) - if conf[__configinfo_struct[:default_value]].index('{') - conf[__configinfo_struct[:default_value]] = - tk_split_list(conf[__configinfo_struct[:default_value]]) - else - conf[__configinfo_struct[:default_value]] = - tk_tcl2ruby(conf[__configinfo_struct[:default_value]]) - end - end - if conf[__configinfo_struct[:current_value]] - if conf[__configinfo_struct[:current_value]].index('{') - conf[__configinfo_struct[:current_value]] = - tk_split_list(conf[__configinfo_struct[:current_value]]) - else - conf[__configinfo_struct[:current_value]] = - tk_tcl2ruby(conf[__configinfo_struct[:current_value]]) - end - end - end - - if ( __configinfo_struct[:alias] \ - && conf.size == __configinfo_struct[:alias] + 1 \ - && conf[__configinfo_struct[:alias]][0] == ?- ) - conf[__configinfo_struct[:alias]] = - conf[__configinfo_struct[:alias]][1..-1] - end - - conf - } - - __font_optkeys.each{|optkey| - optkey = optkey.to_s - fontconf = ret.assoc(optkey) - if fontconf && fontconf.size > 2 - ret.delete_if{|inf| inf[0] =~ /^(|latin|ascii|kanji)#{optkey}$/} - fnt = fontconf[__configinfo_struct[:default_value]] - if TkFont.is_system_font?(fnt) - fontconf[__configinfo_struct[:default_value]] \ - = TkNamedFont.new(fnt) - end - fontconf[__configinfo_struct[:current_value]] = fontobj(optkey) - ret.push(fontconf) - end - } - - __methodcall_optkeys.each{|optkey, m| - ret << [optkey.to_s, '', '', '', self.__send__(m)] - } - - ret - end - end - - else # ! TkComm::GET_CONFIGINFO_AS_ARRAY - if (slot && - slot.to_s =~ /^(|latin|ascii|kanji)(#{__font_optkeys.join('|')})$/) - fontkey = $2 - # conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__confinfo_cmd << "-#{fontkey}")))) - conf = tk_split_simplelist(tk_call_without_enc(*(__confinfo_cmd << "-#{fontkey}")), false, true) - conf[__configinfo_struct[:key]] = - conf[__configinfo_struct[:key]][1..-1] - - if ( ! __configinfo_struct[:alias] \ - || conf.size > __configinfo_struct[:alias] + 1 ) - fnt = conf[__configinfo_struct[:default_value]] - if TkFont.is_system_font?(fnt) - conf[__configinfo_struct[:default_value]] = TkNamedFont.new(fnt) - end - conf[__configinfo_struct[:current_value]] = fontobj(fontkey) - { conf.shift => conf } - elsif ( __configinfo_struct[:alias] \ - && conf.size == __configinfo_struct[:alias] + 1 ) - if conf[__configinfo_struct[:alias]][0] == ?- - conf[__configinfo_struct[:alias]] = - conf[__configinfo_struct[:alias]][1..-1] - end - { conf[0] => conf[1] } - else - { conf.shift => conf } - end - else - if slot - slot = slot.to_s - - alias_name, real_name = __optkey_aliases.find{|k,var| k.to_s == slot} - if real_name - slot = real_name.to_s - end - - case slot - when /^(#{__val2ruby_optkeys().keys.join('|')})$/ - method = _symbolkey2str(__val2ruby_optkeys())[slot] - conf = tk_split_simplelist(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")), false, true) - if ( __configinfo_struct[:default_value] \ - && conf[__configinfo_struct[:default_value]] ) - optval = conf[__configinfo_struct[:default_value]] - begin - val = method.call(optval) - rescue => e - warn("Warning:: #{e.message} (when #{method}.call(#{optval.inspect})") if $DEBUG - val = optval - end - conf[__configinfo_struct[:default_value]] = val - end - if ( conf[__configinfo_struct[:current_value]] ) - optval = conf[__configinfo_struct[:current_value]] - begin - val = method.call(optval) - rescue => e - warn("Warning:: #{e.message} (when #{method}.call(#{optval.inspect})") if $DEBUG - val = optval - end - conf[__configinfo_struct[:current_value]] = val - end - - when /^(#{__methodcall_optkeys.keys.join('|')})$/ - method = _symbolkey2str(__methodcall_optkeys)[slot] - return {slot => ['', '', '', self.__send__(method)]} - - when /^(#{__numval_optkeys.join('|')})$/ - # conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")))) - conf = tk_split_simplelist(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")), false, true) - - if ( __configinfo_struct[:default_value] \ - && conf[__configinfo_struct[:default_value]] ) - begin - conf[__configinfo_struct[:default_value]] = - number(conf[__configinfo_struct[:default_value]]) - rescue - conf[__configinfo_struct[:default_value]] = nil - end - end - if ( conf[__configinfo_struct[:current_value]] ) - begin - conf[__configinfo_struct[:current_value]] = - number(conf[__configinfo_struct[:current_value]]) - rescue - conf[__configinfo_struct[:current_value]] = nil - end - end - - when /^(#{__numstrval_optkeys.join('|')})$/ - # conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")))) - conf = tk_split_simplelist(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")), false, true) - - if ( __configinfo_struct[:default_value] \ - && conf[__configinfo_struct[:default_value]] ) - conf[__configinfo_struct[:default_value]] = - num_or_str(conf[__configinfo_struct[:default_value]]) - end - if ( conf[__configinfo_struct[:current_value]] ) - conf[__configinfo_struct[:current_value]] = - num_or_str(conf[__configinfo_struct[:current_value]]) - end - - when /^(#{__boolval_optkeys.join('|')})$/ - # conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")))) - conf = tk_split_simplelist(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")), false, true) - - if ( __configinfo_struct[:default_value] \ - && conf[__configinfo_struct[:default_value]] ) - begin - conf[__configinfo_struct[:default_value]] = - bool(conf[__configinfo_struct[:default_value]]) - rescue - conf[__configinfo_struct[:default_value]] = nil - end - end - if ( conf[__configinfo_struct[:current_value]] ) - begin - conf[__configinfo_struct[:current_value]] = - bool(conf[__configinfo_struct[:current_value]]) - rescue - conf[__configinfo_struct[:current_value]] = nil - end - end - - when /^(#{__listval_optkeys.join('|')})$/ - # conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")))) - conf = tk_split_simplelist(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")), false, true) - - if ( __configinfo_struct[:default_value] \ - && conf[__configinfo_struct[:default_value]] ) - conf[__configinfo_struct[:default_value]] = - simplelist(conf[__configinfo_struct[:default_value]]) - end - if ( conf[__configinfo_struct[:current_value]] ) - conf[__configinfo_struct[:current_value]] = - simplelist(conf[__configinfo_struct[:current_value]]) - end - - when /^(#{__numlistval_optkeys.join('|')})$/ - # conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")))) - conf = tk_split_simplelist(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")), false, true) - - if ( __configinfo_struct[:default_value] \ - && conf[__configinfo_struct[:default_value]] \ - && conf[__configinfo_struct[:default_value]] =~ /^[0-9]/ ) - conf[__configinfo_struct[:default_value]] = - list(conf[__configinfo_struct[:default_value]]) - end - if ( conf[__configinfo_struct[:current_value]] \ - && conf[__configinfo_struct[:current_value]] =~ /^[0-9]/ ) - conf[__configinfo_struct[:current_value]] = - list(conf[__configinfo_struct[:current_value]]) - end - - when /^(#{__tkvariable_optkeys.join('|')})$/ - conf = tk_split_simplelist(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")), false, true) - - if ( __configinfo_struct[:default_value] \ - && conf[__configinfo_struct[:default_value]] ) - v = conf[__configinfo_struct[:default_value]] - if v.empty? - conf[__configinfo_struct[:default_value]] = nil - else - conf[__configinfo_struct[:default_value]] = TkVarAccess.new(v) - end - end - if ( conf[__configinfo_struct[:current_value]] ) - v = conf[__configinfo_struct[:current_value]] - if v.empty? - conf[__configinfo_struct[:current_value]] = nil - else - conf[__configinfo_struct[:current_value]] = TkVarAccess.new(v) - end - end - - when /^(#{__strval_optkeys.join('|')})$/ - # conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")))) - conf = tk_split_simplelist(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")), false, true) - else - # conf = tk_split_list(_fromUTF8(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")))) - conf = tk_split_list(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")), 0, false, true) - end - conf[__configinfo_struct[:key]] = - conf[__configinfo_struct[:key]][1..-1] - - if ( __configinfo_struct[:alias] \ - && conf.size == __configinfo_struct[:alias] + 1 ) - if conf[__configinfo_struct[:alias]][0] == ?- - conf[__configinfo_struct[:alias]] = - conf[__configinfo_struct[:alias]][1..-1] - end - { conf[0] => conf[1] } - else - { conf.shift => conf } - end - - else - ret = {} - # tk_split_simplelist(_fromUTF8(tk_call_without_enc(*__confinfo_cmd))).each{|conflist| - # conf = tk_split_simplelist(conflist) - tk_split_simplelist(tk_call_without_enc(*__confinfo_cmd), false, false).each{|conflist| - conf = tk_split_simplelist(conflist, false, true) - conf[__configinfo_struct[:key]] = - conf[__configinfo_struct[:key]][1..-1] - - optkey = conf[__configinfo_struct[:key]] - case optkey - when /^(#{__val2ruby_optkeys().keys.join('|')})$/ - method = _symbolkey2str(__val2ruby_optkeys())[optkey] - if ( __configinfo_struct[:default_value] \ - && conf[__configinfo_struct[:default_value]] ) - optval = conf[__configinfo_struct[:default_value]] - begin - val = method.call(optval) - rescue => e - warn("Warning:: #{e.message} (when #{method}.call(#{optval.inspect})") if $DEBUG - val = optval - end - conf[__configinfo_struct[:default_value]] = val - end - if ( conf[__configinfo_struct[:current_value]] ) - optval = conf[__configinfo_struct[:current_value]] - begin - val = method.call(optval) - rescue => e - warn("Warning:: #{e.message} (when #{method}.call(#{optval.inspect})") if $DEBUG - val = optval - end - conf[__configinfo_struct[:current_value]] = val - end - - when /^(#{__strval_optkeys.join('|')})$/ - # do nothing - - when /^(#{__numval_optkeys.join('|')})$/ - if ( __configinfo_struct[:default_value] \ - && conf[__configinfo_struct[:default_value]] ) - begin - conf[__configinfo_struct[:default_value]] = - number(conf[__configinfo_struct[:default_value]]) - rescue - conf[__configinfo_struct[:default_value]] = nil - end - end - if ( conf[__configinfo_struct[:current_value]] ) - begin - conf[__configinfo_struct[:current_value]] = - number(conf[__configinfo_struct[:current_value]]) - rescue - conf[__configinfo_struct[:current_value]] = nil - end - end - - when /^(#{__numstrval_optkeys.join('|')})$/ - if ( __configinfo_struct[:default_value] \ - && conf[__configinfo_struct[:default_value]] ) - conf[__configinfo_struct[:default_value]] = - num_or_str(conf[__configinfo_struct[:default_value]]) - end - if ( conf[__configinfo_struct[:current_value]] ) - conf[__configinfo_struct[:current_value]] = - num_or_str(conf[__configinfo_struct[:current_value]]) - end - - when /^(#{__boolval_optkeys.join('|')})$/ - if ( __configinfo_struct[:default_value] \ - && conf[__configinfo_struct[:default_value]] ) - begin - conf[__configinfo_struct[:default_value]] = - bool(conf[__configinfo_struct[:default_value]]) - rescue - conf[__configinfo_struct[:default_value]] = nil - end - end - if ( conf[__configinfo_struct[:current_value]] ) - begin - conf[__configinfo_struct[:current_value]] = - bool(conf[__configinfo_struct[:current_value]]) - rescue - conf[__configinfo_struct[:current_value]] = nil - end - end - - when /^(#{__listval_optkeys.join('|')})$/ - if ( __configinfo_struct[:default_value] \ - && conf[__configinfo_struct[:default_value]] ) - conf[__configinfo_struct[:default_value]] = - simplelist(conf[__configinfo_struct[:default_value]]) - end - if ( conf[__configinfo_struct[:current_value]] ) - conf[__configinfo_struct[:current_value]] = - simplelist(conf[__configinfo_struct[:current_value]]) - end - - when /^(#{__numlistval_optkeys.join('|')})$/ - if ( __configinfo_struct[:default_value] \ - && conf[__configinfo_struct[:default_value]] \ - && conf[__configinfo_struct[:default_value]] =~ /^[0-9]/ ) - conf[__configinfo_struct[:default_value]] = - list(conf[__configinfo_struct[:default_value]]) - end - if ( conf[__configinfo_struct[:current_value]] \ - && conf[__configinfo_struct[:current_value]] =~ /^[0-9]/ ) - conf[__configinfo_struct[:current_value]] = - list(conf[__configinfo_struct[:current_value]]) - end - - when /^(#{__tkvariable_optkeys.join('|')})$/ - if ( __configinfo_struct[:default_value] \ - && conf[__configinfo_struct[:default_value]] ) - v = conf[__configinfo_struct[:default_value]] - if v.empty? - conf[__configinfo_struct[:default_value]] = nil - else - conf[__configinfo_struct[:default_value]] = TkVarAccess.new - end - end - if ( conf[__configinfo_struct[:current_value]] ) - v = conf[__configinfo_struct[:current_value]] - if v.empty? - conf[__configinfo_struct[:current_value]] = nil - else - conf[__configinfo_struct[:current_value]] = TkVarAccess.new - end - end - - else - if ( __configinfo_struct[:default_value] \ - && conf[__configinfo_struct[:default_value]] ) - if conf[__configinfo_struct[:default_value]].index('{') - conf[__configinfo_struct[:default_value]] = - tk_split_list(conf[__configinfo_struct[:default_value]]) - else - conf[__configinfo_struct[:default_value]] = - tk_tcl2ruby(conf[__configinfo_struct[:default_value]]) - end - end - if conf[__configinfo_struct[:current_value]] - if conf[__configinfo_struct[:current_value]].index('{') - conf[__configinfo_struct[:current_value]] = - tk_split_list(conf[__configinfo_struct[:current_value]]) - else - conf[__configinfo_struct[:current_value]] = - tk_tcl2ruby(conf[__configinfo_struct[:current_value]]) - end - end - end - - if ( __configinfo_struct[:alias] \ - && conf.size == __configinfo_struct[:alias] + 1 ) - if conf[__configinfo_struct[:alias]][0] == ?- - conf[__configinfo_struct[:alias]] = - conf[__configinfo_struct[:alias]][1..-1] - end - ret[conf[0]] = conf[1] - else - ret[conf.shift] = conf - end - } - - __font_optkeys.each{|optkey| - optkey = optkey.to_s - fontconf = ret[optkey] - if fontconf.kind_of?(Array) - ret.delete(optkey) - ret.delete('latin' << optkey) - ret.delete('ascii' << optkey) - ret.delete('kanji' << optkey) - fnt = fontconf[__configinfo_struct[:default_value]] - if TkFont.is_system_font?(fnt) - fontconf[__configinfo_struct[:default_value]] \ - = TkNamedFont.new(fnt) - end - fontconf[__configinfo_struct[:current_value]] = fontobj(optkey) - ret[optkey] = fontconf - end - } - - __methodcall_optkeys.each{|optkey, m| - ret[optkey.to_s] = ['', '', '', self.__send__(m)] - } - - ret - end - end - end - end - private :__configinfo_core - - def configinfo(slot = nil) - if slot && TkConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__ - begin - __configinfo_core(slot) - rescue - Array.new(__configinfo_struct.values.max).unshift(slot.to_s) - end - else - __configinfo_core(slot) - end - end - - def current_configinfo(slot = nil) - if TkComm::GET_CONFIGINFO_AS_ARRAY - if slot - org_slot = slot - begin - conf = configinfo(slot) - if ( ! __configinfo_struct[:alias] \ - || conf.size > __configinfo_struct[:alias] + 1 ) - return {conf[0] => conf[-1]} - end - slot = conf[__configinfo_struct[:alias]] - end while(org_slot != slot) - fail RuntimeError, - "there is a configure alias loop about '#{org_slot}'" - else - ret = {} - configinfo().each{|cnf| - if ( ! __configinfo_struct[:alias] \ - || cnf.size > __configinfo_struct[:alias] + 1 ) - ret[cnf[0]] = cnf[-1] - end - } - ret - end - else # ! TkComm::GET_CONFIGINFO_AS_ARRAY - ret = {} - configinfo(slot).each{|key, cnf| - ret[key] = cnf[-1] if cnf.kind_of?(Array) - } - ret - end - end -end - -class TkObject<TkKernel - extend TkCore - include Tk - include TkConfigMethod - include TkBindCore - -### --> definition is moved to TkUtil module -# def path -# @path -# end - - def epath - @path - end - - def to_eval - @path - end - - def tk_send(cmd, *rest) - tk_call(path, cmd, *rest) - end - def tk_send_without_enc(cmd, *rest) - tk_call_without_enc(path, cmd, *rest) - end - def tk_send_with_enc(cmd, *rest) - tk_call_with_enc(path, cmd, *rest) - end - # private :tk_send, :tk_send_without_enc, :tk_send_with_enc - - def tk_send_to_list(cmd, *rest) - tk_call_to_list(path, cmd, *rest) - end - def tk_send_to_list_without_enc(cmd, *rest) - tk_call_to_list_without_enc(path, cmd, *rest) - end - def tk_send_to_list_with_enc(cmd, *rest) - tk_call_to_list_with_enc(path, cmd, *rest) - end - def tk_send_to_simplelist(cmd, *rest) - tk_call_to_simplelist(path, cmd, *rest) - end - def tk_send_to_simplelist_without_enc(cmd, *rest) - tk_call_to_simplelist_without_enc(path, cmd, *rest) - end - def tk_send_to_simplelist_with_enc(cmd, *rest) - tk_call_to_simplelist_with_enc(path, cmd, *rest) - end - - def method_missing(id, *args) - name = id.id2name - case args.length - when 1 - if name[-1] == ?= - configure name[0..-2], args[0] - args[0] - else - configure name, args[0] - self - end - when 0 - begin - cget(name) - rescue - if self.kind_of?(TkWindow) && name != "to_ary" && name != "to_str" - fail NameError, - "unknown option '#{id}' for #{self.inspect} (deleted widget?)" - else - super(id, *args) - end -# fail NameError, -# "undefined local variable or method `#{name}' for #{self.to_s}", -# error_at - end - else - super(id, *args) -# fail NameError, "undefined method `#{name}' for #{self.to_s}", error_at - end - end - -=begin - def [](id) - cget(id) - end - - def []=(id, val) - configure(id, val) - val - end -=end - - def event_generate(context, keys=nil) - if context.kind_of?(TkEvent::Event) - context.generate(self, ((keys)? keys: {})) - elsif keys - #tk_call('event', 'generate', path, - # "<#{tk_event_sequence(context)}>", *hash_kv(keys)) - tk_call_without_enc('event', 'generate', path, - "<#{tk_event_sequence(context)}>", - *hash_kv(keys, true)) - else - #tk_call('event', 'generate', path, "<#{tk_event_sequence(context)}>") - tk_call_without_enc('event', 'generate', path, - "<#{tk_event_sequence(context)}>") - end - end - - def tk_trace_variable(v) - #unless v.kind_of?(TkVariable) - # fail(ArgumentError, "type error (#{v.class}); must be TkVariable object") - #end - v - end - private :tk_trace_variable - - def destroy - #tk_call 'trace', 'vdelete', @tk_vn, 'w', @var_id if @var_id - end -end - - -class TkWindow<TkObject - include TkWinfo - extend TkBindCore - include Tk::Wm_for_General - include Tk::Busy - - @@WIDGET_INSPECT_FULL = false - def TkWindow._widget_inspect_full_? - @@WIDGET_INSPECT_FULL - end - def TkWindow._widget_inspect_full_=(mode) - @@WIDGET_INSPECT_FULL = (mode && true) || false - end - - TkCommandNames = [].freeze - ## ==> If TkCommandNames[0] is a string (not a null string), - ## assume the string is a Tcl/Tk's create command of the widget class. - WidgetClassName = ''.freeze - # WidgetClassNames[WidgetClassName] = self - ## ==> If self is a widget class, entry to the WidgetClassNames table. - def self.to_eval - self::WidgetClassName - end - - def initialize(parent=nil, keys=nil) - if parent.kind_of? Hash - keys = _symbolkey2str(parent) - parent = keys.delete('parent') - widgetname = keys.delete('widgetname') - install_win(if parent then parent.path end, widgetname) - without_creating = keys.delete('without_creating') - # if without_creating && !widgetname - # fail ArgumentError, - # "if set 'without_creating' to true, need to define 'widgetname'" - # end - elsif keys - keys = _symbolkey2str(keys) - widgetname = keys.delete('widgetname') - install_win(if parent then parent.path end, widgetname) - without_creating = keys.delete('without_creating') - # if without_creating && !widgetname - # fail ArgumentError, - # "if set 'without_creating' to true, need to define 'widgetname'" - # end - else - install_win(if parent then parent.path end) - end - if self.method(:create_self).arity == 0 - p 'create_self has no arg' if $DEBUG - create_self unless without_creating - if keys - # tk_call @path, 'configure', *hash_kv(keys) - configure(keys) - end - else - p 'create_self has args' if $DEBUG - fontkeys = {} - methodkeys = {} - if keys - #['font', 'kanjifont', 'latinfont', 'asciifont'].each{|key| - # fontkeys[key] = keys.delete(key) if keys.key?(key) - #} - __font_optkeys.each{|key| - fkey = key.to_s - fontkeys[fkey] = keys.delete(fkey) if keys.key?(fkey) - - fkey = "kanji#{key}" - fontkeys[fkey] = keys.delete(fkey) if keys.key?(fkey) - - fkey = "latin#{key}" - fontkeys[fkey] = keys.delete(fkey) if keys.key?(fkey) - - fkey = "ascii#{key}" - fontkeys[fkey] = keys.delete(fkey) if keys.key?(fkey) - } - - __optkey_aliases.each{|alias_name, real_name| - alias_name = alias_name.to_s - if keys.has_key?(alias_name) - keys[real_name.to_s] = keys.delete(alias_name) - end - } - - __methodcall_optkeys.each{|key| - key = key.to_s - methodkeys[key] = keys.delete(key) if keys.key?(key) - } - - __ruby2val_optkeys.each{|key, method| - key = key.to_s - keys[key] = method.call(keys[key]) if keys.has_key?(key) - } - end - if without_creating && keys - #configure(keys) - configure(__conv_keyonly_opts(keys)) - else - #create_self(keys) - create_self(__conv_keyonly_opts(keys)) - end - font_configure(fontkeys) unless fontkeys.empty? - configure(methodkeys) unless methodkeys.empty? - end - end - - def create_self(keys) - # may need to override - begin - cmd = self.class::TkCommandNames[0] - fail unless (cmd.kind_of?(String) && cmd.length > 0) - rescue - fail RuntimeError, "class #{self.class} may be an abstract class" - end - - if keys and keys != None - unless TkConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__ - tk_call_without_enc(cmd, @path, *hash_kv(keys, true)) - else - begin - tk_call_without_enc(cmd, @path, *hash_kv(keys, true)) - rescue => e - tk_call_without_enc(cmd, @path) - keys = __check_available_configure_options(keys) - unless keys.empty? - begin - # try to configure - configure(keys) - rescue - # fail => includes options adaptable when creation only? - begin - tk_call_without_enc('destroy', @path) - rescue - # cannot rescue options error - fail e - else - # re-create widget - tk_call_without_enc(cmd, @path, *hash_kv(keys, true)) - end - end - end - end - end - else - tk_call_without_enc(cmd, @path) - end - end - private :create_self - - def inspect - if @@WIDGET_INSPECT_FULL - super - else - str = super - str[0..(str.index(' '))] << '@path=' << @path.inspect << '>' - end - end - - def exist? - TkWinfo.exist?(self) - end - - alias subcommand tk_send - - def bind_class - @db_class || self.class() - end - - def database_classname - TkWinfo.classname(self) - end - def database_class - name = database_classname() - if WidgetClassNames[name] - WidgetClassNames[name] - else - TkDatabaseClass.new(name) - end - end - def self.database_classname - self::WidgetClassName - end - def self.database_class - WidgetClassNames[self::WidgetClassName] - end - - def pack(keys = nil) - #tk_call_without_enc('pack', epath, *hash_kv(keys, true)) - if keys - TkPack.configure(self, keys) - else - TkPack.configure(self) - end - self - end - - def pack_in(target, keys = nil) - if keys - keys = keys.dup - keys['in'] = target - else - keys = {'in'=>target} - end - #tk_call 'pack', epath, *hash_kv(keys) - TkPack.configure(self, keys) - self - end - - def pack_forget - #tk_call_without_enc('pack', 'forget', epath) - TkPack.forget(self) - self - end - alias unpack pack_forget - - def pack_config(slot, value=None) - #if slot.kind_of? Hash - # tk_call 'pack', 'configure', epath, *hash_kv(slot) - #else - # tk_call 'pack', 'configure', epath, "-#{slot}", value - #end - if slot.kind_of? Hash - TkPack.configure(self, slot) - else - TkPack.configure(self, slot=>value) - end - end - alias pack_configure pack_config - - def pack_info() - #ilist = list(tk_call('pack', 'info', epath)) - #info = {} - #while key = ilist.shift - # info[key[1..-1]] = ilist.shift - #end - #return info - TkPack.info(self) - end - - def pack_propagate(mode=None) - #if mode == None - # bool(tk_call('pack', 'propagate', epath)) - #else - # tk_call('pack', 'propagate', epath, mode) - # self - #end - if mode == None - TkPack.propagate(self) - else - TkPack.propagate(self, mode) - self - end - end - - def pack_slaves() - #list(tk_call('pack', 'slaves', epath)) - TkPack.slaves(self) - end - - def grid(keys = nil) - #tk_call 'grid', epath, *hash_kv(keys) - if keys - TkGrid.configure(self, keys) - else - TkGrid.configure(self) - end - self - end - - def grid_in(target, keys = nil) - if keys - keys = keys.dup - keys['in'] = target - else - keys = {'in'=>target} - end - #tk_call 'grid', epath, *hash_kv(keys) - TkGrid.configure(self, keys) - self - end - - def grid_anchor(anchor=None) - if anchor == None - TkGrid.anchor(self) - else - TkGrid.anchor(self, anchor) - self - end - end - - def grid_forget - #tk_call('grid', 'forget', epath) - TkGrid.forget(self) - self - end - alias ungrid grid_forget - - def grid_bbox(*args) - #list(tk_call('grid', 'bbox', epath, *args)) - TkGrid.bbox(self, *args) - end - - def grid_config(slot, value=None) - #if slot.kind_of? Hash - # tk_call 'grid', 'configure', epath, *hash_kv(slot) - #else - # tk_call 'grid', 'configure', epath, "-#{slot}", value - #end - if slot.kind_of? Hash - TkGrid.configure(self, slot) - else - TkGrid.configure(self, slot=>value) - end - end - alias grid_configure grid_config - - def grid_columnconfig(index, keys) - #tk_call('grid', 'columnconfigure', epath, index, *hash_kv(keys)) - TkGrid.columnconfigure(self, index, keys) - end - alias grid_columnconfigure grid_columnconfig - - def grid_rowconfig(index, keys) - #tk_call('grid', 'rowconfigure', epath, index, *hash_kv(keys)) - TkGrid.rowconfigure(self, index, keys) - end - alias grid_rowconfigure grid_rowconfig - - def grid_columnconfiginfo(index, slot=nil) - #if slot - # tk_call('grid', 'columnconfigure', epath, index, "-#{slot}").to_i - #else - # ilist = list(tk_call('grid', 'columnconfigure', epath, index)) - # info = {} - # while key = ilist.shift - # info[key[1..-1]] = ilist.shift - # end - # info - #end - TkGrid.columnconfiginfo(self, index, slot) - end - - def grid_rowconfiginfo(index, slot=nil) - #if slot - # tk_call('grid', 'rowconfigure', epath, index, "-#{slot}").to_i - #else - # ilist = list(tk_call('grid', 'rowconfigure', epath, index)) - # info = {} - # while key = ilist.shift - # info[key[1..-1]] = ilist.shift - # end - # info - #end - TkGrid.rowconfiginfo(self, index, slot) - end - - def grid_column(index, keys=nil) - if keys.kind_of?(Hash) - grid_columnconfigure(index, keys) - else - grid_columnconfiginfo(index, keys) - end - end - - def grid_row(index, keys=nil) - if keys.kind_of?(Hash) - grid_rowconfigure(index, keys) - else - grid_rowconfiginfo(index, keys) - end - end - - def grid_info() - #list(tk_call('grid', 'info', epath)) - TkGrid.info(self) - end - - def grid_location(x, y) - #list(tk_call('grid', 'location', epath, x, y)) - TkGrid.location(self, x, y) - end - - def grid_propagate(mode=None) - #if mode == None - # bool(tk_call('grid', 'propagate', epath)) - #else - # tk_call('grid', 'propagate', epath, mode) - # self - #end - if mode == None - TkGrid.propagate(self) - else - TkGrid.propagate(self, mode) - self - end - end - - def grid_remove() - #tk_call 'grid', 'remove', epath - TkGrid.remove(self) - self - end - - def grid_size() - #list(tk_call('grid', 'size', epath)) - TkGrid.size(self) - end - - def grid_slaves(keys = nil) - #list(tk_call('grid', 'slaves', epath, *hash_kv(args))) - TkGrid.slaves(self, keys) - end - - def place(keys) - #tk_call 'place', epath, *hash_kv(keys) - TkPlace.configure(self, keys) - self - end - - def place_in(target, keys = nil) - if keys - keys = keys.dup - keys['in'] = target - else - keys = {'in'=>target} - end - #tk_call 'place', epath, *hash_kv(keys) - TkPlace.configure(self, keys) - self - end - - def place_forget - #tk_call 'place', 'forget', epath - TkPlace.forget(self) - self - end - alias unplace place_forget - - def place_config(slot, value=None) - #if slot.kind_of? Hash - # tk_call 'place', 'configure', epath, *hash_kv(slot) - #else - # tk_call 'place', 'configure', epath, "-#{slot}", value - #end - TkPlace.configure(self, slot, value) - end - alias place_configure place_config - - def place_configinfo(slot = nil) - # for >= Tk8.4a2 ? - #if slot - # conf = tk_split_list(tk_call('place', 'configure', epath, "-#{slot}") ) - # conf[0] = conf[0][1..-1] - # conf - #else - # tk_split_simplelist(tk_call('place', - # 'configure', epath)).collect{|conflist| - # conf = tk_split_simplelist(conflist) - # conf[0] = conf[0][1..-1] - # conf - # } - #end - TkPlace.configinfo(self, slot) - end - - def place_info() - #ilist = list(tk_call('place', 'info', epath)) - #info = {} - #while key = ilist.shift - # info[key[1..-1]] = ilist.shift - #end - #return info - TkPlace.info(self) - end - - def place_slaves() - #list(tk_call('place', 'slaves', epath)) - TkPlace.slaves(self) - end - - def set_focus(force=false) - if force - tk_call_without_enc('focus', '-force', path) - else - tk_call_without_enc('focus', path) - end - self - end - alias focus set_focus - - def grab(opt = nil) - unless opt - tk_call_without_enc('grab', 'set', path) - return self - end - - case opt - when 'set', :set - tk_call_without_enc('grab', 'set', path) - return self - when 'global', :global - #return(tk_call('grab', 'set', '-global', path)) - tk_call_without_enc('grab', 'set', '-global', path) - return self - when 'release', :release - #return tk_call('grab', 'release', path) - tk_call_without_enc('grab', 'release', path) - return self - when 'current', :current - return window(tk_call_without_enc('grab', 'current', path)) - when 'status', :status - return tk_call_without_enc('grab', 'status', path) - else - return tk_call_without_enc('grab', opt, path) - end - end - - def grab_current - grab('current') - end - alias current_grab grab_current - def grab_release - grab('release') - end - alias release_grab grab_release - def grab_set - grab('set') - end - alias set_grab grab_set - def grab_set_global - grab('global') - end - alias set_global_grab grab_set_global - def grab_status - grab('status') - end - - def lower(below=None) - # below = below.epath if below.kind_of?(TkObject) - below = _epath(below) - tk_call 'lower', epath, below - self - end - alias lower_window lower - def raise(above=None) - #above = above.epath if above.kind_of?(TkObject) - above = _epath(above) - tk_call 'raise', epath, above - self - end - alias raise_window raise - - def command(cmd=nil, &b) - if cmd - configure_cmd('command', cmd) - elsif b - configure_cmd('command', Proc.new(&b)) - else - cget('command') - end - end - - def colormodel(model=None) - tk_call('tk', 'colormodel', path, model) - self - end - - def caret(keys=nil) - TkXIM.caret(path, keys) - end - - def destroy - super - children = [] - rexp = /^#{self.path}\.[^.]+$/ - TkCore::INTERP.tk_windows.each{|path, obj| - children << [path, obj] if path =~ rexp - } - if defined?(@cmdtbl) - for id in @cmdtbl - uninstall_cmd id - end - end - - children.each{|path, obj| - obj.instance_eval{ - if defined?(@cmdtbl) - for id in @cmdtbl - uninstall_cmd id - end - end - } - TkCore::INTERP.tk_windows.delete(path) - } - - begin - tk_call_without_enc('destroy', epath) - rescue - end - uninstall_win - end - - def wait_visibility(on_thread = true) - on_thread &= (Thread.list.size != 1) - if on_thread - INTERP._thread_tkwait('visibility', path) - else - INTERP._invoke('tkwait', 'visibility', path) - end - end - def eventloop_wait_visibility - wait_visibility(false) - end - def thread_wait_visibility - wait_visibility(true) - end - alias wait wait_visibility - alias tkwait wait_visibility - alias eventloop_wait eventloop_wait_visibility - alias eventloop_tkwait eventloop_wait_visibility - alias eventloop_tkwait_visibility eventloop_wait_visibility - alias thread_wait thread_wait_visibility - alias thread_tkwait thread_wait_visibility - alias thread_tkwait_visibility thread_wait_visibility - - def wait_destroy(on_thread = true) - on_thread &= (Thread.list.size != 1) - if on_thread - INTERP._thread_tkwait('window', epath) - else - INTERP._invoke('tkwait', 'window', epath) - end - end - alias wait_window wait_destroy - def eventloop_wait_destroy - wait_destroy(false) - end - alias eventloop_wait_window eventloop_wait_destroy - def thread_wait_destroy - wait_destroy(true) - end - alias thread_wait_window thread_wait_destroy - - alias tkwait_destroy wait_destroy - alias tkwait_window wait_destroy - - alias eventloop_tkwait_destroy eventloop_wait_destroy - alias eventloop_tkwait_window eventloop_wait_destroy - - alias thread_tkwait_destroy thread_wait_destroy - alias thread_tkwait_window thread_wait_destroy - - def bindtags(taglist=nil) - if taglist - fail ArgumentError, "taglist must be Array" unless taglist.kind_of? Array - tk_call('bindtags', path, taglist) - taglist - else - list(tk_call('bindtags', path)).collect{|tag| - if tag.kind_of?(String) - if cls = WidgetClassNames[tag] - cls - elsif btag = TkBindTag.id2obj(tag) - btag - else - tag - end - else - tag - end - } - end - end - - def bindtags=(taglist) - bindtags(taglist) - taglist - end - - def bindtags_shift - taglist = bindtags - tag = taglist.shift - bindtags(taglist) - tag - end - - def bindtags_unshift(tag) - bindtags(bindtags().unshift(tag)) - end -end -TkWidget = TkWindow - -# freeze core modules -#TclTkLib.freeze -#TclTkIp.freeze -#TkUtil.freeze -#TkKernel.freeze -#TkComm.freeze -#TkComm::Event.freeze -#TkCore.freeze -#Tk.freeze - -module Tk - RELEASE_DATE = '2014-10-19'.freeze - - autoload :AUTO_PATH, 'tk/variable' - autoload :TCL_PACKAGE_PATH, 'tk/variable' - autoload :PACKAGE_PATH, 'tk/variable' - autoload :TCL_LIBRARY_PATH, 'tk/variable' - autoload :LIBRARY_PATH, 'tk/variable' - autoload :TCL_PRECISION, 'tk/variable' -end - -# call setup script for Tk extension libraries (base configuration) -begin - require 'tkextlib/version.rb' - require 'tkextlib/setup.rb' -rescue LoadError - # ignore -end diff --git a/ext/tk/lib/tk/after.rb b/ext/tk/lib/tk/after.rb deleted file mode 100644 index 3213a6b818..0000000000 --- a/ext/tk/lib/tk/after.rb +++ /dev/null @@ -1,7 +0,0 @@ -# frozen_string_literal: false -# -# tk/after.rb : methods for Tcl/Tk after command -# -# $Id$ -# -require 'tk/timer' diff --git a/ext/tk/lib/tk/autoload.rb b/ext/tk/lib/tk/autoload.rb deleted file mode 100644 index ef82c8944c..0000000000 --- a/ext/tk/lib/tk/autoload.rb +++ /dev/null @@ -1,763 +0,0 @@ -# frozen_string_literal: false -# -# autoload -# -############################################ -# geometry manager -module Tk - autoload :Grid, 'tk/grid' - def Grid(*args); TkGrid.configure(*args); end - - autoload :Pack, 'tk/pack' - def Pack(*args); TkPack.configure(*args); end - - autoload :Place, 'tk/place' - def Place(*args); TkPlace.configure(*args); end -end - -autoload :TkGrid, 'tk/grid' -def TkGrid(*args); TkGrid.configure(*args); end - -autoload :TkPack, 'tk/pack' -def TkPack(*args); TkPack.configure(*args); end - -autoload :TkPlace, 'tk/place' -def TkPlace(*args); TkPlace.configure(*args); end - - -############################################ -# classes on Tk module -module Tk - autoload :Busy, 'tk/busy' - - autoload :Button, 'tk/button' - - autoload :Canvas, 'tk/canvas' - - autoload :CheckButton, 'tk/checkbutton' - autoload :Checkbutton, 'tk/checkbutton' - - autoload :Entry, 'tk/entry' - - autoload :Frame, 'tk/frame' - - autoload :Label, 'tk/label' - - autoload :LabelFrame, 'tk/labelframe' - autoload :Labelframe, 'tk/labelframe' - - autoload :Listbox, 'tk/listbox' - - autoload :Menu, 'tk/menu' - autoload :MenuClone, 'tk/menu' - autoload :CloneMenu, 'tk/menu' - autoload :SystemMenu, 'tk/menu' - autoload :SysMenu_Help, 'tk/menu' - autoload :SysMenu_System, 'tk/menu' - autoload :SysMenu_Apple, 'tk/menu' - autoload :Menubutton, 'tk/menu' - autoload :MenuButton, 'tk/menu' - autoload :OptionMenubutton, 'tk/menu' - autoload :OptionMenBbutton, 'tk/menu' - - autoload :Message, 'tk/message' - - autoload :PanedWindow, 'tk/panedwindow' - autoload :Panedwindow, 'tk/panedwindow' - - autoload :RadioButton, 'tk/radiobutton' - autoload :Radiobutton, 'tk/radiobutton' - - autoload :Root, 'tk/root' - - autoload :Scale, 'tk/scale' - - autoload :Scrollbar, 'tk/scrollbar' - autoload :XScrollbar, 'tk/scrollbar' - autoload :YScrollbar, 'tk/scrollbar' - - autoload :Spinbox, 'tk/spinbox' - - autoload :Text, 'tk/text' - - autoload :Toplevel, 'tk/toplevel' -end - - -############################################ -# sub-module of Tk -module Tk - autoload :Clock, 'tk/clock' - - autoload :OptionObj, 'tk/optionobj' - - autoload :X_Scrollable, 'tk/scrollable' - autoload :Y_Scrollable, 'tk/scrollable' - autoload :Scrollable, 'tk/scrollable' - - autoload :Fontchooser, 'tk/fontchooser' - - autoload :Wm, 'tk/wm' - autoload :Wm_for_General, 'tk/wm' - - autoload :MacResource, 'tk/macpkg' - - autoload :WinDDE, 'tk/winpkg' - autoload :WinRegistry, 'tk/winpkg' - - autoload :ValidateConfigure, 'tk/validation' - autoload :ItemValidateConfigure, 'tk/validation' - - autoload :EncodedString, 'tk/encodedstr' - def Tk.EncodedString(str, enc = nil); Tk::EncodedString.new(str, enc); end - - autoload :BinaryString, 'tk/encodedstr' - def Tk.BinaryString(str); Tk::BinaryString.new(str); end - - autoload :UTF8_String, 'tk/encodedstr' - def Tk.UTF8_String(str); Tk::UTF8_String.new(str); end - -end - - -############################################ -# toplevel classes/modules (fixed) -autoload :TkBgError, 'tk/bgerror' - -autoload :TkBindTag, 'tk/bindtag' -autoload :TkBindTagAll, 'tk/bindtag' -autoload :TkDatabaseClass, 'tk/bindtag' - -autoload :TkConsole, 'tk/console' - -autoload :TkcItem, 'tk/canvas' -autoload :TkcArc, 'tk/canvas' -autoload :TkcBitmap, 'tk/canvas' -autoload :TkcImage, 'tk/canvas' -autoload :TkcLine, 'tk/canvas' -autoload :TkcOval, 'tk/canvas' -autoload :TkcPolygon, 'tk/canvas' -autoload :TkcRectangle, 'tk/canvas' -autoload :TkcText, 'tk/canvas' -autoload :TkcWindow, 'tk/canvas' - -autoload :TkcTagAccess, 'tk/canvastag' -autoload :TkcTag, 'tk/canvastag' -autoload :TkcTagString, 'tk/canvastag' -autoload :TkcNamedTag, 'tk/canvastag' -autoload :TkcTagAll, 'tk/canvastag' -autoload :TkcTagCurrent, 'tk/canvastag' -autoload :TkcTagGroup, 'tk/canvastag' - -autoload :TkClipboard, 'tk/clipboard' - -autoload :TkComposite, 'tk/composite' - -autoload :TkConsole, 'tk/console' - -autoload :TkDialog, 'tk/dialog' -autoload :TkDialog2, 'tk/dialog' -autoload :TkDialogObj, 'tk/dialog' -autoload :TkWarning, 'tk/dialog' -autoload :TkWarning2, 'tk/dialog' -autoload :TkWarningObj, 'tk/dialog' - -autoload :TkEvent, 'tk/event' - -autoload :TkFont, 'tk/font' -autoload :TkNamedFont, 'tk/font' - -autoload :TkImage, 'tk/image' -autoload :TkBitmapImage, 'tk/image' -autoload :TkPhotoImage, 'tk/image' - -autoload :TkItemConfigMethod, 'tk/itemconfig' - -autoload :TkTreatItemFont, 'tk/itemfont' - -autoload :TkKinput, 'tk/kinput' - -autoload :TkSystemMenu, 'tk/menu' - -autoload :TkMenubar, 'tk/menubar' - -autoload :TkMenuSpec, 'tk/menuspec' - -autoload :TkManageFocus, 'tk/mngfocus' - -autoload :TkMsgCatalog, 'tk/msgcat' -autoload :TkMsgCat, 'tk/msgcat' - -autoload :TkNamespace, 'tk/namespace' - -autoload :TkOptionDB, 'tk/optiondb' -autoload :TkOption, 'tk/optiondb' -autoload :TkResourceDB, 'tk/optiondb' - -autoload :TkPackage, 'tk/package' - -autoload :TkPalette, 'tk/palette' - -autoload :TkRoot, 'tk/root' - -autoload :TkScrollbox, 'tk/scrollbox' - -autoload :TkSelection, 'tk/selection' - -autoload :TkTreatTagFont, 'tk/tagfont' - -autoload :TkTextImage, 'tk/textimage' -autoload :TktImage, 'tk/textimage' - -autoload :TkTextMark, 'tk/textmark' -autoload :TkTextNamedMark, 'tk/textmark' -autoload :TkTextMarkInsert, 'tk/textmark' -autoload :TkTextMarkCurrent, 'tk/textmark' -autoload :TkTextMarkAnchor, 'tk/textmark' -autoload :TktMark, 'tk/textmark' -autoload :TktNamedMark, 'tk/textmark' -autoload :TktMarkInsert, 'tk/textmark' -autoload :TktMarkCurrent, 'tk/textmark' -autoload :TktMarkAnchor, 'tk/textmark' - -autoload :TkTextTag, 'tk/texttag' -autoload :TkTextNamedTag, 'tk/texttag' -autoload :TkTextTagSel, 'tk/texttag' -autoload :TktTag, 'tk/texttag' -autoload :TktNamedTag, 'tk/texttag' -autoload :TktTagSel, 'tk/texttag' - -autoload :TkTextWindow, 'tk/textwindow' -autoload :TktWindow, 'tk/textwindow' - -autoload :TkAfter, 'tk/timer' -autoload :TkTimer, 'tk/timer' -autoload :TkRTTimer, 'tk/timer' - -autoload :TkTextWin, 'tk/txtwin_abst' - -autoload :TkValidation, 'tk/validation' -autoload :TkValidateCommand, 'tk/validation' - -autoload :TkVariable, 'tk/variable' -autoload :TkVarAccess, 'tk/variable' - -autoload :TkVirtualEvent, 'tk/virtevent' -autoload :TkNamedVirtualEvent,'tk/virtevent' - -autoload :TkWinfo, 'tk/winfo' - -autoload :TkXIM, 'tk/xim' - - -############################################ -# toplevel classes/modules (switchable) -module Tk - @TOPLEVEL_ALIAS_TABLE = {} - @TOPLEVEL_ALIAS_TABLE[:Tk] = { - :TkButton => 'tk/button', - - :TkCanvas => 'tk/canvas', - - :TkCheckButton => 'tk/checkbutton', - :TkCheckbutton => 'tk/checkbutton', - - # :TkDialog => 'tk/dialog', - # :TkDialog2 => 'tk/dialog', - # :TkDialogObj => 'tk/dialog', - # :TkWarning => 'tk/dialog', - # :TkWarning2 => 'tk/dialog', - # :TkWarningObj => 'tk/dialog', - - :TkEntry => 'tk/entry', - - :TkFrame => 'tk/frame', - - :TkLabel => 'tk/label', - - :TkLabelFrame => 'tk/labelframe', - :TkLabelframe => 'tk/labelframe', - - :TkListbox => 'tk/listbox', - - :TkMacResource => 'tk/macpkg', - - :TkMenu => 'tk/menu', - :TkMenuClone => 'tk/menu', - :TkCloneMenu => 'tk/menu', - # :TkSystemMenu => 'tk/menu', - :TkSysMenu_Help => 'tk/menu', - :TkSysMenu_System => 'tk/menu', - :TkSysMenu_Apple => 'tk/menu', - :TkMenubutton => 'tk/menu', - :TkMenuButton => 'tk/menu', - :TkOptionMenubutton => 'tk/menu', - :TkOptionMenuButton => 'tk/menu', - - :TkMessage => 'tk/message', - - :TkPanedWindow => 'tk/panedwindow', - :TkPanedwindow => 'tk/panedwindow', - - :TkRadioButton => 'tk/radiobutton', - :TkRadiobutton => 'tk/radiobutton', - - # :TkRoot => 'tk/root', - - :TkScale => 'tk/scale', - - :TkScrollbar => 'tk/scrollbar', - :TkXScrollbar => 'tk/scrollbar', - :TkYScrollbar => 'tk/scrollbar', - - :TkSpinbox => 'tk/spinbox', - - :TkText => 'tk/text', - - :TkToplevel => 'tk/toplevel', - - :TkWinDDE => 'tk/winpkg', - :TkWinRegistry => 'tk/winpkg', - } - - @TOPLEVEL_ALIAS_OWNER = {} - - @TOPLEVEL_ALIAS_SETUP_PROC = {} - - @AUTOLOAD_FILE_SYM_TABLE = Hash.new{|h,k| h[k]={}} # TABLE[file][sym] -> obj - - @current_default_widget_set = nil - - module TOPLEVEL_ALIASES; end -end - -class Object - include Tk::TOPLEVEL_ALIASES -end - -############################################ -# methods to control default widget set -############################################ - -class << Tk - def default_widget_set - @current_default_widget_set - end - - def default_widget_set=(target) - target = target.to_sym - return target if target == @current_default_widget_set - - if (cmd = @TOPLEVEL_ALIAS_SETUP_PROC[target]) - cmd.call(target) - end - - _replace_toplevel_aliases(target) - end - - def widget_set_symbols - @TOPLEVEL_ALIAS_TABLE.keys - end - - def toplevel_aliases_on_widget_set(widget_set) - if (tbl = @TOPLEVEL_ALIAS_TABLE[widget_set.to_sym]) - tbl.collect{|k, v| (v.nil?)? nil: k}.compact - else - fail ArgumentError, "unknown widget_set #{widget_set.to_sym.inspect}" - end - end - - def __toplevel_alias_setup_proc__(*target_list, &cmd) - target_list.each{|target| @TOPLEVEL_ALIAS_SETUP_PROC[target.to_sym] = cmd} - end - - def topobj_defined?(sym) #=> alias_filename or object or false - Object.autoload?(sym) || - (Object.const_defined?(sym) && Object.const_get(sym)) - end - def topalias_defined?(sym) #=> alias_filename or object or false - Tk::TOPLEVEL_ALIASES.autoload?(sym) || - (Tk::TOPLEVEL_ALIASES.const_defined?(sym) && - Tk::TOPLEVEL_ALIASES.const_get(sym)) - end - def define_topobj(sym, obj) - if obj.kind_of? String - # obj is an autoload path - Object.autoload(sym, obj) - unless Object.autoload?(sym) - # file is autoloaded? - if @AUTOLOAD_FILE_SYM_TABLE.has_key?(obj) && - (loaded_obj = @AUTOLOAD_FILE_SYM_TABLE[obj][sym]) - Object.const_set(sym, loaded_obj) - else - fail ArgumentError, "cannot define autoload file (already loaded?)" - end - end - else - # object - Object.const_set(sym, obj) - end - end - def define_topalias(sym, obj) - if obj.kind_of? String - # obj is an autoload path - Tk::TOPLEVEL_ALIASES.autoload(sym, obj) - unless Tk::TOPLEVEL_ALIASES.autoload?(sym) - # file is autoloaded? - if @AUTOLOAD_FILE_SYM_TABLE.has_key?(obj) && - (loaded_obj = @AUTOLOAD_FILE_SYM_TABLE[obj][sym]) - Tk::TOPLEVEL_ALIASES.const_set(sym, loaded_obj) - else - fail ArgumentError, "cannot define autoload file (already loaded?)" - end - end - else - # object - Tk::TOPLEVEL_ALIASES.const_set(sym, obj) - end - end - def replace_topobj(sym, obj) #=> old_obj (alias_filename or object) or nil - if old_obj = topobj_defined?(sym) - Object.class_eval{remove_const sym} rescue nil # ignore err - end - define_topobj(sym, obj) - old_obj - end - def replace_topalias(sym, obj) #=> old_obj (alias_filename or object) or nil - if old_obj = topalias_defined?(sym) - Tk::TOPLEVEL_ALIASES.module_eval{remove_const sym} rescue nil #ignore err - end - define_topalias(sym, obj) - old_obj - end - private :topobj_defined?, :topalias_defined? - private :define_topobj, :define_topalias - private :replace_topobj, :replace_topalias - - def __regist_toplevel_aliases__(target, obj, *symbols) - # initial regist - @TOPLEVEL_ALIAS_TABLE[target = target.to_sym] ||= {} - symbols.each{|sym| - @TOPLEVEL_ALIAS_TABLE[target][sym = sym.to_sym] = obj - if !topalias_defined?(sym) || target == @current_default_widget_set - @TOPLEVEL_ALIAS_OWNER[sym] = target - replace_topalias(sym, obj) - replace_topobj(sym, obj) unless obj.kind_of?(String) # NOT autoload - end - } - end - - def regist_sym_for_loaded_file(auto, obj, sym) - @AUTOLOAD_FILE_SYM_TABLE[auto][sym] = obj - - reg = /^#{Regexp.quote(auto)}(\.rb|\.so|)$/ - @TOPLEVEL_ALIAS_TABLE.each_key{|set| - if @TOPLEVEL_ALIAS_TABLE[set][sym] =~ reg - @TOPLEVEL_ALIAS_TABLE[set][sym] = obj - if @TOPLEVEL_ALIAS_OWNER[sym].nil? || @TOPLEVEL_ALIAS_OWNER[sym] == set - replace_topalias(sym, obj) - replace_topobj(sym, obj) if set == @current_default_widget_set - end - end - } - if (f = Object.autoload?(sym)) && f =~ reg - replace_topobj(sym, obj) - end - if (f = Tk::TOPLEVEL_ALIASES.autoload?(sym)) && f =~ reg - replace_topalias(sym, obj) - end - end - private :regist_sym_for_loaded_file - - def set_topalias(target, obj, sym) - # obj is a kind of String : define autoload path - # Class : use the class object - if target == @current_default_widget_set - case @TOPLEVEL_ALIAS_OWNER[sym] - when false - # Object::sym is out of control. --> not change - # Make ALIAS::sym under control, because target widget set is current. - # Keep OWNER[sym] - @TOPLEVEL_ALIAS_TABLE[target][sym] = obj - replace_topalias(sym, obj) - - when target - if current_obj = topobj_defined?(sym) - if current_obj == obj - # Make current_obj under control. - # Keep Object::sym. - # Keep OWNER[sym]. - @TOPLEVEL_ALIAS_TABLE[target][sym] = obj - replace_topalias(sym, obj) - - else # current_obj != obj - if current_obj == topalias_defined?(sym) - # Change controlled object - # Keep OWNER[sym]. - @TOPLEVEL_ALIAS_TABLE[target][sym] = obj - replace_topalias(sym, obj) - replace_topobj(sym, obj) - - else # current_obj != topalias_defined?(sym) - # Maybe current_obj is defined by user. --> OWNER[sym] = false - # Keep Object::sym. - @TOPLEVEL_ALIAS_OWNER[sym] = false - @TOPLEVEL_ALIAS_TABLE[target][sym] = obj - replace_topalias(sym, obj) - end - end - - else # NOT topobj_defined?(sym) - # New definition for sym at target. - # Keep OWNER[sym]. - @TOPLEVEL_ALIAS_TABLE[target][sym] = obj - replace_topalias(sym, obj) - define_topobj(sym, obj) - end - - when nil - # New definition for sym at target. - @TOPLEVEL_ALIAS_OWNER[sym] = target - @TOPLEVEL_ALIAS_TABLE[target][sym] = obj - replace_topalias(sym, obj) - - else # others - # Maybe planning to make sym under control. - @TOPLEVEL_ALIAS_OWNER[sym] = target - @TOPLEVEL_ALIAS_TABLE[target][sym] = obj - replace_topalias(sym, obj) - replace_topobj(sym, obj) - end - - else # target != @current_default_widget_set - case @TOPLEVEL_ALIAS_OWNER[sym] - when false - # Object::sym is out of control. --> not change - if topalias_defined?(sym) - # ALIAS[sym] may be defined by other widget set. - # Keep Object::sym (even if it is not defined) - # Keep ALIAS[sym]. - # Keep OWNER[sym]. - @TOPLEVEL_ALIAS_TABLE[target][sym] = obj - - else # NOT topalias_defined?(sym) - # Nobody controls ALIAS[sym]. - # At least, current widget set doesn't control ALIAS[sym]. - # Keep Object::sym (even if it is not defined) - # Keep OWNER[sym]. - @TOPLEVEL_ALIAS_TABLE[target][sym] = obj - define_topalias(sym, obj) - end - - when target - # Maybe change controlled object, because Object::sym is under control. - # Keep OWNER[sym]. - @TOPLEVEL_ALIAS_TABLE[target][sym] = obj - replace_topalias(sym, obj) - replace_topobj(sym, obj) - - when nil - # New definition for sym - @TOPLEVEL_ALIAS_OWNER[sym] = target - @TOPLEVEL_ALIAS_TABLE[target][sym] = obj - replace_topalias(sym, obj) - replace_topobj(sym, obj) - - else # others - # An other widget set controls sym. - # Keep Object::sym (even if it is not defined) - # Keep ALIAS[sym]. - # Keep OWNER[sym]. - @TOPLEVEL_ALIAS_TABLE[target][sym] = obj - - end - end - - sym - end - private :set_topalias - - def __set_toplevel_aliases__(target, obj, *symbols) - # obj is a kind of String : define autoload path - # Class : use the class object - target = target.to_sym - symbols.each{|sym| set_topalias(target, obj, sym.to_sym)} - end - - def __set_loaded_toplevel_aliases__(autopath, target, obj, *symbols) - # autopath is an autoload file - # Currently, this method doesn't support that autoload loads - # different toplevels between <basename>.rb and <basename>.so extension. - shortpath = (autopath =~ /^(.*)(.rb|.so)$/)? $1: autopath - target = target.to_sym - symbols.map!{|sym| sym.to_sym} - - symbols.each{|sym| regist_sym_for_loaded_file(shortpath, obj, sym) } - symbols.each{|sym| set_topalias(target, obj, sym)} - end - - def backup_current_topdef(sym) - return if (current = @current_default_widget_set).nil? - - case @TOPLEVEL_ALIAS_OWNER[sym] - when false - # Object::sym is out of control. - if (cur_alias = topalias_defined?(sym)) && ! cur_alias.kind_of?(String) - @TOPLEVEL_ALIAS_TABLE[current][sym] = cur_alias - end - - when current - if cur_obj = topobj_defined?(sym) - if ! cur_obj.kind_of?(String) && (cur_alias = topalias_defined?(sym)) - if cur_alias.kind_of?(String) - # Maybe, user replaced Object::sym. - # Make Object::sym out of control. - @TOPLEVEL_ALIAS_OWNER[sym] = false - elsif cur_obj == cur_alias - # Possibly, defined normally. Backup it - @TOPLEVEL_ALIAS_TABLE[current][sym] = cur_alias - else - # Maybe, user replaced Object::sym. - # Make Object::sym out of control. - @TOPLEVEL_ALIAS_OWNER[sym] = false - end - end - else - # Maybe, user replaced Object::sym. - # Make Object::sym out of control. - @TOPLEVEL_ALIAS_OWNER[sym] = false - end - - when nil - # Object::sym is out of control. - if (cur_alias = topalias_defined?(sym)) && ! cur_alias.kind_of?(String) - # Possibly, defined normally. Backup it. - @TOPLEVEL_ALIAS_TABLE[current][sym] = cur_alias - end - else - # No authority to control Object::sym and ALIASES::sym. - # Do nothing. - end - end - private :backup_current_topdef - - def _replace_toplevel_aliases(target) - # backup - @TOPLEVEL_ALIAS_TABLE[target].each_key{|sym| - backup_current_topdef(sym) - } - - # replace - @TOPLEVEL_ALIAS_TABLE[target].each_key{|sym| - next if (obj = @TOPLEVEL_ALIAS_TABLE[target][sym]).nil? - if @TOPLEVEL_ALIAS_OWNER[sym] == false - # Object::sym is out of control. --> not change - # Keep OWNER[sym]. - replace_topalias(sym, obj) - else - # New definition - @TOPLEVEL_ALIAS_OWNER[sym] = target - replace_topalias(sym, obj) - replace_topobj(sym, obj) - end - } - - # change default_widget_set - @current_default_widget_set = target - end - private :_replace_toplevel_aliases - - def __import_toplevel_aliases__(target, *symbols) - current = @current_default_widget_set - symbols.each{|sym| - sym = sym.to_sym - if (obj = @TOPLEVEL_ALIAS_TABLE[target][sym]).nil? - # remove - @TOPLEVEL_ALIAS_TABLE[current].delete(sym) - @TOPLEVEL_ALIAS_OWNER.delete(sym) - Tk::TOPLEVEL_ALIASES.module_eval{remove_const sym} if topalias_defined?(sym) - Object.class_eval{remove_const sym} if topobj_defined?(sym) - - elsif obj == false - # remove, but OWNER[sym] <- false and not treat Object::sym - @TOPLEVEL_ALIAS_TABLE[current].delete(sym) - @TOPLEVEL_ALIAS_OWNER[sym] = false - Tk::TOPLEVEL_ALIASES.module_eval{remove_const sym} if topalias_defined?(sym) - - elsif @TOPLEVEL_ALIAS_OWNER[sym] == false - # Object::sym is out of control. --> not change - # Keep OWNER[sym]. - @TOPLEVEL_ALIAS_TABLE[current][sym] = obj - replace_topalias(sym, obj) - - else - # new definition under control - @TOPLEVEL_ALIAS_OWNER[sym] = current - @TOPLEVEL_ALIAS_TABLE[current][sym] = obj - replace_topalias(sym, obj) - replace_topobj(sym, obj) - end - } - end - - def __remove_toplevel_aliases__(*symbols) - # remove toplevel aliases of current widget set - current = @current_default_widget_set - symbols.each{|sym| - sym = sym.to_sym - @TOPLEVEL_ALIAS_TABLE[current].delete(sym) - @TOPLEVEL_ALIAS_OWNER.delete(sym) - Tk::TOPLEVEL_ALIASES.module_eval{remove_const sym} if topalias_defined?(sym) - Object.class_eval{remove_const sym} if topobj_defined?(sym) - } - end - - def __reset_toplevel_owner__(*symbols) - symbols.each{|sym| @TOPLEVEL_ALIAS_OWNER.delete(sym.to_sym)} - end - - def __disable_toplevel_control__(*symbols) - symbols.each{|sym| @TOPLEVEL_ALIAS_OWNER[sym.to_sym] = false} - end - - def __create_widget_set__(new_set, src_set={}) - new_set = new_set.to_sym - if @TOPLEVEL_ALIAS_TABLE[new_set] - fail RuntimeError, "A widget-set #{new_set.inspect} is already exist." - end - if src_set.kind_of?(Symbol) - # new_set is an alias name of existed widget set. - @TOPLEVEL_ALIAS_TABLE[new_set] = @TOPLEVEL_ALIAS_TABLE[src_set] - else - @TOPLEVEL_ALIAS_TABLE[new_set] = {} - src_set.each{|sym, obj| set_topalias(new_set, obj, sym.to_sym) } - end - end -end - - -############################################ -# setup default widget set => :Tk -Tk.default_widget_set = :Tk - - -############################################ -# depend on the version of Tcl/Tk -# major, minor, type, patchlevel = TclTkLib.get_version - -############################################ -# Ttk (Tile) support -=begin -if major > 8 || - (major == 8 && minor > 5) || - (major == 8 && minor == 5 && type >= TclTkLib::RELEASE_TYPE::BETA) - # Tcl/Tk 8.5 beta or later - Object.autoload :Ttk, 'tkextlib/tile' - Tk.autoload :Tile, 'tkextlib/tile' - - require 'tk/ttk_selector' -end -=end -Object.autoload :Ttk, 'tkextlib/tile' -Tk.autoload :Tile, 'tkextlib/tile' -require 'tk/ttk_selector' diff --git a/ext/tk/lib/tk/bgerror.rb b/ext/tk/lib/tk/bgerror.rb deleted file mode 100644 index 9d2f59357e..0000000000 --- a/ext/tk/lib/tk/bgerror.rb +++ /dev/null @@ -1,30 +0,0 @@ -# frozen_string_literal: false -# -# tkbgerror -- bgerror ( tkerror ) module -# 1998/07/16 by Hidetoshi Nagai <nagai@ai.kyutech.ac.jp> -# -require 'tk' - -module TkBgError - extend Tk - - TkCommandNames = ['bgerror'.freeze].freeze - - def bgerror(message) - tk_call('bgerror', message) - end - alias tkerror bgerror - alias show bgerror - module_function :bgerror, :tkerror, :show - - def set_handler(hdlr = Proc.new) #==> handler :: proc{|msg| ...body... } - tk_call('proc', 'bgerror', 'msg', install_cmd(hdlr) + ' $msg') - end - def set_default - begin - tk_call('rename', 'bgerror', '') - rescue RuntimeError - end - end - module_function :set_handler, :set_default -end diff --git a/ext/tk/lib/tk/bindtag.rb b/ext/tk/lib/tk/bindtag.rb deleted file mode 100644 index ad3c90b505..0000000000 --- a/ext/tk/lib/tk/bindtag.rb +++ /dev/null @@ -1,139 +0,0 @@ -# frozen_string_literal: false -# -# tk/bind.rb : control event binding -# -require 'tk' - -class TkBindTag - include TkBindCore - - #BTagID_TBL = {} - BTagID_TBL = TkCore::INTERP.create_table - - (Tk_BINDTAG_ID = ["btag".freeze, TkUtil.untrust("00000")]).instance_eval{ - @mutex = Mutex.new - def mutex; @mutex; end - freeze - } - - TkCore::INTERP.init_ip_env{ - BTagID_TBL.mutex.synchronize{ BTagID_TBL.clear } - } - - def TkBindTag.id2obj(id) - BTagID_TBL.mutex.synchronize{ - (BTagID_TBL[id])? BTagID_TBL[id]: id - } - end - -=begin - def TkBindTag.new_by_name(name, *args, &b) - BTagID_TBL.mutex.synchronize{ - return BTagID_TBL[name] if BTagID_TBL[name] - } - - self.new.instance_eval{ - BTagID_TBL.mutex.synchronize{ - BTagID_TBL.delete @id - @id = name - BTagID_TBL[@id] = self - } - bind(*args, &b) if args != [] - self - } - end -=end - def TkBindTag.new_by_name(name, *args, &b) - obj = nil - BTagID_TBL.mutex.synchronize{ - if BTagID_TBL[name] - obj = BTagID_TBL[name] - else - (obj = BTagID_TBL[name] = self.allocate).instance_eval{ - @id = name - } - end - } - bind(*args, &b) if obj && args != [] - obj - end - - def initialize(*args, &b) - Tk_BINDTAG_ID.mutex.synchronize{ - # @id = Tk_BINDTAG_ID.join('') - @id = Tk_BINDTAG_ID.join(TkCore::INTERP._ip_id_) - Tk_BINDTAG_ID[1].succ! - } - BTagID_TBL.mutex.synchronize{ - BTagID_TBL[@id] = self - } - bind(*args, &b) if args != [] - end - - ALL = self.new_by_name('all') - - def name - @id - end - - def to_eval - @id - end - - def inspect - #Kernel.format "#<TkBindTag: %s>", @id - '#<TkBindTag: ' + @id + '>' - end -end - - -class TkBindTagAll<TkBindTag - def TkBindTagAll.new(*args, &b) - $stderr.puts "Warning: TkBindTagALL is obsolete. Use TkBindTag::ALL\n" - - TkBindTag::ALL.bind(*args, &b) if args != [] - TkBindTag::ALL - end -end - - -class TkDatabaseClass<TkBindTag -=begin - def self.new(name, *args, &b) - BTagID_TBL.mutex.synchronize{ - return BTagID_TBL[name] if BTagID_TBL[name] - } - super(name, *args, &b) - end - - def initialize(name, *args, &b) - @id = name - BTagID_TBL.mutex.synchronize{ - BTagID_TBL[@id] = self - } - bind(*args, &b) if args != [] - end -=end - def self.new(name, *args, &b) - BTagID_TBL.mutex.synchronize{ - if BTagID_TBL[name] - BTagID_TBL[name] - else - BTagID_TBL[name] = self.allocate.instance_eval{ - initialize(name, *args, &b) - self - } - end - } - end - - def initialize(name, *args, &b) - @id = name - bind(*args, &b) if args != [] - end - - def inspect - #Kernel.format "#<TkDatabaseClass: %s>", @id - '#<TkDatabaseClass: ' + @id + '>' - end -end diff --git a/ext/tk/lib/tk/busy.rb b/ext/tk/lib/tk/busy.rb deleted file mode 100644 index 18ebede9dd..0000000000 --- a/ext/tk/lib/tk/busy.rb +++ /dev/null @@ -1,119 +0,0 @@ -# frozen_string_literal: false -# -# tk/busy.rb: support 'tk busy' command (Tcl/Tk8.6 or later) -# -require 'tk' - -module Tk::Busy - include TkCore - extend TkCore - extend TkItemConfigMethod -end - -class << Tk::Busy - def __item_cget_cmd(win) - # maybe need to override - ['tk', 'busy', 'cget', win.path] - end - private :__item_cget_cmd - - def __item_config_cmd(win) - # maybe need to override - ['tk', 'busy', 'configure', win.path] - end - private :__item_config_cmd - - def __item_confinfo_cmd(win) - # maybe need to override - __item_config_cmd(win) - end - private :__item_confinfo_cmd - - alias cget_tkstring itemcget_tkstring - alias cget itemcget - alias cget_strict itemcget_strict - alias configure itemconfigure - alias configinfo itemconfiginfo - alias current_configinfo current_itemconfiginfo - - private :itemcget_tkstring, :itemcget, :itemcget_strict - private :itemconfigure, :itemconfiginfo, :current_itemconfiginfo - - 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 - super(id, *args) - end - else - super(id, *args) - end - end - - def hold(win, keys={}) - tk_call_without_enc('tk', 'busy', 'hold', win, *hash_kv(keys)) - win - end - - def forget(*wins) - tk_call_without_enc('tk', 'busy', 'forget', *wins) - self - end - - def current(pat=None) - list(tk_call('tk', 'busy', 'current', pat)) - end - - def status(win) - bool(tk_call_without_enc('tk', 'busy', 'status', win)) - end -end - -module Tk::Busy - def busy_configinfo(option=nil) - Tk::Busy.configinfo(self, option) - end - - def busy_current_configinfo(option=nil) - Tk::Busy.current_configinfo(self, option) - end - - def busy_configure(option, value=None) - Tk::Busy.configure(self, option, value) - self - end - - def busy_cget(option) - Tk::Busy.configure(self, option) - end - - def busy(keys={}) - Tk::Busy.hold(self, keys) - self - end - alias busy_hold busy - - def busy_forget - Tk::Busy.forget(self) - self - end - - def busy_current? - ! Tk::Busy.current(self.path).empty? - end - - def busy_status - Tk::Busy.status(self) - end -end diff --git a/ext/tk/lib/tk/button.rb b/ext/tk/lib/tk/button.rb deleted file mode 100644 index dc252d8e82..0000000000 --- a/ext/tk/lib/tk/button.rb +++ /dev/null @@ -1,32 +0,0 @@ -# frozen_string_literal: false -# -# tk/button.rb : treat button widget -# -require 'tk' -require 'tk/label' - -class Tk::Button<Tk::Label - TkCommandNames = ['button'.freeze].freeze - WidgetClassName = 'Button'.freeze - WidgetClassNames[WidgetClassName] ||= self - #def create_self(keys) - # if keys and keys != None - # tk_call_without_enc('button', @path, *hash_kv(keys, true)) - # else - # tk_call_without_enc('button', @path) - # end - #end - #private :create_self - - def invoke - _fromUTF8(tk_send_without_enc('invoke')) - end - def flash - tk_send_without_enc('flash') - self - end -end - -#TkButton = Tk::Button unless Object.const_defined? :TkButton -#Tk.__set_toplevel_aliases__(:Tk, Tk::Button, :TkButton) -Tk.__set_loaded_toplevel_aliases__('tk/button.rb', :Tk, Tk::Button, :TkButton) diff --git a/ext/tk/lib/tk/canvas.rb b/ext/tk/lib/tk/canvas.rb deleted file mode 100644 index d707733d8c..0000000000 --- a/ext/tk/lib/tk/canvas.rb +++ /dev/null @@ -1,847 +0,0 @@ -# frozen_string_literal: false -# -# tk/canvas.rb - Tk canvas classes -# by Yukihiro Matsumoto <matz@caelum.co.jp> -# -require 'tk' -require 'tk/canvastag' -require 'tk/itemconfig' -require 'tk/scrollable' - -module TkCanvasItemConfig - include TkItemConfigMethod - - def __item_strval_optkeys(id) - # maybe need to override - super(id) + [ - 'fill', 'activefill', 'disabledfill', - 'outline', 'activeoutline', 'disabledoutline' - ] - end - private :__item_strval_optkeys - - def __item_methodcall_optkeys(id) - {'coords'=>'coords'} - end - private :__item_methodcall_optkeys - - def __item_val2ruby_optkeys(id) # { key=>proc, ... } - super(id).update('window'=>proc{|i, v| window(v)}, - 'tags'=>proc{|i, v| - simplelist(v).collect{|tag| TkcTag.id2obj(self, tag)} - }) - end - private :__item_val2ruby_optkeys - - def __item_pathname(tagOrId) - if tagOrId.kind_of?(TkcItem) || tagOrId.kind_of?(TkcTag) - self.path + ';' + tagOrId.id.to_s - else - self.path + ';' + tagOrId.to_s - end - end - private :__item_pathname -end - -class Tk::Canvas<TkWindow - include TkCanvasItemConfig - include Tk::Scrollable - - TkCommandNames = ['canvas'.freeze].freeze - WidgetClassName = 'Canvas'.freeze - WidgetClassNames[WidgetClassName] ||= self - - def __destroy_hook__ - TkcItem::CItemID_TBL.delete(@path) - end - - #def create_self(keys) - # if keys and keys != None - # tk_call_without_enc('canvas', @path, *hash_kv(keys, true)) - # else - # tk_call_without_enc('canvas', @path) - # end - #end - #private :create_self - - def __numval_optkeys - super() + ['closeenough'] - end - private :__numval_optkeys - - def __boolval_optkeys - super() + ['confine'] - end - private :__boolval_optkeys - - def tagid(tag) - if tag.kind_of?(TkcItem) || tag.kind_of?(TkcTag) - tag.id - else - tag # maybe an Array of configure parameters - end - end - private :tagid - - - # create a canvas item without creating a TkcItem object - def create(type, *args) - if type.kind_of?(Class) && type < TkcItem - # do nothing - elsif TkcItem.type2class(type.to_s) - type = TkcItem.type2class(type.to_s) - else - fail ArgumentError, "type must a subclass of TkcItem class, or a string in CItemTypeToClass" - end - type.create(self, *args) - end - - def addtag(tag, mode, *args) - mode = mode.to_s - if args[0] && mode =~ /^(above|below|with(tag)?)$/ - args[0] = tagid(args[0]) - end - tk_send_without_enc('addtag', tagid(tag), mode, *args) - self - end - def addtag_above(tagOrId, target) - addtag(tagOrId, 'above', tagid(target)) - end - def addtag_all(tagOrId) - addtag(tagOrId, 'all') - end - def addtag_below(tagOrId, target) - addtag(tagOrId, 'below', tagid(target)) - end - def addtag_closest(tagOrId, x, y, halo=None, start=None) - addtag(tagOrId, 'closest', x, y, halo, start) - end - def addtag_enclosed(tagOrId, x1, y1, x2, y2) - addtag(tagOrId, 'enclosed', x1, y1, x2, y2) - end - def addtag_overlapping(tagOrId, x1, y1, x2, y2) - addtag(tagOrId, 'overlapping', x1, y1, x2, y2) - end - def addtag_withtag(tagOrId, tag) - addtag(tagOrId, 'withtag', tagid(tag)) - end - - def bbox(tagOrId, *tags) - list(tk_send_without_enc('bbox', tagid(tagOrId), - *tags.collect{|t| tagid(t)})) - end - - #def itembind(tag, context, cmd=Proc.new, *args) - # _bind([path, "bind", tagid(tag)], context, cmd, *args) - # self - #end - def itembind(tag, 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([path, "bind", tagid(tag)], context, cmd, *args) - self - end - - #def itembind_append(tag, context, cmd=Proc.new, *args) - # _bind_append([path, "bind", tagid(tag)], context, cmd, *args) - # self - #end - def itembind_append(tag, 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([path, "bind", tagid(tag)], context, cmd, *args) - self - end - - def itembind_remove(tag, context) - _bind_remove([path, "bind", tagid(tag)], context) - self - end - - def itembindinfo(tag, context=nil) - _bindinfo([path, "bind", tagid(tag)], context) - end - - def canvasx(screen_x, *args) - #tk_tcl2ruby(tk_send_without_enc('canvasx', screen_x, *args)) - number(tk_send_without_enc('canvasx', screen_x, *args)) - end - def canvasy(screen_y, *args) - #tk_tcl2ruby(tk_send_without_enc('canvasy', screen_y, *args)) - number(tk_send_without_enc('canvasy', screen_y, *args)) - end - alias canvas_x canvasx - alias canvas_y canvasy - - def coords(tag, *args) - if args.empty? - tk_split_list(tk_send_without_enc('coords', tagid(tag))) - else - tk_send_without_enc('coords', tagid(tag), *(args.flatten)) - self - end - end - - def dchars(tag, first, last=None) - tk_send_without_enc('dchars', tagid(tag), - _get_eval_enc_str(first), _get_eval_enc_str(last)) - self - end - - def delete(*args) - tbl = nil - TkcItem::CItemID_TBL.mutex.synchronize{ - tbl = TkcItem::CItemID_TBL[self.path] - } - if tbl - args.each{|tag| - find('withtag', tag).each{|item| - if item.kind_of?(TkcItem) - TkcItem::CItemID_TBL.mutex.synchronize{ - tbl.delete(item.id) - } - end - } - } - end - tk_send_without_enc('delete', *args.collect{|t| tagid(t)}) - self - end - alias remove delete - - def dtag(tag, tag_to_del=None) - tk_send_without_enc('dtag', tagid(tag), tagid(tag_to_del)) - self - end - alias deltag dtag - - def find(mode, *args) - list(tk_send_without_enc('find', mode, *args)).collect!{|id| - TkcItem.id2obj(self, id) - } - end - def find_above(target) - find('above', tagid(target)) - end - def find_all - find('all') - end - def find_below(target) - find('below', tagid(target)) - end - def find_closest(x, y, halo=None, start=None) - find('closest', x, y, halo, start) - end - def find_enclosed(x1, y1, x2, y2) - find('enclosed', x1, y1, x2, y2) - end - def find_overlapping(x1, y1, x2, y2) - find('overlapping', x1, y1, x2, y2) - end - def find_withtag(tag) - find('withtag', tag) - end - - def itemfocus(tagOrId=nil) - if tagOrId - tk_send_without_enc('focus', tagid(tagOrId)) - self - else - ret = tk_send_without_enc('focus') - if ret == "" - nil - else - TkcItem.id2obj(self, ret) - end - end - end - - def gettags(tagOrId) - list(tk_send_without_enc('gettags', tagid(tagOrId))).collect{|tag| - TkcTag.id2obj(self, tag) - } - end - - def icursor(tagOrId, index) - tk_send_without_enc('icursor', tagid(tagOrId), index) - self - end - - def imove(tagOrId, idx, x, y) - tk_send_without_enc('imove', tagid(tagOrId), idx, x, y) - self - end - alias i_move imove - - def index(tagOrId, idx) - number(tk_send_without_enc('index', tagid(tagOrId), idx)) - end - - def insert(tagOrId, index, string) - tk_send_without_enc('insert', tagid(tagOrId), index, - _get_eval_enc_str(string)) - self - end - -=begin - def itemcget(tagOrId, option) - case option.to_s - when 'dash', 'activedash', 'disableddash' - conf = tk_send_without_enc('itemcget', tagid(tagOrId), "-#{option}") - if conf =~ /^[0-9]/ - list(conf) - else - conf - end - when 'text', 'label', 'show', 'data', 'file', 'maskdata', 'maskfile' - _fromUTF8(tk_send_without_enc('itemcget', tagid(tagOrId), "-#{option}")) - when 'font', 'kanjifont' - #fnt = tk_tcl2ruby(tk_send('itemcget', tagid(tagOrId), "-#{option}")) - fnt = tk_tcl2ruby(_fromUTF8(tk_send_with_enc('itemcget', tagid(tagOrId), '-font'))) - unless fnt.kind_of?(TkFont) - fnt = tagfontobj(tagid(tagOrId), fnt) - end - if option.to_s == 'kanjifont' && JAPANIZED_TK && TK_VERSION =~ /^4\.*/ - # obsolete; just for compatibility - fnt.kanji_font - else - fnt - end - else - tk_tcl2ruby(_fromUTF8(tk_send_without_enc('itemcget', tagid(tagOrId), - "-#{option}"))) - end - end - - def itemconfigure(tagOrId, key, value=None) - if key.kind_of? Hash - key = _symbolkey2str(key) - coords = key.delete('coords') - self.coords(tagOrId, coords) if coords - - if ( key['font'] || key['kanjifont'] \ - || key['latinfont'] || key['asciifont'] ) - tagfont_configure(tagid(tagOrId), key.dup) - else - _fromUTF8(tk_send_without_enc('itemconfigure', tagid(tagOrId), - *hash_kv(key, true))) - end - - else - if ( key == 'coords' || key == :coords ) - self.coords(tagOrId, value) - elsif ( key == 'font' || key == :font || - key == 'kanjifont' || key == :kanjifont || - key == 'latinfont' || key == :latinfont || - key == 'asciifont' || key == :asciifont ) - if value == None - tagfontobj(tagid(tagOrId)) - else - tagfont_configure(tagid(tagOrId), {key=>value}) - end - else - _fromUTF8(tk_send_without_enc('itemconfigure', tagid(tagOrId), - "-#{key}", _get_eval_enc_str(value))) - end - end - self - end -# def itemconfigure(tagOrId, key, value=None) -# if key.kind_of? Hash -# tk_send 'itemconfigure', tagid(tagOrId), *hash_kv(key) -# else -# tk_send 'itemconfigure', tagid(tagOrId), "-#{key}", value -# end -# end -# def itemconfigure(tagOrId, keys) -# tk_send 'itemconfigure', tagid(tagOrId), *hash_kv(keys) -# end - - def itemconfiginfo(tagOrId, key=nil) - if TkComm::GET_CONFIGINFO_AS_ARRAY - if key - case key.to_s - when 'coords' - return ['coords', '', '', '', self.coords(tagOrId)] - when 'dash', 'activedash', 'disableddash' - conf = tk_split_simplelist(tk_send_without_enc('itemconfigure', tagid(tagOrId), "-#{key}")) - if conf[3] && conf[3] =~ /^[0-9]/ - conf[3] = list(conf[3]) - end - if conf[4] && conf[4] =~ /^[0-9]/ - conf[4] = list(conf[4]) - end - when 'text', 'label', 'show', 'data', 'file', 'maskdata', 'maskfile' - conf = tk_split_simplelist(_fromUTF8(tk_send_without_enc('itemconfigure', tagid(tagOrId), "-#{key}"))) - when 'font', 'kanjifont' - conf = tk_split_simplelist(_fromUTF8(tk_send_without_enc('itemconfigure', tagid(tagOrId),"-#{key}"))) - conf[4] = tagfont_configinfo(tagid(tagOrId), conf[4]) - else - conf = tk_split_list(_fromUTF8(tk_send_without_enc('itemconfigure', tagid(tagOrId), "-#{key}"))) - end - conf[0] = conf[0][1..-1] - conf - else - ret = tk_split_simplelist(_fromUTF8(tk_send_without_enc('itemconfigure', tagid(tagOrId)))).collect{|conflist| - conf = tk_split_simplelist(conflist) - conf[0] = conf[0][1..-1] - case conf[0] - when 'text', 'label', 'show', 'data', 'file', 'maskdata', 'maskfile' - when 'dash', 'activedash', 'disableddash' - if conf[3] && conf[3] =~ /^[0-9]/ - conf[3] = list(conf[3]) - end - if conf[4] && conf[4] =~ /^[0-9]/ - conf[4] = list(conf[4]) - end - else - if conf[3] - if conf[3].index('{') - conf[3] = tk_split_list(conf[3]) - else - conf[3] = tk_tcl2ruby(conf[3]) - end - end - if conf[4] - if conf[4].index('{') - conf[4] = tk_split_list(conf[4]) - else - conf[4] = tk_tcl2ruby(conf[4]) - end - end - end - conf[1] = conf[1][1..-1] if conf.size == 2 # alias info - conf - } - - fontconf = ret.assoc('font') - if fontconf - ret.delete_if{|item| item[0] == 'font' || item[0] == 'kanjifont'} - fontconf[4] = tagfont_configinfo(tagid(tagOrId), fontconf[4]) - ret.push(fontconf) - end - - ret << ['coords', '', '', '', self.coords(tagOrId)] - end - else # ! TkComm::GET_CONFIGINFO_AS_ARRAY - if key - case key.to_s - when 'coords' - {'coords' => ['', '', '', self.coords(tagOrId)]} - when 'dash', 'activedash', 'disableddash' - conf = tk_split_simplelist(tk_send_without_enc('itemconfigure', - tagid(tagOrId), - "-#{key}")) - if conf[3] && conf[3] =~ /^[0-9]/ - conf[3] = list(conf[3]) - end - if conf[4] && conf[4] =~ /^[0-9]/ - conf[4] = list(conf[4]) - end - when 'text', 'label', 'show', 'data', 'file', 'maskdata', 'maskfile' - conf = tk_split_simplelist(_fromUTF8(tk_send_without_enc('itemconfigure', tagid(tagOrId), "-#{key}"))) - when 'font', 'kanjifont' - conf = tk_split_simplelist(_fromUTF8(tk_send_without_enc('itemconfigure', tagid(tagOrId),"-#{key}"))) - conf[4] = tagfont_configinfo(tagid(tagOrId), conf[4]) - else - conf = tk_split_list(_fromUTF8(tk_send_without_enc('itemconfigure', tagid(tagOrId), "-#{key}"))) - end - key = conf.shift[1..-1] - { key => conf } - else - ret = {} - tk_split_simplelist(_fromUTF8(tk_send_without_enc('itemconfigure', tagid(tagOrId)))).each{|conflist| - conf = tk_split_simplelist(conflist) - key = conf.shift[1..-1] - case key - when 'text', 'label', 'show', 'data', 'file', 'maskdata', 'maskfile' - when 'dash', 'activedash', 'disableddash' - if conf[2] && conf[2] =~ /^[0-9]/ - conf[2] = list(conf[2]) - end - if conf[3] && conf[3] =~ /^[0-9]/ - conf[3] = list(conf[3]) - end - else - if conf[2] - if conf[2].index('{') - conf[2] = tk_split_list(conf[2]) - else - conf[2] = tk_tcl2ruby(conf[2]) - end - end - if conf[3] - if conf[3].index('{') - conf[3] = tk_split_list(conf[3]) - else - conf[3] = tk_tcl2ruby(conf[3]) - end - end - end - if conf.size == 1 - ret[key] = conf[0][1..-1] # alias info - else - ret[key] = conf - end - } - - fontconf = ret['font'] - if fontconf - ret.delete('font') - ret.delete('kanjifont') - fontconf[3] = tagfont_configinfo(tagid(tagOrId), fontconf[3]) - ret['font'] = fontconf - end - - ret['coords'] = ['', '', '', self.coords(tagOrId)] - - ret - end - end - end - - def current_itemconfiginfo(tagOrId, key=nil) - if TkComm::GET_CONFIGINFO_AS_ARRAY - if key - conf = itemconfiginfo(tagOrId, key) - {conf[0] => conf[4]} - else - ret = {} - itemconfiginfo(tagOrId).each{|conf| - ret[conf[0]] = conf[4] if conf.size > 2 - } - ret - end - else # ! TkComm::GET_CONFIGINFO_AS_ARRAY - ret = {} - itemconfiginfo(tagOrId, key).each{|k, conf| - ret[k] = conf[-1] if conf.kind_of?(Array) - } - ret - end - end -=end - - def lower(tag, below=nil) - if below - tk_send_without_enc('lower', tagid(tag), tagid(below)) - else - tk_send_without_enc('lower', tagid(tag)) - end - self - end - - def move(tag, dx, dy) - tk_send_without_enc('move', tagid(tag), dx, dy) - self - end - - def moveto(tag, x, y) - # Tcl/Tk 8.6 or later - tk_send_without_enc('moveto', tagid(tag), x, y) - self - end - alias move_to moveto - - def postscript(keys) - tk_send("postscript", *hash_kv(keys)) - end - - def raise(tag, above=nil) - if above - tk_send_without_enc('raise', tagid(tag), tagid(above)) - else - tk_send_without_enc('raise', tagid(tag)) - end - self - end - - def rchars(tag, first, last, str_or_coords) - # Tcl/Tk 8.6 or later - str_or_coords = str_or_coords.flatten if str_or_coords.kinad_of? Array - tk_send_without_enc('rchars', tagid(tag), first, last, str_or_coords) - self - end - alias replace_chars rchars - alias replace_coords rchars - - def scale(tag, x, y, xs, ys) - tk_send_without_enc('scale', tagid(tag), x, y, xs, ys) - self - end - - def scan_mark(x, y) - tk_send_without_enc('scan', 'mark', x, y) - self - end - def scan_dragto(x, y, gain=None) - tk_send_without_enc('scan', 'dragto', x, y, gain) - self - end - - def select(mode, *args) - r = tk_send_without_enc('select', mode, *args) - (mode == 'item')? TkcItem.id2obj(self, r): self - end - def select_adjust(tagOrId, index) - select('adjust', tagid(tagOrId), index) - end - def select_clear - select('clear') - end - def select_from(tagOrId, index) - select('from', tagid(tagOrId), index) - end - def select_item - select('item') - end - def select_to(tagOrId, index) - select('to', tagid(tagOrId), index) - end - - def itemtype(tag) - TkcItem.type2class(tk_send('type', tagid(tag))) - end - - def create_itemobj_from_id(idnum) - id = TkcItem.id2obj(self, idnum.to_i) - return id if id.kind_of?(TkcItem) - - typename = tk_send('type', id) - unless type = TkcItem.type2class(typename) - (itemclass = typename.dup)[0,1] = typename[0,1].upcase - type = TkcItem.const_set(itemclass, Class.new(TkcItem)) - type.const_set("CItemTypeName", typename.freeze) - TkcItem::CItemTypeToClass[typename] = type - end - - canvas = self - (obj = type.allocate).instance_eval{ - @parent = @c = canvas - @path = canvas.path - @id = id - TkcItem::CItemID_TBL.mutex.synchronize{ - TkcItem::CItemID_TBL[@path] = {} unless TkcItem::CItemID_TBL[@path] - TkcItem::CItemID_TBL[@path][@id] = self - } - } - end -end - -#TkCanvas = Tk::Canvas unless Object.const_defined? :TkCanvas -#Tk.__set_toplevel_aliases__(:Tk, Tk::Canvas, :TkCanvas) -Tk.__set_loaded_toplevel_aliases__('tk/canvas.rb', :Tk, Tk::Canvas, :TkCanvas) - - -class TkcItem<TkObject - extend Tk - include TkcTagAccess - extend TkItemFontOptkeys - extend TkItemConfigOptkeys - - CItemTypeName = nil - CItemTypeToClass = {} - - CItemID_TBL = TkCore::INTERP.create_table - - TkCore::INTERP.init_ip_env{ - CItemID_TBL.mutex.synchronize{ CItemID_TBL.clear } - } - - def TkcItem.type2class(type) - CItemTypeToClass[type] - end - - def TkcItem.id2obj(canvas, id) - cpath = canvas.path - CItemID_TBL.mutex.synchronize{ - if CItemID_TBL[cpath] - CItemID_TBL[cpath][id]? CItemID_TBL[cpath][id]: id - else - id - end - } - end - - ######################################## - def self._parse_create_args(args) - fontkeys = {} - methodkeys = {} - if args[-1].kind_of? Hash - keys = _symbolkey2str(args.pop) - if args.size == 0 - args = keys.delete('coords') - unless args.kind_of?(Array) - fail "coords parameter must be given by an Array" - end - end - - #['font', 'kanjifont', 'latinfont', 'asciifont'].each{|key| - # fontkeys[key] = keys.delete(key) if keys.key?(key) - #} - __item_font_optkeys(nil).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) - } - - __item_optkey_aliases(nil).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 - } - - __item_methodcall_optkeys(nil).each{|key| - key = key.to_s - methodkeys[key] = keys.delete(key) if keys.key?(key) - } - - __item_ruby2val_optkeys(nil).each{|key, method| - key = key.to_s - keys[key] = method.call(keys[key]) if keys.has_key?(key) - } - - #args = args.flatten.concat(hash_kv(keys)) - args = args.flatten.concat(itemconfig_hash_kv(nil, keys)) - else - args = args.flatten - end - - [args, fontkeys, methodkeys] - end - private_class_method :_parse_create_args - - def self.create(canvas, *args) - unless self::CItemTypeName - fail RuntimeError, "#{self} is an abstract class" - end - args, fontkeys, methodkeys = _parse_create_args(args) - idnum = tk_call_without_enc(canvas.path, 'create', - self::CItemTypeName, *args) - canvas.itemconfigure(idnum, fontkeys) unless fontkeys.empty? - canvas.itemconfigure(idnum, methodkeys) unless methodkeys.empty? - idnum.to_i # 'canvas item id' is an integer number - end - ######################################## - - def initialize(parent, *args) - #unless parent.kind_of?(Tk::Canvas) - # fail ArgumentError, "expect Tk::Canvas for 1st argument" - #end - @parent = @c = parent - @path = parent.path - - @id = create_self(*args) # an integer number as 'canvas item id' - CItemID_TBL.mutex.synchronize{ - CItemID_TBL[@path] = {} unless CItemID_TBL[@path] - CItemID_TBL[@path][@id] = self - } - end - def create_self(*args) - self.class.create(@c, *args) # return an integer number as 'canvas item id' - end - private :create_self - - def id - @id - end - - def exist? - if @c.find_withtag(@id) - true - else - false - end - end - - def delete - @c.delete @id - CItemID_TBL.mutex.synchronize{ - CItemID_TBL[@path].delete(@id) if CItemID_TBL[@path] - } - self - end - alias remove delete - alias destroy delete -end - -class TkcArc<TkcItem - CItemTypeName = 'arc'.freeze - CItemTypeToClass[CItemTypeName] = self -end - -class TkcBitmap<TkcItem - CItemTypeName = 'bitmap'.freeze - CItemTypeToClass[CItemTypeName] = self -end - -class TkcImage<TkcItem - CItemTypeName = 'image'.freeze - CItemTypeToClass[CItemTypeName] = self -end - -class TkcLine<TkcItem - CItemTypeName = 'line'.freeze - CItemTypeToClass[CItemTypeName] = self -end - -class TkcOval<TkcItem - CItemTypeName = 'oval'.freeze - CItemTypeToClass[CItemTypeName] = self -end - -class TkcPolygon<TkcItem - CItemTypeName = 'polygon'.freeze - CItemTypeToClass[CItemTypeName] = self -end - -class TkcRectangle<TkcItem - CItemTypeName = 'rectangle'.freeze - CItemTypeToClass[CItemTypeName] = self -end - -class TkcText<TkcItem - CItemTypeName = 'text'.freeze - CItemTypeToClass[CItemTypeName] = self - def self.create(canvas, *args) - if args[-1].kind_of?(Hash) - keys = _symbolkey2str(args.pop) - txt = keys['text'] - keys['text'] = _get_eval_enc_str(txt) if txt - args.push(keys) - end - super(canvas, *args) - end -end - -class TkcWindow<TkcItem - CItemTypeName = 'window'.freeze - CItemTypeToClass[CItemTypeName] = self - def self.create(canvas, *args) - if args[-1].kind_of?(Hash) - keys = _symbolkey2str(args.pop) - win = keys['window'] - # keys['window'] = win.epath if win.kind_of?(TkWindow) - keys['window'] = _epath(win) if win - args.push(keys) - end - super(canvas, *args) - end -end diff --git a/ext/tk/lib/tk/canvastag.rb b/ext/tk/lib/tk/canvastag.rb deleted file mode 100644 index 4a14cd78a9..0000000000 --- a/ext/tk/lib/tk/canvastag.rb +++ /dev/null @@ -1,460 +0,0 @@ -# frozen_string_literal: false -# -# tk/canvastag.rb - methods for treating canvas tags -# -require 'tk' -require 'tk/tagfont' - -module TkcTagAccess - include TkComm - include TkTreatTagFont -end - -require 'tk/canvas' - -module TkcTagAccess - def addtag(tag) - @c.addtag(tag, 'withtag', @id) - self - end - - def bbox - @c.bbox(@id) - end - - #def bind(seq, cmd=Proc.new, *args) - # @c.itembind(@id, seq, cmd, *args) - # self - #end - def bind(seq, *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 - @c.itembind(@id, seq, cmd, *args) - self - end - - #def bind_append(seq, cmd=Proc.new, *args) - # @c.itembind_append(@id, seq, cmd, *args) - # self - #end - def bind_append(seq, *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 - @c.itembind_append(@id, seq, cmd, *args) - self - end - - def bind_remove(seq) - @c.itembind_remove(@id, seq) - self - end - - def bindinfo(seq=nil) - @c.itembindinfo(@id, seq) - end - - def cget_tkstring(option) - @c.itemcget_tkstring(@id, option) - end - def cget(option) - @c.itemcget(@id, option) - end - def cget_strict(option) - @c.itemcget_strict(@id, option) - end - - def configure(key, value=None) - @c.itemconfigure(@id, key, value) - self - end -# def configure(keys) -# @c.itemconfigure @id, keys -# end - - def configinfo(key=nil) - @c.itemconfiginfo(@id, key) - end - - def current_configinfo(key=nil) - @c.current_itemconfiginfo(@id, key) - end - - def coords(*args) - @c.coords(@id, *args) - end - - def dchars(first, last=None) - @c.dchars(@id, first, last) - self - end - - def dtag(tag_to_del=None) - @c.dtag(@id, tag_to_del) - self - end - alias deltag dtag - - def find - @c.find('withtag', @id) - end - alias list find - - def focus - @c.itemfocus(@id) - end - - def gettags - @c.gettags(@id) - end - - def icursor(index) - @c.icursor(@id, index) - self - end - - def imove(idx, x, y) - # Tcl/Tk 8.6 or later - @c.imove(@id, idx, x, y) - self - end - alias i_move imove - - def index(idx) - @c.index(@id, idx) - end - - def insert(beforethis, string) - @c.insert(@id, beforethis, string) - self - end - - def lower(belowthis=None) - @c.lower(@id, belowthis) - self - end - - def move(xamount, yamount) - @c.move(@id, xamount, yamount) - self - end - - def moveto(x, y) - # Tcl/Tk 8.6 or later - @c.moveto(@id, x, y) - self - end - alias move_to moveto - - def raise(abovethis=None) - @c.raise(@id, abovethis) - self - end - - def scale(xorigin, yorigin, xscale, yscale) - @c.scale(@id, xorigin, yorigin, xscale, yscale) - self - end - - def rchars(first, last, str_or_coords) - # Tcl/Tk 8.6 or later - @c.rchars(@id, first, last, str_or_coords) - self - end - alias replace_chars rchars - alias replace_coords rchars - - def select_adjust(index) - @c.select('adjust', @id, index) - self - end - def select_from(index) - @c.select('from', @id, index) - self - end - def select_to(index) - @c.select('to', @id, index) - self - end - - def itemtype - @c.itemtype(@id) - end - - # Following operators support logical expressions of canvas tags - # (for Tk8.3+). - # If tag1.path is 't1' and tag2.path is 't2', then - # ltag = tag1 & tag2; ltag.path => "(t1)&&(t2)" - # ltag = tag1 | tag2; ltag.path => "(t1)||(t2)" - # ltag = tag1 ^ tag2; ltag.path => "(t1)^(t2)" - # ltag = - tag1; ltag.path => "!(t1)" - def & (tag) - if tag.kind_of? TkObject - TkcTagString.new(@c, '(' + @id + ')&&(' + tag.path + ')') - else - TkcTagString.new(@c, '(' + @id + ')&&(' + tag.to_s + ')') - end - end - - def | (tag) - if tag.kind_of? TkObject - TkcTagString.new(@c, '(' + @id + ')||(' + tag.path + ')') - else - TkcTagString.new(@c, '(' + @id + ')||(' + tag.to_s + ')') - end - end - - def ^ (tag) - if tag.kind_of? TkObject - TkcTagString.new(@c, '(' + @id + ')^(' + tag.path + ')') - else - TkcTagString.new(@c, '(' + @id + ')^(' + tag.to_s + ')') - end - end - - def -@ - TkcTagString.new(@c, '!(' + @id + ')') - end -end - -class TkcTag<TkObject - include TkcTagAccess - - CTagID_TBL = TkCore::INTERP.create_table - - (Tk_CanvasTag_ID = ['ctag'.freeze, TkUtil.untrust('00000')]).instance_eval{ - @mutex = Mutex.new - def mutex; @mutex; end - freeze - } - - TkCore::INTERP.init_ip_env{ - CTagID_TBL.mutex.synchronize{ CTagID_TBL.clear } - } - - def TkcTag.id2obj(canvas, id) - cpath = canvas.path - CTagID_TBL.mutex.synchronize{ - if CTagID_TBL[cpath] - CTagID_TBL[cpath][id]? CTagID_TBL[cpath][id]: id - else - id - end - } - end - - def initialize(parent, mode=nil, *args) - #unless parent.kind_of?(TkCanvas) - # fail ArgumentError, "expect TkCanvas for 1st argument" - #end - @c = parent - @cpath = parent.path - Tk_CanvasTag_ID.mutex.synchronize{ - # @path = @id = Tk_CanvasTag_ID.join('') - @path = @id = Tk_CanvasTag_ID.join(TkCore::INTERP._ip_id_) - Tk_CanvasTag_ID[1].succ! - } - CTagID_TBL.mutex.synchronize{ - CTagID_TBL[@cpath] = {} unless CTagID_TBL[@cpath] - CTagID_TBL[@cpath][@id] = self - } - if mode - tk_call_without_enc(@c.path, "addtag", @id, mode, *args) - end - end - def id - @id - end - - def exist? - if @c.find_withtag(@id) - true - else - false - end - end - - def delete - @c.delete @id - CTagID_TBL.mutex.synchronize{ - CTagID_TBL[@cpath].delete(@id) if CTagID_TBL[@cpath] - } - self - end - alias remove delete - alias destroy delete - - def set_to_above(target) - @c.addtag_above(@id, target) - self - end - alias above set_to_above - - def set_to_all - @c.addtag_all(@id) - self - end - alias all set_to_all - - def set_to_below(target) - @c.addtag_below(@id, target) - self - end - alias below set_to_below - - def set_to_closest(x, y, halo=None, start=None) - @c.addtag_closest(@id, x, y, halo, start) - self - end - alias closest set_to_closest - - def set_to_enclosed(x1, y1, x2, y2) - @c.addtag_enclosed(@id, x1, y1, x2, y2) - self - end - alias enclosed set_to_enclosed - - def set_to_overlapping(x1, y1, x2, y2) - @c.addtag_overlapping(@id, x1, y1, x2, y2) - self - end - alias overlapping set_to_overlapping - - def set_to_withtag(target) - @c.addtag_withtag(@id, target) - self - end - alias withtag set_to_withtag -end - -class TkcTagString<TkcTag - def self.new(parent, name, mode=nil, *args) - obj = nil - CTagID_TBL.mutex.synchronize{ - if CTagID_TBL[parent.path] && CTagID_TBL[parent.path][name] - obj = CTagID_TBL[parent.path][name] - else - # super(parent, name, *args) - (obj = self.allocate).instance_eval{ - @c = parent - @cpath = parent.path - @path = @id = name - CTagID_TBL[@cpath] = {} unless CTagID_TBL[@cpath] - CTagID_TBL[@cpath][@id] = self - } - end - } - if obj && mode - tk_call_without_enc(@c.path, "addtag", @id, mode, *args) - end - obj - end - - def initialize(parent, name, mode=nil, *args) - # dummy:: not called by 'new' method - - #unless parent.kind_of?(TkCanvas) - # fail ArgumentError, "expect TkCanvas for 1st argument" - #end - @c = parent - @cpath = parent.path - @path = @id = name - - if mode - tk_call_without_enc(@c.path, "addtag", @id, mode, *args) - end - end -end -TkcNamedTag = TkcTagString - -class TkcTagAll<TkcTagString - def self.new(parent) - super(parent, 'all') - end -=begin - def initialize(parent) - #unless parent.kind_of?(TkCanvas) - # fail ArgumentError, "expect TkCanvas for 1st argument" - #end - @c = parent - @cpath = parent.path - @path = @id = 'all' - CTagID_TBL.mutex.synchronize{ - CTagID_TBL[@cpath] = {} unless CTagID_TBL[@cpath] - CTagID_TBL[@cpath][@id] = self - } - end -=end -end - -class TkcTagCurrent<TkcTagString - def self.new(parent) - super(parent, 'current') - end -=begin - def initialize(parent) - #unless parent.kind_of?(TkCanvas) - # fail ArgumentError, "expect TkCanvas for 1st argument" - #end - @c = parent - @cpath = parent.path - @path = @id = 'current' - CTagID_TBL.mutex.synchronize{ - CTagID_TBL[@cpath] = {} unless CTagID_TBL[@cpath] - CTagID_TBL[@cpath][@id] = self - } - end -=end -end - -class TkcGroup<TkcTag - (Tk_cGroup_ID = ['tkcg'.freeze, TkUtil.untrust('00000')]).instance_eval{ - @mutex = Mutex.new - def mutex; @mutex; end - freeze - } - - #def create_self(parent, *args) - def initialize(parent, *args) - #unless parent.kind_of?(TkCanvas) - # fail ArgumentError, "expect TkCanvas for 1st argument" - #end - @c = parent - @cpath = parent.path - Tk_cGroup_ID.mutex.synchronize{ - # @path = @id = Tk_cGroup_ID.join('') - @path = @id = Tk_cGroup_ID.join(TkCore::INTERP._ip_id_) - Tk_cGroup_ID[1].succ! - } - CTagID_TBL.mutex.synchronize{ - CTagID_TBL[@cpath] = {} unless CTagID_TBL[@cpath] - CTagID_TBL[@cpath][@id] = self - } - include(*args) if args != [] - end - #private :create_self - - def include(*tags) - for i in tags - #i.addtag(@id) - @c.addtag_withtag(@id, i) - end - self - end - alias add include - - def exclude(*tags) - for i in tags - #i.dtag(@id) - @c.dtag(i, @id) - end - self - end -end diff --git a/ext/tk/lib/tk/checkbutton.rb b/ext/tk/lib/tk/checkbutton.rb deleted file mode 100644 index 521b015b3e..0000000000 --- a/ext/tk/lib/tk/checkbutton.rb +++ /dev/null @@ -1,33 +0,0 @@ -# frozen_string_literal: false -# -# tk/checkbutton.rb : treat checkbutton widget -# -require 'tk' -require 'tk/radiobutton' - -class Tk::CheckButton<Tk::RadioButton - TkCommandNames = ['checkbutton'.freeze].freeze - WidgetClassName = 'Checkbutton'.freeze - WidgetClassNames[WidgetClassName] ||= self - #def create_self(keys) - # if keys and keys != None - # tk_call_without_enc('checkbutton', @path, *hash_kv(keys, true)) - # else - # tk_call_without_enc('checkbutton', @path) - # end - #end - #private :create_self - - def toggle - tk_send_without_enc('toggle') - self - end -end - -Tk::Checkbutton = Tk::CheckButton -#TkCheckButton = Tk::CheckButton unless Object.const_defined? :TkCheckButton -#TkCheckbutton = Tk::Checkbutton unless Object.const_defined? :TkCheckbutton -#Tk.__set_toplevel_aliases__(:Tk, Tk::CheckButton, -# :TkCheckButton, :TkCheckbutton) -Tk.__set_loaded_toplevel_aliases__('tk/checkbutton.rb', :Tk, Tk::CheckButton, - :TkCheckButton, :TkCheckbutton) diff --git a/ext/tk/lib/tk/clipboard.rb b/ext/tk/lib/tk/clipboard.rb deleted file mode 100644 index c5f481f979..0000000000 --- a/ext/tk/lib/tk/clipboard.rb +++ /dev/null @@ -1,76 +0,0 @@ -# frozen_string_literal: false -# -# tk/clipboard.rb : methods to treat clipboard -# -require 'tk' - -module TkClipboard - include Tk - extend Tk - - TkCommandNames = ['clipboard'.freeze].freeze - - def self.clear(win=nil) - if win - tk_call_without_enc('clipboard', 'clear', '-displayof', win) - else - tk_call_without_enc('clipboard', 'clear') - end - end - def self.clear_on_display(win) - tk_call_without_enc('clipboard', 'clear', '-displayof', win) - end - - def self.get(type=nil) - if type - tk_call_without_enc('clipboard', 'get', '-type', type) - else - tk_call_without_enc('clipboard', 'get') - end - end - def self.get_on_display(win, type=nil) - if type - tk_call_without_enc('clipboard', 'get', '-displayof', win, '-type', type) - else - tk_call_without_enc('clipboard', 'get', '-displayof', win) - end - end - - def self.set(data, keys=nil) - clear - append(data, keys) - end - def self.set_on_display(win, data, keys=nil) - clear(win) - append_on_display(win, data, keys) - end - - def self.append(data, keys=nil) - args = ['clipboard', 'append'] - args.concat(hash_kv(keys)) - args.concat(['--', data]) - tk_call(*args) - end - def self.append_on_display(win, data, keys=nil) - args = ['clipboard', 'append', '-displayof', win] - args.concat(hash_kv(keys)) - args.concat(['--', data]) - tk_call(*args) - end - - def clear - TkClipboard.clear_on_display(self) - self - end - def get(type=nil) - TkClipboard.get_on_display(self, type) - end - def set(data, keys=nil) - TkClipboard.set_on_display(self, data, keys) - self - end - def append(data, keys=nil) - TkClipboard.append_on_display(self, data, keys) - self - end -end diff --git a/ext/tk/lib/tk/clock.rb b/ext/tk/lib/tk/clock.rb deleted file mode 100644 index df900d7364..0000000000 --- a/ext/tk/lib/tk/clock.rb +++ /dev/null @@ -1,72 +0,0 @@ -# frozen_string_literal: false -# -# tk/clock.rb : methods for clock command -# -require 'tk' - -module Tk - module Clock - include Tk - extend TkCore - - def self.add(clk, *args) - tk_call_without_enc('clock','add', clk, *args).to_i - end - - def self.clicks(ms=nil) - ms = ms.to_s if ms.kind_of?(Symbol) - case ms - when nil, '' - tk_call_without_enc('clock','clicks').to_i - when /^mic/ - tk_call_without_enc('clock','clicks','-microseconds').to_i - when /^mil/ - tk_call_without_enc('clock','clicks','-milliseconds').to_i - else - tk_call_without_enc('clock','clicks','-milliseconds').to_i - end - end - - def self.format(clk, form=nil) - if form - tk_call('clock','format',clk,'-format',form) - else - tk_call('clock','format',clk) - end - end - - def self.formatGMT(clk, form=nil) - if form - tk_call('clock','format',clk,'-format',form,'-gmt','1') - else - tk_call('clock','format',clk,'-gmt','1') - end - end - - def self.scan(str, base=nil) - if base - tk_call('clock','scan',str,'-base',base).to_i - else - tk_call('clock','scan',str).to_i - end - end - - def self.scanGMT(str, base=nil) - if base - tk_call('clock','scan',str,'-base',base,'-gmt','1').to_i - else - tk_call('clock','scan',str,'-gmt','1').to_i - end - end - - def self.seconds - tk_call_without_enc('clock','seconds').to_i - end - def self.milliseconds - tk_call_without_enc('clock','milliseconds').to_i - end - def self.microseconds - tk_call_without_enc('clock','microseconds').to_i - end - end -end diff --git a/ext/tk/lib/tk/composite.rb b/ext/tk/lib/tk/composite.rb deleted file mode 100644 index 830d383d69..0000000000 --- a/ext/tk/lib/tk/composite.rb +++ /dev/null @@ -1,485 +0,0 @@ -# frozen_string_literal: false -# -# tk/composite.rb : -# -require 'tk' - -module TkComposite - include Tk - extend Tk - -=begin - def initialize(parent=nil, *args) - @delegates = {} - @option_methods = {} - @option_setting = {} - - if parent.kind_of? Hash - keys = _symbolkey2str(parent) - parent = keys.delete('parent') - @frame = TkFrame.new(parent) - @path = @epath = @frame.path - initialize_composite(keys) - else - @frame = TkFrame.new(parent) - @path = @epath = @frame.path - initialize_composite(*args) - end - end -=end - - def _choice_classname_of_baseframe - base_class_name = nil - - klass = WidgetClassNames[self.class::WidgetClassName] - - if klass - # WidgetClassName is a known class - #if klass <= TkFrame || klass < TkComposite - if klass <= TkFrame || klass < Tk::Frame || klass < TkComposite - # klass is valid for the base frame - if self.class <= klass - # use my classname - base_class_name = self.class.name - if base_class_name == '' - # anonymous class -> use ancestor's name - base_class_name = klass.name - end - else - # not subclass -> use WidgetClassName - base_class_name = klass.name - end - - else - # klass is invalid for the base frame - #if self.class < TkFrame || self.class.superclass < TkComposite - if self.class < TkFrame || self.class.superclass < Tk::Frame || self.class.superclass < TkComposite - # my class name is valid for the base frame -> use my classname - base_class_name = self.class.name - if base_class_name == '' - # anonymous class -> use TkFrame - base_class_name = nil - end - else - # no idea for the base frame -> use TkFrame - base_class_name = nil - end - end - - elsif self.class::WidgetClassName && ! self.class::WidgetClassName.empty? - # unknown WidgetClassName is defined -> use it for the base frame - base_class_name = self.class::WidgetClassName - - else - # no valid WidgetClassName - #if self.class < TkFrame || self.class.superclass < TkComposite - if self.class < TkFrame || self.class.superclass < Tk::Frame || self.class.superclass < TkComposite - # my class name is valid for the base frame -> use my classname - base_class_name = self.class.name - if base_class_name == '' - # anonymous class -> use TkFrame - base_class_name = nil - end - else - # no idea for the base frame -> use TkFrame - base_class_name = nil - end - end - - base_class_name - end - private :_choice_classname_of_baseframe - - # def initialize(parent=nil, *args) - def initialize(*args) - @delegates = {} - @option_methods = {} - @option_setting = {} - - if args[-1].kind_of?(Hash) - keys = _symbolkey2str(args.pop) - else - keys = {} - end - parent = args.shift - parent = keys.delete('parent') if keys.has_key?('parent') - - if keys.key?('classname') - keys['class'] = keys.delete('classname') - end - if (base_class_name = (keys.delete('class')).to_s).empty? - base_class_name = _choice_classname_of_baseframe - end - - if base_class_name - # @frame = Tk::Frame.new(parent, :class=>base_class_name) - # --> use current TkFrame class - @frame = TkFrame.new(parent, :class=>base_class_name) - else - # @frame = Tk::Frame.new(parent) - # --> use current TkFrame class - @frame = TkFrame.new(parent) - end - @path = @epath = @frame.path - - args.push(keys) unless keys.empty? - initialize_composite(*args) - end - - def database_classname - @frame.database_classname - end - - def database_class - @frame.database_class - end - - def epath - @epath - end - - def initialize_composite(*args) end - private :initialize_composite - - def inspect - str = super - str.chop << ' @epath=' << @epath.inspect << '>' - end - - def _get_opt_method_list(arg) - m_set, m_cget, m_info = arg - m_set = m_set.to_s - m_cget = m_set if !m_cget && self.method(m_set).arity == -1 - m_cget = m_cget.to_s if m_cget - m_info = m_info.to_s if m_info - [m_set, m_cget, m_info] - end - private :_get_opt_method_list - - def option_methods(*opts) - if opts.size == 1 && opts[0].kind_of?(Hash) - # {name => [m_set, m_cget, m_info], name => method} style - opts[0].each{|name, arg| - m_set, m_cget, m_info = _get_opt_method_list(arg) - @option_methods[name.to_s] = { - :set => m_set, :cget => m_cget, :info => m_info - } - } - else - # [m_set, m_cget, m_info] or method style - opts.each{|arg| - m_set, m_cget, m_info = _get_opt_method_list(arg) - @option_methods[m_set] = { - :set => m_set, :cget => m_cget, :info => m_info - } - } - end - end - - def delegate_alias(alias_opt, option, *wins) - if wins.length == 0 - fail ArgumentError, "target widgets are not given" - end - if alias_opt != option && (alias_opt == 'DEFAULT' || option == 'DEFAULT') - fail ArgumentError, "cannot alias 'DEFAULT' option" - end - alias_opt = alias_opt.to_s - option = option.to_s - if @delegates[alias_opt].kind_of?(Array) - if (elem = @delegates[alias_opt].assoc(option)) - wins.each{|w| elem[1].push(w)} - else - @delegates[alias_opt] << [option, wins] - end - else - @delegates[alias_opt] = [ [option, wins] ] - end - end - - def delegate(option, *wins) - delegate_alias(option, option, *wins) - end - - def __cget_delegates(slot) - slot = slot.to_s - - if @option_methods.include?(slot) - if @option_methods[slot][:cget] - return self.__send__(@option_methods[slot][:cget]) - else - if @option_setting[slot] - return @option_setting[slot] - else - return '' - end - end - end - - tbl = @delegates[slot] - tbl = @delegates['DEFAULT'] unless tbl - - begin - if tbl - opt, wins = tbl[-1] - opt = slot if opt == 'DEFAULT' - if wins && wins[-1] - # return wins[-1].cget(opt) - return wins[-1].cget_strict(opt) - end - end - rescue - end - - return None - end - private :__cget_delegates - - def cget_tkstring(slot) - if (ret = __cget_delegates(slot)) == None - super(slot) - else - _get_eval_string(ret) - end - end - - def cget(slot) - if (ret = __cget_delegates(slot)) == None - super(slot) - else - ret - end - end - - def cget_strict(slot) - if (ret = __cget_delegates(slot)) == None - super(slot) - else - ret - end - end - -=begin - def cget(slot) - slot = slot.to_s - - if @option_methods.include?(slot) - if @option_methods[slot][:cget] - return self.__send__(@option_methods[slot][:cget]) - else - if @option_setting[slot] - return @option_setting[slot] - else - return '' - end - end - end - - tbl = @delegates[slot] - tbl = @delegates['DEFAULT'] unless tbl - - begin - if tbl - opt, wins = tbl[-1] - opt = slot if opt == 'DEFAULT' - if wins && wins[-1] - return wins[-1].cget(opt) - end - end - rescue - end - - super(slot) - end -=end - - def configure(slot, value=None) - if slot.kind_of? Hash - slot.each{|slot,value| configure slot, value} - return self - end - - slot = slot.to_s - - if @option_methods.include?(slot) - unless @option_methods[slot][:cget] - if value.kind_of?(Symbol) - @option_setting[slot] = value.to_s - else - @option_setting[slot] = value - end - end - return self.__send__(@option_methods[slot][:set], value) - end - - tbl = @delegates[slot] - tbl = @delegates['DEFAULT'] unless tbl - - begin - if tbl - last = nil - tbl.each{|opt, wins| - opt = slot if opt == 'DEFAULT' - wins.each{|w| last = w.configure(opt, value)} - } - return last - end - rescue - end - - super(slot, value) - end - - def configinfo(slot = nil) - if TkComm::GET_CONFIGINFO_AS_ARRAY - if slot - slot = slot.to_s - if @option_methods.include?(slot) - if @option_methods[slot][:info] - return self.__send__(@option_methods[slot][:info]) - else - return [slot, '', '', '', self.cget(slot)] - end - end - - tbl = @delegates[slot] - tbl = @delegates['DEFAULT'] unless tbl - - begin - if tbl - if tbl.length == 1 - opt, wins = tbl[0] - if slot == opt || opt == 'DEFAULT' - return wins[-1].configinfo(slot) - else - info = wins[-1].configinfo(opt) - info[0] = slot - return info - end - else - opt, wins = tbl[-1] - return [slot, '', '', '', wins[-1].cget(opt)] - end - end - rescue - end - - super(slot) - - else # slot == nil - info_list = super(slot) - - tbl = @delegates['DEFAULT'] - if tbl - wins = tbl[0][1] - if wins && wins[-1] - wins[-1].configinfo.each{|info| - slot = info[0] - info_list.delete_if{|i| i[0] == slot} << info - } - end - end - - @delegates.each{|slot, tbl| - next if slot == 'DEFAULT' - if tbl.length == 1 - opt, wins = tbl[0] - next unless wins && wins[-1] - if slot == opt - info_list.delete_if{|i| i[0] == slot} << - wins[-1].configinfo(slot) - else - info = wins[-1].configinfo(opt) - info[0] = slot - info_list.delete_if{|i| i[0] == slot} << info - end - else - opt, wins = tbl[-1] - info_list.delete_if{|i| i[0] == slot} << - [slot, '', '', '', wins[-1].cget(opt)] - end - } - - @option_methods.each{|slot, m| - if m[:info] - info = self.__send__(m[:info]) - else - info = [slot, '', '', '', self.cget(slot)] - end - info_list.delete_if{|i| i[0] == slot} << info - } - - info_list - end - - else # ! TkComm::GET_CONFIGINFO_AS_ARRAY - if slot - slot = slot.to_s - if @option_methods.include?(slot) - if @option_methods[slot][:info] - return self.__send__(@option_methods[slot][:info]) - else - return {slot => ['', '', '', self.cget(slot)]} - end - end - - tbl = @delegates[slot] - tbl = @delegates['DEFAULT'] unless tbl - - begin - if tbl - if tbl.length == 1 - opt, wins = tbl[0] - if slot == opt || opt == 'DEFAULT' - return wins[-1].configinfo(slot) - else - return {slot => wins[-1].configinfo(opt)[opt]} - end - else - opt, wins = tbl[-1] - return {slot => ['', '', '', wins[-1].cget(opt)]} - end - end - rescue - end - - super(slot) - - else # slot == nil - info_list = super(slot) - - tbl = @delegates['DEFAULT'] - if tbl - wins = tbl[0][1] - info_list.update(wins[-1].configinfo) if wins && wins[-1] - end - - @delegates.each{|slot, tbl| - next if slot == 'DEFAULT' - if tbl.length == 1 - opt, wins = tbl[0] - next unless wins && wins[-1] - if slot == opt - info_list.update(wins[-1].configinfo(slot)) - else - info_list.update({slot => wins[-1].configinfo(opt)[opt]}) - end - else - opt, wins = tbl[-1] - info_list.update({slot => ['', '', '', wins[-1].cget(opt)]}) - end - } - - @option_methods.each{|slot, m| - if m[:info] - info = self.__send__(m[:info]) - else - info = {slot => ['', '', '', self.cget(slot)]} - end - info_list.update(info) - } - - info_list - end - end - end -end diff --git a/ext/tk/lib/tk/console.rb b/ext/tk/lib/tk/console.rb deleted file mode 100644 index c560912da8..0000000000 --- a/ext/tk/lib/tk/console.rb +++ /dev/null @@ -1,53 +0,0 @@ -# frozen_string_literal: false -# -# tk/console.rb : control the console on system without a real console -# -require 'tk' - -module TkConsole - include Tk - extend Tk - - TkCommandNames = ['console'.freeze, 'consoleinterp'.freeze].freeze - - def self.create - TkCore::INTERP._create_console - end - self.create # initialize console - - def self.title(str=None) - tk_call 'console', str - end - def self.hide - tk_call_without_enc('console', 'hide') - end - def self.show - tk_call_without_enc('console', 'show') - end - def self.eval(tcl_script) - # - # supports a Tcl script only - # I have no idea to support a Ruby script seamlessly. - # - _fromUTF8(tk_call_without_enc('console', 'eval', - _get_eval_enc_str(tcl_script))) - end - def self.maininterp_eval(tcl_script) - # - # supports a Tcl script only - # I have no idea to support a Ruby script seamlessly. - # - _fromUTF8(tk_call_without_enc('consoleinterp', 'eval', - _get_eval_enc_str(tcl_script))) - - end - def self.maininterp_record(tcl_script) - # - # supports a Tcl script only - # I have no idea to support a Ruby script seamlessly. - # - _fromUTF8(tk_call_without_enc('consoleinterp', 'record', - _get_eval_enc_str(tcl_script))) - - end -end diff --git a/ext/tk/lib/tk/dialog.rb b/ext/tk/lib/tk/dialog.rb deleted file mode 100644 index 0b19be7cfa..0000000000 --- a/ext/tk/lib/tk/dialog.rb +++ /dev/null @@ -1,327 +0,0 @@ -# frozen_string_literal: false -# -# tk/dialog.rb : create dialog boxes -# -require 'tk' -require 'tk/variable.rb' - -class TkDialogObj < TkWindow - extend Tk - - TkCommandNames = ['tk_dialog'.freeze].freeze - - def self.show(*args) - dlog = self.new(*args) - dlog.show - dlog - end - - def _set_button_config(configs) - set_config = proc{|c,i| - if $VERBOSE && (c.has_key?('command') || c.has_key?(:command)) - STDERR.print("Warning: cannot give a command option " + - "to the dialog button#{i}. It was removed.\n") - end - c.delete('command'); c.delete(:command) - # @config << Kernel.format("%s.button%s configure %s; ", - # @path, i, hash_kv(c).join(' ')) - # @config << @path+'.button'+i.to_s+' configure '+hash_kv(c).join(' ')+'; ' - @config << @path+'.button'+i.to_s+' configure '+ - array2tk_list(hash_kv(c))+'; ' - } - case configs - when Proc - @buttons.each_index{|i| - if (c = configs.call(i)).kind_of?(Hash) - set_config.call(c,i) - end - } - - when Array - @buttons.each_index{|i| - if (c = configs[i]).kind_of?(Hash) - set_config.call(c,i) - end - } - - when Hash - @buttons.each_with_index{|s,i| - if (c = configs[s]).kind_of?(Hash) - set_config.call(c,i) - end - } - end - # @config = 'after idle {' + @config + '};' if @config != "" - @config = array2tk_list(['after', 'idle', @config]) << ';' if @config != "" - end - private :_set_button_config - - # initialize tk_dialog - def create_self(keys) - # @var = TkVariable.new - @val = nil - - @title = title - - @message = message - @message_config = message_config - @msgframe_config = msgframe_config - - @bitmap = bitmap - @bitmap_config = message_config - - @default_button = default_button - - @buttons = buttons - @button_configs = proc{|num| button_configs(num)} - @btnframe_config = btnframe_config - - #@config = "puts [winfo children .w0000];" - @config = "" - - @command = prev_command - - if keys.kind_of?(Hash) - @title = keys['title'] if keys.key? 'title' - @message = keys['message'] if keys.key? 'message' - @bitmap = keys['bitmap'] if keys.key? 'bitmap' - # @bitmap = '{}' if @bitmap == nil || @bitmap == "" - @bitmap = '' unless @bitmap - @default_button = keys['default'] if keys.key? 'default' - @buttons = keys['buttons'] if keys.key? 'buttons' - - @command = keys['prev_command'] if keys.key? 'prev_command' - - @message_config = keys['message_config'] if keys.key? 'message_config' - @msgframe_config = keys['msgframe_config'] if keys.key? 'msgframe_config' - @bitmap_config = keys['bitmap_config'] if keys.key? 'bitmap_config' - @button_configs = keys['button_configs'] if keys.key? 'button_configs' - @btnframe_config = keys['btnframe_config'] if keys.key? 'btnframe_config' - end - - #if @title.include? ?\s - # @title = '{' + @title + '}' - #end - - if @buttons.kind_of?(Array) - _set_button_config(@buttons.collect{|cfg| - (cfg.kind_of? Array)? cfg[1]: nil}) - @buttons = @buttons.collect{|cfg| (cfg.kind_of? Array)? cfg[0]: cfg} - end - if @buttons.kind_of?(Hash) - _set_button_config(@buttons) - @buttons = @buttons.keys - end - @buttons = tk_split_simplelist(@buttons) if @buttons.kind_of?(String) - @buttons = [] unless @buttons -=begin - @buttons = @buttons.collect{|s| - if s.kind_of?(Array) - s = s.join(' ') - end - if s.include? ?\s - '{' + s + '}' - else - s - end - } -=end - - if @message_config.kind_of?(Hash) - # @config << Kernel.format("%s.msg configure %s;", - # @path, hash_kv(@message_config).join(' ')) - # @config << @path+'.msg configure '+hash_kv(@message_config).join(' ')+';' - @config << @path+'.msg configure '+ - array2tk_list(hash_kv(@message_config))+';' - end - - if @msgframe_config.kind_of?(Hash) - # @config << Kernel.format("%s.top configure %s;", - # @path, hash_kv(@msgframe_config).join(' ')) - # @config << @path+'.top configure '+hash_kv(@msgframe_config).join(' ')+';' - @config << @path+'.top configure '+ - array2tk_list(hash_kv(@msgframe_config))+';' - end - - if @btnframe_config.kind_of?(Hash) - # @config << Kernel.format("%s.bot configure %s;", - # @path, hash_kv(@btnframe_config).join(' ')) - # @config << @path+'.bot configure '+hash_kv(@btnframe_config).join(' ')+';' - @config << @path+'.bot configure '+ - array2tk_list(hash_kv(@btnframe_config))+';' - end - - if @bitmap_config.kind_of?(Hash) - # @config << Kernel.format("%s.bitmap configure %s;", - # @path, hash_kv(@bitmap_config).join(' ')) - # @config << @path+'.bitmap configure '+hash_kv(@bitmap_config).join(' ')+';' - @config << @path+'.bitmap configure '+ - array2tk_list(hash_kv(@bitmap_config))+';' - end - - _set_button_config(@button_configs) if @button_configs - end - private :create_self - - def show - # if @command.kind_of?(Proc) - if TkComm._callback_entry?(@command) - @command.call(self) - end - - if @default_button.kind_of?(String) - default_button = @buttons.index(@default_button) - else - default_button = @default_button - end - # default_button = '{}' if default_button == nil - default_button = '' if default_button == nil - #Tk.ip_eval('eval {global '+@var.id+';'+@config+ - # 'set '+@var.id+' [tk_dialog '+ - # @path+" "+@title+" {#{@message}} "+@bitmap+" "+ - # String(default_button)+" "+@buttons.join(' ')+']}') - Tk.ip_eval(@config) - # @val = Tk.ip_eval('tk_dialog ' + @path + ' ' + @title + - # ' {' + @message + '} ' + @bitmap + ' ' + - # String(default_button) + ' ' + @buttons.join(' ')).to_i - # @val = Tk.ip_eval(self.class::TkCommandNames[0] + ' ' + @path + ' ' + - # @title + ' {' + @message + '} ' + @bitmap + ' ' + - # String(default_button) + ' ' + @buttons.join(' ')).to_i - @val = Tk.ip_eval(array2tk_list([ - self.class::TkCommandNames[0], - @path, @title, @message, @bitmap, - String(default_button) - ].concat(@buttons))).to_i - end - - def value - # @var.value.to_i - @val - end - - def name - (@val)? @buttons[@val]: nil - end - - ############################################################ - # # - # following methods should be overridden for each dialog # - # # - ############################################################ - private - - def title - # returns a title string of the dialog window - return "DIALOG" - end - def message - # returns a message text to display on the dialog - return "MESSAGE" - end - def message_config - # returns a Hash {option=>value, ...} for the message text - return nil - end - def msgframe_config - # returns a Hash {option=>value, ...} for the message text frame - return nil - end - def bitmap - # returns a bitmap name or a bitmap file path - # (@ + path ; e.g. '@/usr/share/bitmap/sample.xbm') - return "info" - end - def bitmap_config - # returns nil or a Hash {option=>value, ...} for the bitmap - return nil - end - def default_button - # returns a default button's number or name - # if nil or null string, set no-default - return 0 - end - def buttons - #return "BUTTON1 BUTTON2" - return ["BUTTON1", "BUTTON2"] - end - def button_configs(num) - # returns nil / Proc / Array or Hash (see _set_button_config) - return nil - end - def btnframe_config - # returns nil or a Hash {option=>value, ...} for the button frame - return nil - end - def prev_command - # returns nil or a Proc - return nil - end -end -TkDialog2 = TkDialogObj - -# -# TkDialog : with showing at initialize -# -class TkDialog < TkDialogObj - def self.show(*args) - self.new(*args) - end - - def initialize(*args) - super(*args) - show - end -end - - -# -# dialog for warning -# -class TkWarningObj < TkDialogObj - def initialize(parent = nil, mes = nil) - if !mes - if parent.kind_of?(TkWindow) - mes = "" - else - mes = parent.to_s - parent = nil - end - end - super(parent, :message=>mes) - end - - def show(mes = nil) - mes_bup = @message - @message = mes if mes - ret = super() - @message = mes_bup - ret - end - - ####### - private - - def title - return "WARNING"; - end - def bitmap - return "warning"; - end - def default_button - return 0; - end - def buttons - return "OK"; - end -end -TkWarning2 = TkWarningObj - -class TkWarning < TkWarningObj - def self.show(*args) - self.new(*args) - end - def initialize(*args) - super(*args) - show - end -end diff --git a/ext/tk/lib/tk/encodedstr.rb b/ext/tk/lib/tk/encodedstr.rb deleted file mode 100644 index 9ca13b3d1a..0000000000 --- a/ext/tk/lib/tk/encodedstr.rb +++ /dev/null @@ -1,188 +0,0 @@ -# frozen_string_literal: false -# -# tk/encodedstr.rb : Tk::EncodedString class -# -require 'tk' - -########################################### -# string with Tcl's encoding -########################################### -module Tk - class EncodedString < String - Encoding = nil - - def self.subst_utf_backslash(str) - # str.gsub(/\\u([0-9A-Fa-f]{1,4})/){[$1.hex].pack('U')} - TclTkLib._subst_UTF_backslash(str) - end - def self.utf_backslash(str) - self.subst_utf_backslash(str) - end - - def self.subst_tk_backslash(str) - TclTkLib._subst_Tcl_backslash(str) - end - - def self.utf_to_backslash_sequence(str) - str.unpack('U*').collect{|c| - if c <= 0xFF # ascii character - c.chr - else - format('\u%X', c) - end - }.join('') - end - def self.utf_to_backslash(str) - self.utf_to_backslash_sequence(str) - end - - def self.to_backslash_sequence(str) - str.unpack('U*').collect{|c| - if c <= 0x1F # control character - case c - when 0x07; '\a' - when 0x08; '\b' - when 0x09; '\t' - when 0x0a; '\n' - when 0x0b; '\v' - when 0x0c; '\f' - when 0x0d; '\r' - else - format('\x%02X', c) - end - elsif c <= 0xFF # ascii character - c.chr - else - format('\u%X', c) - end - }.join('') - end - - def self.new_with_utf_backslash(str, enc = nil) - self.new('', enc).replace(self.subst_utf_backslash(str)) - end - - def self.new_without_utf_backslash(str, enc = nil) - self.new('', enc).replace(str) - end - - def initialize(str, enc = nil) - super(str) - # @encoding = ( enc || - # ((self.class::Encoding)? - # self.class::Encoding : Tk.encoding_system) ) - enc ||= (self.class::Encoding)? - self.class::Encoding : - ((Tk.encoding)? Tk.encoding : Tk.encoding_system) - if TkCore::WITH_ENCODING - unless encobj = Tk::Encoding::ENCODING_TABLE.get_obj(enc) - fail ArgumentError, "unsupported Tk encoding '#{enc}'" - end - self.force_encoding(encobj) - else - @encoding = enc - end - end - - if TkCore::WITH_ENCODING - alias encoding_obj encoding - alias __encoding encoding - def encoding - Tk::Encoding::ENCODING_TABLE.get_name(super()) - end - else - def encoding - @encoding - end - alias encoding_obj encoding - end - - if TkCore::WITH_ENCODING - # wrapper methods for compatibility - alias __instance_variable_get instance_variable_get - alias __instance_variable_set instance_variable_set - alias __instance_eval instance_eval - alias __instance_variables instance_variables - - def instance_variable_get(key) - if (key.to_s == '@encoding') - self.encoding - else - super(key) - end - end - - def instance_variable_set(key, value) - if (key.to_s == '@encoding') - if value - self.force_encoding(value) - else - self.force_encoding(Tk::Encoding::UNKNOWN) - end - value - else - super(key, value) - end - end - - def instance_eval(*args, &b) - old_enc = @encoding = self.encoding - - ret = super(*args, &b) - - if @encoding - if @encoding != old_enc - # modified by user - self.force_encoding(@encoding) - end - remove_instance_variable(:@encoding) - else - begin - remove_instance_variable(:@encoding) - # user sets to nil -> use current default - self.force_encoding(Tk.encoding) - rescue NameError - # removed by user -> ignore, because user don't use @encoding - end - end - ret - end - end - - def instance_variables - ret = super() - ret << :@encoding # fake !! - ret - end - end - # def Tk.EncodedString(str, enc = nil) - # Tk::EncodedString.new(str, enc) - # end - - ################################## - - class BinaryString < EncodedString - Encoding = 'binary'.freeze - end - # def Tk.BinaryString(str) - # Tk::BinaryString.new(str) - # end - - ################################## - - class UTF8_String < EncodedString - Encoding = 'utf-8'.freeze - def self.new(str) - super(self.subst_utf_backslash(str)) - end - - def to_backslash_sequence - Tk::EncodedString.utf_to_backslash_sequence(self) - end - alias to_backslash to_backslash_sequence - end - # def Tk.UTF8_String(str) - # Tk::UTF8_String.new(str) - # end - -end diff --git a/ext/tk/lib/tk/entry.rb b/ext/tk/lib/tk/entry.rb deleted file mode 100644 index aa40e4755c..0000000000 --- a/ext/tk/lib/tk/entry.rb +++ /dev/null @@ -1,121 +0,0 @@ -# frozen_string_literal: false -# -# tk/entry.rb - Tk entry classes -# by Yukihiro Matsumoto <matz@caelum.co.jp> - -require 'tk' -require 'tk/label' -require 'tk/scrollable' -require 'tk/validation' - -class Tk::Entry<Tk::Label - include X_Scrollable - include TkValidation - - TkCommandNames = ['entry'.freeze].freeze - WidgetClassName = 'Entry'.freeze - WidgetClassNames[WidgetClassName] ||= self - - #def create_self(keys) - # super(__conv_vcmd_on_hash_kv(keys)) - #end - #private :create_self - - def __strval_optkeys - super() + ['show', 'disabledbackground', 'readonlybackground'] - end - private :__strval_optkeys - - def bbox(index) - list(tk_send_without_enc('bbox', index)) - end - def cursor - number(tk_send_without_enc('index', 'insert')) - end - alias icursor cursor - def cursor=(index) - tk_send_without_enc('icursor', index) - #self - index - end - alias icursor= cursor= - def index(idx) - number(tk_send_without_enc('index', idx)) - end - def insert(pos,text) - tk_send_without_enc('insert', pos, _get_eval_enc_str(text)) - self - end - def delete(first, last=None) - tk_send_without_enc('delete', first, last) - self - end - def mark(pos) - tk_send_without_enc('scan', 'mark', pos) - self - end - def dragto(pos) - tk_send_without_enc('scan', 'dragto', pos) - self - end - def selection_adjust(index) - tk_send_without_enc('selection', 'adjust', index) - self - end - def selection_clear - tk_send_without_enc('selection', 'clear') - self - end - def selection_from(index) - tk_send_without_enc('selection', 'from', index) - self - end - def selection_present() - bool(tk_send_without_enc('selection', 'present')) - end - def selection_range(s, e) - tk_send_without_enc('selection', 'range', s, e) - self - end - def selection_to(index) - tk_send_without_enc('selection', 'to', index) - self - end - - def invoke_validate - bool(tk_send_without_enc('validate')) - end - def validate(mode = nil) - if mode - configure 'validate', mode - else - invoke_validate - end - end - - def value - _fromUTF8(tk_send_without_enc('get')) - end - def value= (val) - tk_send_without_enc('delete', 0, 'end') - tk_send_without_enc('insert', 0, _get_eval_enc_str(val)) - val - end - alias get value - alias set value= - - def [](*args) - self.value[*args] - end - def []=(*args) - val = args.pop - str = self.value - str[*args] = val - self.value = str - val - end -end - -#TkEntry = Tk::Entry unless Object.const_defined? :TkEntry -#Tk.__set_toplevel_aliases__(:Tk, Tk::Entry, :TkEntry) -Tk.__set_loaded_toplevel_aliases__('tk/entry.rb', :Tk, Tk::Entry, :TkEntry) diff --git a/ext/tk/lib/tk/event.rb b/ext/tk/lib/tk/event.rb deleted file mode 100644 index 5658e92874..0000000000 --- a/ext/tk/lib/tk/event.rb +++ /dev/null @@ -1,563 +0,0 @@ -# frozen_string_literal: false -# -# tk/event.rb - module for event -# - -module TkEvent -end - -######################## - -require 'tkutil' -require 'tk' unless Object.const_defined? :TkComm - -######################## - -module TkEvent - class Event < TkUtil::CallbackSubst - module Grp - KEY = 0x1 - BUTTON = 0x2 - MOTION = 0x4 - CROSSING = 0x8 - FOCUS = 0x10 - EXPOSE = 0x20 - VISIBILITY = 0x40 - CREATE = 0x80 - DESTROY = 0x100 - UNMAP = 0x200 - MAP = 0x400 - REPARENT = 0x800 - CONFIG = 0x1000 - GRAVITY = 0x2000 - CIRC = 0x4000 - PROP = 0x8000 - COLORMAP = 0x10000 - VIRTUAL = 0x20000 - ACTIVATE = 0x40000 - MAPREQ = 0x80000 - CONFIGREQ = 0x100000 - RESIZEREQ = 0x200000 - CIRCREQ = 0x400000 - - MWHEEL = KEY - - STRING_DATA = 0x80000000 # special flag for 'data' field - - ALL = 0xFFFFFFFF - - KEY_BUTTON_MOTION_VIRTUAL = (KEY|MWHEEL|BUTTON|MOTION|VIRTUAL) - KEY_BUTTON_MOTION_CROSSING = (KEY|MWHEEL|BUTTON|MOTION|CROSSING|VIRTUAL) - end - - type_data = [ - #-----+-------------------+------------------+-----------------------# - # ID | const | group_flag | context_name # - #-----+-------------------+------------------+-----------------------# - [ 2, :KeyPress, Grp::KEY, 'KeyPress', 'Key' ], - [ 3, :KeyRelease, Grp::KEY, 'KeyRelease' ], - [ 4, :ButtonPress, Grp::BUTTON, 'ButtonPress', 'Button' ], - [ 5, :ButtonRelease, Grp::BUTTON, 'ButtonRelease' ], - [ 6, :MotionNotify, Grp::MOTION, 'Motion' ], - [ 7, :EnterNotify, Grp::CROSSING, 'Enter' ], - [ 8, :LeaveNotify, Grp::CROSSING, 'Leave' ], - [ 9, :FocusIn, Grp::FOCUS, 'FocusIn' ], - [ 10, :FocusOut, Grp::FOCUS, 'FocusOut' ], - [ 11, :KeymapNotify, 0, ], - [ 12, :Expose, Grp::EXPOSE, 'Expose' ], - [ 13, :GraphicsExpose, Grp::EXPOSE, ], - [ 14, :NoExpose, 0, ], - [ 15, :VisibilityNotify, Grp::VISIBILITY, 'Visibility' ], - [ 16, :CreateNotify, Grp::CREATE, 'Create' ], - [ 17, :DestroyNotify, Grp::DESTROY, 'Destroy' ], - [ 18, :UnmapNotify, Grp::UNMAP, 'Unmap' ], - [ 19, :MapNotify, Grp::MAP, 'Map' ], - [ 20, :MapRequest, Grp::MAPREQ, 'MapRequest' ], - [ 21, :ReparentNotify, Grp::REPARENT, 'Reparent' ], - [ 22, :ConfigureNotify, Grp::CONFIG, 'Configure' ], - [ 23, :ConfigureRequest, Grp::CONFIGREQ, 'ConfigureRequest' ], - [ 24, :GravityNotify, Grp::GRAVITY, 'Gravity' ], - [ 25, :ResizeRequest, Grp::RESIZEREQ, 'ResizeRequest' ], - [ 26, :CirculateNotify, Grp::CIRC, 'Circulate' ], - [ 27, :CirculateRequest, 0, 'CirculateRequest' ], - [ 28, :PropertyNotify, Grp::PROP, 'Property' ], - [ 29, :SelectionClear, 0, ], - [ 30, :SelectionRequest, 0, ], - [ 31, :SelectionNotify, 0, ], - [ 32, :ColormapNotify, Grp::COLORMAP, 'Colormap' ], - [ 33, :ClientMessage, 0, ], - [ 34, :MappingNotify, 0, ], - [ 35, :VirtualEvent, Grp::VIRTUAL, ], - [ 36, :ActivateNotify, Grp::ACTIVATE, 'Activate' ], - [ 37, :DeactivateNotify, Grp::ACTIVATE, 'Deactivate' ], - [ 38, :MouseWheelEvent, Grp::MWHEEL, 'MouseWheel' ], - [ 39, :TK_LASTEVENT, 0, ] - ] - - module TypeNum - end - - TYPE_NAME_TBL = Hash.new - TYPE_ID_TBL = Hash.new - TYPE_GROUP_TBL = Hash.new - - type_data.each{|id, c_name, g_flag, *t_names| - TypeNum.const_set(c_name, id) - t_names.each{|t_name| t_name.freeze; TYPE_NAME_TBL[t_name] = id } - TYPE_ID_TBL[id] = t_names - TYPE_GROUP_TBL[id] = g_flag - } - - TYPE_NAME_TBL.freeze - TYPE_ID_TBL.freeze - - def self.type_id(name) - TYPE_NAME_TBL[name.to_s] - end - - def self.type_name(id) - TYPE_ID_TBL[id] && TYPE_ID_TBL[id][0] - end - - def self.group_flag(id) - TYPE_GROUP_TBL[id] || 0 - end - - ############################################# - - module StateMask - ShiftMask = (1<<0) - LockMask = (1<<1) - ControlMask = (1<<2) - Mod1Mask = (1<<3) - Mod2Mask = (1<<4) - Mod3Mask = (1<<5) - Mod4Mask = (1<<6) - Mod5Mask = (1<<7) - Button1Mask = (1<<8) - Button2Mask = (1<<9) - Button3Mask = (1<<10) - Button4Mask = (1<<11) - Button5Mask = (1<<12) - - AnyModifier = (1<<15) - - META_MASK = (AnyModifier<<1) - ALT_MASK = (AnyModifier<<2) - EXTENDED_MASK = (AnyModifier<<3) - - CommandMask = Mod1Mask - OptionMask = Mod2Mask - end - - ############################################# - - FIELD_FLAG = { - # key => flag - 'above' => Grp::CONFIG, - 'borderwidth' => (Grp::CREATE|Grp::CONFIG), - 'button' => Grp::BUTTON, - 'count' => Grp::EXPOSE, - 'data' => (Grp::VIRTUAL|Grp::STRING_DATA), - 'delta' => Grp::MWHEEL, - 'detail' => (Grp::FOCUS|Grp::CROSSING), - 'focus' => Grp::CROSSING, - 'height' => (Grp::EXPOSE|Grp::CONFIG), - 'keycode' => Grp::KEY, - 'keysym' => Grp::KEY, - 'mode' => (Grp::CROSSING|Grp::FOCUS), - 'override' => (Grp::CREATE|Grp::MAP|Grp::REPARENT|Grp::CONFIG), - 'place' => Grp::CIRC, - 'root' => (Grp::KEY_BUTTON_MOTION_VIRTUAL|Grp::CROSSING), - 'rootx' => (Grp::KEY_BUTTON_MOTION_VIRTUAL|Grp::CROSSING), - 'rooty' => (Grp::KEY_BUTTON_MOTION_VIRTUAL|Grp::CROSSING), - 'sendevent' => Grp::ALL, - 'serial' => Grp::ALL, - 'state' => (Grp::KEY_BUTTON_MOTION_VIRTUAL| - Grp::CROSSING|Grp::VISIBILITY), - 'subwindow' => (Grp::KEY_BUTTON_MOTION_VIRTUAL|Grp::CROSSING), - 'time' => (Grp::KEY_BUTTON_MOTION_VIRTUAL|Grp::CROSSING| - Grp::PROP), - 'warp' => Grp::KEY_BUTTON_MOTION_VIRTUAL, - 'width' => (Grp::EXPOSE|Grp::CREATE|Grp::CONFIG), - 'window' => (Grp::CREATE|Grp::UNMAP|Grp::MAP|Grp::REPARENT| - Grp::CONFIG|Grp::GRAVITY|Grp::CIRC), - 'when' => Grp::ALL, - 'x' => (Grp::KEY_BUTTON_MOTION_VIRTUAL|Grp::CROSSING| - Grp::EXPOSE|Grp::CREATE|Grp::CONFIG|Grp::GRAVITY| - Grp::REPARENT), - 'y' => (Grp::KEY_BUTTON_MOTION_VIRTUAL|Grp::CROSSING| - Grp::EXPOSE|Grp::CREATE|Grp::CONFIG|Grp::GRAVITY| - Grp::REPARENT), - } - - FIELD_OPERATION = { - 'root' => proc{|val| - begin - Tk.tk_call_without_enc('winfo', 'pathname', val) - val - rescue - nil - end - }, - - 'subwindow' => proc{|val| - begin - Tk.tk_call_without_enc('winfo', 'pathname', val) - val - rescue - nil - end - }, - - 'window' => proc{|val| nil} - } - - #------------------------------------------- - - def valid_fields(group_flag=nil) - group_flag = self.class.group_flag(self.type) unless group_flag - - fields = {} - FIELD_FLAG.each{|key, flag| - next if (flag & group_flag) == 0 - begin - val = self.__send__(key) - rescue - next - end - # next if !val || val == '??' - next if !val || (val == '??' && (flag & Grp::STRING_DATA)) - fields[key] = val - } - - fields - end - - def valid_for_generate(group_flag=nil) - fields = valid_fields(group_flag) - - FIELD_OPERATION.each{|key, cmd| - next unless fields.has_key?(key) - val = FIELD_OPERATION[key].call(fields[key]) - if val - fields[key] = val - else - fields.delete(key) - end - } - - fields - end - - def generate(win, modkeys={}) - klass = self.class - - if modkeys.has_key?(:type) || modkeys.has_key?('type') - modkeys = TkComm._symbolkey2str(modkeys) - type_id = modkeys.delete('type') - else - type_id = self.type - end - - type_name = klass.type_name(type_id) - unless type_name - fail RuntimeError, "type_id #{type_id} is invalid" - end - - group_flag = klass.group_flag(type_id) - - opts = valid_for_generate(group_flag) - - modkeys.each{|key, val| - if val - opts[key.to_s] = val - else - opts.delete(key.to_s) - end - } - - if group_flag != Grp::KEY - Tk.event_generate(win, type_name, opts) - else - # If type is KEY event, focus should be set to target widget. - # If not set, original widget will get the same event. - # That will make infinite loop. - w = Tk.tk_call_without_enc('focus') - begin - Tk.tk_call_without_enc('focus', win) - Tk.event_generate(win, type_name, opts) - ensure - Tk.tk_call_without_enc('focus', w) - end - end - end - - ############################################# - - # [ <'%' subst-key char>, <proc type char>, <instance var (accessor) name>] - KEY_TBL = [ - [ ?#, ?n, :serial ], - [ ?a, ?s, :above ], - [ ?b, ?n, :num ], - [ ?c, ?n, :count ], - [ ?d, ?s, :detail ], - # ?e - [ ?f, ?b, :focus ], - # ?g - [ ?h, ?n, :height ], - [ ?i, ?s, :win_hex ], - # ?j - [ ?k, ?n, :keycode ], - # ?l - [ ?m, ?s, :mode ], - # ?n - [ ?o, ?b, :override ], - [ ?p, ?s, :place ], - # ?q - # ?r - [ ?s, ?x, :state ], - [ ?t, ?n, :time ], - # ?u - [ ?v, ?n, :value_mask ], - [ ?w, ?n, :width ], - [ ?x, ?n, :x ], - [ ?y, ?n, :y ], - # ?z - [ ?A, ?s, :char ], - [ ?B, ?n, :borderwidth ], - # ?C - [ ?D, ?n, :wheel_delta ], - [ ?E, ?b, :send_event ], - # ?F - # ?G - # ?H - # ?I - # ?J - [ ?K, ?s, :keysym ], - # ?L - # ?M - [ ?N, ?n, :keysym_num ], - # ?O - [ ?P, ?s, :property ], - # ?Q - [ ?R, ?s, :rootwin_id ], - [ ?S, ?s, :subwindow ], - [ ?T, ?n, :type ], - # ?U - # ?V - [ ?W, ?w, :widget ], - [ ?X, ?n, :x_root ], - [ ?Y, ?n, :y_root ], - # ?Z - nil - ] - - # [ <'%' subst-key str>, <proc type char>, <instance var (accessor) name>] - # the subst-key string will be converted to a bytecode (128+idx). - LONGKEY_TBL = [ - # for example, for %CTT and %CST subst-key on tkdnd-2.0 - # ['CTT', ?l, :drop_target_type], - # ['CST', ?l, :drop_source_type], - ] - - # [ <proc type char>, <proc/method to convert tcl-str to ruby-obj>] - PROC_TBL = [ - [ ?n, TkComm.method(:num_or_str) ], - [ ?s, TkComm.method(:string) ], - [ ?b, TkComm.method(:bool) ], - [ ?w, TkComm.method(:window) ], - - [ ?x, proc{|val| - begin - TkComm::number(val) - rescue ArgumentError - val - end - } - ], - - nil - ] - -=begin - # for Ruby m17n :: ?x --> String --> char-code ( getbyte(0) ) - KEY_TBL.map!{|inf| - if inf.kind_of?(Array) - inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String) - inf[1] = inf[1].getbyte(0) if inf[1].kind_of?(String) - end - inf - } - - PROC_TBL.map!{|inf| - if inf.kind_of?(Array) - inf[0] = inf[0].getbyte(0) if inf[0].kind_of?(String) - end - inf - } -=end - - # setup tables to be used by scan_args, _get_subst_key, _get_all_subst_keys - # - # _get_subst_key() and _get_all_subst_keys() generates key-string - # which describe how to convert callback arguments to ruby objects. - # When binding parameters are given, use _get_subst_key(). - # But when no parameters are given, use _get_all_subst_keys() to - # create a Event class object as a callback parameter. - # - # scan_args() is used when doing callback. It convert arguments - # ( which are Tcl strings ) to ruby objects based on the key string - # that is generated by _get_subst_key() or _get_all_subst_keys(). - # - _setup_subst_table(KEY_TBL, PROC_TBL) - # _setup_subst_table(KEY_TBL, LONGKEY_TBL, PROC_TBL) # if use longname-keys - - # - # NOTE: The order of parameters which passed to callback procedure is - # <extra_arg>, <extra_arg>, ... , <subst_arg>, <subst_arg>, ... - # - - # If you need support extra arguments given by Tcl/Tk, - # please override _get_extra_args_tbl - # - #def self._get_extra_args_tbl - # # return an array of convert procs - # [] - #end - -=begin - alias button num - alias delta wheel_delta - alias root rootwin_id - alias rootx x_root - alias root_x x_root - alias rooty y_root - alias root_y y_root - alias sendevent send_event -=end - ALIAS_TBL = { - :button => :num, - :data => :detail, - :delta => :wheel_delta, - :root => :rootwin_id, - :rootx => :x_root, - :root_x => :x_root, - :rooty => :y_root, - :root_y => :y_root, - :sendevent => :send_event, - :window => :widget - } - - _define_attribute_aliases(ALIAS_TBL) - - end - - ############################################### - - def install_bind_for_event_class(klass, cmd, *args) - extra_args_tbl = klass._get_extra_args_tbl - - if args.compact.size > 0 - args.map!{|arg| klass._sym2subst(arg)} - args = args.join(' ') - keys = klass._get_subst_key(args) - - if cmd.kind_of?(String) - id = cmd - elsif cmd.kind_of?(TkCallbackEntry) - id = install_cmd(cmd) - else - id = install_cmd(proc{|*arg| - ex_args = [] - extra_args_tbl.reverse_each{|conv| ex_args << conv.call(arg.pop)} - begin - TkUtil.eval_cmd(cmd, *(ex_args.concat(klass.scan_args(keys, arg)))) - rescue Exception=>e - if TkCore::INTERP.kind_of?(TclTkIp) - fail e - else - # MultiTkIp - fail Exception, "#{e.class}: #{e.message.dup}" - end - end - }) - end - elsif cmd.respond_to?(:arity) && cmd.arity == 0 # args.size == 0 - args = '' - if cmd.kind_of?(String) - id = cmd - elsif cmd.kind_of?(TkCallbackEntry) - id = install_cmd(cmd) - else - id = install_cmd(proc{ - begin - TkUtil.eval_cmd(cmd) - rescue Exception=>e - if TkCore::INTERP.kind_of?(TclTkIp) - fail e - else - # MultiTkIp - fail Exception, "#{e.class}: #{e.message.dup}" - end - end - }) - end - else - keys, args = klass._get_all_subst_keys - - if cmd.kind_of?(String) - id = cmd - elsif cmd.kind_of?(TkCallbackEntry) - id = install_cmd(cmd) - else - id = install_cmd(proc{|*arg| - ex_args = [] - extra_args_tbl.reverse_each{|conv| ex_args << conv.call(arg.pop)} - begin - TkUtil.eval_cmd(cmd, *(ex_args << klass.new(*klass.scan_args(keys, arg)))) - rescue Exception=>e - if TkCore::INTERP.kind_of?(TclTkIp) - fail e - else - # MultiTkIp - fail Exception, "#{e.class}: #{e.message.dup}" - end - end - }) - end - end - - if TkCore::INTERP.kind_of?(TclTkIp) - id + ' ' + args - else - # MultiTkIp - "if {[set st [catch {#{id} #{args}} ret]] != 0} { - if {$st == 4} { - return -code continue $ret - } elseif {$st == 3} { - return -code break $ret - } elseif {$st == 2} { - return -code return $ret - } elseif {[regexp {^Exception: (TkCallbackContinue: .*)$} \ - $ret m msg]} { - return -code continue $msg - } elseif {[regexp {^Exception: (TkCallbackBreak: .*)$} $ret m msg]} { - return -code break $msg - } elseif {[regexp {^Exception: (TkCallbackReturn: .*)$} $ret m msg]} { - return -code return $msg - } elseif {[regexp {^Exception: (\\S+: .*)$} $ret m msg]} { - return -code return $msg - } else { - return -code error $ret - } - } else { - set ret - }" - end - end - - def install_bind(cmd, *args) - install_bind_for_event_class(TkEvent::Event, cmd, *args) - end -end diff --git a/ext/tk/lib/tk/font.rb b/ext/tk/lib/tk/font.rb deleted file mode 100644 index 6ae46ebb8e..0000000000 --- a/ext/tk/lib/tk/font.rb +++ /dev/null @@ -1,2352 +0,0 @@ -# frozen_string_literal: false -# -# tk/font.rb - the class to treat fonts on Ruby/Tk -# -# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) -# -require 'tk' - -class TkFont - include Tk - extend TkCore - - TkCommandNames = ['font'.freeze].freeze - - (Tk_FontID = ["@font".freeze, TkUtil.untrust("00000")]).instance_eval{ - @mutex = Mutex.new - def mutex; @mutex; end - freeze - } - - Tk_FontNameTBL = TkCore::INTERP.create_table - Tk_FontUseTBL = TkCore::INTERP.create_table - - TkCore::INTERP.init_ip_env{ - Tk_FontNameTBL.mutex.synchronize{ Tk_FontNameTBL.clear } - Tk_FontUseTBL.mutex.synchronize{ Tk_FontUseTBL.clear } - } - - # option_type : default => string - OptionType = Hash.new(?s) - OptionType['size'] = ?n - OptionType['pointadjust'] = ?n - OptionType['underline'] = ?b - OptionType['overstrike'] = ?b - - # metric_type : default => num_or_str - MetricType = Hash.new(?n) - MetricType['fixed'] = ?b - - # system font names - SYSTEM_FONT_NAMES = [] - def SYSTEM_FONT_NAMES.add(font_names) - (@mutex ||= Mutex.new).synchronize{ - self.replace(self | font_names.map{|name| name.to_s}) - } - end - def SYSTEM_FONT_NAMES.include?(name) - (@mutex ||= Mutex.new).synchronize{ - super(name.to_s) - } - end - - # set default font - case Tk::TK_VERSION - when /^4\..*/ - DEFAULT_LATIN_FONT_NAME = 'a14'.freeze - DEFAULT_KANJI_FONT_NAME = 'k14'.freeze - - when /^8\.[0-4]/ - if JAPANIZED_TK - begin - fontnames = tk_call('font', 'names') - case fontnames - when /defaultgui/ - # Tcl/Tk-JP for Windows - ltn = 'defaultgui' - knj = 'defaultgui' - when /Mincho:Helvetica-Bold-12/ - # Tcl/Tk-JP for UNIX/X - ltn, knj = tk_split_simplelist(tk_call('font', 'configure', - 'Mincho:Helvetica-Bold-12', - '-compound')) - else - # unknown Tcl/Tk-JP - #platform = tk_call('set', 'tcl_platform(platform)') - platform = Tk::PLATFORM['platform'] - case platform - when 'unix' - ltn = {'family'=>'Helvetica'.freeze, - 'size'=>-12, 'weight'=>'bold'.freeze} - #knj = 'k14' - #knj = '-misc-fixed-medium-r-normal--14-*-*-*-c-*-jisx0208.1983-0' - knj = '-*-fixed-bold-r-normal--12-*-*-*-c-*-jisx0208.1983-0' - when 'windows' - ltn = {'family'=>'MS Sans Serif'.freeze, 'size'=>8} - knj = 'mincho' - when 'macintosh' - ltn = 'system' - knj = 'mincho' - else # unknown - ltn = 'Helvetica' - knj = 'mincho' - end - end - rescue - ltn = 'Helvetica' - knj = 'mincho' - end - - else # not JAPANIZED_TK - begin - #platform = tk_call('set', 'tcl_platform(platform)') - platform = Tk::PLATFORM['platform'] - case platform - when 'unix' - ltn = {'family'=>'Helvetica'.freeze, - 'size'=>-12, 'weight'=>'bold'.freeze} - when 'windows' - ltn = {'family'=>'MS Sans Serif'.freeze, 'size'=>8} - when 'macintosh' - ltn = 'system' - else # unknown - ltn = 'Helvetica' - end - rescue - ltn = 'Helvetica' - end - - knj = ltn.dup - end - - DEFAULT_LATIN_FONT_NAME = ltn.freeze - DEFAULT_KANJI_FONT_NAME = knj.freeze - - when /^8\.[5-9]/, /^9\..*/ - if tk_call('font', 'names') =~ /\bTkDefaultFont\b/ - DEFAULT_LATIN_FONT_NAME = 'TkDefaultFont'.freeze - DEFAULT_KANJI_FONT_NAME = 'TkDefaultFont'.freeze - else - DEFAULT_LATIN_FONT_NAME = 'Helvetica'.freeze - DEFAULT_KANJI_FONT_NAME = 'mincho'.freeze - end - - else # unknown version - DEFAULT_LATIN_FONT_NAME = 'Helvetica'.freeze - DEFAULT_KANJI_FONT_NAME = 'mincho'.freeze - - end - - if $DEBUG - print "default latin font = "; p DEFAULT_LATIN_FONT_NAME - print "default kanji font = "; p DEFAULT_KANJI_FONT_NAME - end - - - ################################### - class DescendantFont - def initialize(compound, type) - unless compound.kind_of?(TkFont) - fail ArgumentError, "a TkFont object is expected for the 1st argument" - end - - @compound = compound - case type - when 'kanji', 'latin', 'ascii' - @type = type - when :kanji, :latin, :ascii - @type = type.to_s - else - fail ArgumentError, "unknown type '#{type}'" - end - end - - def dup - fail RuntimeError, "cannot duplicate a descendant font" - end - def clone - fail RuntimeError, "cannot clone a descendant font" - end - - def to_eval - @compound.__send__(@type + '_font_id') - end - def font - @compound.__send__(@type + '_font_id') - end - alias font_id font - alias name font - alias to_s font - - def [](slot) - @compound.__send__(@type + '_configinfo', slot) - end - def []=(slot, value) - @compound.__send__(@type + '_configure', slot, value) - value - end - - def method_missing(id, *args) - @compound.__send__(@type + '_' + id.id2name, *args) - end - end - - - ################################### - # class methods - ################################### - def TkFont.is_system_font?(fnt) - # true --> system font which is available on the current system - # false --> not system font (or unknown system font) - # nil --> system font name, but not available on the current system - fnt = fnt.to_s - SYSTEM_FONT_NAMES.include?(fnt) && self.names.index(fnt) && true - end - - def TkFont.actual(fnt, option=nil) - fnt = '{}' if fnt == '' - if fnt.kind_of?(TkFont) - fnt.actual(option) - else - actual_core(fnt, nil, option) - end - end - def TkFont.actual_hash(fnt, option=nil) - Hash[TkFont.actual(fnt, option)] - end - - def TkFont.actual_displayof(fnt, win, option=nil) - fnt = '{}' if fnt == '' - if fnt.kind_of?(TkFont) - fnt.actual_displayof(win, option) - else - win = '.' unless win - actual_core(fnt, win, option) - end - end - def TkFont.actual_hash_displayof(fnt, option=nil) - Hash[TkFont.actual_displayof(fnt, option)] - end - - def TkFont.configure(fnt, slot, value=None) - if fnt.kind_of?(TkFont) - fnt.configure(fnt, slot, value) - else - configure_core(fnt, slot, value) - end - fnt - end - - def TkFont.configinfo(fnt, slot=nil) - if fnt.kind_of?(TkFont) - fnt.configinfo(fnt, slot) - else - configinfo_core(fnt, slot) - end - end - - def TkFont.current_configinfo(fnt, slot=nil) - if fnt.kind_of?(TkFont) - fnt.current_configinfo(fnt, slot) - else - current_configinfo_core(fnt, slot) - end - end - - def TkFont.measure(fnt, text) - fnt = '{}' if fnt == '' - if fnt.kind_of?(TkFont) - fnt.measure(text) - else - measure_core(fnt, nil, text) - end - end - - def TkFont.measure_displayof(fnt, win, text) - fnt = '{}' if fnt == '' - if fnt.kind_of?(TkFont) - fnt.measure_displayof(win, text) - else - win = '.' unless win - measure_core(fnt, win, text) - end - end - - def TkFont.metrics(fnt, option=nil) - fnt = '{}' if fnt == '' - if fnt.kind_of?(TkFont) - fnt.metrics(option) - else - metrics_core(fnt, nil, option) - end - end - def TkFont.metrics_hash(fnt, option=nil) - if option - val = TkFont.metrics(fnt, option) - case TkFont::MetricsType[option.to_s] - when ?n - val = TkComm::num_or_str(val) - when ?b - val = TkComm::bool(val) - else - # do nothing - end - return val - end - - h = Hash[TkFont.metrics(fnt)] - h.keys.each{|k| - case TkFont::MetricsType[k.to_s] - when ?n - h[k] = TkComm::num_or_str(h[k]) - when ?b - h[k] = TkComm::bool(h[k]) - else - # do nothing - end - } - h - end - - def TkFont.metrics_displayof(fnt, win, option=nil) - fnt = '{}' if fnt == '' - if fnt.kind_of?(TkFont) - font.metrics_displayof(win, option=nil) - else - win = '.' unless win - metrics_core(fnt, win, option) - end - end - def TkFont.metrics_hash_displayof(fnt, win, option=nil) - if option - val = TkFont.metrics_displayof(fnt, win, option) - case TkFont::MetricsType[option.to_s] - when ?n - val = TkComm::num_or_str(val) - when ?b - val = TkComm::bool(val) - else - # do nothing - end - return val - end - - h = Hash[TkFont.metrics_displayof(fnt, win, option)] - h.keys.each{|k| - case TkFont::MetricsType[k.to_s] - when ?n - h[k] = TkComm::num_or_str(h[k]) - when ?b - h[k] = TkComm::bool(h[k]) - else - # do nothing - end - } - h - end - - def TkFont.families(win=nil) - case (Tk::TK_VERSION) - when /^4\..*/ - ['fixed'] - - when /^8\..*/ - if win - tk_split_simplelist(tk_call('font', 'families', '-displayof', win)) - else - tk_split_simplelist(tk_call('font', 'families')) - end - end - end - - def TkFont.names - case (Tk::TK_VERSION) - when /^4\..*/ - r = ['fixed'] - r += ['a14', 'k14'] if JAPANIZED_TK - Tk_FontNameTBL.mutex.synchronize{ - Tk_FontNameTBL.each_value{|obj| r.push(obj)} - } - #r | [] - r.uniq - - when /^8\..*/ - tk_split_simplelist(tk_call('font', 'names')) - - end - end - - def TkFont.create_copy(font) - fail 'source-font must be a TkFont object' unless font.kind_of? TkFont - if TkComm::GET_CONFIGINFOwoRES_AS_ARRAY - keys = {} - font.configinfo.each{|key,value| keys[key] = value } - TkFont.new(font.latin_font_id, font.kanji_font_id, keys) - else # ! TkComm::GET_CONFIGINFOwoRES_AS_ARRAY - TkFont.new(font.latin_font_id, font.kanji_font_id, font.configinfo) - end - end - - def TkFont.get_obj(name) - name = name.to_s - if name =~ /^(@font[0-9]+)(|c|l|k)$/ - Tk_FontNameTBL.mutex.synchronize{ - Tk_FontNameTBL[$1] - } - else - Tk_FontNameTBL.mutex.synchronize{ - Tk_FontNameTBL[name] - } - end - end - - def TkFont.init_widget_font(pathname, *args) - win, tag, key = pathname.split(';') - key = 'font' if key == nil || key == '' - path = [win, tag, key].join(';') - - case (Tk::TK_VERSION) - when /^4\..*/ - regexp = /^-(|kanji)#{key} / - - conf_list = tk_split_simplelist(tk_call(*args)). - find_all{|prop| prop =~ regexp}. - collect{|prop| tk_split_simplelist(prop)} - - if conf_list.size == 0 - raise RuntimeError, "the widget may not support 'font' option" - end - - args << {} - - ltn_key = "-#{key}" - knj_key = "-kanji#{key}" - - ltn_info = conf_list.find{|conf| conf[0] == ltn_key} - ltn = ltn_info[-1] - ltn = nil if ltn == [] || ltn == "" - - knj_info = conf_list.find{|conf| conf[0] == knj_key} - knj = knj_info[-1] - knj = nil if knj == [] || knj == "" - - TkFont.new(ltn, knj).call_font_configure([path, key], *args) - - when /^8\.[0-4]/ - regexp = /^-#{key} / - - conf_list = tk_split_simplelist(tk_call(*args)). - find_all{|prop| prop =~ regexp}. - collect{|prop| tk_split_simplelist(prop)} - - if conf_list.size == 0 - raise RuntimeError, "the widget may not support 'font' option" - end - - args << {} - - optkey = "-#{key}" - - info = conf_list.find{|conf| conf[0] == optkey} - fnt = info[-1] - fnt = nil if fnt == [] || fnt == "" - - unless fnt - # create dummy - # TkFont.new(nil, nil).call_font_configure([path, key], *args) - dummy_fnt = TkFont.allocate - dummy_fnt.instance_eval{ init_dummy_fontobj() } - dummy_fnt - else - begin - compound = tk_split_simplelist( - Hash[*tk_split_simplelist(tk_call('font', 'configure', - fnt))].collect{|k,v| - [k[1..-1], v] - }.assoc('compound')[1]) - rescue - compound = [] - end - if compound == [] - if TkFont.is_system_font?(fnt) - TkNamedFont.new(fnt).call_font_configure([path, key], *args) - else - TkFont.new(fnt).call_font_configure([path, key], *args) - end - else - TkFont.new(compound[0], - compound[1]).call_font_configure([path, key], *args) - end - end - - when /^8\.[5-9]/, /^9\..*/ - regexp = /^-#{key} / - - conf_list = tk_split_simplelist(tk_call(*args)). - find_all{|prop| prop =~ regexp}. - collect{|prop| tk_split_simplelist(prop)} - - if conf_list.size == 0 - raise RuntimeError, "the widget may not support 'font' option" - end - - args << {} - - optkey = "-#{key}" - - info = conf_list.find{|conf| conf[0] == optkey} - fnt = info[-1] - fnt = nil if fnt == [] || fnt == "" - - unless fnt - # create dummy - # TkFont.new(nil, nil).call_font_configure([path, key], *args) - dummy_fnt = TkFont.allocate - dummy_fnt.instance_eval{ init_dummy_fontobj() } - dummy_fnt - else - if TkFont.is_system_font?(fnt) - TkNamedFont.new(fnt).call_font_configure([path, key], *args) - else - TkFont.new(fnt).call_font_configure([path, key], *args) - end - end - end - end - - def TkFont.used_on(path=nil) - Tk_FontUseTBL.mutex.synchronize{ - if path - Tk_FontUseTBL[path] - else - # Tk_FontUseTBL.values | [] - Tk_FontUseTBL.values.uniq - end - } - end - - def TkFont.failsafe(font) - begin - if /^8\..*/ === Tk::TK_VERSION && JAPANIZED_TK - tk_call('font', 'failsafe', font) - end - rescue - end - end - - ################################### - # instance methods - ################################### - private - ################################### - def init_dummy_fontobj - Tk_FontID.mutex.synchronize{ - @id = Tk_FontID.join(TkCore::INTERP._ip_id_) - Tk_FontID[1].succ! - } - Tk_FontNameTBL.mutex.synchronize{ - Tk_FontNameTBL[@id] = self - } - - # @latin_desscendant = nil - # @kanji_desscendant = nil - @descendant = [nil, nil] # [latin, kanji] - - case (Tk::TK_VERSION) - when /^4\..*/ - @latinfont = "" - @kanjifont = "" - if JAPANIZED_TK - @compoundfont = [[@latinfont], [@kanjifont]] - @fontslot = {'font'=>@latinfont, 'kanjifont'=>@kanjifont} - else - @compoundfont = @latinfont - @fontslot = {'font'=>@latinfont} - end - else - @latinfont = @id + 'l' - @kanjifont = @id + 'k' - @compoundfont = @id + 'c' - - if JAPANIZED_TK - tk_call('font', 'create', @latinfont, '-charset', 'iso8859') - tk_call('font', 'create', @kanjifont, '-charset', 'jisx0208.1983') - tk_call('font', 'create', @compoundfont, - '-compound', [@latinfont, @kanjifont]) - else - tk_call('font', 'create', @latinfont) - tk_call('font', 'create', @kanjifont) - tk_call('font', 'create', @compoundfont) - end - - @fontslot = {'font'=>@compoundfont} - end - - self - end - - def initialize(ltn=nil, knj=nil, keys=nil) - ltn = '{}' if ltn == '' - knj = '{}' if knj == '' - - Tk_FontID.mutex.synchronize{ - # @id = Tk_FontID.join('') - @id = Tk_FontID.join(TkCore::INTERP._ip_id_) - Tk_FontID[1].succ! - } - Tk_FontNameTBL.mutex.synchronize{ - Tk_FontNameTBL[@id] = self - } - - # @latin_desscendant = nil - # @kanji_desscendant = nil - @descendant = [nil, nil] # [latin, kanji] - - # @latinfont = @id + 'l' - # @kanjifont = @id + 'k' - # @compoundfont = @id + 'c' - # @fontslot = {} - - if knj.kind_of?(Hash) && !keys - keys = knj - knj = nil - end - - # compound font check - if Tk::TK_VERSION == '8.0' && JAPANIZED_TK - begin - compound = tk_split_simplelist(tk_call('font', 'configure', - ltn, '-compound')) - if knj == nil - if compound != [] - ltn, knj = compound - end - else - if compound != [] - ltn = compound[0] - end - compound = tk_split_simplelist(tk_call('font', 'configure', - knj, '-compound')) - if compound != [] - knj = compound[1] - end - end - rescue - end - end - - if ltn - if JAPANIZED_TK && !knj - if Tk::TK_VERSION =~ /^4..*/ - knj = DEFAULT_KANJI_FONT_NAME - else - knj = ltn - end - end - else - ltn = DEFAULT_LATIN_FONT_NAME - knj = DEFAULT_KANJI_FONT_NAME if JAPANIZED_TK && !knj - end - - create_compoundfont(ltn, knj, keys) - end - - def initialize_copy(font) - unless font.kind_of?(TkFont) - fail TypeError, '"initialize_copy should take same class object' - end - if TkComm::GET_CONFIGINFOwoRES_AS_ARRAY - keys = {} - font.configinfo.each{|key,value| keys[key] = value } - initialize(font.latin_font_id, font.kanji_font_id, keys) - else # ! TkComm::GET_CONFIGINFOwoRES_AS_ARRAY - initialize(font.latin_font_id, font.kanji_font_id, font.configinfo) - end - end - - def _get_font_info_from_hash(font) - font = _symbolkey2str(font) - foundry = (info = font['foundry'] .to_s)? info: '*' - family = (info = font['family'] .to_s)? info: '*' - weight = (info = font['weight'] .to_s)? info: '*' - slant = (info = font['slant'] .to_s)? info: '*' - swidth = (info = font['swidth'] .to_s)? info: '*' - adstyle = (info = font['adstyle'] .to_s)? info: '*' - pixels = (info = font['pixels'] .to_s)? info: '*' - points = (info = font['points'] .to_s)? info: '*' - resx = (info = font['resx'] .to_s)? info: '*' - resy = (info = font['resy'] .to_s)? info: '*' - space = (info = font['space'] .to_s)? info: '*' - avgWidth = (info = font['avgWidth'].to_s)? info: '*' - charset = (info = font['charset'] .to_s)? info: '*' - encoding = (info = font['encoding'].to_s)? info: '*' - - [foundry, family, weight, slant, swidth, adstyle, - pixels, points, resx, resy, space, avgWidth, charset, encoding] - end - - def create_latinfont_tk4x(font) - if font.kind_of? Hash - @latinfont = '-' + _get_font_info_from_hash(font).join('-') + '-' - - elsif font.kind_of? Array - finfo = {} - finfo['family'] = font[0].to_s - if font[1] - fsize = font[1].to_s - if fsize != '0' && fsize =~ /^(|\+|-)([0-9]+)$/ - if $1 == '-' - finfo['pixels'] = $2 - else - finfo['points'] = $2 - end - else - finfo['points'] = '13' - end - end - font[2..-1].each{|style| - case (style) - when 'normal' - finfo['weight'] = style - when 'bold' - finfo['weight'] = style - when 'roman' - finfo['slant'] = 'r' - when 'italic' - finfo['slant'] = 'i' - end - } - - @latinfont = '-' + _get_font_info_from_hash(finfo).join('-') + '-' - - elsif font.kind_of? TkFont - @latinfont = font.latin_font - - else - if font - @latinfont = font - else - @latinfont = DEFAULT_LATIN_FONT_NAME - end - - end - end - - def create_kanjifont_tk4x(font) - unless JAPANIZED_TK - @kanjifont = "" - return - end - - if font.kind_of? Hash - @kanjifont = '-' + _get_font_info_from_hash(font).join('-') + '-' - - elsif font.kind_of? Array - finfo = {} - finfo['family'] = font[0].to_s - if font[1] - fsize = font[1].to_s - if fsize != '0' && fsize =~ /^(|\+|-)([0-9]+)$/ - if $1 == '-' - finfo['pixels'] = $2 - else - finfo['points'] = $2 - end - else - finfo['points'] = '13' - end - end - font[2..-1].each{|style| - case (style) - when 'normal' - finfo['weight'] = style - when 'bold' - finfo['weight'] = style - when 'roman' - finfo['slant'] = 'r' - when 'italic' - finfo['slant'] = 'i' - end - } - - @kanjifont = '-' + _get_font_info_from_hash(finfo).join('-') + '-' - elsif font.kind_of? TkFont - @kanjifont = font.kanji_font_id - else - if font - @kanjifont = font - else - @kanjifont = DEFAULT_KANJI_FONT_NAME - end - end - end - - def create_compoundfont_tk4x(ltn, knj, keys) - create_latinfont(ltn) - create_kanjifont(knj) - - if JAPANIZED_TK - @compoundfont = [[@latinfont], [@kanjifont]] - @fontslot = {'font'=>@latinfont, 'kanjifont'=>@kanjifont} - # @fontslot.clear - # @fontslot['font'] = @latinfont - # @fontslot['kanjifont'] = @kanjifont - else - @compoundfont = @latinfont - @fontslot = {'font'=>@latinfont} - # @fontslot.clear - # @fontslot['font'] = @latinfont - end - end - - def create_latinfont_tk8x(font) - @latinfont = @id + 'l' - - if JAPANIZED_TK - if font.kind_of? Hash - if font[:charset] || font['charset'] - tk_call('font', 'create', @latinfont, *hash_kv(font)) - else - tk_call('font', 'create', @latinfont, - '-charset', 'iso8859', *hash_kv(font)) - end - elsif font.kind_of? Array - tk_call('font', 'create', @latinfont, '-copy', array2tk_list(font)) - tk_call('font', 'configure', @latinfont, '-charset', 'iso8859') - elsif font.kind_of? TkFont - tk_call('font', 'create', @latinfont, '-copy', font.latin_font) - elsif font - tk_call('font', 'create', @latinfont, '-copy', font, - '-charset', 'iso8859') - else - tk_call('font', 'create', @latinfont, '-charset', 'iso8859') - end - else - if font.kind_of? Hash - tk_call('font', 'create', @latinfont, *hash_kv(font)) - else - keys = {} - if font.kind_of? Array - actual_core(array2tk_list(font)).each{|key,val| keys[key] = val} - elsif font.kind_of? TkFont - actual_core(font.latin_font).each{|key,val| keys[key] = val} - elsif font - actual_core(font).each{|key,val| keys[key] = val} - end - tk_call('font', 'create', @latinfont, *hash_kv(keys)) - end - - if font && @compoundfont - keys = {} - actual_core(@latinfont).each{|key,val| keys[key] = val} - tk_call('font', 'configure', @compoundfont, *hash_kv(keys)) - end - end - end - - def create_kanjifont_tk8x(font) - @kanjifont = @id + 'k' - - if JAPANIZED_TK - if font.kind_of? Hash - if font[:charset] || font['charset'] - tk_call('font', 'create', @kanjifont, *hash_kv(font)) - else - tk_call('font', 'create', @kanjifont, - '-charset', 'jisx0208.1983', *hash_kv(font)) - end - elsif font.kind_of? Array - tk_call('font', 'create', @kanjifont, '-copy', array2tk_list(font)) - tk_call('font', 'configure', @kanjifont, '-charset', 'jisx0208.1983') - elsif font.kind_of? TkFont - tk_call('font', 'create', @kanjifont, '-copy', font.kanji_font_id) - elsif font - tk_call('font', 'create', @kanjifont, '-copy', font, - '-charset', 'jisx0208.1983') - else - tk_call('font', 'create', @kanjifont, '-charset', 'jisx0208.1983') - end - # end of JAPANIZED_TK - - else - if font.kind_of? Hash - tk_call('font', 'create', @kanjifont, *hash_kv(font)) - else - keys = {} - if font.kind_of? Array - actual_core(array2tk_list(font)).each{|key,val| keys[key] = val} - elsif font.kind_of? TkFont - actual_core(font.kanji_font_id).each{|key,val| keys[key] = val} - elsif font - actual_core(font).each{|key,val| keys[key] = val} - end - tk_call('font', 'create', @kanjifont, *hash_kv(keys)) - end - - if font && @compoundfont - keys = {} - actual_core(@kanjifont).each{|key,val| keys[key] = val} - tk_call('font', 'configure', @compoundfont, *hash_kv(keys)) - end - end - end - - def create_compoundfont_tk8x(ltn, knj, keys) - if knj - create_latinfont(ltn) - create_kanjifont(knj) - else - cfnt = ltn - create_kanjifont(cfnt) - create_latinfont(cfnt) - end - - @compoundfont = @id + 'c' - - if JAPANIZED_TK - unless keys - keys = {} - else - keys = keys.dup - end - if (tk_call('font', 'configure', @latinfont, '-underline') == '1' && - tk_call('font', 'configure', @kanjifont, '-underline') == '1' && - !keys.key?('underline')) - keys['underline'] = true - end - if (tk_call('font', 'configure', @latinfont, '-overstrike') == '1' && - tk_call('font', 'configure', @kanjifont, '-overstrike') == '1' && - !keys.key?('overstrike')) - keys['overstrike'] = true - end - - @fontslot = {'font'=>@compoundfont} - # @fontslot['font'] = @compoundfont - begin - tk_call('font', 'create', @compoundfont, - '-compound', [@latinfont, @kanjifont], *hash_kv(keys)) - rescue RuntimeError => e - if ltn == knj - if e.message =~ /kanji font .* specified/ - tk_call('font', 'delete', @latinfont) - create_latinfont(DEFAULT_LATIN_FONT_NAME) - opts = [] - Hash[*(tk_split_simplelist(tk_call('font', 'configure', - @kanjifont)))].each{|k,v| - case k - when '-size', '-weight', '-slant', '-underline', '-overstrike' - opts << k << v - end - } - tk_call('font', 'configure', @latinfont, *opts) - tk_call('font', 'create', @compoundfont, - '-compound', [@latinfont, @kanjifont], *hash_kv(keys)) - - elsif e.message =~ /ascii font .* specified/ - tk_call('font', 'delete', @kanjifont) - create_kanjifont(DEFAULT_KANJI_FONT_NAME) - opts = [] - Hash[*(tk_split_simplelist(tk_call('font', 'configure', - @latinfont)))].each{|k,v| - case k - when '-size', '-weight', '-slant', '-underline', '-overstrike' - opts << k << v - end - } - tk_call('font', 'configure', @kanjifont, *opts) - tk_call('font', 'create', @compoundfont, - '-compound', [@latinfont, @kanjifont], *hash_kv(keys)) - - else - raise e - end - else - raise e - end - end - else - tk_call('font', 'create', @compoundfont) - - latinkeys = {} - begin - actual_core(@latinfont).each{|key,val| latinkeys[key] = val} - rescue - latinkeys = {} - end - if latinkeys != {} - tk_call('font', 'configure', @compoundfont, *hash_kv(latinkeys)) - end - - if knj - compoundkeys = nil - kanjikeys = {} - begin - actual_core(@kanjifont).each{|key,val| kanjikeys[key] = val} - rescue - kanjikeys = {} - end - if kanjikeys != {} - tk_call('font', 'configure', @compoundfont, *hash_kv(kanjikeys)) - end - end - - if cfnt - if cfnt.kind_of?(Hash) - compoundkeys = cfnt.dup - else - compoundkeys = {} - actual_core(cfnt).each{|key,val| compoundkeys[key] = val} - end - compoundkeys.update(_symbolkey2str(keys)) - keys = compoundkeys - end - - @fontslot = {'font'=>@compoundfont} - # @fontslot['font'] = @compoundfont - tk_call('font', 'configure', @compoundfont, *hash_kv(keys)) - end - end - - ################################### - public - ################################### - def inspect - sprintf("#<%s:%0x:%s>", self.class.inspect, self.__id__, @compoundfont) - 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 - configinfo name - rescue - super(id, *args) -# 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 - - def call_font_configure(path, *args) - if path.kind_of?(Array) - # [path, optkey] - win, tag = path[0].split(';') - optkey = path[1].to_s - else - win, tag, optkey = path.split(';') - end - - fontslot = _symbolkey2str(@fontslot) - if optkey && optkey != "" - ltn = fontslot.delete('font') - knj = fontslot.delete('kanjifont') - fontslot[optkey] = ltn if ltn - fontslot["kanji#{optkey}"] = knj if knj - end - - keys = _symbolkey2str(args.pop).update(fontslot) - args.concat(hash_kv(keys)) - begin - tk_call(*args) - rescue => e - unless TkConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__ - fail e - end - end - Tk_FontUseTBL.mutex.synchronize{ - Tk_FontUseTBL[[win, tag, optkey].join(';')] = self - } - self - end - - def used - ret = [] - table = nil - Tk_FontUseTBL.mutex.synchronize{ - table = Tk_FontUseTBL.clone # to avoid deadlock - } - table.each{|key,value| - next unless self == value - if key.include?(';') - win, tag, optkey = key.split(';') - winobj = tk_tcl2ruby(win) - #if winobj.kind_of? TkText - if winobj.kind_of?(TkText) || winobj.kind_of?(Tk::Text) - if optkey - ret.push([winobj, winobj.tagid2obj(tag), optkey]) - else - ret.push([winobj, winobj.tagid2obj(tag)]) - end - #elsif winobj.kind_of? TkCanvas - elsif winobj.kind_of?(TkCanvas) || winobj.kind_of?(Tk::Canvas) - if (tagobj = TkcTag.id2obj(winobj, tag)).kind_of? TkcTag - if optkey - ret.push([winobj, tagobj, optkey]) - else - ret.push([winobj, tagobj]) - end - elsif (tagobj = TkcItem.id2obj(winobj, tag)).kind_of? TkcItem - if optkey - ret.push([winobj, tagobj, optkey]) - else - ret.push([winobj, tagobj]) - end - else - if optkey - ret.push([winobj, tag, optkey]) - else - ret.push([winobj, tag]) - end - end - #elsif winobj.kind_of? TkMenu - elsif winobj.kind_of?(TkMenu) || winobj.kind_of?(Tk::Menu) - if optkey - ret.push([winobj, tag, optkey]) - else - ret.push([winobj, tag]) - end - else - if optkey - ret.push([win, tag, optkey]) - else - ret.push([win, tag]) - end - end - else - ret.push(tk_tcl2ruby(key)) - end - } - ret - end - - def id - @id - end - - def to_eval - font - end - - def font - @compoundfont - end - alias font_id font - alias name font - alias to_s font - - def latin_font_id - @latinfont - end - - def latin_font - # @latinfont - if @descendant[0] # [0] -> latin - @descendant[0] - else - @descendant[0] = DescendantFont.new(self, 'latin') - end -=begin - if @latin_descendant - @latin_descendant - else - @latin_descendant = DescendantFont.new(self, 'latin') - end -=end - end - alias latinfont latin_font - - def kanji_font_id - @kanjifont - end - - def kanji_font - # @kanjifont - if @descendant[1] # [1] -> kanji - @descendant[1] - else - @descendant[1] = DescendantFont.new(self, 'kanji') - end -=begin - if @kanji_descendant - @kanji_descendant - else - @kanji_descendant = DescendantFont.new(self, 'kanji') - end -=end - end - alias kanjifont kanji_font - - def actual(option=nil) - actual_core(@compoundfont, nil, option) - end - def actual_hash(option=nil) - Hash[actual(option)] - end - - def actual_displayof(win, option=nil) - win = '.' unless win - actual_core(@compoundfont, win, option) - end - def actual_hash_displayof(win, option=nil) - Hash[actual_displayof(win, option)] - end - - def latin_actual(option=nil) - if @latinfont == nil - actual_core(@compoundfont, nil, option) # use @compoundfont - else - actual_core(@latinfont, nil, option) - end - end - def latin_actual_hash(option=nil) - Hash[latin_actual(option)] - end - - def latin_actual_displayof(win, option=nil) - win = '.' unless win - if @latinfont == nil - actual_core(@compoundfont, win, option) # use @compoundfont - else - actual_core(@latinfont, win, option) - end - end - def latin_actual_hash_displayof(win, option=nil) - Hash[latin_actual_displayof(win, option)] - end - - def kanji_actual(option=nil) - #if JAPANIZED_TK - if @kanjifont == nil - actual_core(@compoundfont, nil, option) # use @compoundfont - elsif @kanjifont != "" - actual_core(@kanjifont, nil, option) - else - actual_core_tk4x(nil, nil, option) - end - end - def kanji_actual_hash(option=nil) - Hash[kanji_actual(option)] - end - - def kanji_actual_displayof(win, option=nil) - #if JAPANIZED_TK - if @kanjifont == nil - actual_core(@compoundfont, nil, option) # use @compoundfont - elsif @kanjifont != "" - win = '.' unless win - actual_core(@kanjifont, win, option) - else - actual_core_tk4x(nil, win, option) - end - end - def kanji_actual_hash_displayof(win, option=nil) - Hash[kanji_actual_displayof(win, option)] - end - - def [](slot) - configinfo slot - end - - def []=(slot, val) - configure slot, val - val - end - - def configure(slot, value=None) - configure_core(@compoundfont, slot, value) - self - end - - def configinfo(slot=nil) - configinfo_core(@compoundfont, slot) - end - - def current_configinfo(slot=nil) - current_configinfo_core(@compoundfont, slot) - end - - def delete - delete_core - end - - def latin_configure(slot, value=None) - if JAPANIZED_TK - configure_core(@latinfont, slot, value) - else - configure(slot, value) - end - self - end - - def latin_configinfo(slot=nil) - if JAPANIZED_TK - configinfo_core(@latinfont, slot) - else - configinfo(slot) - end - end - def latin_current_configinfo(slot=nil) - Hash[latin_configinfo(slot)] - end - - def kanji_configure(slot, value=None) - #if JAPANIZED_TK - if @kanjifont == nil - configure_core(@compoundfont, slot, value) # use @compoundfont - elsif @kanjifont != "" - configure_core(@kanjifont, slot, value) - configure('size'=>configinfo('size')) # to reflect new configuration - else - #"" - configure(slot, value) - end - self - end - - def kanji_configinfo(slot=nil) - #if JAPANIZED_TK - if @kanjifont == nil - configure_core(@compoundfont, slot) # use @compoundfont - elsif @kanjifont != "" - configinfo_core(@kanjifont, slot) - else - #[] - configinfo(slot) - end - end - def kanji_current_configinfo(slot=nil) - Hash[kanji_configinfo(slot)] - end - - def replace(ltn, knj=None) - knj = ltn if knj == None - latin_replace(ltn) - kanji_replace(knj) - self - end - - def latin_replace(ltn) - if @latinfont - latin_replace_core(ltn) - reset_pointadjust - else - # not compound font -> copy properties of ltn - latinkeys = {} - begin - actual_core(ltn).each{|key,val| latinkeys[key] = val} - rescue - latinkeys = {} - end - begin - tk_call('font', 'configure', @compoundfont, *hash_kv(latinkeys)) - rescue - # not exist? (deleted?) -> create font - tk_call('font', 'create', @compoundfont, *hash_kv(latinkeys)) - end - end - - self - end - - def kanji_replace(knj) - return self unless @kanjifont # ignore - kanji_replace_core(knj) - reset_pointadjust - self - end - - def measure(text) - measure_core(@compoundfont, nil, text) - end - - def measure_displayof(win, text) - win = '.' unless win - measure_core(@compoundfont, win, text) - end - - def metrics(option=nil) - metrics_core(@compoundfont, nil, option) - end - def metrics_hash(option=nil) - if option - val = metrics(option) - case TkFont::MetricsType[option.to_s] - when ?n - val = TkComm::num_or_str(val) - when ?b - val = TkComm::bool(val) - else - # do nothing - end - return val - end - - h = Hash[metrics(option)] - h.keys.each{|k| - case TkFont::MetricsType[k.to_s] - when ?n - h[k] = TkComm::num_or_str(h[k]) - when ?b - h[k] = TkComm::bool(h[k]) - else - # do nothing - end - } - h - end - - def metrics_displayof(win, option=nil) - win = '.' unless win - metrics_core(@compoundfont, win, option) - end - def metrics_hash_displayof(win, option=nil) - if option - val = metrics_displayof(win, option) - case TkFont::MetricsType[option.to_s] - when ?n - val = TkComm::num_or_str(val) - when ?b - val = TkComm::bool(val) - else - # do nothing - end - return val - end - - h = Hash[metrics_displayof(win, option)] - h.keys.each{|k| - case TkFont::MetricsType[k.to_s] - when ?n - h[k] = TkComm::num_or_str(h[k]) - when ?b - h[k] = TkComm::bool(h[k]) - else - # do nothing - end - } - h - end - - def latin_metrics(option=nil) - if @latinfont == nil - metrics_core(@compoundfont, nil, option) # use @compoundfont - else - metrics_core(@latinfont, nil, option) - end - end - def latin_metrics_hash(option=nil) - if option - val = latin_metrics(option) - case TkFont::MetricsType[option.to_s] - when ?n - val = TkComm::num_or_str(val) - when ?b - val = TkComm::bool(val) - else - # do nothing - end - return val - end - - h = Hash[latin_metrics(option)] - h.keys.each{|k| - case TkFont::MetricsType[k.to_s] - when ?n - h[k] = TkComm::num_or_str(h[k]) - when ?b - h[k] = TkComm::bool(h[k]) - else - # do nothing - end - } - h - end - - def latin_metrics_displayof(win, option=nil) - win = '.' unless win - if @latinfont == nil - metrics_core(@compoundfont, win, option) # use @compoundfont - else - metrics_core(@latinfont, win, option) - end - end - def latin_metrics_hash_displayof(win, option=nil) - if option - val = latin_metrics_displayof(win, option) - case TkFont::MetricsType[option.to_s] - when ?n - val = TkComm::num_or_str(val) - when ?b - val = TkComm::bool(val) - else - # do nothing - end - return val - end - - h = Hash[latin_metrics_displayof(win, option)] - h.keys.each{|k| - case TkFont::MetricsType[k.to_s] - when ?n - h[k] = TkComm::num_or_str(h[k]) - when ?b - h[k] = TkComm::bool(h[k]) - else - # do nothing - end - } - h - end - - def kanji_metrics(option=nil) - if @latinfont == nil - metrics_core(@compoundfont, nil, option) # use @compoundfont - elsif JAPANIZED_TK - metrics_core(@kanjifont, nil, option) - else - metrics_core_tk4x(nil, nil, option) - end - end - def kanji_metrics_hash(option=nil) - if option - val = kanji_metrics(option) - case TkFont::MetricsType[option.to_s] - when ?n - val = TkComm::num_or_str(val) - when ?b - val = TkComm::bool(val) - else - # do nothing - end - return val - end - - h = Hash[kanji_metrics(option)] - h.keys.each{|k| - case TkFont::MetricsType[k.to_s] - when ?n - h[k] = TkComm::num_or_str(h[k]) - when ?b - h[k] = TkComm::bool(h[k]) - else - # do nothing - end - } - h - end - - def kanji_metrics_displayof(win, option=nil) - win = '.' unless win - if @latinfont == nil - metrics_core(@compoundfont, win, option) # use @compoundfont - elsif JAPANIZED_TK - metrics_core(@kanjifont, win, option) - else - metrics_core_tk4x(nil, win, option) - end - end - def kanji_metrics_hash_displayof(win, option=nil) - if option - val = kanji_metrics_displayof(win, option) - case TkFont::MetricsType[option.to_s] - when ?n - val = TkComm::num_or_str(val) - when ?b - val = TkComm::bool(val) - else - # do nothing - end - return val - end - - h = Hash[kanji_metrics_displayof(win, option)] - h.keys.each{|k| - case TkFont::MetricsType[k.to_s] - when ?n - h[k] = TkComm::num_or_str(h[k]) - when ?b - h[k] = TkComm::bool(h[k]) - else - # do nothing - end - } - h - end - - def reset_pointadjust - begin - if /^8\..*/ === Tk::TK_VERSION && JAPANIZED_TK - configure('pointadjust' => latin_actual.assoc('size')[1].to_f / - kanji_actual.assoc('size')[1].to_f ) - end - rescue - end - self - end - - ################################### - # private alias - ################################### - case (Tk::TK_VERSION) - when /^4\..*/ - alias create_latinfont create_latinfont_tk4x - alias create_kanjifont create_kanjifont_tk4x - alias create_compoundfont create_compoundfont_tk4x - - when /^8\.[0-5]/ - alias create_latinfont create_latinfont_tk8x - alias create_kanjifont create_kanjifont_tk8x - alias create_compoundfont create_compoundfont_tk8x - - else - alias create_latinfont create_latinfont_tk8x - alias create_kanjifont create_kanjifont_tk8x - alias create_compoundfont create_compoundfont_tk8x - - end - - ################################### - # public alias - ################################### - alias ascii_font latin_font - alias asciifont latinfont - alias create_asciifont create_latinfont - alias ascii_actual latin_actual - alias ascii_actual_displayof latin_actual_displayof - alias ascii_configure latin_configure - alias ascii_configinfo latin_configinfo - alias ascii_replace latin_replace - alias ascii_metrics latin_metrics - - ################################### -=begin - def dup - TkFont.new(self) - end - def clone - TkFont.new(self) - end -=end -end - -module TkFont::CoreMethods - include Tk - extend TkCore - - private - - def actual_core_tk4x(font, win=nil, option=nil) - # dummy - if option == 'pointadjust' || option == :pointadjust - 1.0 - elsif option - case TkFont::OptionType[option.to_s] - when ?n - 0 - when ?b - false - else - '' - end - else - [['family',''], ['size',0], ['weight',''], ['slant',''], - ['underline',false], ['overstrike',false], ['charset',''], - ['pointadjust',0]] - end - end - - def actual_core_tk8x(font, win=nil, option=nil) - font = '{}' if font == '' - - if option == 'compound' || option == :compound - "" - elsif option - if win - val = tk_call('font', 'actual', font, - "-displayof", win, "-#{option}") - else - val = tk_call('font', 'actual', font, "-#{option}") - end - case TkFont::OptionType[option.to_s] - when ?n - num_or_str(val) - when ?b - bool(val) - else - val - end - else - l = tk_split_simplelist(if win - tk_call('font', 'actual', font, - "-displayof", win) - else - tk_call('font', 'actual', font) - end) - r = [] - while key=l.shift - if key == '-compound' - l.shift - else - key = key[1..-1] - val = l.shift - case TkFont::OptionType[key] - when ?n - r.push [key, num_or_str(val)] - when ?b - r.push [key, bool(val)] - else - r.push [key, val] - end - end - end - r - end - end - - def configure_core_tk4x(font, slot, value=None) - #"" - self - end - - def configinfo_core_tk4x(font, option=nil) - # dummy - if TkComm::GET_CONFIGINFOwoRES_AS_ARRAY - if option == 'pointadjust' || option == :pointadjust - 1.0 - elsif option - case TkFont::OptionType[option.to_s] - when ?n - 0 - when ?b - false - else - '' - end - else - [['family',''], ['size',0], ['weight',''], ['slant',''], - ['underline',false], ['overstrike',false], ['charset',''], - ['pointadjust',1.0]] - end - else # ! TkComm::GET_CONFIGINFOwoRES_AS_ARRAY - current_configinfo_core_tk4x(font, option) - end - end - - def current_configinfo_core_tk4x(font, option=nil) - if option - case TkFont::OptionType[option.to_s] - when ?n - 0 - when ?b - false - else - '' - end - else - {'family'=>'', 'size'=>0, 'weight'=>'', 'slant'=>'', - 'underline'=>false, 'overstrike'=>false, - 'charset'=>false, 'pointadjust'=>1.0} - end - end - - def configure_core_tk8x(font, slot, value=None) - if JAPANIZED_TK - begin - padjust = tk_call('font', 'configure', font, '-pointadjust') - rescue - padjust = nil - end - else - padjust = nil - end - if slot.kind_of? Hash - if JAPANIZED_TK && (slot.key?('family') || slot.key?(:family)) - slot = _symbolkey2str(slot) - configure_core_tk8x(font, 'family', slot.delete('family')) - end - - if ((slot.key?('size') || slot.key?(:size)) && - padjust && !slot.key?('pointadjust') && !slot.key?(:pointadjust)) - tk_call('font', 'configure', font, - '-pointadjust', padjust, *hash_kv(slot)) - else - tk_call('font', 'configure', font, *hash_kv(slot)) - end - elsif (slot == 'size' || slot == :size) && padjust != nil - tk_call('font', 'configure', font, - "-#{slot}", value, '-pointadjust', padjust) - elsif JAPANIZED_TK && (slot == 'family' || slot == :family) - # compound font? - begin - compound = tk_split_simplelist(tk_call('font', 'configure', - font, '-compound')) - rescue - tk_call('font', 'configure', font, '-family', value) - return self - end - if compound == [] - tk_call('font', 'configure', font, '-family', value) - return self - end - ltn, knj = compound - - lfnt = tk_call('font', 'create', '-copy', ltn) - begin - tk_call('font', 'configure', lfnt, '-family', value) - latin_replace_core_tk8x(lfnt) - rescue RuntimeError => e - fail e if $DEBUG - ensure - tk_call('font', 'delete', lfnt) if lfnt != '' - end - - kfnt = tk_call('font', 'create', '-copy', knj) - begin - tk_call('font', 'configure', kfnt, '-family', value) - kanji_replace_core_tk8x(lfnt) - rescue RuntimeError => e - fail e if $DEBUG - ensure - tk_call('font', 'delete', kfnt) if kfnt != '' - end - - else - tk_call('font', 'configure', font, "-#{slot}", value) - end - self - end - - def configinfo_core_tk8x(font, option=nil) - if TkComm::GET_CONFIGINFOwoRES_AS_ARRAY - if option == 'compound' || option == :compound - "" - elsif option - val = tk_call('font', 'configure', font, "-#{option}") - case TkFont::OptionType[option.to_s] - when ?n - num_or_str(val) - when ?b - bool(val) - else - val - end - else - l = tk_split_simplelist(tk_call('font', 'configure', font)) - r = [] - while key=l.shift - if key == '-compound' - l.shift - else - key = key[1..-1] - val = l.shift - case TkFont::OptionType[key] - when ?n - r.push [key, num_or_str(val)] - when ?b - r.push [key, bool(val)] - else - r.push [key, val] - end - end - end - r - end - else # ! TkComm::GET_CONFIGINFOwoRES_AS_ARRAY - current_configinfo_core_tk8x(font, option) - end - end - - def current_configinfo_core_tk8x(font, option=nil) - if option == 'compound' - "" - elsif option - val = tk_call('font', 'configure', font, "-#{option}") - case TkFont::OptionType[option.to_s] - when ?n - num_or_str(val) - when ?b - bool(val) - else - val - end - else - l = tk_split_simplelist(tk_call('font', 'configure', font)) - h = {} - while key=l.shift - if key == '-compound' - l.shift - else - key = key[1..-1] - val = l.shift - case TkFont::OptionType[key] - when ?n - h[key] = num_or_str(val) - when ?b - h[key] = bool(val) - else - h[key] = val - end - end - end - h - end - end - - def delete_core_tk4x - TkFont::Tk_FontNameTBL.mutex.synchronize{ - TkFont::Tk_FontNameTBL.delete(@id) - } - TkFont::Tk_FontUseTBL.mutex.synchronize{ - TkFont::Tk_FontUseTBL.delete_if{|key,value| value == self} - } - end - - def delete_core_tk8x - begin - tk_call('font', 'delete', @latinfont) if @latinfont - rescue - end - begin - tk_call('font', 'delete', @kanjifont) if @kanjifont - rescue - end - begin - tk_call('font', 'delete', @compoundfont) if @compoundfont - rescue - end - TkFont::Tk_FontNameTBL.mutex.synchronize{ - TkFont::Tk_FontNameTBL.delete(@id) - } - TkFont::Tk_FontUseTBL.mutex.synchronize{ - TkFont::Tk_FontUseTBL.delete_if{|key,value| value == self} - } - end - - def latin_replace_core_tk4x(ltn) - create_latinfont_tk4x(ltn) - @compoundfont[0] = [@latinfont] if JAPANIZED_TK - @fontslot['font'] = @latinfont - table = nil - TkFont::Tk_FontUseTBL.mutex.synchronize{ - table = TkFont::Tk_FontUseTBL.clone - } - table.each{|w, fobj| - if self == fobj - begin - if w.include?(';') - win, tag, optkey = w.split(';') - optkey = 'font' if optkey == nil || optkey == '' - winobj = tk_tcl2ruby(win) -# winobj.tagfont_configure(tag, {'font'=>@latinfont}) - #if winobj.kind_of? TkText - if winobj.kind_of?(TkText) || winobj.kind_of?(Tk::Text) - tk_call(win, 'tag', 'configure', tag, "-#{optkey}", @latinfont) - #elsif winobj.kind_of? TkCanvas - elsif winobj.kind_of?(TkCanvas) || winobj.kind_of?(Tk::Canvas) - tk_call(win, 'itemconfigure', tag, "-#{optkey}", @latinfont) - #elsif winobj.kind_of? TkMenu - elsif winobj.kind_of?(TkMenu) || winobj.kind_of?(Tk::Menu) - tk_call(win, 'entryconfigure', tag, "-#{optkey}", @latinfont) - else - raise RuntimeError, "unknown widget type" - end - else -# tk_tcl2ruby(w).font_configure('font'=>@latinfont) - tk_call(w, 'configure', '-font', @latinfont) - end - rescue - TkFont::Tk_FontUseTBL.mutex.synchronize{ - TkFont::Tk_FontUseTBL.delete(w) - } - end - end - } - self - end - - def kanji_replace_core_tk4x(knj) - return self unless JAPANIZED_TK - - create_kanjifont_tk4x(knj) - @compoundfont[1] = [@kanjifont] - @fontslot['kanjifont'] = @kanjifont - table = nil - TkFont::Tk_FontUseTBL.mutex.synchronize{ - table = TkFont::Tk_FontUseTBL.clone - } - table.dup.each{|w, fobj| - if self == fobj - begin - if w.include?(';') - win, tag, optkey = w.split(';') - optkey = 'kanjifont' unless optkey - winobj = tk_tcl2ruby(win) -# winobj.tagfont_configure(tag, {'kanjifont'=>@kanjifont}) - #if winobj.kind_of? TkText - if winobj.kind_of?(TkText) || winobj.kind_of?(Tk::Text) - tk_call(win, 'tag', 'configure', tag, "-#{optkey}", @kanjifont) - #elsif winobj.kind_of? TkCanvas - elsif winobj.kind_of?(TkCanvas) || winobj.kind_of?(Tk::Canvas) - tk_call(win, 'itemconfigure', tag, "-#{optkey}", @kanjifont) - #elsif winobj.kind_of? TkMenu - elsif winobj.kind_of?(TkMenu) || winobj.kind_of?(Tk::Menu) - tk_call(win, 'entryconfigure', tag, "-#{optkey}", @latinfont) - else - raise RuntimeError, "unknown widget type" - end - else -# tk_tcl2ruby(w).font_configure('kanjifont'=>@kanjifont) - tk_call(w, 'configure', '-kanjifont', @kanjifont) - end - rescue - Tk_FontUseTBL.mutex.synchronize{ - TkFont::Tk_FontUseTBL.delete(w) - } - end - end - } - self - end - - def latin_replace_core_tk8x(ltn) - ltn = '{}' if ltn == '' - - if JAPANIZED_TK - begin - tk_call('font', 'delete', '@font_tmp') - rescue - end - begin - fnt_bup = tk_call('font', 'create', '@font_tmp', '-copy', @latinfont) - rescue - #fnt_bup = '' - fnt_bup = TkFont::DEFAULT_LATIN_FONT_NAME - end - end - - begin - tk_call('font', 'delete', @latinfont) - rescue - end - create_latinfont(ltn) - - if JAPANIZED_TK - keys = self.configinfo - tk_call('font', 'delete', @compoundfont) - begin - tk_call('font', 'create', @compoundfont, - '-compound', [@latinfont, @kanjifont], *hash_kv(keys)) -=begin - latinkeys = {} - begin - actual_core(@latinfont).each{|key,val| latinkeys[key] = val} - rescue - latinkeys = {} - end - if latinkeys != {} - tk_call('font', 'configure', @compoundfont, *hash_kv(latinkeys)) - end -=end - rescue RuntimeError => e - tk_call('font', 'delete', @latinfont) - if fnt_bup && fnt_bup != '' - tk_call('font', 'create', @latinfont, '-copy', fnt_bup) - tk_call('font', 'create', @compoundfont, - '-compound', [@latinfont, @kanjifont], *hash_kv(keys)) - tk_call('font', 'delete', fnt_bup) - else - fail e - end - end - - else - latinkeys = {} - begin - actual_core(@latinfont).each{|key,val| latinkeys[key] = val} - rescue - latinkeys = {} - end - begin - tk_call('font', 'configure', @compoundfont, *hash_kv(latinkeys)) - rescue - # not exist? (deleted?) -> create font - tk_call('font', 'create', @compoundfont, *hash_kv(latinkeys)) - end - end - self - end - - def kanji_replace_core_tk8x(knj) - knj = '{}' if knj == '' - - if JAPANIZED_TK - begin - tk_call('font', 'delete', '@font_tmp') - rescue - end - begin - fnt_bup = tk_call('font', 'create', '@font_tmp', '-copy', @kanjifont) - rescue - #fnt_bup = '' - fnt_bup = TkFont::DEFAULT_KANJI_FONT_NAME - end - end - - begin - tk_call('font', 'delete', @kanjifont) - rescue - end - create_kanjifont(knj) - - if JAPANIZED_TK - keys = self.configinfo - tk_call('font', 'delete', @compoundfont) - begin - tk_call('font', 'create', @compoundfont, - '-compound', [@latinfont, @kanjifont], *hash_kv(keys)) - rescue RuntimeError => e - tk_call('font', 'delete', @kanjifont) - if fnt_bup && fnt_bup != '' - tk_call('font', 'create', @kanjifont, '-copy', fnt_bup) - tk_call('font', 'create', @compoundfont, - '-compound', [@latinfont, @kanjifont], *hash_kv(keys)) - tk_call('font', 'delete', fnt_bup) - else - fail e - end - end - end - self - end - - def measure_core_tk4x(font, win, text) - 0 - end - - def measure_core_tk8x(font, win, text) - font = '{}' if font == '' - - if win - number(tk_call('font', 'measure', font, - '-displayof', win, text)) - else - number(tk_call('font', 'measure', font, text)) - end - end - - def metrics_core_tk4x(font, win, option=nil) - # dummy - if option - "" - else - [['ascent',[]], ['descent',[]], ['linespace',[]], ['fixed',[]]] - end - end - - def metrics_core_tk8x(font, win, option=nil) - font = '{}' if font == '' - - if option - if win - number(tk_call('font', 'metrics', font, - "-displayof", win, "-#{option}")) - else - number(tk_call('font', 'metrics', font, "-#{option}")) - end - else - l = tk_split_list(if win - tk_call('font','metrics',font,"-displayof",win) - else - tk_call('font','metrics',font) - end) - r = [] - while key=l.shift - r.push [key[1..-1], l.shift.to_i] -=begin - if key == '-fixed' # boolean value - r.push [key[1..-1], bool(l.shift)] - else - r.push [key[1..-1], l.shift.to_i] - end -=end - end - r - end - end - - ################################### - # private alias - ################################### - case (Tk::TK_VERSION) - when /^4\..*/ - alias actual_core actual_core_tk4x - alias configure_core configure_core_tk4x - alias configinfo_core configinfo_core_tk4x - alias current_configinfo_core current_configinfo_core_tk4x - alias delete_core delete_core_tk4x - alias latin_replace_core latin_replace_core_tk4x - alias kanji_replace_core kanji_replace_core_tk4x - alias measure_core measure_core_tk4x - alias metrics_core metrics_core_tk4x - - when /^8\.[0-9]/ - alias actual_core actual_core_tk8x - alias configure_core configure_core_tk8x - alias configinfo_core configinfo_core_tk8x - alias current_configinfo_core current_configinfo_core_tk8x - alias delete_core delete_core_tk8x - alias latin_replace_core latin_replace_core_tk8x - alias kanji_replace_core kanji_replace_core_tk8x - alias measure_core measure_core_tk8x - alias metrics_core metrics_core_tk8x - - else - alias actual_core actual_core_tk8x - alias configure_core configure_core_tk8x - alias configinfo_core configinfo_core_tk8x - alias current_configinfo_core current_configinfo_core_tk8x - alias delete_core delete_core_tk8x - alias latin_replace_core latin_replace_core_tk8x - alias kanji_replace_core kanji_replace_core_tk8x - alias measure_core measure_core_tk8x - alias metrics_core metrics_core_tk8x - - end -end - -class TkFont - include TkFont::CoreMethods - extend TkFont::CoreMethods -end - -class TkNamedFont < TkFont - # for built-in named fonts - def TkNamedFont.find(name) - name = name.to_s - unless (obj = Tk_FontNameTBL[name]) - obj = self.new(name) if TkFont.is_system_font?(name) - end - obj - end - - def TkNamedFont.new(name, keys=nil) - name = name.to_s - obj = nil - Tk_FontNameTBL.mutex.synchronize{ - unless (obj = Tk_FontNameTBL[name]) - (obj = self.allocate).instance_eval{ - @id = @compoundfont = name.to_s - @latinfont = nil - @kanjifont = nil - @descendant = [self, self] # [latin, kanji] : dummy - Tk_FontNameTBL[@id] = self - } - end - } - obj.instance_eval{ initialize(name, keys) } - obj - end - - ########################### - private - ########################### - def initialize(name, keys=nil) - @id = @compoundfont = name.to_s - - # if not exist named font, create it. - begin - if keys - tk_call('font', 'configure', @compoundfont, keys) - else - tk_call('font', 'configure', @compoundfont) - end - rescue - # the named font doesn't exist -> create - if keys - tk_call('font', 'create', @compoundfont, keys) - else - tk_call('font', 'create', @compoundfont) - end - end - end - - def create_latinfont(fnt) - # ignore - end - def create_kanjifont(fnt) - # ignore - end - def create_compoundfont(ltn, knj, keys) - # ignore - end - - ########################### - public - ########################### - def latin_font_id - @compoundfont - end - def kanji_font_id - @compoundfont - end -end - -####################################### -# define system font names -####################################### -if Tk::TCL_MAJOR_VERSION > 8 || - (Tk::TCL_MAJOR_VERSION == 8 && Tk::TCL_MINOR_VERSION >= 5) - # add standard fonts of Tcl/Tk 8.5+ - TkFont::SYSTEM_FONT_NAMES.add [ - 'TkDefaultFont', 'TkTextFont', 'TkFixedFont', 'TkMenuFont', - 'TkHeadingFont', 'TkCaptionFont', 'TkSmallCaptionFont', - 'TkIconFont', 'TkTooltipFont' - ] -end - -# platform-specific fonts -# -- windows -TkFont::SYSTEM_FONT_NAMES.add [ - 'ansifixed', 'ansi', 'device', 'oemfixed', 'systemfixed', 'system' -] - -# -- macintosh, macosx -TkFont::SYSTEM_FONT_NAMES.add ['system', 'application'] - -if Tk::TCL_MAJOR_VERSION > 8 || - (Tk::TCL_MAJOR_VERSION == 8 && Tk::TCL_MINOR_VERSION >= 5) - TkFont::SYSTEM_FONT_NAMES.add ['menu'] -end - -# -- macosx (Aqua theme) -if Tk::TCL_MAJOR_VERSION > 8 || - (Tk::TCL_MAJOR_VERSION == 8 && Tk::TCL_MINOR_VERSION >= 5) - TkFont::SYSTEM_FONT_NAMES.add [ - 'systemSystemFont', 'systemEmphasizedSystemFont', - 'systemSmallSystemFont', 'systemSmallEmphasizedSystemFont', - 'systemApplicationFont', 'systemLabelFont', 'systemViewsFont', - 'systemMenuTitleFont', 'systemMenuItemFont', 'systemMenuItemMarkFont', - 'systemMenuItemCmdKeyFont', 'systemWindowTitleFont', - 'systemPushButtonFont', 'systemUtilityWindowTitleFont', - 'systemAlertHeaderFont', 'systemToolbarFont', 'systemMiniSystemFont', - 'systemDetailSystemFont', 'systemDetailEmphasizedSystemFont' - ] -end - -####################################### -# autoload -####################################### -class TkFont - autoload :Chooser, 'tk/fontchooser' -end diff --git a/ext/tk/lib/tk/fontchooser.rb b/ext/tk/lib/tk/fontchooser.rb deleted file mode 100644 index 325ca4dbd2..0000000000 --- a/ext/tk/lib/tk/fontchooser.rb +++ /dev/null @@ -1,181 +0,0 @@ -# frozen_string_literal: false -# -# tk/fontchooser.rb -- "tk fontchooser" support (Tcl/Tk8.6 or later) -# -require 'tk' -require 'tk/font' - -module TkFont::Chooser - extend TkCore -end - -module Tk - Fontchooser = TkFont::Chooser -end - -class << TkFont::Chooser - 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 - super(id, *args) - end - else - super(id, *args) - end - end - - def __configinfo_value(key, val) - case key - when 'parent' - window(val) - when 'title' - val - when 'font' - if (lst = tk_split_simplelist(val)).size == 1 - lst[0] - else - lst.map{|elem| num_or_str(elem)} - end - when 'command' - tk_tcl2ruby(val) - when 'visible' - bool(val) - else # unknown - val - end - end - private :__configinfo_value - - def configinfo(option=nil) - if !option && TkComm::GET_CONFIGINFOwoRES_AS_ARRAY - lst = tk_split_simplelist(tk_call('tk', 'fontchooser', 'configure')) - ret = [] - TkComm.slice_ary(lst, 2){|k, v| - k = k[1..-1] - ret << [k, __configinfo_value(k, v)] - } - ret - else - current_configinfo(option) - end - end - - def current_configinfo(option=nil) - if option - opt = option.to_s - fail ArgumentError, "Invalid option `#{option.inspect}'" if opt.empty? - __configinfo_value(option.to_s, tk_call('tk','fontchooser', - 'configure',"-#{opt}")) - else - lst = tk_split_simplelist(tk_call('tk', 'fontchooser', 'configure')) - ret = {} - TkComm.slice_ary(lst, 2){|k, v| - k = k[1..-1] - ret[k] = __configinfo_value(k, v) - } - ret - end - end - - def configure(option, value=None) - if option.kind_of? Hash - tk_call('tk', 'fontchooser', 'configure', - *hash_kv(_symbolkey2str(option))) - else - opt = option.to_s - fail ArgumentError, "Invalid option `#{option.inspect}'" if opt.empty? - tk_call('tk', 'fontchooser', 'configure', "-#{opt}", value) - end - self - end - - def configure_cmd(slot, value) - configure(slot, install_cmd(value)) - end - - 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 cget(slot) - configinfo slot - end - - def [](slot) - cget slot - end - - def []=(slot, val) - configure slot, val - val - end - - def show - tk_call('tk', 'fontchooser', 'show') - self - end - - def hide - tk_call('tk', 'fontchooser', 'hide') - self - end - - def toggle - cget(:visible) ? hide: show - self - end - - def set_for(target, title="Font") - if target.kind_of? TkFont - configs = { - :font=>target.actual_hash, - :command=>proc{|fnt, *args| - target.configure(TkFont.actual_hash(fnt)) - } - } - elsif target.kind_of? Hash - # key=>value list or OptionObj - fnt = target[:font] rescue '' - fnt = fnt.actual_hash if fnt.kind_of?(TkFont) - configs = { - :font => fnt, - :command=>proc{|fnt, *args| - target[:font] = TkFont.actual_hash(fnt) - } - } - else - configs = { - :font=>target.cget_tkstring(:font), - :command=>proc{|fnt, *args| - target.font = TkFont.actual_hash_displayof(fnt, target) - } - } - end - - configs[:title] = title if title - configure(configs) - target - end - - def unset - configure(:command, nil) - end -end diff --git a/ext/tk/lib/tk/frame.rb b/ext/tk/lib/tk/frame.rb deleted file mode 100644 index 0682faf3fe..0000000000 --- a/ext/tk/lib/tk/frame.rb +++ /dev/null @@ -1,133 +0,0 @@ -# frozen_string_literal: false -# -# tk/frame.rb : treat frame widget -# -require 'tk' - -class Tk::Frame<TkWindow - TkCommandNames = ['frame'.freeze].freeze - WidgetClassName = 'Frame'.freeze - WidgetClassNames[WidgetClassName] ||= self - -################# old version -# def initialize(parent=nil, keys=nil) -# if keys.kind_of? Hash -# keys = keys.dup -# @classname = keys.delete('classname') if keys.key?('classname') -# @colormap = keys.delete('colormap') if keys.key?('colormap') -# @container = keys.delete('container') if keys.key?('container') -# @visual = keys.delete('visual') if keys.key?('visual') -# end -# super(parent, keys) -# end -# -# def create_self -# s = [] -# s << "-class" << @classname if @classname -# s << "-colormap" << @colormap if @colormap -# s << "-container" << @container if @container -# s << "-visual" << @visual if @visual -# tk_call 'frame', @path, *s -# end -################# - - def __boolval_optkeys - super() << 'container' - end - private :__boolval_optkeys - - def initialize(parent=nil, keys=nil) - my_class_name = nil - if self.class < WidgetClassNames[self.class::WidgetClassName] - my_class_name = self.class.name - my_class_name = nil if my_class_name == '' - end - if parent.kind_of? Hash - keys = _symbolkey2str(parent) - else - if keys - keys = _symbolkey2str(keys) - keys['parent'] = parent - else - keys = {'parent'=>parent} - end - end - if keys.key?('classname') - keys['class'] = keys.delete('classname') - end - @classname = keys['class'] - @colormap = keys['colormap'] - @container = keys['container'] - @visual = keys['visual'] - if !@classname && my_class_name - keys['class'] = @classname = my_class_name - end - if @classname.kind_of? TkBindTag - @db_class = @classname - @classname = @classname.id - elsif @classname - @db_class = TkDatabaseClass.new(@classname) - else - @db_class = self.class - @classname = @db_class::WidgetClassName - end - super(keys) - end - - #def create_self(keys) - # if keys and keys != None - # tk_call_without_enc('frame', @path, *hash_kv(keys)) - # else - # tk_call_without_enc( 'frame', @path) - # end - #end - #private :create_self - - def database_classname - @classname - end - - def self.database_class - if self == WidgetClassNames[WidgetClassName] || self.name == '' - self - else - TkDatabaseClass.new(self.name) - end - end - def self.database_classname - self.database_class.name - end - - def self.bind(*args, &b) - if self == WidgetClassNames[WidgetClassName] || self.name == '' - super(*args, &b) - else - TkDatabaseClass.new(self.name).bind(*args, &b) - end - end - def self.bind_append(*args, &b) - if self == WidgetClassNames[WidgetClassName] || self.name == '' - super(*args, &b) - else - TkDatabaseClass.new(self.name).bind_append(*args, &b) - end - end - def self.bind_remove(*args) - if self == WidgetClassNames[WidgetClassName] || self.name == '' - super(*args) - else - TkDatabaseClass.new(self.name).bind_remove(*args) - end - end - def self.bindinfo(*args) - if self == WidgetClassNames[WidgetClassName] || self.name == '' - super(*args) - else - TkDatabaseClass.new(self.name).bindinfo(*args) - end - end -end - -#TkFrame = Tk::Frame unless Object.const_defined? :TkFrame -#Tk.__set_toplevel_aliases__(:Tk, Tk::Frame, :TkFrame) -Tk.__set_loaded_toplevel_aliases__('tk/frame.rb', :Tk, Tk::Frame, :TkFrame) diff --git a/ext/tk/lib/tk/grid.rb b/ext/tk/lib/tk/grid.rb deleted file mode 100644 index 5a4a26403a..0000000000 --- a/ext/tk/lib/tk/grid.rb +++ /dev/null @@ -1,280 +0,0 @@ -# frozen_string_literal: false -# -# tk/grid.rb : control grid geometry manager -# -require 'tk' - -module TkGrid - include Tk - extend Tk - - TkCommandNames = ['grid'.freeze].freeze - - def anchor(master, anchor=None) - # master = master.epath if master.kind_of?(TkObject) - master = _epath(master) - tk_call_without_enc('grid', 'anchor', master, anchor) - end - - def bbox(master, *args) - # master = master.epath if master.kind_of?(TkObject) - master = _epath(master) - args.unshift(master) - list(tk_call_without_enc('grid', 'bbox', *args)) - end - -=begin - def configure(win, *args) - if args[-1].kind_of?(Hash) - opts = args.pop - else - opts = {} - end - params = [] - params.push(_epath(win)) - args.each{|win| - case win - when '-', 'x', '^' # RELATIVE PLACEMENT - params.push(win) - else - params.push(_epath(win)) - end - } - opts.each{|k, v| - params.push("-#{k}") - params.push((v.kind_of?(TkObject))? v.epath: v) - } - if Tk::TCL_MAJOR_VERSION < 8 || - (Tk::TCL_MAJOR_VERSION == 8 && Tk::TCL_MINOR_VERSION <= 3) - if params[0] == '-' || params[0] == 'x' || params[0] == '^' - tk_call_without_enc('grid', *params) - else - tk_call_without_enc('grid', 'configure', *params) - end - else - tk_call_without_enc('grid', 'configure', *params) - end - end -=end - def configure(*args) - if args[-1].kind_of?(Hash) - opts = args.pop - else - opts = {} - end - fail ArgumentError, 'no widget is given' if args.empty? - params = [] - args.flatten(1).each{|win| - case win - when '-', ?- # RELATIVE PLACEMENT (increase columnspan) - params.push('-') - when /^-+$/ # RELATIVE PLACEMENT (increase columnspan) |