diff options
author | knu <knu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2008-05-18 15:02:36 +0000 |
---|---|---|
committer | knu <knu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2008-05-18 15:02:36 +0000 |
commit | 8480bcc8d5c72b61055cfa98e80f37fd62ae7ad4 (patch) | |
tree | f404254dbcee2a59866dbb3f7baab4df8e4b23ce /ext/tk | |
parent | 32378c5abea38a8278dae28eae9abcd547ac8a95 (diff) |
Merge -r16241:16456 from ruby_1_8.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_1_8_7@16458 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'ext/tk')
29 files changed, 636 insertions, 224 deletions
diff --git a/ext/tk/ChangeLog.tkextlib b/ext/tk/ChangeLog.tkextlib index 359b466a32..8c5d01a954 100644 --- a/ext/tk/ChangeLog.tkextlib +++ b/ext/tk/ChangeLog.tkextlib @@ -1,3 +1,9 @@ +2008-05-12 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp> + + * ext/tk/lib/tkextlib/tkDND/shape.rb: wrong package name. + +--------------< ... some changes ... >------------------ + 2007-05-26 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp> * ext/tk/lib/tkextlib/tcllib/tablelist.rb: fix typo. diff --git a/ext/tk/lib/tk.rb b/ext/tk/lib/tk.rb index 2aafcfecc3..e827d71ebc 100644 --- a/ext/tk/lib/tk.rb +++ b/ext/tk/lib/tk.rb @@ -775,7 +775,7 @@ end private :_curr_cmd_id, :_next_cmd_id module_function :_curr_cmd_id, :_next_cmd_id - def TkComm.install_cmd(cmd) + def TkComm.install_cmd(cmd, local_cmdtbl=nil) return '' if cmd == '' begin ns = TkCore::INTERP._invoke_without_enc('namespace', 'current') @@ -794,6 +794,15 @@ end @cmdtbl = [] unless defined? @cmdtbl @cmdtbl.taint unless @cmdtbl.tainted? @cmdtbl.push id + + if local_cmdtbl && local_cmdtbl.kind_of?(Array) + begin + local_cmdtbl << id + rescue Exception + # ignore + end + end + #return Kernel.format("rb_out %s", id); if ns 'rb_out' << TkCore::INTERP._ip_id_ << ' ' << ns << ' ' << id @@ -801,19 +810,29 @@ end 'rb_out' << TkCore::INTERP._ip_id_ << ' ' << id end end - def TkComm.uninstall_cmd(id) + 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) + TkComm.install_cmd(cmd, @cmdtbl) end def uninstall_cmd(id) - TkComm.uninstall_cmd(id) + TkComm.uninstall_cmd(id, @cmdtbl) end =begin @@ -1447,7 +1466,9 @@ module TkCore def after(ms, cmd=Proc.new) cmdid = install_cmd(proc{ret = cmd.call;uninstall_cmd(cmdid); ret}) - tk_call_without_enc("after",ms,cmdid) # return id + 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) @@ -1477,7 +1498,9 @@ module TkCore def after_idle(cmd=Proc.new) cmdid = install_cmd(proc{ret = cmd.call;uninstall_cmd(cmdid); ret}) - tk_call_without_enc('after','idle',cmdid) + 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) @@ -1495,6 +1518,11 @@ module TkCore 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 @@ -4947,6 +4975,15 @@ class TkWindow<TkObject 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) @@ -4978,12 +5015,14 @@ class TkWindow<TkObject TkGrid.columnconfigure(self, index, keys) end alias grid_columnconfigure grid_columnconfig + alias grid_column 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 + alias grid_row grid_rowconfig def grid_columnconfiginfo(index, slot=nil) #if slot @@ -5226,11 +5265,13 @@ class TkWindow<TkObject end children.each{|path, obj| - if defined?(@cmdtbl) - for id in @cmdtbl - uninstall_cmd id + obj.instance_eval{ + if defined?(@cmdtbl) + for id in @cmdtbl + uninstall_cmd id + end end - end + } TkCore::INTERP.tk_windows.delete(path) } @@ -5348,7 +5389,7 @@ TkWidget = TkWindow #Tk.freeze module Tk - RELEASE_DATE = '2008-04-18'.freeze + RELEASE_DATE = '2008-05-16'.freeze autoload :AUTO_PATH, 'tk/variable' autoload :TCL_PACKAGE_PATH, 'tk/variable' diff --git a/ext/tk/lib/tk/event.rb b/ext/tk/lib/tk/event.rb index 0042fcaa63..d8aad6248b 100644 --- a/ext/tk/lib/tk/event.rb +++ b/ext/tk/lib/tk/event.rb @@ -352,6 +352,14 @@ module TkEvent 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) ], @@ -371,6 +379,7 @@ module TkEvent nil ] +=begin # for Ruby m17n :: ?x --> String --> char-code ( getbyte(0) ) KEY_TBL.map!{|inf| if inf.kind_of?(Array) @@ -386,6 +395,7 @@ module TkEvent end inf } +=end # setup tables to be used by scan_args, _get_subst_key, _get_all_subst_keys # @@ -399,7 +409,8 @@ module TkEvent # ( 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, 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 @@ -447,6 +458,7 @@ module TkEvent 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) diff --git a/ext/tk/lib/tk/grid.rb b/ext/tk/lib/tk/grid.rb index 10fdf3569b..0dfd7263a7 100644 --- a/ext/tk/lib/tk/grid.rb +++ b/ext/tk/lib/tk/grid.rb @@ -22,6 +22,7 @@ module TkGrid list(tk_call_without_enc('grid', 'bbox', *args)) end +=begin def configure(win, *args) if args[-1].kind_of?(Hash) opts = args.pop @@ -53,6 +54,48 @@ module TkGrid 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) + params.concat(win.to_s.split(//)) + when '^', ?^ # RELATIVE PLACEMENT (increase rowspan) + params.push('^') + when /^\^+$/ # RELATIVE PLACEMENT (increase rowspan) + params.concat(win.to_s.split(//)) + when 'x', :x, ?x, nil, '' # RELATIVE PLACEMENT (empty column) + params.push('x') + when /^x+$/ # RELATIVE PLACEMENT (empty column) + params.concat(win.to_s.split(//)) + else + params.push(_epath(win)) + end + } + opts.each{|k, v| + params.push("-#{k}") + params.push(_epath(v)) # have to use 'epath' (hash_kv() is unavailable) + } + 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 alias grid configure def columnconfigure(master, index, args) @@ -61,12 +104,14 @@ module TkGrid tk_call_without_enc("grid", 'columnconfigure', master, index, *hash_kv(args)) end + alias column columnconfigure def rowconfigure(master, index, args) # master = master.epath if master.kind_of?(TkObject) master = _epath(master) tk_call_without_enc("grid", 'rowconfigure', master, index, *hash_kv(args)) end + alias row rowconfigure def columnconfiginfo(master, index, slot=nil) # master = master.epath if master.kind_of?(TkObject) @@ -189,10 +234,10 @@ module TkGrid list(tk_call_without_enc('grid', 'slaves', master, *hash_kv(args))) end - module_function :bbox, :forget, :propagate, :info + module_function :anchor, :bbox, :add, :forget, :propagate, :info module_function :remove, :size, :slaves, :location module_function :grid, :configure, :columnconfigure, :rowconfigure - module_function :columnconfiginfo, :rowconfiginfo + module_function :column, :row, :columnconfiginfo, :rowconfiginfo end =begin def TkGrid(win, *args) diff --git a/ext/tk/lib/tk/pack.rb b/ext/tk/lib/tk/pack.rb index 8fab363121..220a38e524 100644 --- a/ext/tk/lib/tk/pack.rb +++ b/ext/tk/lib/tk/pack.rb @@ -9,6 +9,7 @@ module TkPack TkCommandNames = ['pack'.freeze].freeze +=begin def configure(win, *args) if args[-1].kind_of?(Hash) opts = args.pop @@ -29,6 +30,22 @@ module TkPack } tk_call_without_enc("pack", 'configure', *params) 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| params.push(_epath(win))} + opts.each{|k, v| + params.push("-#{k}") + params.push(_epath(v)) # have to use 'epath' (hash_kv() is unavailable) + } + tk_call_without_enc("pack", 'configure', *params) + end alias pack configure def forget(*args) diff --git a/ext/tk/lib/tk/spinbox.rb b/ext/tk/lib/tk/spinbox.rb index e372c58009..34dc1904f7 100644 --- a/ext/tk/lib/tk/spinbox.rb +++ b/ext/tk/lib/tk/spinbox.rb @@ -37,6 +37,7 @@ class Tk::Spinbox<Tk::Entry nil ] +=begin # for Ruby m17n :: ?x --> String --> char-code ( getbyte(0) ) KEY_TBL.map!{|inf| if inf.kind_of?(Array) @@ -52,6 +53,7 @@ class Tk::Spinbox<Tk::Entry end inf } +=end _setup_subst_table(KEY_TBL, PROC_TBL); diff --git a/ext/tk/lib/tk/validation.rb b/ext/tk/lib/tk/validation.rb index 1da38c776d..60bd433cdc 100644 --- a/ext/tk/lib/tk/validation.rb +++ b/ext/tk/lib/tk/validation.rb @@ -50,7 +50,8 @@ module Tk key2class.each{|key, klass| if keys[key].kind_of?(Array) cmd, *args = keys[key] - keys[key] = klass.new(cmd, args.join(' ')) + #keys[key] = klass.new(cmd, args.join(' ')) + keys[key] = klass.new(cmd, *args) # elsif keys[key].kind_of?(Proc) || keys[key].kind_of?(Method) elsif TkComm._callback_entry?(keys[key]) keys[key] = klass.new(keys[key]) @@ -151,7 +152,8 @@ module Tk key2class.each{|key, klass| if keys[key].kind_of?(Array) cmd, *args = keys[key] - keys[key] = klass.new(cmd, args.join(' ')) + #keys[key] = klass.new(cmd, args.join(' ')) + keys[key] = klass.new(cmd, *args) # elsif keys[key].kind_of?(Proc) || keys[key].kind_of?(Method) elsif TkComm._callback_entry?(keys[key]) keys[key] = klass.new(keys[key]) @@ -249,6 +251,7 @@ class TkValidateCommand nil ] +=begin # for Ruby m17n :: ?x --> String --> char-code ( getbyte(0) ) KEY_TBL.map!{|inf| if inf.kind_of?(Array) @@ -264,6 +267,7 @@ class TkValidateCommand end inf } +=end _setup_subst_table(KEY_TBL, PROC_TBL); @@ -293,6 +297,7 @@ class TkValidateCommand 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) diff --git a/ext/tk/lib/tk/wm.rb b/ext/tk/lib/tk/wm.rb index 49dd4d73c2..0394296189 100644 --- a/ext/tk/lib/tk/wm.rb +++ b/ext/tk/lib/tk/wm.rb @@ -362,7 +362,7 @@ module Tk end end def overrideredirect(mode=TkComm::None) - Wm.overrideredirect(self, mode=TkComm::None) + Wm.overrideredirect(self, mode) end alias wm_overrideredirect overrideredirect TOPLEVEL_METHODCALL_OPTKEYS['overrideredirect'] = 'overrideredirect' @@ -545,7 +545,7 @@ module Tk module Wm_for_General Wm.instance_methods.each{|m| if (m = m.to_s) =~ /^wm_(.*)$/ - eval "def #{m}(*args); Tk::Wm.#{$1}(self, *args); end" + eval "def #{m}(*args, &b); Tk::Wm.#{$1}(self, *args, &b); end" end } end diff --git a/ext/tk/lib/tkextlib/blt/dragdrop.rb b/ext/tk/lib/tkextlib/blt/dragdrop.rb index 98b1a4832f..201548504a 100644 --- a/ext/tk/lib/tkextlib/blt/dragdrop.rb +++ b/ext/tk/lib/tkextlib/blt/dragdrop.rb @@ -81,6 +81,7 @@ module Tk::BLT nil ] +=begin # for Ruby m17n :: ?x --> String --> char-code ( getbyte(0) ) KEY_TBL.map!{|inf| if inf.kind_of?(Array) @@ -96,6 +97,7 @@ module Tk::BLT end inf } +=end _setup_subst_table(KEY_TBL, PROC_TBL) @@ -123,6 +125,7 @@ module Tk::BLT nil ] +=begin # for Ruby m17n :: ?x --> String --> char-code ( getbyte(0) ) KEY_TBL.map!{|inf| if inf.kind_of?(Array) @@ -138,6 +141,7 @@ module Tk::BLT end inf } +=end _setup_subst_table(KEY_TBL, PROC_TBL) @@ -177,6 +181,7 @@ module Tk::BLT nil ] +=begin # for Ruby m17n :: ?x --> String --> char-code ( getbyte(0) ) KEY_TBL.map!{|inf| if inf.kind_of?(Array) @@ -192,6 +197,7 @@ module Tk::BLT end inf } +=end _setup_subst_table(KEY_TBL, PROC_TBL) end diff --git a/ext/tk/lib/tkextlib/blt/treeview.rb b/ext/tk/lib/tkextlib/blt/treeview.rb index fc890614be..672869bfa2 100644 --- a/ext/tk/lib/tkextlib/blt/treeview.rb +++ b/ext/tk/lib/tkextlib/blt/treeview.rb @@ -239,6 +239,7 @@ class Tk::BLT::Treeview nil ] +=begin # for Ruby m17n :: ?x --> String --> char-code ( getbyte(0) ) KEY_TBL.map!{|inf| if inf.kind_of?(Array) @@ -254,6 +255,7 @@ class Tk::BLT::Treeview end inf } +=end _setup_subst_table(KEY_TBL, PROC_TBL); @@ -492,6 +494,7 @@ class Tk::BLT::Treeview nil ] +=begin # for Ruby m17n :: ?x --> String --> char-code ( getbyte(0) ) KEY_TBL.map!{|inf| if inf.kind_of?(Array) @@ -507,6 +510,7 @@ class Tk::BLT::Treeview end inf } +=end _setup_subst_table(KEY_TBL, PROC_TBL); @@ -523,7 +527,8 @@ class Tk::BLT::Treeview def _find_exec_flag_value(val) if val.kind_of?(Array) cmd, *args = val - FindExecFlagValue.new(cmd, args.join(' ')) + #FindExecFlagValue.new(cmd, args.join(' ')) + FindExecFlagValue.new(cmd, *args) elsif TkComm._callback_entry?(val) FindExecFlagValue.new(val) else diff --git a/ext/tk/lib/tkextlib/iwidgets/calendar.rb b/ext/tk/lib/tkextlib/iwidgets/calendar.rb index 236ca96f00..8495f0e29b 100644 --- a/ext/tk/lib/tkextlib/iwidgets/calendar.rb +++ b/ext/tk/lib/tkextlib/iwidgets/calendar.rb @@ -46,6 +46,7 @@ class Tk::Iwidgets::Calendar KEY_TBL = [ [?d, ?s, :date], nil ] PROC_TBL = [ [?s, TkComm.method(:string) ], nil ] +=begin # for Ruby m17n :: ?x --> String --> char-code ( getbyte(0) ) KEY_TBL.map!{|inf| if inf.kind_of?(Array) @@ -61,6 +62,7 @@ class Tk::Iwidgets::Calendar end inf } +=end _setup_subst_table(KEY_TBL, PROC_TBL); diff --git a/ext/tk/lib/tkextlib/iwidgets/entryfield.rb b/ext/tk/lib/tkextlib/iwidgets/entryfield.rb index 1f9effb46e..d53df216bf 100644 --- a/ext/tk/lib/tkextlib/iwidgets/entryfield.rb +++ b/ext/tk/lib/tkextlib/iwidgets/entryfield.rb @@ -43,6 +43,7 @@ class Tk::Iwidgets::Entryfield nil ] +=begin # for Ruby m17n :: ?x --> String --> char-code ( getbyte(0) ) KEY_TBL.map!{|inf| if inf.kind_of?(Array) @@ -58,6 +59,7 @@ class Tk::Iwidgets::Entryfield end inf } +=end _setup_subst_table(KEY_TBL, PROC_TBL); end diff --git a/ext/tk/lib/tkextlib/iwidgets/hierarchy.rb b/ext/tk/lib/tkextlib/iwidgets/hierarchy.rb index 4e7d8f8579..d9220fecbf 100644 --- a/ext/tk/lib/tkextlib/iwidgets/hierarchy.rb +++ b/ext/tk/lib/tkextlib/iwidgets/hierarchy.rb @@ -31,6 +31,7 @@ class Tk::Iwidgets::Hierarchy KEY_TBL = [ [?n, ?s, :node], nil ] PROC_TBL = [ [?s, TkComm.method(:string) ], nil ] +=begin # for Ruby m17n :: ?x --> String --> char-code ( getbyte(0) ) KEY_TBL.map!{|inf| if inf.kind_of?(Array) @@ -46,6 +47,7 @@ class Tk::Iwidgets::Hierarchy end inf } +=end _setup_subst_table(KEY_TBL, PROC_TBL); @@ -74,6 +76,7 @@ class Tk::Iwidgets::Hierarchy nil ] +=begin # for Ruby m17n :: ?x --> String --> char-code ( getbyte(0) ) KEY_TBL.map!{|inf| if inf.kind_of?(Array) @@ -89,6 +92,7 @@ class Tk::Iwidgets::Hierarchy end inf } +=end _setup_subst_table(KEY_TBL, PROC_TBL); @@ -112,6 +116,7 @@ class Tk::Iwidgets::Hierarchy ] PROC_TBL = [ [ ?s, TkComm.method(:string) ], nil ] +=begin # for Ruby m17n :: ?x --> String --> char-code ( getbyte(0) ) KEY_TBL.map!{|inf| if inf.kind_of?(Array) @@ -127,6 +132,7 @@ class Tk::Iwidgets::Hierarchy end inf } +=end _setup_subst_table(KEY_TBL, PROC_TBL); diff --git a/ext/tk/lib/tkextlib/iwidgets/spinner.rb b/ext/tk/lib/tkextlib/iwidgets/spinner.rb index 126cfe7c95..aeee5c9038 100644 --- a/ext/tk/lib/tkextlib/iwidgets/spinner.rb +++ b/ext/tk/lib/tkextlib/iwidgets/spinner.rb @@ -38,6 +38,7 @@ class Tk::Iwidgets::Spinner nil ] +=begin # for Ruby m17n :: ?x --> String --> char-code ( getbyte(0) ) KEY_TBL.map!{|inf| if inf.kind_of?(Array) @@ -53,6 +54,7 @@ class Tk::Iwidgets::Spinner end inf } +=end _setup_subst_table(KEY_TBL, PROC_TBL); end diff --git a/ext/tk/lib/tkextlib/tile.rb b/ext/tk/lib/tkextlib/tile.rb index b6beb8a11e..60ea012cc0 100644 --- a/ext/tk/lib/tkextlib/tile.rb +++ b/ext/tk/lib/tkextlib/tile.rb @@ -201,6 +201,38 @@ module Tk args.map!{|arg| TkComm._get_eval_string(arg)}.join('.') end + def self.themes(glob_ptn = nil) + if TILE_SPEC_VERSION_ID < 8 && Tk.info(:commands, '::ttk::themes').empty? + fail RuntimeError, 'not support glob option' if glob_ptn + cmd = ['::tile::availableThemes'] + else + glob_ptn = '*' unless glob_ptn + cmd = ['::ttk::themes', glob_ptn] + end + + begin + TkComm.simplelist(Tk.tk_call_without_enc(*cmd)) + rescue + TkComm.simplelist(Tk.tk_call('lsearch', '-all', '-inline', + Tk::Tile::Style.theme_names, + glob_ptn)) + end + end + + def self.set_theme(theme) + if TILE_SPEC_VERSION_ID < 8 && Tk.info(:commands, '::ttk::setTheme').empty? + cmd = '::tile::setTheme' + else + cmd = '::ttk::setTheme' + end + + begin + Tk.tk_call_without_enc(cmd, theme) + rescue + Tk::Tile::Style.theme_use(theme) + end + end + module KeyNav if Tk::Tile::TILE_SPEC_VERSION_ID < 8 def self.enableMnemonics(w) @@ -332,12 +364,16 @@ module Tk autoload :TLabelframe, 'tkextlib/tile/tlabelframe' autoload :Labelframe, 'tkextlib/tile/tlabelframe' + autoload :TLabelFrame, 'tkextlib/tile/tlabelframe' + autoload :LabelFrame, 'tkextlib/tile/tlabelframe' autoload :TLabel, 'tkextlib/tile/tlabel' autoload :Label, 'tkextlib/tile/tlabel' autoload :TMenubutton, 'tkextlib/tile/tmenubutton' autoload :Menubutton, 'tkextlib/tile/tmenubutton' + autoload :TMenuButton, 'tkextlib/tile/tmenubutton' + autoload :MenuButton, 'tkextlib/tile/tmenubutton' autoload :TNotebook, 'tkextlib/tile/tnotebook' autoload :Notebook, 'tkextlib/tile/tnotebook' diff --git a/ext/tk/lib/tkextlib/tile/style.rb b/ext/tk/lib/tkextlib/tile/style.rb index 098f4e4f72..ca7ee99c32 100644 --- a/ext/tk/lib/tkextlib/tile/style.rb +++ b/ext/tk/lib/tkextlib/tile/style.rb @@ -33,6 +33,8 @@ class << Tk::Tile::Style # conflict with some definitions on Tcl/Tk scripts. if Tk::Tile::TILE_SPEC_VERSION_ID < 7 def __define_wrapper_proc_for_compatibility__! + __define_themes_and_setTheme_proc__! + unless Tk.info(:commands, '::ttk::style').empty? # fail RuntimeError, # "can't define '::ttk::style' command (already exist)" @@ -59,6 +61,8 @@ class << Tk::Tile::Style end else ### TILE_SPEC_VERSION_ID == 7 def __define_wrapper_proc_for_compatibility__! + __define_themes_and_setTheme_proc__! + unless Tk.info(:commands, '::ttk::style').empty? # fail RuntimeError, # "can't define '::ttk::style' command (already exist)" @@ -91,6 +95,8 @@ class << Tk::Tile::Style TkCommandNames = ['::ttk::style'.freeze].freeze def __define_wrapper_proc_for_compatibility__! + __define_themes_and_setTheme_proc__! + unless Tk.info(:commands, '::style').empty? # fail RuntimeError, "can't define '::style' command (already exist)" @@ -120,6 +126,36 @@ class << Tk::Tile::Style end end + def __define_themes_and_setTheme_proc__! + TkCore::INTERP.add_tk_procs('::ttk::themes', '{ptn *}', <<-'EOS') + #set themes [list] + set themes [::ttk::style theme names] + foreach pkg [lsearch -inline -all -glob [package names] ttk::theme::$ptn] { + set theme [namespace tail $pkg] + if {[lsearch -exact $themes $theme] < 0} { + lappend themes $theme + } + } + foreach pkg [lsearch -inline -all -glob [package names] tile::theme::$ptn] { + set theme [namespace tail $pkg] + if {[lsearch -exact $themes $theme] < 0} { + lappend themes $theme + } + } + return $themes + EOS + ######################### + TkCore::INTERP.add_tk_procs('::ttk::setTheme', 'theme', <<-'EOS') + variable currentTheme + if {[lsearch -exact [::ttk::style theme names] $theme] < 0} { + package require [lsearch -inline -regexp [package names] (ttk|tile)::theme::$theme] + } + ::ttk::style theme use $theme + set currentTheme $theme + EOS + end + private :__define_themes_and_setTheme_proc__! + def configure(style=nil, keys=nil) if style.kind_of?(Hash) keys = style diff --git a/ext/tk/lib/tkextlib/tile/tnotebook.rb b/ext/tk/lib/tkextlib/tile/tnotebook.rb index 76f225c579..075059d5cc 100644 --- a/ext/tk/lib/tkextlib/tile/tnotebook.rb +++ b/ext/tk/lib/tkextlib/tile/tnotebook.rb @@ -77,9 +77,9 @@ class Tk::Tile::TNotebook < TkWindow def add(child, keys=nil) if keys && keys != None - tk_send_without_enc('add', _epath(child), *hash_kv(keys)) + tk_send('add', _epath(child), *hash_kv(keys)) else - tk_send_without_enc('add', _epath(child)) + tk_send('add', _epath(child)) end self end diff --git a/ext/tk/lib/tkextlib/tkDND/shape.rb b/ext/tk/lib/tkextlib/tkDND/shape.rb index 570c93b0d9..d44068ed33 100644 --- a/ext/tk/lib/tkextlib/tkDND/shape.rb +++ b/ext/tk/lib/tkextlib/tkDND/shape.rb @@ -11,15 +11,15 @@ require 'tkextlib/setup.rb' # call setup script require 'tkextlib/tkDND/setup.rb' -# TkPackage.require('shape', '0.3') -TkPackage.require('shape') +# TkPackage.require('Shape', '0.3') +TkPackage.require('Shape') module Tk module TkDND module Shape extend TkCore - PACKAGE_NAME = 'shape'.freeze + PACKAGE_NAME = 'Shape'.freeze def self.package_name PACKAGE_NAME end @@ -27,26 +27,28 @@ module Tk =begin def self.package_version begin - TkPackage.require('shape') + TkPackage.require('Shape') rescue '' end end =end - def self.package_version - Tk.tk_call('set', 'shape_version') - end - alias shape_version package_version + class << self + def package_version + Tk.tk_call('set', 'shape_version') + end + alias shape_version package_version - def self.package_patchlevel - Tk.tk_call('set', 'shape_patchlevel') - end - alias shape_patchlevel package_patchlevel + def package_patchlevel + Tk.tk_call('set', 'shape_patchLevel') + end + alias shape_patchlevel package_patchlevel - def self.version - tk_call('shape', 'version') + def version + tk_call('shape', 'version') + end + alias xshape_version version end - alias xshape_version version ############################ diff --git a/ext/tk/lib/tkextlib/tkDND/tkdnd.rb b/ext/tk/lib/tkextlib/tkDND/tkdnd.rb index ea91d3d1f4..9a9b2dc42c 100644 --- a/ext/tk/lib/tkextlib/tkDND/tkdnd.rb +++ b/ext/tk/lib/tkextlib/tkDND/tkdnd.rb @@ -57,6 +57,7 @@ module Tk nil ] +=begin # for Ruby m17n :: ?x --> String --> char-code ( getbyte(0) ) KEY_TBL.map!{|inf| if inf.kind_of?(Array) @@ -72,6 +73,7 @@ module Tk end inf } +=end # setup tables _setup_subst_table(KEY_TBL, PROC_TBL); diff --git a/ext/tk/lib/tkextlib/tktable/tktable.rb b/ext/tk/lib/tkextlib/tktable/tktable.rb index fb8a8b0f72..b5bf4ea6c3 100644 --- a/ext/tk/lib/tkextlib/tktable/tktable.rb +++ b/ext/tk/lib/tkextlib/tktable/tktable.rb @@ -291,6 +291,7 @@ class Tk::TkTable nil ] +=begin # for Ruby m17n :: ?x --> String --> char-code ( getbyte(0) ) KEY_TBL.map!{|inf| if inf.kind_of?(Array) @@ -306,6 +307,7 @@ class Tk::TkTable end inf } +=end _setup_subst_table(KEY_TBL, PROC_TBL); @@ -340,6 +342,7 @@ class Tk::TkTable nil ] +=begin # for Ruby m17n :: ?x --> String --> char-code ( getbyte(0) ) KEY_TBL.map!{|inf| if inf.kind_of?(Array) @@ -355,6 +358,7 @@ class Tk::TkTable end inf } +=end _setup_subst_table(KEY_TBL, PROC_TBL); @@ -387,6 +391,7 @@ class Tk::TkTable nil ] +=begin # for Ruby m17n :: ?x --> String --> char-code ( getbyte(0) ) KEY_TBL.map!{|inf| if inf.kind_of?(Array) @@ -402,6 +407,7 @@ class Tk::TkTable end inf } +=end _setup_subst_table(KEY_TBL, PROC_TBL); @@ -437,6 +443,7 @@ class Tk::TkTable nil ] +=begin # for Ruby m17n :: ?x --> String --> char-code ( getbyte(0) ) KEY_TBL.map!{|inf| if inf.kind_of?(Array) @@ -452,6 +459,7 @@ class Tk::TkTable end inf } +=end _setup_subst_table(KEY_TBL, PROC_TBL); end diff --git a/ext/tk/lib/tkextlib/treectrl/tktreectrl.rb b/ext/tk/lib/tkextlib/treectrl/tktreectrl.rb index d025bc4086..5e86a19406 100644 --- a/ext/tk/lib/tkextlib/treectrl/tktreectrl.rb +++ b/ext/tk/lib/tkextlib/treectrl/tktreectrl.rb @@ -137,6 +137,7 @@ class Tk::TreeCtrl::NotifyEvent nil ] +=begin # for Ruby m17n :: ?x --> String --> char-code ( getbyte(0) ) KEY_TBL.map!{|inf| if inf.kind_of?(Array) @@ -152,6 +153,7 @@ class Tk::TreeCtrl::NotifyEvent end inf } +=end # setup tables to be used by scan_args, _get_subst_key, _get_all_subst_keys # diff --git a/ext/tk/lib/tkextlib/version.rb b/ext/tk/lib/tkextlib/version.rb index 08cccf56c2..f437dea7fd 100644 --- a/ext/tk/lib/tkextlib/version.rb +++ b/ext/tk/lib/tkextlib/version.rb @@ -2,5 +2,5 @@ # release date of tkextlib # module Tk - Tkextlib_RELEASE_DATE = '2008-04-18'.freeze + Tkextlib_RELEASE_DATE = '2008-05-14'.freeze end diff --git a/ext/tk/lib/tkextlib/winico/winico.rb b/ext/tk/lib/tkextlib/winico/winico.rb index 30fb9682d5..00316fd441 100644 --- a/ext/tk/lib/tkextlib/winico/winico.rb +++ b/ext/tk/lib/tkextlib/winico/winico.rb @@ -150,6 +150,7 @@ class Tk::Winico nil ] +=begin # for Ruby m17n :: ?x --> String --> char-code ( getbyte(0) ) KEY_TBL.map!{|inf| if inf.kind_of?(Array) @@ -165,6 +166,7 @@ class Tk::Winico end inf } +=end _setup_subst_table(KEY_TBL, PROC_TBL); @@ -185,7 +187,8 @@ class Tk::Winico Winico_callback._config_keys.each{|k| if keys[k].kind_of?(Array) cmd, *args = keys[k] - keys[k] = Winico_callback.new(cmd, args.join(' ')) + #keys[k] = Winico_callback.new(cmd, args.join(' ')) + keys[k] = Winico_callback.new(cmd, *args) # elsif keys[k].kind_of?(Proc) elsif TkComm._callback_entry?(keys[k]) keys[k] = Winico_callback.new(keys[k]) @@ -201,7 +204,8 @@ class Tk::Winico Winico_callback._config_keys.each{|k| if keys[k].kind_of?(Array) cmd, *args = keys[k] - keys[k] = Winico_callback.new(cmd, args.join(' ')) + #keys[k] = Winico_callback.new(cmd, args.join(' ')) + keys[k] = Winico_callback.new(cmd, *args) # elsif keys[k].kind_of?(Proc) elsif TkComm._callback_entry?(keys[k]) keys[k] = Winico_callback.new(keys[k]) diff --git a/ext/tk/sample/demos-en/aniwave.rb b/ext/tk/sample/demos-en/aniwave.rb index ebe27b875f..bdb8d217c0 100644 --- a/ext/tk/sample/demos-en/aniwave.rb +++ b/ext/tk/sample/demos-en/aniwave.rb @@ -58,6 +58,7 @@ class AnimatedWaveDemo @backupCoords = [] n = 0 (-10..300).step(5){|n| @waveCoords << [n, 100]; @backupCoords << [n, 100] } + n = 305 @waveCoords << [n, 0]; @backupCoords << [n, 0] @waveCoords << [n+5, 200]; @backupCoords << [n+5, 200] @coordsLen = @waveCoords.length diff --git a/ext/tk/sample/demos-jp/aniwave.rb b/ext/tk/sample/demos-jp/aniwave.rb index 5f94add111..ec307dbc0c 100644 --- a/ext/tk/sample/demos-jp/aniwave.rb +++ b/ext/tk/sample/demos-jp/aniwave.rb @@ -60,6 +60,7 @@ class AnimatedWaveDemo @backupCoords = [] n = 0 (-10..300).step(5){|n| @waveCoords << [n, 100]; @backupCoords << [n, 100] } + n = 305 @waveCoords << [n, 0]; @backupCoords << [n, 0] @waveCoords << [n+5, 200]; @backupCoords << [n+5, 200] @coordsLen = @waveCoords.length diff --git a/ext/tk/sample/ttk_wrapper.rb b/ext/tk/sample/ttk_wrapper.rb index 8bd818f5c4..1580668994 100644 --- a/ext/tk/sample/ttk_wrapper.rb +++ b/ext/tk/sample/ttk_wrapper.rb @@ -4,7 +4,7 @@ # # by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) # -version = '0.1.1' +version = '0.1.3' # ########################################################################## # parse commandline arguments @@ -108,37 +108,36 @@ TkItemConfigMethod.__set_IGNORE_UNKNOWN_CONFIGURE_OPTION__! true ########################################################################## -# define utility method +# set theme of widget style ########################################################################## -def setTheme(theme) - unless Tk::Tile::Style.theme_names.find{|n| n == theme} - if (pkg = TkPackage.names.find{|n| n =~ /(tile|ttk)::theme::#{theme}/}) - TkPackage.require(pkg) - end - end - Tk::Tile::Style.theme_use(theme) +if OPTS[:list] || OPTS[:verbose] + print "supported theme names: #{Tk::Tile.themes.inspect}\n" + exit if OPTS[:list] && ARGV.empty? end +print "use theme: \"#{OPTS[:theme]}\"\n" if OPTS[:theme] && OPTS[:verbose] +#setTheme(OPTS[:theme]) if OPTS[:theme] +Tk::Tile.set_theme(OPTS[:theme]) if OPTS[:theme] ########################################################################## -# make theme name list +# replace $0 and $RPAGRAM_NAME ########################################################################## -ThemesList = Tk::Tile::Style.theme_names -TkPackage.names.find_all{|n| n =~ /^(tile|ttk)::theme::/}.each{|pkg| - ThemesList << pkg.split('::')[-1] -} -ThemesList.uniq! +# When the expand_path of the target script is long, ruby sometimes +# fails to set the path to $0 (the path string is trimmed). +# The following replaces $0 and $PROGNAME to avoid such trouble. +progname_obj = $0.dup +$program_name = progname_obj +alias $REAL_PROGRAM_NAME $0 +alias $PROGRAM_NAME $program_name +alias $0 $program_name -########################################################################## -# set theme of widget style -########################################################################## -if OPTS[:list] || OPTS[:verbose] - print "supported theme names: #{ThemesList.inspect}\n" - exit if OPTS[:list] && ARGV.empty? -end -print "use theme: \"#{OPTS[:theme]}\"\n" if OPTS[:theme] && OPTS[:verbose] -setTheme(OPTS[:theme]) if OPTS[:theme] +trace_var(:$program_name){|val| + unless progname_obj.object_id == val.object_id + progname_obj.replace(val.to_s) + $program_name = progname_obj + end +} ########################################################################## @@ -146,6 +145,7 @@ setTheme(OPTS[:theme]) if OPTS[:theme] ########################################################################## if (path = ARGV.shift) && (script = File.expand_path(path)) print "load script \"#{script}\"\n" if OPTS[:verbose] + $0 = script load(script) else print "Error: no script is given.\n" diff --git a/ext/tk/tcltklib.c b/ext/tk/tcltklib.c index e9aeb7d2fc..680b8da984 100644 --- a/ext/tk/tcltklib.c +++ b/ext/tk/tcltklib.c @@ -4,7 +4,7 @@ * Oct. 24, 1997 Y. Matsumoto */ -#define TCLTKLIB_RELEASE_DATE "2008-04-02" +#define TCLTKLIB_RELEASE_DATE "2008-05-16" #include "ruby.h" @@ -3153,6 +3153,7 @@ ip_ruby_cmd(clientData, interp, argc, argv) str, "'", (char *)NULL); rbtk_pending_exception = rb_exc_new2(rb_eArgError, Tcl_GetStringResult(interp)); + if (old_gc == Qfalse) rb_gc_enable(); return TCL_ERROR; #endif } @@ -5155,6 +5156,8 @@ ip_finalize(ip) Tcl_CreateCommand(ip, "ruby_cmd", ip_null_proc, (ClientData)NULL, (Tcl_CmdDeleteProc *)NULL); #endif + rb_thread_critical = thr_crit_bup; + return; } /* delete root widget */ @@ -5162,7 +5165,7 @@ ip_finalize(ip) DUMP1("check `destroy'"); if (Tcl_GetCommandInfo(ip, "destroy", &info)) { DUMP1("call `destroy'"); - Tcl_GlobalEval(ip, "destroy ."); + Tcl_GlobalEval(ip, "catch {destroy .}"); } #endif #if 1 @@ -7106,7 +7109,8 @@ lib_toUTF8_core(ip_obj, src, encodename) if (NIL_P(enc)) { encoding = (Tcl_Encoding)NULL; } else { - StringValue(enc); + /* StringValue(enc); */ + enc = rb_funcall(enc, ID_to_s, 0, 0); /* encoding = Tcl_GetEncoding(interp, RSTRING_PTR(enc)); */ encoding = Tcl_GetEncoding((Tcl_Interp*)NULL, RSTRING_PTR(enc)); @@ -7292,7 +7296,8 @@ lib_fromUTF8_core(ip_obj, src, encodename) if (NIL_P(enc)) { encoding = (Tcl_Encoding)NULL; } else { - StringValue(enc); + /* StringValue(enc); */ + enc = rb_funcall(enc, ID_to_s, 0, 0); /* encoding = Tcl_GetEncoding(interp, RSTRING_PTR(enc)); */ encoding = Tcl_GetEncoding((Tcl_Interp*)NULL, RSTRING_PTR(enc)); diff --git a/ext/tk/tkutil/extconf.rb b/ext/tk/tkutil/extconf.rb index 51f775619c..015bc3a45e 100644 --- a/ext/tk/tkutil/extconf.rb +++ b/ext/tk/tkutil/extconf.rb @@ -8,5 +8,6 @@ end if has_tk require 'mkmf' have_func("rb_obj_instance_exec", "ruby.h") + have_func("strndup", "string.h") create_makefile('tkutil') end diff --git a/ext/tk/tkutil/tkutil.c b/ext/tk/tkutil/tkutil.c index 1781dd5e4a..d6c70db22e 100644 --- a/ext/tk/tkutil/tkutil.c +++ b/ext/tk/tkutil/tkutil.c @@ -7,7 +7,7 @@ ************************************************/ -#define TKUTIL_RELEASE_DATE "2008-03-29" +#define TKUTIL_RELEASE_DATE "2008-05-14" #include "ruby.h" @@ -1073,11 +1073,13 @@ tcl2rb_num_or_str(self, value) /*************************************/ +#define CBSUBST_TBL_MAX (256) struct cbsubst_info { - int size; - char *key; - char *type; - ID *ivar; + int full_subst_length; + int keylen[CBSUBST_TBL_MAX]; + unsigned char *key[CBSUBST_TBL_MAX]; + unsigned char type[CBSUBST_TBL_MAX]; + ID ivar[CBSUBST_TBL_MAX]; VALUE proc; VALUE aliases; }; @@ -1094,42 +1096,49 @@ static void subst_free(ptr) struct cbsubst_info *ptr; { + int i; + if (ptr) { - if (ptr->key != (char*)NULL) free(ptr->key); - if (ptr->type != (char*)NULL) free(ptr->type); - if (ptr->ivar != (ID*)NULL) free(ptr->ivar); - free(ptr); + for(i = 0; i < CBSUBST_TBL_MAX; i++) { + if (ptr->key[i] != (unsigned char *)NULL) free(ptr->key[i]); + } + free(ptr); } } -static void -cbsubst_init() +static struct cbsubst_info * +allocate_cbsubst_info() { - struct cbsubst_info *inf; - ID *ivar; - volatile VALUE proc, aliases; - - inf = ALLOC(struct cbsubst_info); + struct cbsubst_info *inf; + volatile VALUE proc, aliases; + int idx; - inf->size = 0; + inf = ALLOC(struct cbsubst_info); - inf->key = ALLOC_N(char, 1); - inf->key[0] = '\0'; + inf->full_subst_length = 0; - inf->type = ALLOC_N(char, 1); - inf->type[0] = '\0'; + for(idx = 0; idx < CBSUBST_TBL_MAX; idx++) { + inf->keylen[idx] = 0; + inf->key[idx] = (unsigned char *) NULL; + inf->type[idx] = '\0'; + inf->ivar[idx] = (ID) 0; + } - ivar = ALLOC_N(ID, 1); - inf->ivar = ivar; + proc = rb_hash_new(); + inf->proc = proc; - proc = rb_hash_new(); - inf->proc = proc; + aliases = rb_hash_new(); + inf->aliases = aliases; - aliases = rb_hash_new(); - inf->aliases = aliases; + return inf; +} +static void +cbsubst_init() +{ rb_const_set(cCB_SUBST, ID_SUBST_INFO, - Data_Wrap_Struct(cSUBST_INFO, subst_mark, subst_free, inf)); + Data_Wrap_Struct(cSUBST_INFO, subst_mark, subst_free, + allocate_cbsubst_info())); } static VALUE @@ -1139,24 +1148,29 @@ cbsubst_initialize(argc, argv, self) VALUE self; { struct cbsubst_info *inf; - int idx; + int idx, iv_idx; Data_Get_Struct(rb_const_get(rb_obj_class(self), ID_SUBST_INFO), struct cbsubst_info, inf); - for(idx = 0; idx < argc; idx++) { - rb_ivar_set(self, inf->ivar[idx], argv[idx]); + idx = 0; + for(iv_idx = 0; iv_idx < CBSUBST_TBL_MAX; iv_idx++) { + if ( inf->ivar[iv_idx] == (ID) 0 ) continue; + rb_ivar_set(self, inf->ivar[iv_idx], argv[idx++]); + if (idx >= argc) break; } return self; } - static VALUE cbsubst_ret_val(self, val) VALUE self; VALUE val; { + /* This method may be overwritten on some sub-classes. */ + /* This method is used for converting from ruby's callback-return-value */ + /* to tcl's value (e.g. validation procedure of entry widget). */ return val; } @@ -1217,6 +1231,59 @@ cbsubst_def_attr_aliases(self, tbl) } static VALUE +cbsubst_sym_to_subst(self, sym) + VALUE self; + VALUE sym; +{ + struct cbsubst_info *inf; + const char *str; + unsigned char *buf, *ptr; + int idx, len; + ID id; + volatile VALUE ret; + + if (TYPE(sym) != T_SYMBOL) return sym; + + Data_Get_Struct(rb_const_get(self, ID_SUBST_INFO), + struct cbsubst_info, inf); + + if (!NIL_P(ret = rb_hash_aref(inf->aliases, sym))) { + str = rb_id2name(SYM2ID(ret)); + } else { + str = rb_id2name(SYM2ID(sym)); + } + + id = rb_intern(RSTRING_PTR(rb_str_cat2(rb_str_new2("@"), str))); + + for(idx = 0; idx < CBSUBST_TBL_MAX; idx++) { + if (inf->ivar[idx] == id) break; + } + if (idx >= CBSUBST_TBL_MAX) return sym; + + ptr = buf = ALLOC_N(char, inf->full_subst_length + 1); + + *(ptr++) = '%'; + + if (len = inf->keylen[idx]) { + /* longname */ + strncpy(ptr, inf->key[idx], len); + ptr += len; + } else { + /* single char */ + *(ptr++) = idx; + } + + *(ptr++) = ' '; + *(ptr++) = '\0'; + + ret = rb_str_new2(buf); + + free(buf); + + return ret; +} + +static VALUE cbsubst_get_subst_arg(argc, argv, self) int argc; VALUE *argv; @@ -1224,17 +1291,15 @@ cbsubst_get_subst_arg(argc, argv, self) { struct cbsubst_info *inf; const char *str; - char *buf, *ptr; - int i, j, len; + unsigned char *buf, *ptr; + int i, idx, len; ID id; volatile VALUE arg_sym, ret; Data_Get_Struct(rb_const_get(self, ID_SUBST_INFO), struct cbsubst_info, inf); - buf = ALLOC_N(char, 3*argc + 1); - ptr = buf; - len = strlen(inf->key); + ptr = buf = ALLOC_N(char, inf->full_subst_length + 1); for(i = 0; i < argc; i++) { switch(TYPE(argv[i])) { @@ -1256,17 +1321,25 @@ cbsubst_get_subst_arg(argc, argv, self) id = rb_intern(RSTRING_PTR(rb_str_cat2(rb_str_new2("@"), str))); - for(j = 0; j < len; j++) { - if (inf->ivar[j] == id) break; - } - - if (j >= len) { + for(idx = 0; idx < CBSUBST_TBL_MAX; idx++) { + if (inf->ivar[idx] == id) break; + } + if (idx >= CBSUBST_TBL_MAX) { rb_raise(rb_eArgError, "cannot find attribute :%s", str); } - *(ptr++) = '%'; - *(ptr++) = *(inf->key + j); - *(ptr++) = ' '; + *(ptr++) = '%'; + + if (len = inf->keylen[idx]) { + /* longname */ + strncpy(ptr, inf->key[idx], len); + ptr += len; + } else { + /* single char */ + *(ptr++) = idx; + } + + *(ptr++) = ' '; } *ptr = '\0'; @@ -1283,27 +1356,50 @@ cbsubst_get_subst_key(self, str) VALUE self; VALUE str; { + struct cbsubst_info *inf; volatile VALUE list; volatile VALUE ret; - int i, len; - char *buf, *ptr; + VALUE keyval; + int i, len, keylen, idx; + unsigned char *buf, *ptr, *key; list = rb_funcall(cTclTkLib, ID_split_tklist, 1, str); - len = RARRAY_LEN(list); - buf = ALLOC_N(char, len + 1); + + Data_Get_Struct(rb_const_get(self, ID_SUBST_INFO), + struct cbsubst_info, inf); + + ptr = buf = ALLOC_N(unsigned char, inf->full_subst_length + len + 1); for(i = 0; i < len; i++) { - ptr = RSTRING_PTR(RARRAY_PTR(list)[i]); - if (*ptr == '%' && *(ptr + 2) == '\0') { - *(buf + i) = *(ptr + 1); - } else { - *(buf + i) = ' '; - } + keyval = RARRAY_PTR(list)[i]; + key = (unsigned char*)RSTRING_PTR(keyval); + if (*key == '%') { + if (*(key + 2) == '\0') { + /* single char */ + *(ptr++) = *(key + 1); + } else { + /* search longname-key */ + keylen = RSTRING_LEN(keyval) - 1; + for(idx = 0; idx < CBSUBST_TBL_MAX; idx++) { + if (inf->keylen[idx] != keylen) continue; + if (inf->key[idx][0] != *(key + 1)) continue; + if (strncmp(inf->key[idx], key + 1, keylen)) continue; + break; + } + if (idx < CBSUBST_TBL_MAX) { + *(ptr++) = (unsigned char)idx; + } else { + *(ptr++) = ' '; + } + } + } else { + *(ptr++) = ' '; + } } - *(buf + len) = '\0'; + *ptr = '\0'; - ret = rb_str_new2(buf); + ret = rb_str_new2((const char*)buf); free(buf); return ret; } @@ -1313,24 +1409,40 @@ cbsubst_get_all_subst_keys(self) VALUE self; { struct cbsubst_info *inf; - char *buf, *ptr; - int i, len; + unsigned char *buf, *ptr; + unsigned char *keys_buf, *keys_ptr; + int idx, len; volatile VALUE ret; Data_Get_Struct(rb_const_get(self, ID_SUBST_INFO), struct cbsubst_info, inf); - len = strlen(inf->key); - buf = ALLOC_N(char, 3*len + 1); - ptr = buf; - for(i = 0; i < len; i++) { - *(ptr++) = '%'; - *(ptr++) = *(inf->key + i); - *(ptr++) = ' '; + ptr = buf = ALLOC_N(unsigned char, inf->full_subst_length + 1); + keys_ptr = keys_buf = ALLOC_N(unsigned char, CBSUBST_TBL_MAX + 1); + + for(idx = 0; idx < CBSUBST_TBL_MAX; idx++) { + if (inf->ivar[idx] == (ID) 0) continue; + + *(keys_ptr++) = (unsigned char)idx; + + *(ptr++) = '%'; + + if (len = inf->keylen[idx]) { + /* longname */ + strncpy(ptr, inf->key[idx], len); + ptr += len; + } else { + /* single char */ + *(ptr++) = (unsigned char)idx; + } + + *(ptr++) = ' '; } - *(buf + 3*len) = '\0'; - ret = rb_ary_new3(2, rb_str_new2(inf->key), rb_str_new2(buf)); + *ptr = '\0'; + *keys_ptr = '\0'; + + ret = rb_ary_new3(2, rb_str_new2(keys_buf), rb_str_new2((const char*)buf)); free(buf); @@ -1338,75 +1450,124 @@ cbsubst_get_all_subst_keys(self) } static VALUE -cbsubst_table_setup(self, key_inf, proc_inf) - VALUE self; - VALUE key_inf; - VALUE proc_inf; +cbsubst_table_setup(argc, argv, self) + int argc; + VALUE *argv; + VALUE self; { - struct cbsubst_info *subst_inf; - int idx; - int len = RARRAY_LEN(key_inf); - int real_len = 0; - char *key = ALLOC_N(char, len + 1); - char *type = ALLOC_N(char, len + 1); - ID *ivar = ALLOC_N(ID, len + 1); - volatile VALUE proc = rb_hash_new(); - volatile VALUE aliases = rb_hash_new(); - volatile VALUE inf; - - /* init */ - subst_inf = ALLOC(struct cbsubst_info); - /* subst_inf->size = len; */ - subst_inf->key = key; - subst_inf->type = type; - subst_inf->ivar = ivar; - subst_inf->proc = proc; - subst_inf->aliases = aliases; - - /* - * keys : array of [subst, type, ivar] - * subst ==> char code - * type ==> char code - * ivar ==> symbol - */ - for(idx = 0; idx < len; idx++) { - inf = RARRAY_PTR(key_inf)[idx]; - if (TYPE(inf) != T_ARRAY) continue; - *(key + real_len) = NUM2CHR(RARRAY_PTR(inf)[0]); - *(type + real_len) = NUM2CHR(RARRAY_PTR(inf)[1]); - - *(ivar + real_len) - = rb_intern( - RSTRING_PTR( - rb_str_cat2(rb_str_new2("@"), - rb_id2name(SYM2ID(RARRAY_PTR(inf)[2]))) - ) - ); - - rb_attr(self, SYM2ID(RARRAY_PTR(inf)[2]), 1, 0, Qtrue); - real_len++; + volatile VALUE key_inf; + volatile VALUE longkey_inf; + volatile VALUE proc_inf; + VALUE inf; + ID id; + struct cbsubst_info *subst_inf; + int idx, len; + unsigned char chr; + + /* accept (key_inf, proc_inf) or (key_inf, longkey_inf, procinf) */ + if (rb_scan_args(argc, argv, "21", &key_inf, &longkey_inf, &proc_inf) == 2) { + proc_inf = longkey_inf; + longkey_inf = rb_ary_new(); + } + + /* check the number of longkeys */ + if (RARRAY_LEN(longkey_inf) > 125 /* from 0x80 to 0xFD */) { + rb_raise(rb_eArgError, "too many longname-key definitions"); + } + + /* init */ + subst_inf = allocate_cbsubst_info(); + + /* + * keys : array of [subst, type, ivar] + * subst ==> char code or string + * type ==> char code or string + * ivar ==> symbol + */ + len = RARRAY_LEN(key_inf); + for(idx = 0; idx < len; idx++) { + inf = RARRAY_PTR(key_inf)[idx]; + if (TYPE(inf) != T_ARRAY) continue; + + if (TYPE(RARRAY_PTR(inf)[0]) == T_STRING) { + chr = *(RSTRING_PTR(RARRAY_PTR(inf)[0])); + } else { + chr = NUM2CHR(RARRAY_PTR(inf)[0]); } - *(key + real_len) = '\0'; - *(type + real_len) = '\0'; - subst_inf->size = real_len; - - /* - * procs : array of [type, proc] - * type ==> char code - * proc ==> proc/method/obj (must respond to 'call') - */ - len = RARRAY_LEN(proc_inf); - for(idx = 0; idx < len; idx++) { - inf = RARRAY_PTR(proc_inf)[idx]; - if (TYPE(inf) != T_ARRAY) continue; - rb_hash_aset(proc, RARRAY_PTR(inf)[0], RARRAY_PTR(inf)[1]); + if (TYPE(RARRAY_PTR(inf)[1]) == T_STRING) { + subst_inf->type[chr] = *(RSTRING_PTR(RARRAY_PTR(inf)[1])); + } else { + subst_inf->type[chr] = NUM2CHR(RARRAY_PTR(inf)[1]); } - rb_const_set(self, ID_SUBST_INFO, - Data_Wrap_Struct(cSUBST_INFO, subst_mark, - subst_free, subst_inf)); + subst_inf->full_subst_length += 3; - return self; + id = SYM2ID(RARRAY_PTR(inf)[2]); + subst_inf->ivar[chr] = rb_intern(RSTRING_PTR(rb_str_cat2(rb_str_new2("@"), rb_id2name(id)))); + + rb_attr(self, id, 1, 0, Qtrue); + } + + + /* + * longkeys : array of [name, type, ivar] + * name ==> longname key string + * type ==> char code or string + * ivar ==> symbol + */ + len = RARRAY_LEN(longkey_inf); + for(idx = 0; idx < len; idx++) { + inf = RARRAY_PTR(longkey_inf)[idx]; + if (TYPE(inf) != T_ARRAY) continue; + + chr = (unsigned char)(0x80 + idx); + subst_inf->keylen[chr] = RSTRING_LEN(RARRAY_PTR(inf)[0]); +#if HAVE_STRNDUP + subst_inf->key[chr] = strndup(RSTRING_PTR(RARRAY_PTR(inf)[0]), + RSTRING_LEN(RARRAY_PTR(inf)[0])); +#else + subst_inf->key[chr] = malloc(RSTRING_LEN(RARRAY_PTR(inf)[0]) + 1); + if (subst_inf->key[chr]) { + strncpy(subst_inf->key[chr], RSTRING_PTR(RARRAY_PTR(inf)[0]), + RSTRING_LEN(RARRAY_PTR(inf)[0]) + 1); + subst_inf->key[chr][RSTRING_LEN(RARRAY_PTR(inf)[0])] = '\0'; + } +#endif + if (TYPE(RARRAY_PTR(inf)[1]) == T_STRING) { + subst_inf->type[chr] = *(RSTRING_PTR(RARRAY_PTR(inf)[1])); + } else { + subst_inf->type[chr] = NUM2CHR(RARRAY_PTR(inf)[1]); + } + + subst_inf->full_subst_length += (subst_inf->keylen[chr] + 2); + + id = SYM2ID(RARRAY_PTR(inf)[2]); + subst_inf->ivar[chr] = rb_intern(RSTRING_PTR(rb_str_cat2(rb_str_new2("@"), rb_id2name(id)))); + + rb_attr(self, id, 1, 0, Qtrue); + } + + /* + * procs : array of [type, proc] + * type ==> char code or string + * proc ==> proc/method/obj (must respond to 'call') + */ + len = RARRAY_LEN(proc_inf); + for(idx = 0; idx < len; idx++) { + inf = RARRAY_PTR(proc_inf)[idx]; + if (TYPE(inf) != T_ARRAY) continue; + rb_hash_aset(subst_inf->proc, + ((TYPE(RARRAY_PTR(inf)[0]) == T_STRING)? + INT2FIX(*(RSTRING_PTR(RARRAY_PTR(inf)[0]))) : + RARRAY_PTR(inf)[0]), + RARRAY_PTR(inf)[1]); + } + + rb_const_set(self, ID_SUBST_INFO, + Data_Wrap_Struct(cSUBST_INFO, subst_mark, + subst_free, subst_inf)); + + return self; } static VALUE @@ -1424,10 +1585,11 @@ cbsubst_scan_args(self, arg_key, val_ary) { struct cbsubst_info *inf; int idx; - int len = RARRAY_LEN(val_ary); - char c; - char *ptr; - volatile VALUE dst = rb_ary_new2(len); + unsigned char *keyptr = (unsigned char*)RSTRING_PTR(arg_key); + int keylen = RSTRING_LEN(arg_key); + int vallen = RARRAY_LEN(val_ary); + unsigned char type_chr; + volatile VALUE dst = rb_ary_new2(vallen); volatile VALUE proc; int thr_crit_bup; VALUE old_gc; @@ -1440,26 +1602,25 @@ cbsubst_scan_args(self, arg_key, val_ary) Data_Get_Struct(rb_const_get(self, ID_SUBST_INFO), struct cbsubst_info, inf); - for(idx = 0; idx < len; idx++) { - if (idx >= RSTRING_LEN(arg_key)) { - proc = Qnil; - } else if (*(RSTRING_PTR(arg_key) + idx) == ' ') { - proc = Qnil; - } else { - ptr = strchr(inf->key, *(RSTRING_PTR(arg_key) + idx)); - if (ptr == (char*)NULL) { - proc = Qnil; - } else { - c = *(inf->type + (ptr - inf->key)); - proc = rb_hash_aref(inf->proc, INT2FIX(c)); - } - } - - if (NIL_P(proc)) { - rb_ary_push(dst, RARRAY_PTR(val_ary)[idx]); - } else { - rb_ary_push(dst, rb_funcall(proc, ID_call, 1, RARRAY_PTR(val_ary)[idx])); - } + for(idx = 0; idx < vallen; idx++) { + if (idx >= keylen) { + proc = Qnil; + } else if (*(keyptr + idx) == ' ') { + proc = Qnil; + } else { + if (type_chr = inf->type[*(keyptr + idx)]) { + proc = rb_hash_aref(inf->proc, INT2FIX((int)type_chr)); + } else { + proc = Qnil; + } + } + + if (NIL_P(proc)) { + rb_ary_push(dst, RARRAY_PTR(val_ary)[idx]); + } else { + rb_ary_push(dst, rb_funcall(proc, ID_call, 1, + RARRAY_PTR(val_ary)[idx])); + } } if (old_gc == Qfalse) rb_gc_enable(); @@ -1543,6 +1704,8 @@ Init_tkutil() ID_SUBST_INFO = rb_intern("SUBST_INFO"); rb_define_singleton_method(cCB_SUBST, "ret_val", cbsubst_ret_val, 1); rb_define_singleton_method(cCB_SUBST, "scan_args", cbsubst_scan_args, 2); + rb_define_singleton_method(cCB_SUBST, "_sym2subst", + cbsubst_sym_to_subst, 1); rb_define_singleton_method(cCB_SUBST, "subst_arg", cbsubst_get_subst_arg, -1); rb_define_singleton_method(cCB_SUBST, "_get_subst_key", @@ -1550,7 +1713,7 @@ Init_tkutil() rb_define_singleton_method(cCB_SUBST, "_get_all_subst_keys", cbsubst_get_all_subst_keys, 0); rb_define_singleton_method(cCB_SUBST, "_setup_subst_table", - cbsubst_table_setup, 2); + cbsubst_table_setup, -1); rb_define_singleton_method(cCB_SUBST, "_get_extra_args_tbl", cbsubst_get_extra_args_tbl, 0); rb_define_singleton_method(cCB_SUBST, "_define_attribute_aliases", |