summaryrefslogtreecommitdiff
path: root/ext
diff options
context:
space:
mode:
authornagai <nagai@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2008-03-29 05:25:12 +0000
committernagai <nagai@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2008-03-29 05:25:12 +0000
commit3024ffdc3a5fdb115de651edae9e3d7a335a6614 (patch)
treeacfc67e481cd24c5e1ca2a344bd97e514fb26246 /ext
parentb62af05a98bc3ebbbca546270e7efa5abd3a17f5 (diff)
* ext/tk/*: full update Ruby/Tk to support Ruby(1.9|1.8) and Tc/Tk8.5.
* ext/tk/lib/tkextlib/tile.rb: [incompatible] remove TileWidgets' instate/state/identify method to avoid the conflict with standard widget options. Those methods are renamed to ttk_instate/ttk_state/ ttk_identify (tile_instate/tile_state/tile_identify are available too). Although I don't recommend, if you realy need old methods, please define "Tk::USE_OBSOLETE_TILE_STATE_METHOD = true" before "require 'tkextlib/tile'". * ext/tk/lib/tkextlib/tile.rb: "Tk::Tile::__Import_Tile_Widgets__!" is obsolete. It outputs warning. To control default widget set, use "Tk.default_widget_set = :Ttk". * ext/tk/lib/tk.rb: __IGNORE_UNKNOWN_CONFIGURE_OPTION__ method and __set_IGNORE_UNKNOWN_CONFIGURE_OPTION__!(mode) method are defind as module methods of TkConfigMethod. It may help users to wrap old Ruby/Tk scripts (use standard widgets) to force to use Ttk widgets. Ttk widgets don't have some options of standard widgets which are control the view of widgets. When set ignore-mode true, configure method tries to ignoure such unknown options with no exception. Of course, it may raise other troubles on the GUI design. So, those are a little danger methods. * ext/tk/lib/tk/itemconfig.rb: __IGNORE_UNKNOWN_CONFIGURE_OPTION__ method and __set_IGNORE_UNKNOWN_CONFIGURE_OPTION__!(mode) method are defind as module methods of TkItemConfigMethod as the same purpose as TkConfigMethod's ones. * ext/tk/sample/ttk_wrapper.rb: A new example. This is a tool for wrapping old Ruby/Tk scripts (which use standard widgets) to use Ttk (Tile) widgets as default. * ext/tk/sample/tkextlib/tile/demo.rb: use ttk_instate/ttk_state method instead of instate/state method. * ext/tk/lib/tk/root, ext/tk/lib/tk/namespace.rb, ext/tk/lib/tk/text.rb, ext/tk/lib/tkextlib/*: some 'instance_eval's are replaced to "instance_exec(self)". * ext/tk/lib/tk/event.rb: bug fix on KEY_TBL and PROC_TBL (?x is not a character code on Ruby1.9). * ext/tk/lib/tk/variable.rb: support new style of operation argument on Tcl/Tk's 'trace' command for variables. * ext/tk/sample/demos-jp/widget, ext/tk/sample/demos-en/widget: bug fix * ext/tk/sammple/demos-jp/textpeer.rb, ext/tk/sammple/demos-en/textpeer.rb: new widget demo. * ext/tk/tcltklib.c: decrase SEGV troubles (probably) * ext/tk/lib/tk.rb: remove Thread.critical access if Ruby1.9 * ext/tk/lib/tk/multi-tk.rb: support Ruby1.9 (probably) * ext/tk/lib/tkextlib/tile.rb: add method to define Tcl/Tk command to make Tcl/Tk theme sources (based on different version of Tile extension) available. (Tk::Tile::__define_LoadImages_proc_for_comaptibility__) * ext/tk/lib/tk.rb, ext/tk/lib/tk/wm.rb: support dockable frames (Tcl/Tk8.5 feature). 'wm' command can treat many kinds of widgets as toplevel widgets. * ext/tk/lib/tkextlib/tile/style.rb: ditto. (Tk::Tile::Style.__define_wrapper_proc_for_compatibility__) * ext/tk/lib/tk/font.rb: add actual_hash and metrics_hash to get properties as a hash. metrics_hash method returns a boolean value for 'fixed' option. But metrics method returns numeric value (0 or 1) for 'fixed' option, because of backward compatibility. * ext/tk/lib/tk/timer.rb: somtimes fail to set callback procedure. * ext/tk/lib/tk.rb: add Tk.sleep and Tk.wakeup method. Tk.sleep doesn't block the eventloop. It will be better to use the method in event callbacks. * ext/tk/sample/tksleep_sample.rb: sample script about Tk.sleep. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@15848 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'ext')
-rw-r--r--ext/tk/MANUAL_tcltklib.eng7
-rw-r--r--ext/tk/MANUAL_tcltklib.eucj6
-rw-r--r--ext/tk/README.tcltklib14
-rw-r--r--ext/tk/extconf.rb58
-rw-r--r--ext/tk/lib/multi-tk.rb132
-rw-r--r--ext/tk/lib/tk.rb983
-rw-r--r--ext/tk/lib/tk/autoload.rb19
-rw-r--r--ext/tk/lib/tk/bindtag.rb83
-rw-r--r--ext/tk/lib/tk/canvas.rb34
-rw-r--r--ext/tk/lib/tk/canvastag.rb114
-rw-r--r--ext/tk/lib/tk/encodedstr.rb84
-rw-r--r--ext/tk/lib/tk/event.rb25
-rw-r--r--ext/tk/lib/tk/font.rb697
-rw-r--r--ext/tk/lib/tk/image.rb43
-rw-r--r--ext/tk/lib/tk/itemconfig.rb107
-rw-r--r--ext/tk/lib/tk/menu.rb27
-rw-r--r--ext/tk/lib/tk/msgcat.rb6
-rw-r--r--ext/tk/lib/tk/namespace.rb135
-rw-r--r--ext/tk/lib/tk/optiondb.rb14
-rw-r--r--ext/tk/lib/tk/root.rb8
-rw-r--r--ext/tk/lib/tk/scale.rb21
-rw-r--r--ext/tk/lib/tk/scrollbar.rb41
-rw-r--r--ext/tk/lib/tk/spinbox.rb16
-rw-r--r--ext/tk/lib/tk/text.rb34
-rw-r--r--ext/tk/lib/tk/textmark.rb73
-rw-r--r--ext/tk/lib/tk/texttag.rb89
-rw-r--r--ext/tk/lib/tk/timer.rb17
-rw-r--r--ext/tk/lib/tk/ttk_selector.rb9
-rw-r--r--ext/tk/lib/tk/validation.rb16
-rw-r--r--ext/tk/lib/tk/variable.rb486
-rw-r--r--ext/tk/lib/tk/virtevent.rb77
-rw-r--r--ext/tk/lib/tk/wm.rb476
-rw-r--r--ext/tk/lib/tkextlib/SUPPORT_STATUS2
-rw-r--r--ext/tk/lib/tkextlib/blt/bitmap.rb21
-rw-r--r--ext/tk/lib/tkextlib/blt/component.rb351
-rw-r--r--ext/tk/lib/tkextlib/blt/dragdrop.rb48
-rw-r--r--ext/tk/lib/tkextlib/blt/tabset.rb77
-rw-r--r--ext/tk/lib/tkextlib/blt/tree.rb341
-rw-r--r--ext/tk/lib/tkextlib/blt/treeview.rb197
-rw-r--r--ext/tk/lib/tkextlib/blt/vector.rb37
-rw-r--r--ext/tk/lib/tkextlib/blt/watch.rb28
-rw-r--r--ext/tk/lib/tkextlib/bwidget/buttonbox.rb16
-rw-r--r--ext/tk/lib/tkextlib/bwidget/combobox.rb8
-rw-r--r--ext/tk/lib/tkextlib/bwidget/dialog.rb24
-rw-r--r--ext/tk/lib/tkextlib/bwidget/labelframe.rb8
-rw-r--r--ext/tk/lib/tkextlib/bwidget/listbox.rb34
-rw-r--r--ext/tk/lib/tkextlib/bwidget/mainframe.rb48
-rw-r--r--ext/tk/lib/tkextlib/bwidget/messagedlg.rb5
-rw-r--r--ext/tk/lib/tkextlib/bwidget/notebook.rb24
-rw-r--r--ext/tk/lib/tkextlib/bwidget/pagesmanager.rb16
-rw-r--r--ext/tk/lib/tkextlib/bwidget/panedwindow.rb8
-rw-r--r--ext/tk/lib/tkextlib/bwidget/panelframe.rb8
-rw-r--r--ext/tk/lib/tkextlib/bwidget/progressdlg.rb4
-rw-r--r--ext/tk/lib/tkextlib/bwidget/scrollableframe.rb8
-rw-r--r--ext/tk/lib/tkextlib/bwidget/scrolledwindow.rb8
-rw-r--r--ext/tk/lib/tkextlib/bwidget/selectcolor.rb28
-rw-r--r--ext/tk/lib/tkextlib/bwidget/selectfont.rb7
-rw-r--r--ext/tk/lib/tkextlib/bwidget/statusbar.rb8
-rw-r--r--ext/tk/lib/tkextlib/bwidget/titleframe.rb8
-rw-r--r--ext/tk/lib/tkextlib/bwidget/tree.rb34
-rw-r--r--ext/tk/lib/tkextlib/bwidget/widget.rb8
-rw-r--r--ext/tk/lib/tkextlib/itcl/incr_tcl.rb12
-rw-r--r--ext/tk/lib/tkextlib/itk/incr_tk.rb44
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/calendar.rb17
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/entryfield.rb17
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/hierarchy.rb50
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/scrolledcanvas.rb10
-rw-r--r--ext/tk/lib/tkextlib/iwidgets/spinner.rb17
-rw-r--r--ext/tk/lib/tkextlib/tcllib/ico.rb6
-rw-r--r--ext/tk/lib/tkextlib/tcllib/plotchart.rb45
-rw-r--r--ext/tk/lib/tkextlib/tcllib/tkpiechart.rb14
-rw-r--r--ext/tk/lib/tkextlib/tile.rb142
-rw-r--r--ext/tk/lib/tkextlib/tile/style.rb134
-rw-r--r--ext/tk/lib/tkextlib/tile/treeview.rb130
-rw-r--r--ext/tk/lib/tkextlib/tkDND/tkdnd.rb16
-rw-r--r--ext/tk/lib/tkextlib/tkHTML/htmlwidget.rb17
-rw-r--r--ext/tk/lib/tkextlib/tktable/tktable.rb167
-rw-r--r--ext/tk/lib/tkextlib/treectrl/tktreectrl.rb233
-rw-r--r--ext/tk/lib/tkextlib/version.rb2
-rw-r--r--ext/tk/lib/tkextlib/vu/pie.rb73
-rw-r--r--ext/tk/lib/tkextlib/winico/winico.rb49
-rw-r--r--ext/tk/sample/binstr_usage.rb12
-rw-r--r--ext/tk/sample/demos-en/arrow.rb18
-rw-r--r--ext/tk/sample/demos-en/bind.rb9
-rw-r--r--ext/tk/sample/demos-en/ctext.rb45
-rw-r--r--ext/tk/sample/demos-en/hello6
-rw-r--r--ext/tk/sample/demos-en/hscale.rb2
-rw-r--r--ext/tk/sample/demos-en/items.rb9
-rw-r--r--ext/tk/sample/demos-en/patch_1.1c193
-rw-r--r--ext/tk/sample/demos-en/rolodex-j323
-rw-r--r--ext/tk/sample/demos-en/search.rb7
-rw-r--r--ext/tk/sample/demos-en/style.rb34
-rw-r--r--ext/tk/sample/demos-en/textpeer.rb72
-rw-r--r--ext/tk/sample/demos-en/twind.rb6
-rw-r--r--ext/tk/sample/demos-en/vscale.rb1
-rw-r--r--ext/tk/sample/demos-en/widget32
-rw-r--r--ext/tk/sample/demos-jp/arrow.rb18
-rw-r--r--ext/tk/sample/demos-jp/bind.rb9
-rw-r--r--ext/tk/sample/demos-jp/ctext.rb45
-rw-r--r--ext/tk/sample/demos-jp/hscale.rb1
-rw-r--r--ext/tk/sample/demos-jp/items.rb9
-rw-r--r--ext/tk/sample/demos-jp/plot.rb6
-rw-r--r--ext/tk/sample/demos-jp/search.rb7
-rw-r--r--ext/tk/sample/demos-jp/style.rb36
-rw-r--r--ext/tk/sample/demos-jp/textpeer.rb78
-rw-r--r--ext/tk/sample/demos-jp/twind.rb6
-rw-r--r--ext/tk/sample/demos-jp/vscale.rb2
-rw-r--r--ext/tk/sample/demos-jp/widget47
-rw-r--r--ext/tk/sample/encstr_usage.rb5
-rw-r--r--ext/tk/sample/irbtkw.rbw24
-rw-r--r--ext/tk/sample/tkextlib/tile/demo.rb37
-rw-r--r--ext/tk/sample/tkextlib/tile/themes/blue/pkgIndex.tcl2
-rw-r--r--ext/tk/sample/tkextlib/tile/themes/kroc.rb30
-rw-r--r--ext/tk/sample/tkextlib/tile/toolbutton.tcl33
-rw-r--r--ext/tk/sample/tkrttimer.rb13
-rw-r--r--ext/tk/sample/tksleep_sample.rb29
-rw-r--r--ext/tk/sample/ttk_wrapper.rb154
-rw-r--r--ext/tk/stubs.c64
-rw-r--r--ext/tk/tcltklib.c2053
-rw-r--r--ext/tk/tkutil/tkutil.c28
120 files changed, 7771 insertions, 2194 deletions
diff --git a/ext/tk/MANUAL_tcltklib.eng b/ext/tk/MANUAL_tcltklib.eng
index 9ef9adf26c..6fa775b7de 100644
--- a/ext/tk/MANUAL_tcltklib.eng
+++ b/ext/tk/MANUAL_tcltklib.eng
@@ -448,6 +448,10 @@ class TclTkIp
: slave interpreter, same to the TclTkLib module method with
: the same name.
+ encoding_table
+ : For Ruby m17n. Return encoding relation table between Ruby's
+ : Encoding object and Tcl's encoding name.
+
class TkCallbackBreak < StandardError
class TkCallbackContinue < StandardError
: They are exception classes to break or continue the Tk callback
@@ -458,5 +462,8 @@ class TkCallbackContinue < StandardError
: If raise TkCallbackContinue, returns 'continue' code (Then the Tk
: interpreter will break the operateion for the current bindtag and
: starts the operation for the next buindtag for the current event).
+ : However, current tcltklib supports Ruby's 'break' and 'next' to
+ : get the same effect. That is, those classes are obsolete. Those
+ : exist for backward compatibility.
(eof)
diff --git a/ext/tk/MANUAL_tcltklib.eucj b/ext/tk/MANUAL_tcltklib.eucj
index d291b7e807..7df42997b4 100644
--- a/ext/tk/MANUAL_tcltklib.eucj
+++ b/ext/tk/MANUAL_tcltklib.eucj
@@ -559,6 +559,9 @@ require "tcltklib" すると, 以下のモジュール, クラスが利用可能です.
: スレーブ IP の場合には値の設定が許されない (無視される).
: それ以外の点では引数を含めて TclTkLib の同名メソッドに同じ.
+ encoding_table
+ : Ruby m17n 用に Ruby と Tk との間の encoding 対応表を返す.
+
クラス TkCallbackBreak < StandardError
クラス TkCallbackContinue < StandardError
: これらはイベントコールバックにおいて,コールバック処理を適切に中
@@ -569,5 +572,8 @@ require "tcltklib" すると, 以下のモジュール, クラスが利用可能です.
: ドを返す必要がある.Ruby の手続きが普通に値を返すのでは,それが普
: 通の戻り値であるのか否かを区別ができないため,例外発生を利用した
: 実装を行っている.
+ : ただし現在では,コールバック手続きを Ruby の break, next で終了す
+ : ることで同等の結果を得ることができるようになっている.それゆえ,
+ : これらは必要ないものではあるが,互換性のために残してある.
(eof)
diff --git a/ext/tk/README.tcltklib b/ext/tk/README.tcltklib
index e939ba1f51..b94d778104 100644
--- a/ext/tk/README.tcltklib
+++ b/ext/tk/README.tcltklib
@@ -16,18 +16,18 @@ some or all of the following options.
--with-tk-dir=<path>
equal to "--with-tk-include=<path>/include --with-tk-lib=<path>/lib"
- --with-tcl-include=<dir> the directry containts 'tcl.h'
- --with-tk-include=<dir> the directry containts 'tk.h'
+ --with-tcl-include=<dir> the directry contains 'tcl.h'
+ --with-tk-include=<dir> the directry contains 'tk.h'
- --with-tcl-lib=<dir> the directry containts 'libtcl<version>.so'
- --with-tk-lib=<dir> the directry containts 'libtk<version>.so'
+ --with-tcl-lib=<dir> the directry contains 'libtcl<version>.so'
+ --with-tk-lib=<dir> the directry contains 'libtk<version>.so'
--enable-mac-tcltk-framework (MacOS X) use Tcl/Tk framework
(Obsolete. Please use '--enable-tcltk-framework'.)
--enable-tcltk-framework use Tcl/Tk framework
- --with-tcltk-framework=<dir> the directory containts Tcl/Tk framework;
+ --with-tcltk-framework=<dir> the directory contains Tcl/Tk framework;
"<dir>/Tcl.framework" and "<dir>/Tk.framework".
When this option is given, it is assumed that
--enable-tcltk-framework option is given also.
@@ -46,8 +46,8 @@ some or all of the following options.
--with-X11-dir=<path>
equal to "--with-X11-include=<path>/include --with-X11-lib=<path>/lib"
- --with-X11-include=<dir> the directry contains X11 header files
- --with-X11-lib=<dir> the directry contains X11 libraries
+ --with-X11-include=<dir> the directry contais X11 header files
+ --with-X11-lib=<dir> the directry contais X11 libraries
If you forgot to give the options when do 'configure' on toplevel
diff --git a/ext/tk/extconf.rb b/ext/tk/extconf.rb
index 292b18a5c0..cb7621fbd4 100644
--- a/ext/tk/extconf.rb
+++ b/ext/tk/extconf.rb
@@ -2,7 +2,8 @@
require 'mkmf'
-is_win32 = (/mswin32|mingw|cygwin|bccwin32/ =~ RUBY_PLATFORM)
+#is_win32 = (/mswin32|mingw|cygwin|bccwin32/ =~ RUBY_PLATFORM)
+is_win32 = (/mswin|mingw|cygwin|bccwin|wince/ =~ RUBY_PLATFORM)
#is_macosx = (/darwin/ =~ RUBY_PLATFORM)
def find_framework(tcl_hdr, tk_hdr)
@@ -39,9 +40,13 @@ unless is_win32
have_library("m", "log")
end
-dir_config("tk")
-dir_config("tcl")
-dir_config("X11")
+tk_idir, tk_ldir = dir_config("tk")
+tcl_idir, tcl_ldir = dir_config("tcl")
+x11_idir, x11_ldir = dir_config("X11")
+
+tk_ldir2 = with_config("tk-lib")
+tcl_ldir2 = with_config("tcl-lib")
+x11_ldir2 = with_config("X11-lib")
tklib = with_config("tklib")
tcllib = with_config("tcllib")
@@ -49,8 +54,9 @@ stubs = enable_config("tcltk_stubs") || with_config("tcltk_stubs")
use_X = with_config("X11", (! is_win32))
-def find_tcl(tcllib, stubs)
- paths = ["/usr/local/lib", "/usr/pkg/lib", "/usr/lib"]
+def find_tcl(tcllib, stubs, *opt_paths)
+ default_paths = ["/usr/local/lib", "/usr/pkg/lib", "/usr/lib"]
+ paths = opt_paths.compact.concat(default_paths)
if stubs
func = "Tcl_InitStubs"
lib = "tclstub"
@@ -60,24 +66,23 @@ def find_tcl(tcllib, stubs)
end
if tcllib
find_library(tcllib, func, *paths)
- elsif find_library(lib, func, *paths)
- true
else
%w[8.6 8.5 8.4 8.3 8.2 8.1 8.0 7.6].find { |ver|
find_library("#{lib}#{ver}", func, *paths) or
find_library("#{lib}#{ver.delete('.')}", func, *paths) or
- find_library("tcl#{ver}", func, *paths) or
- find_library("tcl#{ver.delete('.')}", func, *paths) or
find_library("#{lib}#{ver}g", func, *paths) or
find_library("#{lib}#{ver.delete('.')}g", func, *paths) or
+ find_library("tcl#{ver}", func, *paths) or
+ find_library("tcl#{ver.delete('.')}", func, *paths) or
find_library("tcl#{ver}g", func, *paths) or
find_library("tcl#{ver.delete('.')}g", func, *paths)
- }
+ } || find_library(lib, func, *paths)
end
end
-def find_tk(tklib, stubs)
- paths = ["/usr/local/lib", "/usr/pkg/lib", "/usr/lib"]
+def find_tk(tklib, stubs, *opt_paths)
+ default_paths = ["/usr/local/lib", "/usr/pkg/lib", "/usr/lib"]
+ paths = opt_paths.compact.concat(default_paths)
if stubs
func = "Tk_InitStubs"
lib = "tkstub"
@@ -87,22 +92,27 @@ def find_tk(tklib, stubs)
end
if tklib
find_library(tklib, func, *paths)
- elsif find_library(lib, func, *paths)
- true
else
%w[8.6 8.5 8.4 8.3 8.2 8.1 8.0 4.2].find { |ver|
find_library("#{lib}#{ver}", func, *paths) or
find_library("#{lib}#{ver.delete('.')}", func, *paths) or
- find_library("tk#{ver}", func, *paths) or
- find_library("tk#{ver.delete('.')}", func, *paths) or
find_library("#{lib}#{ver}g", func, *paths) or
find_library("#{lib}#{ver.delete('.')}g", func, *paths) or
+ find_library("tk#{ver}", func, *paths) or
+ find_library("tk#{ver.delete('.')}", func, *paths) or
find_library("tk#{ver}g", func, *paths) or
find_library("tk#{ver.delete('.')}g", func, *paths)
- }
+ } || find_library(lib, func, *paths)
end
end
+def find_X11(*opt_paths)
+ default_paths =
+ [ "/usr/X11/lib", "/usr/lib/X11", "/usr/X11R6/lib", "/usr/openwin/lib" ]
+ paths = opt_paths.compact.concat(default_paths)
+ find_library("X11", "XOpenDisplay", *paths)
+end
+
def pthread_check()
tcl_major_ver = nil
tcl_minor_ver = nil
@@ -281,13 +291,11 @@ EOF
end
end
-if tcltk_framework ||
- (have_header("tcl.h") && have_header("tk.h") &&
- ( !use_X || find_library("X11", "XOpenDisplay",
- "/usr/X11/lib", "/usr/lib/X11",
- "/usr/X11R6/lib", "/usr/openwin/lib")) &&
- find_tcl(tcllib, stubs) &&
- find_tk(tklib, stubs))
+if have_header("tcl.h") && have_header("tk.h") &&
+ ( tcltk_framework ||
+ ( ( !use_X || find_X11(x11_ldir2, x11_ldir) ) &&
+ find_tcl(tcllib, stubs, tcl_ldir2, tcl_ldir) &&
+ find_tk(tklib, stubs, tk_ldir2, tk_ldir) ) )
$CPPFLAGS += ' -DUSE_TCL_STUBS -DUSE_TK_STUBS' if stubs
$CPPFLAGS += ' -D_WIN32' if /cygwin/ =~ RUBY_PLATFORM
diff --git a/ext/tk/lib/multi-tk.rb b/ext/tk/lib/multi-tk.rb
index ed936bf1a5..fd9a863888 100644
--- a/ext/tk/lib/multi-tk.rb
+++ b/ext/tk/lib/multi-tk.rb
@@ -114,7 +114,14 @@ MultiTkIp_OK.freeze
class MultiTkIp
BASE_DIR = File.dirname(__FILE__)
- @@SLAVE_IP_ID = ['slave'.freeze, '0'.taint].freeze
+ WITH_RUBY_VM = Object.const_defined?(:VM) && ::VM.class == Class
+ WITH_ENCODING = Object.const_defined?(:Encoding) && ::Encoding.class == Class
+
+ (@@SLAVE_IP_ID = ['slave'.freeze, '0'.taint]).instance_eval{
+ @mutex = Mutex.new
+ def mutex; @mutex; end
+ freeze
+ }
@@IP_TABLE = {}.taint unless defined?(@@IP_TABLE)
@@ -126,7 +133,11 @@ class MultiTkIp
unless defined?(@@TK_CMD_TBL)
@@TK_CMD_TBL = Object.new.taint
- @@TK_CMD_TBL.instance_variable_set('@tbl', {}.taint)
+ # @@TK_CMD_TBL.instance_variable_set('@tbl', {}.taint)
+ @@TK_CMD_TBL.instance_variable_set('@tbl', Hash.new{|hash,key|
+ fail IndexError,
+ "unknown command ID '#{key}'"
+ }.taint)
class << @@TK_CMD_TBL
allow = [
@@ -573,7 +584,11 @@ class MultiTkIp
# raise exception
begin
bt = _toUTF8(e.backtrace.join("\n"))
- bt.instance_variable_set(:@encoding, 'utf-8')
+ 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
@@ -695,7 +710,10 @@ class MultiTkIp
######################################
- WITH_RUBY_VM = Object.const_defined?(:VM) && ::VM.class == Class
+ 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
@@ -725,13 +743,24 @@ class MultiTkIp
fail ArgumentError, "expecting a Hash object for the 2nd argument"
end
- unless WITH_RUBY_VM
+ 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{
- Thread.current[:interp] = interp = TclTkIp.new(name, _keys2opts(keys))
+ current = Thread.current
+ current[:interp] = interp = TclTkIp.new(name, _keys2opts(keys))
#sleep
- interp.mainloop(true)
+ current[:mutex] = mutex = Mutex.new
+ current[:root_check] = cond_var = ConditionVariable.new
+
+ begin
+ current[:status] = interp.mainloop(true)
+ rescue Exception=>e
+ current[:status] = e
+ ensure
+ mutex.synchronize{ cond_var.broadcast }
+ end
+ current[:status] = interp.mainloop(false)
}
until @interp_thread[:interp]
Thread.pass
@@ -976,9 +1005,11 @@ class MultiTkIp
private :_parse_slaveopts
def _create_slave_ip_name
- name = @@SLAVE_IP_ID.join('')
- @@SLAVE_IP_ID[1].succ!
- name.freeze
+ @@SLAVE_IP_ID.mutex.synchronize{
+ name = @@SLAVE_IP_ID.join('')
+ @@SLAVE_IP_ID[1].succ!
+ name.freeze
+ }
end
private :_create_slave_ip_name
@@ -1309,11 +1340,11 @@ class MultiTkIp
@@DEFAULT_MASTER.assign_receiver_and_watchdog(self)
@@IP_TABLE[@threadgroup] = self
- _init_ip_internal(@@INIT_IP_ENV, @@ADD_TK_PROCS)
@@TK_TABLE_LIST.size.times{
(tbl = {}).tainted? || tbl.taint
@tk_table_list << tbl
}
+ _init_ip_internal(@@INIT_IP_ENV, @@ADD_TK_PROCS)
class << self
undef :instance_eval
@@ -1391,8 +1422,13 @@ class << MultiTkIp
alias __new new
private :__new
-
def new_master(safe=nil, keys={})
+ if MultiTkIp::WITH_RUBY_VM
+ #### TODO !!!!!!
+ fail RuntimeError,
+ 'sorry, still not support multiple master-interpreters on Ruby VM'
+ end
+
if safe.kind_of?(Hash)
keys = safe
elsif safe.kind_of?(Integer)
@@ -1609,8 +1645,13 @@ class MultiTkIp
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
}
}
@@ -1660,11 +1701,16 @@ class MultiTkIp
id = @@TK_TABLE_LIST.size
obj = Object.new
@@TK_TABLE_LIST << obj
- obj.instance_eval <<-EOD
+ 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)
+ MultiTkIp.tk_object_table(@id).__send__(m, *args)
end
- EOD
+ }
obj.freeze
@@IP_TABLE.each{|tg, ip| ip._add_new_tables }
return obj
@@ -2797,9 +2843,10 @@ class MultiTkIp
i = -1
brace = 1
str.each_byte {|c|
+ c = c.chr
i += 1
- brace += 1 if c == ?{
- brace -= 1 if c == ?}
+ brace += 1 if c == '{'
+ brace -= 1 if c == '}'
break if brace == 0
}
if i == 0
@@ -3238,15 +3285,44 @@ end
# encoding convert
+class << MultiTkIp
+ def encoding_table
+ __getip.encoding_table
+ end
+end
class MultiTkIp
- def encoding
+ def encoding_table
+ @interp.encoding_table
+ end
+
+ def force_default_encoding=(mode)
raise SecurityError, "no permission to manipulate" unless self.manipulable?
- @interp.encoding
+ @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?
@@ -3264,12 +3340,28 @@ end
# remove methods for security
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 of MultiTkIp definition
# defend against modification
diff --git a/ext/tk/lib/tk.rb b/ext/tk/lib/tk.rb
index d80271a326..0d00ecf207 100644
--- a/ext/tk/lib/tk.rb
+++ b/ext/tk/lib/tk.rb
@@ -9,6 +9,9 @@ require 'tkutil'
# autoload
require 'tk/autoload'
+# for Mutex
+require 'thread'
+
class TclTkIp
# backup original (without encoding) _eval and _invoke
alias _eval_without_enc _eval
@@ -36,7 +39,12 @@ module TkComm
#Tk_CMDTBL = {}
#Tk_WINDOWS = {}
- Tk_IDs = ["00000".taint, "00000".taint].freeze # [0]-cmdid, [1]-winid
+ Tk_IDs = ["00000".taint, "00000".taint] # [0]-cmdid, [1]-winid
+ Tk_IDs.instance_eval{
+ @mutex = Mutex.new
+ def mutex; @mutex; end
+ freeze
+ }
# for backward compatibility
Tk_CMDTBL = Object.new
@@ -217,7 +225,9 @@ module TkComm
TkCore::INTERP.tk_windows[val]?
TkCore::INTERP.tk_windows[val] : _genobj_for_tkwidget(val)
when /\Ai(_\d+_)?\d+\z/
- TkImage::Tk_IMGTBL[val]? TkImage::Tk_IMGTBL[val] : val
+ 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 /\\ /
@@ -334,6 +344,8 @@ if USE_TCLs_LIST_FUNCTIONS
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
@@ -346,11 +358,20 @@ if USE_TCLs_LIST_FUNCTIONS
if sys_enc && dst_enc
dst.map!{|s| _toUTF8(s)}
ret = TkCore::INTERP._merge_tklist(*dst)
- 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')
+ 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
@@ -410,46 +431,6 @@ else
tk_split_sublist(token, depth - 1)
}
end
-=begin
- def tk_split_list(str)
- return [] if str == ""
- idx = str.index('{')
- while idx and idx > 0 and str[idx-1] == ?\\
- idx = str.index('{', idx+1)
- end
- unless idx
- list = tk_tcl2ruby(str)
- unless Array === list
- list = [list]
- end
- return list
- end
-
- list = tk_tcl2ruby(str[0,idx])
- list = [] if list == ""
- str = str[idx+1..-1]
- i = -1
- escape = false
- brace = 1
- str.each_byte {|c|
- i += 1
- brace += 1 if c == ?{ && !escape
- brace -= 1 if c == ?} && !escape
- escape = (c == ?\\)
- break if brace == 0
- }
- if str.size == i + 1
- return tk_split_list(str[0, i])
- end
- if str[0, i] == ' '
- list.push ' '
- else
- list.push tk_split_list(str[0, i])
- end
- list += tk_split_list(str[i+1..-1])
- list
- end
-=end
def tk_split_simplelist(str, src_enc=true, dst_enc=true)
return [] if str == ""
@@ -600,7 +581,9 @@ end
end
def image_obj(val)
if val =~ /^i(_\d+_)?\d+$/
- TkImage::Tk_IMGTBL[val]? TkImage::Tk_IMGTBL[val] : val
+ TkImage::Tk_IMGTBL.mutex.synchronize{
+ TkImage::Tk_IMGTBL[val]? TkImage::Tk_IMGTBL[val] : val
+ }
else
val
end
@@ -782,10 +765,12 @@ end
id = "c" + TkCore::INTERP._ip_id_ + TkComm::Tk_IDs[0]
end
def _next_cmd_id
- id = _curr_cmd_id
- #Tk_IDs[0] += 1
- TkComm::Tk_IDs[0].succ!
- 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
@@ -855,8 +840,10 @@ end
return TkCore::INTERP.tk_windows[@path] = self
end
else
- name = "w" + TkCore::INTERP._ip_id_ + Tk_IDs[1]
- Tk_IDs[1].succ!
+ Tk_IDs.mutex.synchronize{
+ name = "w" + TkCore::INTERP._ip_id_ + Tk_IDs[1]
+ Tk_IDs[1].succ!
+ }
end
if !ppath or ppath == '.'
@path = '.' + name
@@ -935,7 +922,12 @@ module TkComm
def _bindinfo(what, context=nil)
if context
- tk_call_without_enc(*what+["<#{tk_event_sequence(context)}>"]).each_line.collect {|cmdline|
+ 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]
@@ -1106,10 +1098,9 @@ module TkCore
opts = ''
end
- if !WITH_RUBY_VM || RUN_EVENTLOOP_ON_MAIN_THREAD ### Ruby 1.9 !!!!!!!!!!!
+ if !WITH_RUBY_VM || RUN_EVENTLOOP_ON_MAIN_THREAD ### check Ruby 1.9 !!!!!!!
INTERP = TclTkIp.new(name, opts)
else
- require 'thread'
INTERP_MUTEX = Mutex.new
INTERP_ROOT_CHECK = ConditionVariable.new
INTERP_THREAD = Thread.new{
@@ -1146,7 +1137,10 @@ module TkCore
end
INTERP.instance_eval{
- @tk_cmd_tbl = {}.taint
+ # @tk_cmd_tbl = {}.taint
+ @tk_cmd_tbl = Hash.new{|hash, key|
+ fail IndexError, "unknown command ID '#{key}'"
+ }.taint
def @tk_cmd_tbl.[]=(idx,val)
if self.has_key?(idx) && Thread.current.group != ThreadGroup::Default
fail SecurityError,"cannot change the entried command"
@@ -1197,6 +1191,10 @@ module TkCore
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)
@@ -1382,7 +1380,11 @@ module TkCore
"\n---< backtrace of Ruby side >-----\n" +
_toUTF8(e.backtrace.join("\n")) +
"\n---< backtrace of Tk side >-------"
- msg.instance_variable_set(:@encoding, 'utf-8')
+ 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" +
@@ -1438,6 +1440,11 @@ module TkCore
end
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
+ end
+=begin
+ def after(ms, cmd=Proc.new)
crit_bup = Thread.critical
Thread.critical = true
@@ -1460,8 +1467,14 @@ module TkCore
# 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})
+ tk_call_without_enc('after','idle',cmdid)
+ end
+=begin
+ def after_idle(cmd=Proc.new)
crit_bup = Thread.critical
Thread.critical = true
@@ -1472,6 +1485,7 @@ module TkCore
tk_call_without_enc('after','idle',cmdid)
end
+=end
def after_cancel(afterId)
tk_call_without_enc('after','cancel',afterId)
@@ -1595,9 +1609,8 @@ module TkCore
def mainloop(check_root = true)
if !TkCore::WITH_RUBY_VM || TkCore::RUN_EVENTLOOP_ON_MAIN_THREAD
- ### Ruby 1.9 !!!!!!!!!!!
TclTkLib.mainloop(check_root)
- else
+ else ### Ruby 1.9 !!!!!
begin
TclTkLib.set_eventloop_window_mode(true)
if check_root
@@ -2096,6 +2109,27 @@ module Tk
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
@@ -2271,16 +2305,432 @@ 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
+
+ BINARY = RubyEncoding.find(BINARY_NAME)
+ UNKNOWN = RubyEncoding.find('ASCII-8BIT')
+
+ ### start of creating ENCODING_TABLE
+ ENCODING_TABLE = TkCore::INTERP.encoding_table
+=begin
+ ENCODING_TABLE = {
+ 'binary' => BINARY,
+ # 'UNKNOWN-8BIT' => UNKNOWN,
+ }
+
+ list = TkCore::INTERP._invoke_without_enc(ENCNAMES_CMD[0],
+ ENCNAMES_CMD[1])
+ TkCore::INTERP._split_tklist(list).each{|name|
+ begin
+ enc = RubyEncoding.find(name)
+ rescue ArgumentError
+ case name
+ when 'identity'
+ enc = BINARY
+ when 'shiftjis'
+ enc = RubyEncoding.find('Shift_JIS')
+ when 'unicode'
+ enc = RubyEncoding.find('UTF-8')
+ #if Tk.tk_call('set', 'tcl_platform(byteOrder)') =='littleEndian'
+ # enc = RubyEncoding.find('UTF-16LE')
+ #else
+ # enc = RubyEncoding.find('UTF-16BE')
+ #end
+ when 'symbol'
+ # single byte data
+ enc = RubyEncoding.find('ASCII-8BIT') ### ???
+ else
+ # unsupported on Ruby, but supported on Tk
+ enc = TkCore::INTERP.create_dummy_encoding_for_tk(name)
+ end
+ end
+ ENCODING_TABLE[name.freeze] = enc
+ }
+=end
+=begin
+ def ENCODING_TABLE.get_name(enc)
+ orig_enc = enc
+
+ # unles enc, use system default
+ # 1st: Ruby/Tk default encoding
+ # 2nd: Tcl/Tk default encoding
+ # 3rd: Ruby's default_external
+ enc ||= TkCore::INTERP.encoding
+ enc ||= TclTkLib.encoding_system
+ enc ||= DEFAULT_EXTERNAL_NAME
+
+ if enc.kind_of?(RubyEncoding)
+ # Ruby's Encoding object
+ if (name = self.key(enc))
+ return name
+ end
+
+ # Is it new ?
+ list = TkCore::INTERP._invoke_without_enc(ENCNAMES_CMD[0],
+ ENCNAMES_CMD[1])
+ TkComm.simplelist(list).each{|name|
+ if ((enc == RubyEncoding.find(name)) rescue false)
+ # new relation!! update table
+ self[name.freeze] = enc
+ return name
+ end
+ }
+ else
+ # String or Symbol ?
+ if self[name = enc.to_s]
+ return name
+ end
+
+ # Is it new ?
+ if (enc_obj = (RubyEncoding.find(name) rescue false))
+ list = TkCore::INTERP._invoke_without_enc(ENCNAMES_CMD[0],
+ ENCNAMES_CMD[1])
+ if TkComm.simplelist(list).index(name)
+ # Tk's encoding name ?
+ self[name.freeze] = enc_obj # new relation!! update table
+ return name
+ else
+ # Ruby's encoding name ?
+ if (name = self.key(enc_obj))
+ return name
+ end
+ end
+ end
+ end
+
+ fail ArgumentError, "unsupported Tk encoding '#{orig_enc}'"
+ end
+
+ def ENCODING_TABLE.get_obj(enc)
+ # returns the encoding object.
+ # If 'enc' is the encoding name on Tk only, it returns nil.
+ ((obj = self[self.get_name(enc)]).kind_of?(RubyEncoding))? obj: nil
+ end
+=end
+ ### end of creating ENCODING_TABLE
+
+ end
+
+ #############################################
+
+ if TkCore::WITH_ENCODING
+ ################################
+ ### Ruby 1.9
+ ################################
+ def force_default_encoding(mode)
+ TkCore::INTERP.force_default_encoding = mode
+ end
+
+ def force_default_encoding?
+ TkCore::INTERP.force_default_encoding?
+ end
+
+ def default_encoding=(enc)
+ TkCore::INTERP.default_encoding = Tk::Encoding::ENCODING_TABLE.get_name(enc)
+ end
+
+ def encoding=(enc)
+ TkCore::INTERP.encoding = Tk::Encoding::ENCODING_TABLE.get_name(enc)
+ end
+
+ def encoding_name
+ Tk::Encoding::ENCODING_TABLE.get_name(TkCore::INTERP.encoding)
+ end
+ def encoding_obj
+ Tk::Encoding::ENCODING_TABLE.get_obj(TkCore::INTERP.encoding)
+ end
+ alias encoding encoding_name
+ alias default_encoding encoding_name
+
+ def tk_encoding_names
+ TkComm.simplelist(TkCore::INTERP._invoke_without_enc(Tk::Encoding::ENCNAMES_CMD[0], Tk::Encoding::ENCNAMES_CMD[1]))
+ 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 = (mode)? true: false
+ end
+
+ def force_default_encoding?
+ @force_default_encoding ||= false
+ end
+
+ def default_encoding=(name)
+ name = name.name if name.kind_of?(::Encoding) if Tk::WITH_ENCODING
+ @encoding = name
+ end
+
# from tkencoding.rb by ttate@jaist.ac.jp
- attr_accessor :encoding
+ #attr_accessor :encoding
+ def encoding=(name)
+ self.force_default_encoding = true # for comaptibility
+ self.default_encoding = name
+ end
- alias __eval _eval
- alias __invoke _invoke
+ def encoding_name
+ (@encoding)? @encoding.dup: nil
+ end
+ alias encoding encoding_name
+ alias default_encoding encoding_name
+
+ def encoding_obj
+ if Tk::WITH_ENCODING
+ Tk::Encoding.tcl2rb_encoding(@encoding)
+ else
+ (@encoding)? @encoding.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
+
+ unless enc_name
+ # 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
@@ -2330,17 +2780,6 @@ if (/^(8\.[1-9]|9\.|[1-9][0-9])/ =~ Tk::TCL_VERSION && !Tk::JAPANIZED_TK)
end
=end
- 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
def _eval(cmd)
if defined?(@encoding) && @encoding != 'utf-8'
@@ -2397,81 +2836,43 @@ if (/^(8\.[1-9]|9\.|[1-9][0-9])/ =~ Tk::TCL_VERSION && !Tk::JAPANIZED_TK)
module TclTkLib
class << self
- alias _encoding encoding
- alias _encoding= encoding=
- def encoding=(name)
- TkCore::INTERP.encoding = name
- end
- def encoding
- TkCore::INTERP.encoding
+ def force_default_encoding=(mode)
+ TkCore::INTERP.force_default_encoding = mode
end
- end
- end
- module Tk
- module Encoding
- extend Encoding
+ def force_default_encoding?
+ TkCore::INTERP.force_default_encoding?
+ end
- TkCommandNames = ['encoding'.freeze].freeze
+ 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
+ def encoding_name
TkCore::INTERP.encoding
end
+ alias encoding encoding_name
+ alias default_encoding encoding_name
- def encoding_names
- TkComm.simplelist(Tk.tk_call('encoding', 'names'))
- end
-
- def encoding_system
- Tk.tk_call('encoding', 'system')
- end
-
- def encoding_system=(enc)
- Tk.tk_call('encoding', 'system', enc)
- end
-
- def encoding_convertfrom(str, enc=nil)
- # str is an usual enc string or a Tcl's internal string expression
- # in enc (which is returned from 'encoding_convertto' method).
- # the return value is a UTF-8 string.
- enc = encoding_system unless enc
- ret = TkCore::INTERP.__invoke('encoding', 'convertfrom', enc, str)
- ret.instance_variable_set('@encoding', 'utf-8')
- ret
- end
- alias encoding_convert_from encoding_convertfrom
-
- def encoding_convertto(str, enc=nil)
- # str must be a UTF-8 string.
- # The return value is a Tcl's internal string expression in enc.
- # To get an usual enc string, use Tk.fromUTF8(ret_val, enc).
- enc = encoding_system unless enc
- ret = TkCore::INTERP.__invoke('encoding', 'convertto', enc, str)
- ret.instance_variable_set('@encoding', 'binary')
- 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)
+ def encoding_obj
+ if Tk::WITH_ENCODING
+ Tk::Encoding.tcl2rb_encoding(TkCore::INTERP.encoding)
+ else
+ TkCore::INTERP.encoding
+ end
end
end
-
- extend Encoding
end
# estimate encoding
- unless TkCore::WITH_ENCODING ### Ruby 1.9 !!!!!!!!!!!!
+ unless TkCore::WITH_ENCODING
case $KCODE
when /^e/i # EUC
Tk.encoding = 'euc-jp'
@@ -2502,89 +2903,147 @@ if (/^(8\.[1-9]|9\.|[1-9][0-9])/ =~ Tk::TCL_VERSION && !Tk::JAPANIZED_TK)
Tk.encoding_system = 'utf-8'
end
end
- else #########################
- $TK_ENCODING ||= Encoding.default_external.name
- case $TK_ENCODING
- when 'US_ASCII'
- Tk.encoding = 'ascii'
- Tk.encoding_system = 'ascii'
- when 'BIG5'
- Tk.encoding = 'big5'
- Tk.encoding_system = 'big5'
- when 'CP1251'
- Tk.encoding = 'cp1251'
- Tk.encoding_system = 'cp1251'
- when 'EUC-JP'
- Tk.encoding = 'euc-jp'
- Tk.encoding_system = 'euc-jp'
- when 'EUC-KR'
- Tk.encoding = 'euc-kr'
- Tk.encoding_system = 'euc-kr'
- when 'EUC-TW', 'EUC-CN'
- Tk.encoding = 'euc-cn'
- Tk.encoding_system = 'euc-cn'
- #when 'GB18030'
- # Tk.encoding = 'gb12345' # ????????????
- # Tk.encoding_system = 'gb12345' # ????????????
- when 'ISO-2022-JP'
- Tk.encoding = 'iso2022-jp'
- Tk.encoding_system = 'iso2022-jp'
- when /ISO-8859-(.*)/
- Tk.encoding = 'iso8859-' << $1
- Tk.encoding_system = 'iso8859-' << $1
- #when 'KOI8', 'KOI8-U'
- # Tk.encoding = 'koi8-u' # ????????????
- # Tk.encoding_system = 'koi8-u' # ????????????
- when 'KOI8-R'
- Tk.encoding = 'koi8-r'
- Tk.encoding_system = 'koi8-r'
- when 'Shift_JIS'
- begin
- if Tk.encoding_system == 'cp932'
- Tk.encoding = 'cp932'
+
+ else ### Ruby 1.9 !!!!!!!!!!!!
+ loc_enc_obj = ::Encoding.find(::Encoding.locale_charmap)
+ ext_enc_obj = ::Encoding.default_external
+ tksys_enc_name = Tk::Encoding::ENCODING_TABLE.get_name(Tk.encoding_system)
+ # p [Tk.encoding, Tk.encoding_system, loc_enc_obj, ext_enc_obj]
+
+=begin
+ if ext_enc_obj == Tk::Encoding::UNKNOWN
+ if defind? DEFAULT_TK_ENCODING
+ if DEFAULT_TK_ENCODING.kind_of?(::Encoding)
+ tk_enc_name = DEFAULT_TK_ENCODING.name
+ tksys_enc_name = DEFAULT_TK_ENCODING.name
else
- Tk.encoding = 'shiftjis'
- Tk.encoding_system = 'shiftjis'
+ tk_enc_name = DEFAULT_TK_ENCODING
+ tksys_enc_name = DEFAULT_TK_ENCODING
end
- rescue StandardError, NameError
- Tk.encoding = 'shiftjis'
- Tk.encoding_system = 'shiftjis'
+ else
+ tk_enc_name = loc_enc_obj.name
+ tksys_enc_name = loc_enc_obj.name
end
- when 'UNICODE'
- Tk.encoding = 'unicode'
- Tk.encoding_system = 'unicode'
- when 'UTF-8'
- Tk.encoding = 'utf-8'
- Tk.encoding_system = 'utf-8'
- else ###### 'ASCII-8BIT'
- if defined? DEFAULT_TK_ENCODING
- Tk.encoding_system = DEFAULT_TK_ENCODING
+ 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
- Tk.encoding = Tk.encoding_system
- rescue StandardError, NameError
- Tk.encoding = 'utf-8'
- Tk.encoding_system = 'utf-8'
+ 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
- end
-else
- # dummy methods
- class TclTkIp
- attr_accessor :encoding
+ # setup Tk.encoding
+ enc_name = nil
- alias __eval _eval
- alias __invoke _invoke
+ 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
- alias _eval_with_enc _eval
- alias _invoke_with_enc _invoke
+ unless enc_name
+ if ext_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 && loc_enc_name != tksys_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
+ # use default_external
+ enc_name = ext_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
@@ -2620,6 +3079,16 @@ else
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
@@ -2949,6 +3418,14 @@ module TkConfigMethod
include TkUtil
include TkTreatFont
+ def TkConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__
+ @mode || false
+ end
+ def TkConfigMethod.__set_IGNORE_UNKNOWN_CONFIGURE_OPTION__!(mode)
+ fail SecurityError, "can't change the mode" if $SAFE>=4
+ @mode = (mode)? true: false
+ end
+
def __cget_cmd
[self.path, 'cget']
end
@@ -3076,7 +3553,7 @@ module TkConfigMethod
val
end
- def cget(slot)
+ def __cget_core(slot)
orig_slot = slot
slot = slot.to_s
@@ -3152,8 +3629,17 @@ module TkConfigMethod
tk_tcl2ruby(tk_call_without_enc(*(__cget_cmd << "-#{slot}")), true)
end
end
+ private :__cget_core
- def configure(slot, value=None)
+ def cget(slot)
+ unless TkConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__
+ __cget_core(slot)
+ else
+ __cget_core(slot) rescue nil
+ end
+ end
+
+ def __configure_core(slot, value=None)
if slot.kind_of? Hash
slot = _symbolkey2str(slot)
@@ -3216,12 +3702,45 @@ module TkConfigMethod
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
+ __configure_core(slot, value) rescue nil
+ end
+ end
+ self
+ end
def configure_cmd(slot, value)
configure(slot, install_cmd(value))
end
- def configinfo(slot = nil)
+ def __configinfo_core(slot = nil)
if TkComm::GET_CONFIGINFO_AS_ARRAY
if (slot &&
slot.to_s =~ /^(|latin|ascii|kanji)(#{__font_optkeys.join('|')})$/)
@@ -3232,6 +3751,10 @@ module TkConfigMethod
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 \
@@ -3568,6 +4091,11 @@ module TkConfigMethod
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
@@ -3592,6 +4120,10 @@ module TkConfigMethod
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] \
@@ -3939,6 +4471,11 @@ module TkConfigMethod
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
@@ -3953,6 +4490,19 @@ module TkConfigMethod
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
@@ -4052,7 +4602,12 @@ class TkObject<TkKernel
begin
cget(name)
rescue
- super(id, *args)
+ if self.kind_of?(TkWindow)
+ fail NameError,
+ "unknown option '#{id}' for #{self.inspect} (deleted widget?)"
+ else
+ super(id, *args)
+ end
# fail NameError,
# "undefined local variable or method `#{name}' for #{self.to_s}",
# error_at
@@ -4107,6 +4662,7 @@ end
class TkWindow<TkObject
include TkWinfo
extend TkBindCore
+ include Tk::Wm_for_General
@@WIDGET_INSPECT_FULL = false
def TkWindow._widget_inspect_full_?
@@ -4210,7 +4766,20 @@ class TkWindow<TkObject
end
if keys and keys != None
- tk_call_without_enc(cmd, @path, *hash_kv(keys, true))
+ 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
+ tk_call_without_enc(cmd, @path)
+ keys = __check_available_configure_options(keys)
+ unless keys.empty?
+ tk_call_without_enc('destroy', @path)
+ tk_call_without_enc(cmd, @path, *hash_kv(keys, true))
+ end
+ end
+ end
else
tk_call_without_enc(cmd, @path)
end
@@ -4748,7 +5317,7 @@ TkWidget = TkWindow
#Tk.freeze
module Tk
- RELEASE_DATE = '2008-02-29'.freeze
+ RELEASE_DATE = '2008-03-29'.freeze
autoload :AUTO_PATH, 'tk/variable'
autoload :TCL_PACKAGE_PATH, 'tk/variable'
diff --git a/ext/tk/lib/tk/autoload.rb b/ext/tk/lib/tk/autoload.rb
index f7037b4033..0773f7708d 100644
--- a/ext/tk/lib/tk/autoload.rb
+++ b/ext/tk/lib/tk/autoload.rb
@@ -93,6 +93,7 @@ module Tk
autoload :Scrollable, 'tk/scrollable'
autoload :Wm, 'tk/wm'
+ autoload :Wm_for_General, 'tk/wm'
autoload :MacResource, 'tk/macpkg'
@@ -159,7 +160,7 @@ autoload :TkWarningObj, 'tk/dialog'
autoload :TkEvent, 'tk/event'
autoload :TkFont, 'tk/font'
-autoload :TkTreatTagFont, 'tk/font'
+autoload :TkNamedFont, 'tk/font'
autoload :TkImage, 'tk/image'
autoload :TkBitmapImage, 'tk/image'
@@ -314,11 +315,16 @@ module Tk
:TkWinRegistry => 'tk/winpkg',
}
+ @TOPLEVEL_ALIAS_OWNER = {}
+
@TOPLEVEL_ALIAS_SETUP_PROC = {}
@current_default_widget_set = nil
end
+
+############################################
+# methods to control default widget set
############################################
class << Tk
@@ -341,7 +347,8 @@ class << Tk
@TOPLEVEL_ALIAS_TABLE[target = target.to_sym] ||= {}
symbols.each{|sym|
@TOPLEVEL_ALIAS_TABLE[target][sym = sym.to_sym] = obj
- if @current_default_widget_set == target
+ # if @current_default_widget_set == target
+ if @TOPLEVEL_ALIAS_OWNER[sym] == target
Object.class_eval{remove_const sym} if Object.const_defined?(sym)
Object.const_set(sym, obj)
end
@@ -372,6 +379,7 @@ class << Tk
# file => loaded class object
Object.const_set(sym, file)
end
+ @TOPLEVEL_ALIAS_OWNER[sym] = target
}
# update current alias
@@ -386,10 +394,11 @@ Tk.default_widget_set = :Tk
############################################
# depend on the version of Tcl/Tk
-major, minor, type, type_name, patchlevel = TclTkLib.get_version
+# major, minor, type, type_name, patchlevel = TclTkLib.get_version
############################################
# Ttk (Tile) support
+=begin
if major > 8 ||
(major == 8 && minor > 5) ||
(major == 8 && minor == 5 && type >= TclTkLib::RELEASE_TYPE::BETA)
@@ -399,3 +408,7 @@ if major > 8 ||
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/bindtag.rb b/ext/tk/lib/tk/bindtag.rb
index 9023a08e06..88c8367a88 100644
--- a/ext/tk/lib/tk/bindtag.rb
+++ b/ext/tk/lib/tk/bindtag.rb
@@ -8,30 +8,64 @@ class TkBindTag
#BTagID_TBL = {}
BTagID_TBL = TkCore::INTERP.create_table
- Tk_BINDTAG_ID = ["btag".freeze, "00000".taint].freeze
- TkCore::INTERP.init_ip_env{ BTagID_TBL.clear }
+ (Tk_BINDTAG_ID = ["btag".freeze, "00000".taint]).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[id]? BTagID_TBL[id]: id
+ BTagID_TBL.mutex.synchronize{
+ (BTagID_TBL[id])? BTagID_TBL[id]: id
+ }
end
+=begin
def TkBindTag.new_by_name(name, *args, &b)
- return BTagID_TBL[name] if BTagID_TBL[name]
+ BTagID_TBL.mutex.synchronize{
+ return BTagID_TBL[name] if BTagID_TBL[name]
+ }
+
self.new.instance_eval{
- BTagID_TBL.delete @id
- @id = name
- BTagID_TBL[@id] = self
+ 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)
- # @id = Tk_BINDTAG_ID.join('')
- @id = Tk_BINDTAG_ID.join(TkCore::INTERP._ip_id_)
- Tk_BINDTAG_ID[1].succ!
- BTagID_TBL[@id] = self
+ 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
@@ -63,14 +97,37 @@ end
class TkDatabaseClass<TkBindTag
+=begin
def self.new(name, *args, &b)
- return BTagID_TBL[name] if BTagID_TBL[name]
+ 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[@id] = self
+ 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
diff --git a/ext/tk/lib/tk/canvas.rb b/ext/tk/lib/tk/canvas.rb
index 4abc992027..fceadd5e9c 100644
--- a/ext/tk/lib/tk/canvas.rb
+++ b/ext/tk/lib/tk/canvas.rb
@@ -185,11 +185,17 @@ class Tk::Canvas<TkWindow
end
def delete(*args)
- if TkcItem::CItemID_TBL[self.path]
+ 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[self.path].delete(item.id)
+ TkcItem::CItemID_TBL.mutex.synchronize{
+ tbl.delete(item.id)
+ }
end
}
}
@@ -584,9 +590,12 @@ class TkcItem<TkObject
CItemTypeName = nil
CItemTypeToClass = {}
+
CItemID_TBL = TkCore::INTERP.create_table
- TkCore::INTERP.init_ip_env{ CItemID_TBL.clear }
+ TkCore::INTERP.init_ip_env{
+ CItemID_TBL.mutex.synchronize{ CItemID_TBL.clear }
+ }
def TkcItem.type2class(type)
CItemTypeToClass[type]
@@ -594,8 +603,13 @@ class TkcItem<TkObject
def TkcItem.id2obj(canvas, id)
cpath = canvas.path
- return id unless CItemID_TBL[cpath]
- CItemID_TBL[cpath][id]? CItemID_TBL[cpath][id]: id
+ CItemID_TBL.mutex.synchronize{
+ if CItemID_TBL[cpath]
+ CItemID_TBL[cpath][id]? CItemID_TBL[cpath][id]: id
+ else
+ id
+ end
+ }
end
########################################
@@ -668,8 +682,10 @@ class TkcItem<TkObject
@path = parent.path
@id = create_self(*args) # an integer number as 'canvas item id'
- CItemID_TBL[@path] = {} unless CItemID_TBL[@path]
- CItemID_TBL[@path][@id] = self
+ 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'
@@ -690,7 +706,9 @@ class TkcItem<TkObject
def delete
@c.delete @id
- CItemID_TBL[@path].delete(@id) if CItemID_TBL[@path]
+ CItemID_TBL.mutex.synchronize{
+ CItemID_TBL[@path].delete(@id) if CItemID_TBL[@path]
+ }
self
end
alias remove delete
diff --git a/ext/tk/lib/tk/canvastag.rb b/ext/tk/lib/tk/canvastag.rb
index a5650ee68b..7feea1575c 100644
--- a/ext/tk/lib/tk/canvastag.rb
+++ b/ext/tk/lib/tk/canvastag.rb
@@ -199,14 +199,26 @@ class TkcTag<TkObject
include TkcTagAccess
CTagID_TBL = TkCore::INTERP.create_table
- Tk_CanvasTag_ID = ['ctag'.freeze, '00000'.taint].freeze
- TkCore::INTERP.init_ip_env{ CTagID_TBL.clear }
+ (Tk_CanvasTag_ID = ['ctag'.freeze, '00000'.taint]).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
- return id unless CTagID_TBL[cpath]
- CTagID_TBL[cpath][id]? CTagID_TBL[cpath][id]: id
+ 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)
@@ -215,11 +227,15 @@ class TkcTag<TkObject
#end
@c = parent
@cpath = parent.path
- # @path = @id = Tk_CanvasTag_ID.join('')
- @path = @id = Tk_CanvasTag_ID.join(TkCore::INTERP._ip_id_)
- CTagID_TBL[@cpath] = {} unless CTagID_TBL[@cpath]
- CTagID_TBL[@cpath][@id] = self
- Tk_CanvasTag_ID[1].succ!
+ 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
@@ -238,7 +254,9 @@ class TkcTag<TkObject
def delete
@c.delete @id
- CTagID_TBL[@cpath].delete(@id) if CTagID_TBL[@cpath]
+ CTagID_TBL.mutex.synchronize{
+ CTagID_TBL[@cpath].delete(@id) if CTagID_TBL[@cpath]
+ }
self
end
alias remove delete
@@ -288,23 +306,38 @@ class TkcTag<TkObject
end
class TkcTagString<TkcTag
- def self.new(parent, name, *args)
- if CTagID_TBL[parent.path] && CTagID_TBL[parent.path][name]
- return CTagID_TBL[parent.path][name]
- else
- super(parent, name, *args)
+ 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
- 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
@@ -312,7 +345,11 @@ class TkcTagString<TkcTag
end
TkcNamedTag = TkcTagString
-class TkcTagAll<TkcTag
+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"
@@ -320,12 +357,19 @@ class TkcTagAll<TkcTag
@c = parent
@cpath = parent.path
@path = @id = 'all'
- CTagID_TBL[@cpath] = {} unless CTagID_TBL[@cpath]
- CTagID_TBL[@cpath][@id] = self
+ CTagID_TBL.mutex.synchronize{
+ CTagID_TBL[@cpath] = {} unless CTagID_TBL[@cpath]
+ CTagID_TBL[@cpath][@id] = self
+ }
end
+=end
end
-class TkcTagCurrent<TkcTag
+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"
@@ -333,13 +377,21 @@ class TkcTagCurrent<TkcTag
@c = parent
@cpath = parent.path
@path = @id = 'current'
- CTagID_TBL[@cpath] = {} unless CTagID_TBL[@cpath]
- CTagID_TBL[@cpath][@id] = self
+ 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, '00000'.taint].freeze
+ (Tk_cGroup_ID = ['tkcg'.freeze, '00000'.taint]).instance_eval{
+ @mutex = Mutex.new
+ def mutex; @mutex; end
+ freeze
+ }
+
#def create_self(parent, *args)
def initialize(parent, *args)
#unless parent.kind_of?(TkCanvas)
@@ -347,11 +399,15 @@ class TkcGroup<TkcTag
#end
@c = parent
@cpath = parent.path
- # @path = @id = Tk_cGroup_ID.join('')
- @path = @id = Tk_cGroup_ID.join(TkCore::INTERP._ip_id_)
- CTagID_TBL[@cpath] = {} unless CTagID_TBL[@cpath]
- CTagID_TBL[@cpath][@id] = self
- Tk_cGroup_ID[1].succ!
+ 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
diff --git a/ext/tk/lib/tk/encodedstr.rb b/ext/tk/lib/tk/encodedstr.rb
index 797e514a4c..02de0b0d85 100644
--- a/ext/tk/lib/tk/encodedstr.rb
+++ b/ext/tk/lib/tk/encodedstr.rb
@@ -70,13 +70,89 @@ module Tk
# @encoding = ( enc ||
# ((self.class::Encoding)?
# self.class::Encoding : Tk.encoding_system) )
- @encoding = ( enc ||
- ((self.class::Encoding)?
+ enc ||= (self.class::Encoding)?
self.class::Encoding :
- ((Tk.encoding)? Tk.encoding : Tk.encoding_system) ) )
+ ((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
- attr_reader :encoding
+ 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)
diff --git a/ext/tk/lib/tk/event.rb b/ext/tk/lib/tk/event.rb
index 9884ca02e7..0042fcaa63 100644
--- a/ext/tk/lib/tk/event.rb
+++ b/ext/tk/lib/tk/event.rb
@@ -15,8 +15,6 @@ require 'tk'
module TkEvent
class Event < TkUtil::CallbackSubst
module Grp
- major, minor, type, type_name, patchlevel = TclTkLib.get_version
-
KEY = 0x1
BUTTON = 0x2
MOTION = 0x4
@@ -43,6 +41,8 @@ module TkEvent
MWHEEL = KEY
+ STRING_DATA = 0x80000000 # special flag for 'data' field
+
ALL = 0xFFFFFFFF
KEY_BUTTON_MOTION_VIRTUAL = (KEY|MWHEEL|BUTTON|MOTION|VIRTUAL)
@@ -157,7 +157,7 @@ module TkEvent
'borderwidth' => (Grp::CREATE|Grp::CONFIG),
'button' => Grp::BUTTON,
'count' => Grp::EXPOSE,
- 'data' => Grp::VIRTUAL,
+ 'data' => (Grp::VIRTUAL|Grp::STRING_DATA),
'delta' => Grp::MWHEEL,
'detail' => (Grp::FOCUS|Grp::CROSSING),
'focus' => Grp::CROSSING,
@@ -225,7 +225,8 @@ module TkEvent
rescue
next
end
- next if !val || val == '??'
+ # next if !val || val == '??'
+ next if !val || (val == '??' && (flag & Grp::STRING_DATA))
fields[key] = val
}
@@ -370,6 +371,22 @@ module TkEvent
nil
]
+ # 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
+ }
+
# 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
diff --git a/ext/tk/lib/tk/font.rb b/ext/tk/lib/tk/font.rb
index 444118e6ae..4641d8a640 100644
--- a/ext/tk/lib/tk/font.rb
+++ b/ext/tk/lib/tk/font.rb
@@ -11,13 +11,18 @@ class TkFont
TkCommandNames = ['font'.freeze].freeze
- Tk_FontID = ["@font".freeze, "00000".taint].freeze
+ (Tk_FontID = ["@font".freeze, "00000".taint]).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.clear
- Tk_FontUseTBL.clear
+ Tk_FontNameTBL.mutex.synchronize{ Tk_FontNameTBL.clear }
+ Tk_FontUseTBL.mutex.synchronize{ Tk_FontUseTBL.clear }
}
# option_type : default => string
@@ -31,13 +36,26 @@ class TkFont
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\.*/
+ when /^4\..*/
DEFAULT_LATIN_FONT_NAME = 'a14'.freeze
DEFAULT_KANJI_FONT_NAME = 'k14'.freeze
- when /^8\.*/
+ when /^8\.[0-4]/
if JAPANIZED_TK
begin
fontnames = tk_call('font', 'names')
@@ -103,6 +121,15 @@ class TkFont
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
@@ -121,6 +148,7 @@ class TkFont
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'
@@ -145,6 +173,9 @@ class TkFont
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)
@@ -163,6 +194,14 @@ class TkFont
###################################
# 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)
@@ -171,6 +210,9 @@ class TkFont
actual_core(fnt, nil, option)
end
end
+ def TkFont.actual_hash(fnt, option=nil)
+ Hash[TkFont.actual_hash(fnt, option)]
+ end
def TkFont.actual_displayof(fnt, win, option=nil)
fnt = '{}' if fnt == ''
@@ -181,6 +223,9 @@ class TkFont
actual_core(fnt, win, option)
end
end
+ def TkFont.actual_hash_displayof(fnt, option=nil)
+ Hash[TkFont.actual_hash_displayof(fnt, option)]
+ end
def TkFont.configure(fnt, slot, value=None)
if fnt.kind_of?(TkFont)
@@ -234,6 +279,33 @@ class TkFont
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 == ''
@@ -244,13 +316,40 @@ class TkFont
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\.*/
+ when /^4\..*/
['fixed']
- when /^8\.*/
+ when /^8\..*/
if win
tk_split_simplelist(tk_call('font', 'families', '-displayof', win))
else
@@ -261,13 +360,16 @@ class TkFont
def TkFont.names
case (Tk::TK_VERSION)
- when /^4\.*/
+ when /^4\..*/
r = ['fixed']
r += ['a14', 'k14'] if JAPANIZED_TK
- Tk_FontNameTBL.each_value{|obj| r.push(obj)}
- r | []
+ Tk_FontNameTBL.mutex.synchronize{
+ Tk_FontNameTBL.each_value{|obj| r.push(obj)}
+ }
+ #r | []
+ r.uniq
- when /^8\.*/
+ when /^8\..*/
tk_split_simplelist(tk_call('font', 'names'))
end
@@ -285,10 +387,15 @@ class TkFont
end
def TkFont.get_obj(name)
+ name = name.to_s
if name =~ /^(@font[0-9]+)(|c|l|k)$/
- Tk_FontNameTBL[$1]
+ Tk_FontNameTBL.mutex.synchronize{
+ Tk_FontNameTBL[$1]
+ }
else
- nil
+ Tk_FontNameTBL.mutex.synchronize{
+ Tk_FontNameTBL[name]
+ }
end
end
@@ -298,7 +405,7 @@ class TkFont
path = [win, tag, key].join(';')
case (Tk::TK_VERSION)
- when /^4\.*/
+ when /^4\..*/
regexp = /^-(|kanji)#{key} /
conf_list = tk_split_simplelist(tk_call(*args)).
@@ -324,7 +431,7 @@ class TkFont
TkFont.new(ltn, knj).call_font_configure([path, key], *args)
- when /^8\.*/
+ when /^8\.[0-4]/
regexp = /^-#{key} /
conf_list = tk_split_simplelist(tk_call(*args)).
@@ -360,26 +467,66 @@ class TkFont
compound = []
end
if compound == []
- TkFont.new(fnt).call_font_configure([path, key], *args)
+ 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)
- if path
- Tk_FontUseTBL[path]
- else
- Tk_FontUseTBL.values | []
- end
+ 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
+ if /^8\..*/ === Tk::TK_VERSION && JAPANIZED_TK
tk_call('font', 'failsafe', font)
end
rescue
@@ -392,15 +539,20 @@ class TkFont
private
###################################
def init_dummy_fontobj
- @id = Tk_FontID.join(TkCore::INTERP._ip_id_)
- Tk_FontID[1].succ!
- Tk_FontNameTBL[@id] = self
+ 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
+ # @latin_desscendant = nil
+ # @kanji_desscendant = nil
+ @descendant = [nil, nil] # [latin, kanji]
case (Tk::TK_VERSION)
- when /^4\.*/
+ when /^4\..*/
@latinfont = ""
@kanjifont = ""
if JAPANIZED_TK
@@ -436,13 +588,23 @@ class TkFont
ltn = '{}' if ltn == ''
knj = '{}' if knj == ''
- # @id = Tk_FontID.join('')
- @id = Tk_FontID.join(TkCore::INTERP._ip_id_)
- Tk_FontID[1].succ!
- Tk_FontNameTBL[@id] = self
+ 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]
- @latin_desscendant = nil
- @kanji_desscendant = nil
+ # @latinfont = @id + 'l'
+ # @kanjifont = @id + 'k'
+ # @compoundfont = @id + 'c'
+ # @fontslot = {}
if knj.kind_of?(Hash) && !keys
keys = knj
@@ -474,7 +636,7 @@ class TkFont
if ltn
if JAPANIZED_TK && !knj
- if Tk::TK_VERSION =~ /^4.*/
+ if Tk::TK_VERSION =~ /^4..*/
knj = DEFAULT_KANJI_FONT_NAME
else
knj = ltn
@@ -625,9 +787,14 @@ class TkFont
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
@@ -753,6 +920,7 @@ class TkFont
end
@fontslot = {'font'=>@compoundfont}
+ # @fontslot['font'] = @compoundfont
begin
tk_call('font', 'create', @compoundfont,
'-compound', [@latinfont, @kanjifont], *hash_kv(keys))
@@ -833,6 +1001,7 @@ class TkFont
end
@fontslot = {'font'=>@compoundfont}
+ # @fontslot['font'] = @compoundfont
tk_call('font', 'configure', @compoundfont, *hash_kv(keys))
end
end
@@ -888,13 +1057,19 @@ class TkFont
keys = _symbolkey2str(args.pop).update(fontslot)
args.concat(hash_kv(keys))
tk_call(*args)
- Tk_FontUseTBL[[win, tag, optkey].join(';')] = self
+ Tk_FontUseTBL.mutex.synchronize{
+ Tk_FontUseTBL[[win, tag, optkey].join(';')] = self
+ }
self
end
def used
ret = []
- Tk_FontUseTBL.each{|key,value|
+ 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(';')
@@ -960,6 +1135,8 @@ class TkFont
@compoundfont
end
alias font_id font
+ alias name font
+ alias to_s font
def latin_font_id
@latinfont
@@ -967,11 +1144,18 @@ class TkFont
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
@@ -981,50 +1165,87 @@ class TkFont
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)
- actual_core(@latinfont, nil, option)
+ 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
- actual_core(@latinfont, win, option)
+ 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 != ""
+ 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 != ""
+ 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
@@ -1068,10 +1289,15 @@ class TkFont
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 != ""
+ 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
@@ -1083,13 +1309,18 @@ class TkFont
def kanji_configinfo(slot=nil)
#if JAPANIZED_TK
- if @kanjifont != ""
+ 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
@@ -1099,12 +1330,30 @@ class TkFont
end
def latin_replace(ltn)
- latin_replace_core(ltn)
- reset_pointadjust
+ 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
@@ -1122,41 +1371,215 @@ class TkFont
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)
- metrics_core(@latinfont, nil, option)
+ 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
- metrics_core(@latinfont, win, option)
+ 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 JAPANIZED_TK
+ 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)
- if JAPANIZED_TK
- win = '.' unless win
+ 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
+ if /^8\..*/ === Tk::TK_VERSION && JAPANIZED_TK
configure('pointadjust' => latin_actual.assoc('size')[1].to_f /
kanji_actual.assoc('size')[1].to_f )
end
@@ -1169,7 +1592,7 @@ class TkFont
# private alias
###################################
case (Tk::TK_VERSION)
- when /^4\.*/
+ when /^4\..*/
alias create_latinfont create_latinfont_tk4x
alias create_kanjifont create_kanjifont_tk4x
alias create_compoundfont create_compoundfont_tk4x
@@ -1474,32 +1897,44 @@ module TkFont::CoreMethods
end
def delete_core_tk4x
- TkFont::Tk_FontNameTBL.delete(@id)
- TkFont::Tk_FontUseTBL.delete_if{|key,value| value == self}
+ 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)
+ tk_call('font', 'delete', @latinfont) if @latinfont
rescue
end
begin
- tk_call('font', 'delete', @kanjifont)
+ tk_call('font', 'delete', @kanjifont) if @kanjifont
rescue
end
begin
- tk_call('font', 'delete', @compoundfont)
+ tk_call('font', 'delete', @compoundfont) if @compoundfont
rescue
end
- TkFont::Tk_FontNameTBL.delete(@id)
- TkFont::Tk_FontUseTBL.delete_if{|key,value| value == self}
+ 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
- TkFont::Tk_FontUseTBL.dup.each{|w, fobj|
+ table = nil
+ TkFont::Tk_FontUseTBL.mutex.synchronize{
+ table = TkFont::Tk_FontUseTBL.clone
+ }
+ table.each{|w, fobj|
if self == fobj
begin
if w.include?(';')
@@ -1524,7 +1959,9 @@ module TkFont::CoreMethods
tk_call(w, 'configure', '-font', @latinfont)
end
rescue
- TkFont::Tk_FontUseTBL.delete(w)
+ TkFont::Tk_FontUseTBL.mutex.synchronize{
+ TkFont::Tk_FontUseTBL.delete(w)
+ }
end
end
}
@@ -1537,7 +1974,11 @@ module TkFont::CoreMethods
create_kanjifont_tk4x(knj)
@compoundfont[1] = [@kanjifont]
@fontslot['kanjifont'] = @kanjifont
- TkFont::Tk_FontUseTBL.dup.each{|w, fobj|
+ table = nil
+ TkFont::Tk_FontUseTBL.mutex.synchronize{
+ table = TkFont::Tk_FontUseTBL.clone
+ }
+ table.dup.each{|w, fobj|
if self == fobj
begin
if w.include?(';')
@@ -1562,7 +2003,9 @@ module TkFont::CoreMethods
tk_call(w, 'configure', '-kanjifont', @kanjifont)
end
rescue
- TkFont::Tk_FontUseTBL.delete(w)
+ Tk_FontUseTBL.mutex.synchronize{
+ TkFont::Tk_FontUseTBL.delete(w)
+ }
end
end
}
@@ -1627,8 +2070,11 @@ module TkFont::CoreMethods
rescue
latinkeys = {}
end
- if latinkeys != {}
+ 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
@@ -1720,6 +2166,13 @@ module TkFont::CoreMethods
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
@@ -1729,7 +2182,7 @@ module TkFont::CoreMethods
# private alias
###################################
case (Tk::TK_VERSION)
- when /^4\.*/
+ when /^4\..*/
alias actual_core actual_core_tk4x
alias configure_core configure_core_tk4x
alias configinfo_core configinfo_core_tk4x
@@ -1769,3 +2222,117 @@ 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
diff --git a/ext/tk/lib/tk/image.rb b/ext/tk/lib/tk/image.rb
index 35e2c4e394..57f82cb812 100644
--- a/ext/tk/lib/tk/image.rb
+++ b/ext/tk/lib/tk/image.rb
@@ -10,9 +10,16 @@ class TkImage<TkObject
TkCommandNames = ['image'.freeze].freeze
Tk_IMGTBL = TkCore::INTERP.create_table
- Tk_Image_ID = ['i'.freeze, '00000'.taint].freeze
- TkCore::INTERP.init_ip_env{ Tk_IMGTBL.clear }
+ (Tk_Image_ID = ['i'.freeze, '00000'.taint]).instance_eval{
+ @mutex = Mutex.new
+ def mutex; @mutex; end
+ freeze
+ }
+
+ TkCore::INTERP.init_ip_env{
+ Tk_IMGTBL.mutex.synchronize{ Tk_IMGTBL.clear }
+ }
def self.new(keys=nil)
if keys.kind_of?(Hash)
@@ -27,7 +34,10 @@ class TkImage<TkObject
obj = name
else
name = _get_eval_string(name)
- obj = Tk_IMGTBL[name]
+ obj = nil
+ Tk_IMGTBL.mutex.synchronize{
+ obj = Tk_IMGTBL[name]
+ }
end
if obj
if !(keys[:without_creating] || keys['without_creating'])
@@ -43,7 +53,13 @@ class TkImage<TkObject
end
end
end
- super(keys)
+ (obj = self.allocate).instance_eval{
+ Tk_IMGTBL.mutex.synchronize{
+ initialize(keys)
+ Tk_IMGTBL[@path] = self
+ }
+ }
+ obj
end
def initialize(keys=nil)
@@ -55,19 +71,22 @@ class TkImage<TkObject
without_creating = keys.delete('without_creating')
end
unless @path
- # @path = Tk_Image_ID.join('')
- @path = Tk_Image_ID.join(TkCore::INTERP._ip_id_)
- Tk_Image_ID[1].succ!
+ Tk_Image_ID.mutex.synchronize{
+ # @path = Tk_Image_ID.join('')
+ @path = Tk_Image_ID.join(TkCore::INTERP._ip_id_)
+ Tk_Image_ID[1].succ!
+ }
end
unless without_creating
tk_call_without_enc('image', 'create',
@type, @path, *hash_kv(keys, true))
end
- Tk_IMGTBL[@path] = self
end
def delete
- Tk_IMGTBL.delete(@id) if @id
+ Tk_IMGTBL.mutex.synchronize{
+ Tk_IMGTBL.delete(@id) if @id
+ }
tk_call_without_enc('image', 'delete', @path)
self
end
@@ -85,8 +104,10 @@ class TkImage<TkObject
end
def TkImage.names
- Tk.tk_call_without_enc('image', 'names').split.collect!{|id|
- (Tk_IMGTBL[id])? Tk_IMGTBL[id] : id
+ Tk_IMGTBL.mutex.synchronize{
+ Tk.tk_call_without_enc('image', 'names').split.collect!{|id|
+ (Tk_IMGTBL[id])? Tk_IMGTBL[id] : id
+ }
}
end
diff --git a/ext/tk/lib/tk/itemconfig.rb b/ext/tk/lib/tk/itemconfig.rb
index a7885e74f3..dbc45a9e7c 100644
--- a/ext/tk/lib/tk/itemconfig.rb
+++ b/ext/tk/lib/tk/itemconfig.rb
@@ -115,6 +115,14 @@ module TkItemConfigMethod
include TkTreatItemFont
include TkItemConfigOptkeys
+ def TkItemConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__
+ @mode || false
+ end
+ def TkItemConfigMethod.__set_IGNORE_UNKNOWN_CONFIGURE_OPTION__!(mode)
+ fail SecurityError, "can't change the mode" if $SAFE>=4
+ @mode = (mode)? true: false
+ end
+
def __item_cget_cmd(id)
# maybe need to override
[self.path, 'itemcget', id]
@@ -149,7 +157,7 @@ module TkItemConfigMethod
################################################
- def itemcget(tagOrId, option)
+ def __itemcget_core(tagOrId, option)
orig_opt = option
option = option.to_s
@@ -224,8 +232,27 @@ module TkItemConfigMethod
tk_tcl2ruby(tk_call_without_enc(*(__item_cget_cmd(tagid(tagOrId)) << "-#{option}")), true)
end
end
+ private :__itemcget_core
- def itemconfigure(tagOrId, slot, value=None)
+ def itemcget(tagOrId, option)
+ unless TkItemConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__
+ __itemcget_core(tagOrId, option)
+ else
+ begin
+ __itemcget_core(tagOrId, option)
+ rescue => e
+ begin
+ __itemconfiginfo_core(tagOrId)
+ # not tag error -> option is unknown
+ nil
+ rescue
+ fail e # tag error
+ end
+ end
+ end
+ end
+
+ def __itemconfigure_core(tagOrId, slot, value=None)
if slot.kind_of? Hash
slot = _symbolkey2str(slot)
@@ -288,6 +315,48 @@ module TkItemConfigMethod
end
self
end
+ private :__itemconfigure_core
+
+ def __check_available_itemconfigure_options(tagOrId, keys)
+ id = tagid(tagOrId)
+ availables = self.current_itemconfiginfo(id).keys
+
+ # add non-standard keys
+ availables |= __font_optkeys.map{|k|
+ [k.to_s, "latin#{k}", "ascii#{k}", "kanji#{k}"]
+ }.flatten
+ availables |= __item_methodcall_optkeys(id).keys.map{|k| k.to_s}
+ availables |= __item_keyonly_optkeys(id).keys.map{|k| k.to_s}
+
+ keys = _symbolkey2str(keys)
+ keys.delete_if{|k, v| !(availables.include?(k))}
+ end
+
+ def itemconfigure(tagOrId, slot, value=None)
+ unless TkItemConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__
+ __itemconfigure_core(tagOrId, slot, value)
+ else
+ if slot.kind_of?(Hash)
+ begin
+ __itemconfigure_core(tagOrId, slot)
+ rescue
+ slot = __check_available_configure_options(tagOrId, slot)
+ __itemconfigure_core(tagOrId, slot) unless slot.empty?
+ end
+ else
+ begin
+ __itemconfigure_core(tagOrId, slot, value)
+ rescue => e
+ begin
+ __itemconfiginfo_core(tagOrId)
+ rescue
+ fail e # tag error
+ end
+ end
+ end
+ end
+ self
+ end
def __itemconfiginfo_core(tagOrId, slot = nil)
if TkComm::GET_CONFIGINFO_AS_ARRAY
@@ -299,6 +368,10 @@ module TkItemConfigMethod
conf[__item_configinfo_struct(tagid(tagOrId))[:key]][1..-1]
if ( ! __item_configinfo_struct(tagid(tagOrId))[:alias] \
|| conf.size > __item_configinfo_struct(tagid(tagOrId))[:alias] + 1 )
+ fnt = conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]]
+ if TkFont.is_system_font?(fnt)
+ conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] = TkNamedFont.new(fnt)
+ end
conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = tagfontobj(tagid(tagOrId), fontkey)
elsif ( __item_configinfo_struct(tagid(tagOrId))[:alias] \
&& conf.size == __item_configinfo_struct(tagid(tagOrId))[:alias] + 1 \
@@ -635,6 +708,10 @@ module TkItemConfigMethod
fontconf = ret.assoc(optkey)
if fontconf && fontconf.size > 2
ret.delete_if{|inf| inf[0] =~ /^(|latin|ascii|kanji)#{optkey}$/}
+ fnt = fontconf[__item_configinfo_struct(tagid(tagOrId))[:default_value]]
+ if TkFont.is_system_font?(fnt)
+ fontconf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] = TkNamedFont.new(fnt)
+ end
fontconf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = tagfontobj(tagid(tagOrId), optkey)
ret.push(fontconf)
end
@@ -658,7 +735,11 @@ module TkItemConfigMethod
if ( ! __item_configinfo_struct(tagid(tagOrId))[:alias] \
|| conf.size > __item_configinfo_struct(tagid(tagOrId))[:alias] + 1 )
- conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = fontobj(tagid(tagOrId), fontkey)
+ fnt = conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]]
+ if TkFont.is_system_font?(fnt)
+ conf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] = TkNamedFont.new(fnt)
+ end
+ conf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = tagfontobj(tagid(tagOrId), fontkey)
{ conf.shift => conf }
elsif ( __item_configinfo_struct(tagid(tagOrId))[:alias] \
&& conf.size == __item_configinfo_struct(tagid(tagOrId))[:alias] + 1 )
@@ -1006,6 +1087,10 @@ module TkItemConfigMethod
ret.delete('latin' << optkey)
ret.delete('ascii' << optkey)
ret.delete('kanji' << optkey)
+ fnt = fontconf[__item_configinfo_struct(tagid(tagOrId))[:default_value]]
+ if TkFont.is_system_font?(fnt)
+ fontconf[__item_configinfo_struct(tagid(tagOrId))[:default_value]] = TkNamedFont.new(fnt)
+ end
fontconf[__item_configinfo_struct(tagid(tagOrId))[:current_value]] = tagfontobj(tagid(tagOrId), optkey)
ret[optkey] = fontconf
end
@@ -1023,7 +1108,21 @@ module TkItemConfigMethod
private :__itemconfiginfo_core
def itemconfiginfo(tagOrId, slot = nil)
- __itemconfiginfo_core(tagOrId, slot)
+ if slot && TkItemConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__
+ begin
+ __itemconfiginfo_core(tagOrId, slot)
+ rescue => e
+ begin
+ __itemconfiginfo_core(tagOrId)
+ # not tag error -> option is unknown
+ Array.new(__item_configinfo_struct.values.max).unshift(slot.to_s)
+ rescue
+ fail e # tag error
+ end
+ end
+ else
+ __itemconfiginfo_core(tagOrId, slot)
+ end
end
def current_itemconfiginfo(tagOrId, slot = nil)
diff --git a/ext/tk/lib/tk/menu.rb b/ext/tk/lib/tk/menu.rb
index e44f0e3ff1..8ba3156293 100644
--- a/ext/tk/lib/tk/menu.rb
+++ b/ext/tk/lib/tk/menu.rb
@@ -202,6 +202,9 @@ class Tk::Menu<TkWindow
tk_send_without_enc('unpost')
self
end
+ def xposition(index)
+ number(tk_send_without_enc('xposition', _get_eval_enc_str(index)))
+ end
def yposition(index)
number(tk_send_without_enc('yposition', _get_eval_enc_str(index)))
end
@@ -503,9 +506,24 @@ class Tk::Menubutton<Tk::Label
WidgetClassNames[WidgetClassName] = self
def create_self(keys)
if keys and keys != None
- # tk_call_without_enc('menubutton', @path, *hash_kv(keys, true))
- tk_call_without_enc(self.class::TkCommandNames[0], @path,
- *hash_kv(keys, true))
+ unless TkConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__
+ # tk_call_without_enc('menubutton', @path, *hash_kv(keys, true))
+ tk_call_without_enc(self.class::TkCommandNames[0], @path,
+ *hash_kv(keys, true))
+ else
+ begin
+ tk_call_without_enc(self.class::TkCommandNames[0], @path,
+ *hash_kv(keys, true))
+ rescue
+ tk_call_without_enc(self.class::TkCommandNames[0], @path)
+ keys = __check_available_configure_options(keys)
+ unless keys.empty?
+ tk_call_without_enc('destroy', @path)
+ tk_call_without_enc(self.class::TkCommandNames[0], @path,
+ *hash_kv(keys, true))
+ end
+ end
+ end
else
# tk_call_without_enc('menubutton', @path)
tk_call_without_enc(self.class::TkCommandNames[0], @path)
@@ -612,6 +630,9 @@ class Tk::OptionMenubutton<Tk::Menubutton
@menu.delete(index, last)
self
end
+ def xposition(index)
+ @menu.xposition(index)
+ end
def yposition(index)
@menu.yposition(index)
end
diff --git a/ext/tk/lib/tk/msgcat.rb b/ext/tk/lib/tk/msgcat.rb
index 061e43fd89..162953f425 100644
--- a/ext/tk/lib/tk/msgcat.rb
+++ b/ext/tk/lib/tk/msgcat.rb
@@ -74,7 +74,11 @@ class TkMsgCatalog < TkObject
"\n---< backtrace of Ruby side >-----\n" +
_toUTF8(e.backtrace.join("\n")) +
"\n---< backtrace of Tk side >-------"
- msg.instance_variable_set(:@encoding, 'utf-8')
+ 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" +
diff --git a/ext/tk/lib/tk/namespace.rb b/ext/tk/lib/tk/namespace.rb
index 5bf6474c5b..9d2213ff51 100644
--- a/ext/tk/lib/tk/namespace.rb
+++ b/ext/tk/lib/tk/namespace.rb
@@ -12,17 +12,24 @@ class TkNamespace < TkObject
].freeze
Tk_Namespace_ID_TBL = TkCore::INTERP.create_table
- Tk_Namespace_ID = ["ns".freeze, "00000".taint].freeze
+
+ (Tk_Namespace_ID = ["ns".freeze, "00000".taint]).instance_eval{
+ @mutex = Mutex.new
+ def mutex; @mutex; end
+ freeze
+ }
Tk_NsCode_RetObjID_TBL = TkCore::INTERP.create_table
TkCore::INTERP.init_ip_env{
- Tk_Namespace_ID_TBL.clear
- Tk_NsCode_RetObjID_TBL.clear
+ Tk_Namespace_ID_TBL.mutex.synchronize{ Tk_Namespace_ID_TBL.clear }
+ Tk_NsCode_RetObjID_TBL.mutex.synchronize{ Tk_NsCode_RetObjID_TBL.clear }
}
def TkNamespace.id2obj(id)
- Tk_Namespace_ID_TBL[id]? Tk_Namespace_ID_TBL[id]: id
+ Tk_Namespace_ID_TBL.mutex.synchronize{
+ Tk_Namespace_ID_TBL[id]? Tk_Namespace_ID_TBL[id]: id
+ }
end
#####################################
@@ -65,11 +72,13 @@ class TkNamespace < TkObject
def cget(slot)
if slot == :namespace || slot == 'namespace'
ns = super(slot)
- if TkNamespace::Tk_Namespace_ID_TBL.key?(ns)
- TkNamespace::Tk_Namespace_ID_TBL[ns]
- else
- ns
- end
+ Tk_Namespace_ID_TBL.mutex.synchronize{
+ if TkNamespace::Tk_Namespace_ID_TBL.key?(ns)
+ TkNamespace::Tk_Namespace_ID_TBL[ns]
+ else
+ ns
+ end
+ }
else
super(slot)
end
@@ -79,9 +88,11 @@ class TkNamespace < TkObject
if slot
if slot == :namespace || slot == 'namespace'
val = super(slot)
- if TkNamespace::Tk_Namespace_ID_TBL.key?(val)
- val = TkNamespace::Tk_Namespace_ID_TBL[val]
- end
+ Tk_Namespace_ID_TBL.mutex.synchronize{
+ if TkNamespace::Tk_Namespace_ID_TBL.key?(val)
+ val = TkNamespace::Tk_Namespace_ID_TBL[val]
+ end
+ }
else
val = super(slot)
end
@@ -96,19 +107,23 @@ class TkNamespace < TkObject
info = super()
if TkComm::GET_CONFIGINFO_AS_ARRAY
- info.map!{|inf|
- if inf[0] == 'namespace' &&
- TkNamespace::Tk_Namespace_ID_TBL.key?(inf[-1])
- [inf[0], TkNamespace::Tk_Namespace_ID_TBL[inf[-1]]]
- else
- inf
- end
+ Tk_Namespace_ID_TBL.mutex.synchronize{
+ info.map!{|inf|
+ if inf[0] == 'namespace' &&
+ TkNamespace::Tk_Namespace_ID_TBL.key?(inf[-1])
+ [inf[0], TkNamespace::Tk_Namespace_ID_TBL[inf[-1]]]
+ else
+ inf
+ end
+ }
}
else # ! TkComm::GET_CONFIGINFO_AS_ARRAY
val = info['namespace']
- if TkNamespace::Tk_Namespace_ID_TBL.key?(val)
- info['namespace'] = TkNamespace::Tk_Namespace_ID_TBL[val]
- end
+ Tk_Namespace_ID_TBL.mutex.synchronize{
+ if TkNamespace::Tk_Namespace_ID_TBL.key?(val)
+ info['namespace'] = TkNamespace::Tk_Namespace_ID_TBL[val]
+ end
+ }
end
info
@@ -215,9 +230,11 @@ class TkNamespace < TkObject
def initialize(name = nil, parent = nil)
unless name
- # name = Tk_Namespace_ID.join('')
- name = Tk_Namespace_ID.join(TkCore::INTERP._ip_id_)
- Tk_Namespace_ID[1].succ!
+ Tk_Namespace_ID.mutex.synchronize{
+ # name = Tk_Namespace_ID.join('')
+ name = Tk_Namespace_ID.join(TkCore::INTERP._ip_id_)
+ Tk_Namespace_ID[1].succ!
+ }
end
name = __tk_call('namespace', 'current') if name == ''
if parent
@@ -252,7 +269,9 @@ class TkNamespace < TkObject
# create namespace
__tk_call('namespace', 'eval', @fullname, '')
- Tk_Namespace_ID_TBL[@fullname] = self
+ Tk_Namespace_ID_TBL.mutex.synchronize{
+ Tk_Namespace_ID_TBL[@fullname] = self
+ }
end
def self.children(*args)
@@ -260,11 +279,13 @@ class TkNamespace < TkObject
# <pattern> must be glob-style pattern
tk_split_simplelist(tk_call('namespace', 'children', *args)).collect{|ns|
# ns is fullname
- if Tk_Namespace_ID_TBL.key?(ns)
- Tk_Namespace_ID_TBL[ns]
- else
- ns
- end
+ Tk_Namespace_ID_TBL.mutex.synchronize{
+ if Tk_Namespace_ID_TBL.key?(ns)
+ Tk_Namespace_ID_TBL[ns]
+ else
+ ns
+ end
+ }
}
end
def children(pattern=None)
@@ -290,14 +311,24 @@ class TkNamespace < TkObject
def code(script = Proc.new)
if script.kind_of?(String)
cmd = proc{|*args|
- ret = ScopeArgs.new(@fullname,*args).instance_eval(script)
+ if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!!
+ obj = ScopeArgs.new(@fullname,*args)
+ ret = obj.instance_exec(obj, script)
+ else
+ ret = ScopeArgs.new(@fullname,*args).instance_eval(script)
+ end
id = ret.object_id
TkNamespace::Tk_NsCode_RetObjID_TBL[id] = ret
id
}
elsif script.kind_of?(Proc)
cmd = proc{|*args|
- ret = ScopeArgs.new(@fullname,*args).instance_eval(&script)
+ if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!!
+ obj = ScopeArgs.new(@fullname,*args)
+ ret = obj.instance_exec(obj, &script)
+ else
+ ret = ScopeArgs.new(@fullname,*args).instance_eval(&script)
+ end
id = ret.object_id
TkNamespace::Tk_NsCode_RetObjID_TBL[id] = ret
id
@@ -319,11 +350,13 @@ class TkNamespace < TkObject
def self.current
ns = self.current_path
- if Tk_Namespace_ID_TBL.key?(ns)
- Tk_Namespace_ID_TBL[ns]
- else
- ns
- end
+ Tk_Namespace_ID_TBL.mutex.synchronize{
+ if Tk_Namespace_ID_TBL.key?(ns)
+ Tk_Namespace_ID_TBL[ns]
+ else
+ ns
+ end
+ }
end
def current_namespace
# ns_tk_call('namespace', 'current')
@@ -335,11 +368,13 @@ class TkNamespace < TkObject
def self.delete(*ns_list)
tk_call('namespace', 'delete', *ns_list)
ns_list.each{|ns|
- if ns.kind_of?(TkNamespace)
- Tk_Namespace_ID_TBL.delete(ns.path)
- else
- Tk_Namespace_ID_TBL.delete(ns.to_s)
- end
+ Tk_Namespace_ID_TBL.mutex.synchronize{
+ if ns.kind_of?(TkNamespace)
+ Tk_Namespace_ID_TBL.delete(ns.path)
+ else
+ Tk_Namespace_ID_TBL.delete(ns.to_s)
+ end
+ }
}
end
def delete
@@ -371,7 +406,7 @@ class TkNamespace < TkObject
def self.eval(namespace, cmd = Proc.new, *args)
#tk_call('namespace', 'eval', namespace, cmd, *args)
- TkNamespace.new(namespece).eval(cmd, *args)
+ TkNamespace.new(namespace).eval(cmd, *args)
end
=begin
def eval(cmd = Proc.new, *args)
@@ -444,11 +479,13 @@ class TkNamespace < TkObject
def self.parent(namespace=None)
ns = tk_call('namespace', 'parent', namespace)
- if Tk_Namespace_ID_TBL.key?(ns)
- Tk_Namespace_ID_TBL[ns]
- else
- ns
- end
+ Tk_Namespace_ID_TBL.mutex.synchronize{
+ if Tk_Namespace_ID_TBL.key?(ns)
+ Tk_Namespace_ID_TBL[ns]
+ else
+ ns
+ end
+ }
end
def parent
tk_call('namespace', 'parent', @fullname)
diff --git a/ext/tk/lib/tk/optiondb.rb b/ext/tk/lib/tk/optiondb.rb
index 6a7708ac53..186811d37d 100644
--- a/ext/tk/lib/tk/optiondb.rb
+++ b/ext/tk/lib/tk/optiondb.rb
@@ -8,7 +8,11 @@ module TkOptionDB
extend Tk
TkCommandNames = ['option'.freeze].freeze
- CmdClassID = ['CMD_CLASS'.freeze, '00000'.taint].freeze
+ (CmdClassID = ['CMD_CLASS'.freeze, '00000'.taint]).instance_eval{
+ @mutex = Mutex.new
+ def mutex; @mutex; end
+ freeze
+ }
module Priority
WidgetDefault = 20
@@ -250,8 +254,10 @@ module TkOptionDB
def __create_new_class(klass, func, safe = 4, add = false, parent = nil)
if klass.kind_of?(TkWindow)
carrier = klass.path
- klass = CmdClassID.join(TkCore::INTERP._ip_id_)
- CmdClassID[1].succ!
+ CmdClassID.mutex.synchronize{
+ klass = CmdClassID.join(TkCore::INTERP._ip_id_)
+ CmdClassID[1].succ!
+ }
parent = nil # ignore parent
else
klass = klass.to_s if klass.kind_of?(Symbol)
@@ -312,7 +318,7 @@ module TkOptionDB
:singleton_methods, :remove_const, :remove_method, :undef_method,
:to_s, :inspect, :display, :method, :methods, :respond_to?,
:instance_variable_get, :instance_variable_set, :instance_method,
- :instance_eval, :instance_variables, :kind_of?, :is_a?,
+ :instance_eval, :instance_exec, :instance_variables, :kind_of?, :is_a?,
:private_methods, :protected_methods, :public_methods ].each{|m|
alias_method(m, :__null_method)
}
diff --git a/ext/tk/lib/tk/root.rb b/ext/tk/lib/tk/root.rb
index 4d83282448..7237b4c614 100644
--- a/ext/tk/lib/tk/root.rb
+++ b/ext/tk/lib/tk/root.rb
@@ -41,7 +41,13 @@ class Tk::Root<TkWindow
}
end
- root.instance_eval(&b) if block_given?
+ if block_given?
+ if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!!
+ root.instance_exec(root, &b)
+ else
+ root.instance_eval(&b)
+ end
+ end
root
end
diff --git a/ext/tk/lib/tk/scale.rb b/ext/tk/lib/tk/scale.rb
index b97ed68072..bf2791ec55 100644
--- a/ext/tk/lib/tk/scale.rb
+++ b/ext/tk/lib/tk/scale.rb
@@ -14,9 +14,24 @@ class Tk::Scale<TkWindow
cmd = keys.delete('command')
keys['command'] = proc{|val| cmd.call(val.to_f)}
end
- #tk_call_without_enc('scale', @path, *hash_kv(keys, true))
- tk_call_without_enc(self.class::TkCommandNames[0], @path,
- *hash_kv(keys, true))
+ unless TkConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__
+ #tk_call_without_enc('scale', @path, *hash_kv(keys, true))
+ tk_call_without_enc(self.class::TkCommandNames[0], @path,
+ *hash_kv(keys, true))
+ else
+ begin
+ tk_call_without_enc(self.class::TkCommandNames[0], @path,
+ *hash_kv(keys, true))
+ rescue
+ tk_call_without_enc(self.class::TkCommandNames[0], @path)
+ keys = __check_available_configure_options(keys)
+ unless keys.empty?
+ tk_call_without_enc('destroy', @path)
+ tk_call_without_enc(self.class::TkCommandNames[0], @path,
+ *hash_kv(keys, true))
+ end
+ end
+ end
else
#tk_call_without_enc('scale', @path)
tk_call_without_enc(self.class::TkCommandNames[0], @path)
diff --git a/ext/tk/lib/tk/scrollbar.rb b/ext/tk/lib/tk/scrollbar.rb
index 66eadbd65f..521fc7e400 100644
--- a/ext/tk/lib/tk/scrollbar.rb
+++ b/ext/tk/lib/tk/scrollbar.rb
@@ -19,9 +19,24 @@ class Tk::Scrollbar<TkWindow
}
if keys and keys != None
- #tk_call_without_enc('scrollbar', @path, *hash_kv(keys, true))
- tk_call_without_enc(self.class::TkCommandNames[0], @path,
- *hash_kv(keys, true))
+ unless TkConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__
+ #tk_call_without_enc('scrollbar', @path, *hash_kv(keys, true))
+ tk_call_without_enc(self.class::TkCommandNames[0], @path,
+ *hash_kv(keys, true))
+ else
+ begin
+ tk_call_without_enc(self.class::TkCommandNames[0], @path,
+ *hash_kv(keys, true))
+ rescue
+ tk_call_without_enc(self.class::TkCommandNames[0], @path)
+ keys = __check_available_configure_options(keys)
+ unless keys.empty?
+ tk_call_without_enc('destroy', @path)
+ tk_call_without_enc(self.class::TkCommandNames[0], @path,
+ *hash_kv(keys, true))
+ end
+ end
+ end
else
#tk_call_without_enc('scrollbar', @path)
tk_call_without_enc(self.class::TkCommandNames[0], @path)
@@ -103,6 +118,26 @@ class Tk::Scrollbar<TkWindow
def activate(element=None)
tk_send_without_enc('activate', element)
end
+
+ def moveto(fraction)
+ tk_send_without_enc('moveto', fraction)
+ self
+ end
+
+ def scroll(*args)
+ tk_send_without_enc('scroll', *args)
+ self
+ end
+
+ def scroll_units(num)
+ scroll(num, 'units')
+ self
+ end
+
+ def scroll_pages(num)
+ scroll(num, 'pages')
+ self
+ end
end
#TkScrollbar = Tk::Scrollbar unless Object.const_defined? :TkScrollbar
diff --git a/ext/tk/lib/tk/spinbox.rb b/ext/tk/lib/tk/spinbox.rb
index e7f223aea7..e372c58009 100644
--- a/ext/tk/lib/tk/spinbox.rb
+++ b/ext/tk/lib/tk/spinbox.rb
@@ -37,6 +37,22 @@ class Tk::Spinbox<Tk::Entry
nil
]
+ # 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
+ }
+
_setup_subst_table(KEY_TBL, PROC_TBL);
def self.ret_val(val)
diff --git a/ext/tk/lib/tk/text.rb b/ext/tk/lib/tk/text.rb
index 2ed1d30cf5..14b9be23f0 100644
--- a/ext/tk/lib/tk/text.rb
+++ b/ext/tk/lib/tk/text.rb
@@ -250,7 +250,11 @@ class Tk::Text<TkTextWin
def self.new(*args, &block)
obj = super(*args){}
obj.init_instance_variable
- obj.instance_eval(&block) if defined? yield
+ if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!!
+ obj.instance_exec(obj, &block) if defined? yield
+ else
+ obj.instance_eval(&block) if defined? yield
+ end
obj
end
@@ -260,8 +264,12 @@ class Tk::Text<TkTextWin
end
def __destroy_hook__
- TkTextTag::TTagID_TBL.delete(@path)
- TkTextMark::TMarkID_TBL.delete(@path)
+ TkTextTag::TTagID_TBL.mutex.synchronize{
+ TkTextTag::TTagID_TBL.delete(@path)
+ }
+ TkTextTag::TMarkID_TBL.mutex.synchronize{
+ TkTextMark::TMarkID_TBL.delete(@path)
+ }
end
def create_self(keys)
@@ -712,15 +720,17 @@ class Tk::Text<TkTextWin
def tag_delete(*tags)
tk_send_without_enc('tag', 'delete',
*(tags.collect{|tag| _get_eval_enc_str(tag)}))
- if TkTextTag::TTagID_TBL[@path]
- tags.each{|tag|
- if tag.kind_of?(TkTextTag)
- TkTextTag::TTagID_TBL[@path].delete(tag.id)
- else
- TkTextTag::TTagID_TBL[@path].delete(tag)
- end
- }
- end
+ TkTextTag::TTagID_TBL.mutex.synchronize{
+ if TkTextTag::TTagID_TBL[@path]
+ tags.each{|tag|
+ if tag.kind_of?(TkTextTag)
+ TkTextTag::TTagID_TBL[@path].delete(tag.id)
+ else
+ TkTextTag::TTagID_TBL[@path].delete(tag)
+ end
+ }
+ end
+ }
self
end
alias deltag tag_delete
diff --git a/ext/tk/lib/tk/textmark.rb b/ext/tk/lib/tk/textmark.rb
index 6ce52b58d7..72c1ce1ab4 100644
--- a/ext/tk/lib/tk/textmark.rb
+++ b/ext/tk/lib/tk/textmark.rb
@@ -8,14 +8,26 @@ class TkTextMark<TkObject
include Tk::Text::IndexModMethods
TMarkID_TBL = TkCore::INTERP.create_table
- Tk_TextMark_ID = ['mark'.freeze, '00000'.taint].freeze
- TkCore::INTERP.init_ip_env{ TMarkID_TBL.clear }
+ (Tk_TextMark_ID = ['mark'.freeze, '00000'.taint]).instance_eval{
+ @mutex = Mutex.new
+ def mutex; @mutex; end
+ freeze
+ }
+
+ TkCore::INTERP.init_ip_env{
+ TMarkID_TBL.mutex.synchronize{ TMarkID_TBL.clear }
+ }
def TkTextMark.id2obj(text, id)
tpath = text.path
- return id unless TMarkID_TBL[tpath]
- TMarkID_TBL[tpath][id]? TMarkID_TBL[tpath][id]: id
+ TMarkID_TBL.mutex.synchronize{
+ if TMarkID_TBL[tpath]
+ TMarkID_TBL[tpath][id]? TMarkID_TBL[tpath][id]: id
+ else
+ id
+ end
+ }
end
def initialize(parent, index)
@@ -24,12 +36,16 @@ class TkTextMark<TkObject
#end
@parent = @t = parent
@tpath = parent.path
- # @path = @id = Tk_TextMark_ID.join('')
- @path = @id = Tk_TextMark_ID.join(TkCore::INTERP._ip_id_).freeze
- TMarkID_TBL[@id] = self
- TMarkID_TBL[@tpath] = {} unless TMarkID_TBL[@tpath]
- TMarkID_TBL[@tpath][@id] = self
- Tk_TextMark_ID[1].succ!
+ Tk_TextMark_ID.mutex.synchronize{
+ # @path = @id = Tk_TextMark_ID.join('')
+ @path = @id = Tk_TextMark_ID.join(TkCore::INTERP._ip_id_).freeze
+ Tk_TextMark_ID[1].succ!
+ }
+ TMarkID_TBL.mutex.synchronize{
+ TMarkID_TBL[@id] = self
+ TMarkID_TBL[@tpath] = {} unless TMarkID_TBL[@tpath]
+ TMarkID_TBL[@tpath][@id] = self
+ }
tk_call_without_enc(@t.path, 'mark', 'set', @id,
_get_eval_enc_str(index))
@t._addtag id, self
@@ -124,27 +140,44 @@ end
TktMark = TkTextMark
class TkTextNamedMark<TkTextMark
- def self.new(parent, name, *args)
- if TMarkID_TBL[parent.path] && TMarkID_TBL[parent.path][name]
- return TMarkID_TBL[parent.path][name]
- else
- super(parent, name, *args)
- end
+ def self.new(parent, name, index=nil)
+ TMarkID_TBL.mutex.synchronize{
+ if TMarkID_TBL[parent.path] && TMarkID_TBL[parent.path][name]
+ obj = TMarkID_TBL[parent.path][name]
+ else
+ # super(parent, name, *args)
+ (obj = self.allocate).instance_eval{
+ @parent = @t = parent
+ @tpath = parent.path
+ @path = @id = name
+ TMarkID_TBL[@id] = self
+ TMarkID_TBL[@tpath] = {} unless TMarkID_TBL[@tpath]
+ TMarkID_TBL[@tpath][@id] = self unless TMarkID_TBL[@tpath][@id]
+ @t._addtag @id, self
+ }
+ obj
+ end
+
+ if obj && index
+ tk_call_without_enc(parent.path, 'mark', 'set', name,
+ _get_eval_enc_str(index))
+ end
+ obj
+ }
end
def initialize(parent, name, index=nil)
+ # dummy:: not called by 'new' method
+
#unless parent.kind_of?(Tk::Text)
# fail ArgumentError, "expect Tk::Text for 1st argument"
#end
@parent = @t = parent
@tpath = parent.path
@path = @id = name
- TMarkID_TBL[@id] = self
- TMarkID_TBL[@tpath] = {} unless TMarkID_TBL[@tpath]
- TMarkID_TBL[@tpath][@id] = self unless TMarkID_TBL[@tpath][@id]
tk_call_without_enc(@t.path, 'mark', 'set', @id,
_get_eval_enc_str(index)) if index
- @t._addtag id, self
+ @t._addtag @id, self
end
end
TktNamedMark = TkTextNamedMark
diff --git a/ext/tk/lib/tk/texttag.rb b/ext/tk/lib/tk/texttag.rb
index 8264d52938..792d544fe7 100644
--- a/ext/tk/lib/tk/texttag.rb
+++ b/ext/tk/lib/tk/texttag.rb
@@ -10,14 +10,26 @@ class TkTextTag<TkObject
include Tk::Text::IndexModMethods
TTagID_TBL = TkCore::INTERP.create_table
- Tk_TextTag_ID = ['tag'.freeze, '00000'.taint].freeze
- TkCore::INTERP.init_ip_env{ TTagID_TBL.clear }
+ (Tk_TextTag_ID = ['tag'.freeze, '00000'.taint]).instance_eval{
+ @mutex = Mutex.new
+ def mutex; @mutex; end
+ freeze
+ }
+
+ TkCore::INTERP.init_ip_env{
+ TTagID_TBL.mutex.synchronize{ TTagID_TBL.clear }
+ }
def TkTextTag.id2obj(text, id)
tpath = text.path
- return id unless TTagID_TBL[tpath]
- TTagID_TBL[tpath][id]? TTagID_TBL[tpath][id]: id
+ TTagID_TBL.mutex.synchronize{
+ if TTagID_TBL[tpath]
+ TTagID_TBL[tpath][id]? TTagID_TBL[tpath][id]: id
+ else
+ id
+ end
+ }
end
def initialize(parent, *args)
@@ -26,12 +38,16 @@ class TkTextTag<TkObject
#end
@parent = @t = parent
@tpath = parent.path
- # @path = @id = Tk_TextTag_ID.join('')
- @path = @id = Tk_TextTag_ID.join(TkCore::INTERP._ip_id_).freeze
- # TTagID_TBL[@id] = self
- TTagID_TBL[@tpath] = {} unless TTagID_TBL[@tpath]
- TTagID_TBL[@tpath][@id] = self
- Tk_TextTag_ID[1].succ!
+ Tk_TextTag_ID.mutex.synchronize{
+ # @path = @id = Tk_TextTag_ID.join('')
+ @path = @id = Tk_TextTag_ID.join(TkCore::INTERP._ip_id_).freeze
+ Tk_TextTag_ID[1].succ!
+ }
+ TTagID_TBL.mutex.synchronize{
+ TTagID_TBL[@id] = self
+ TTagID_TBL[@tpath] = {} unless TTagID_TBL[@tpath]
+ TTagID_TBL[@tpath][@id] = self
+ }
#tk_call @t.path, "tag", "configure", @id, *hash_kv(keys)
if args != []
keys = args.pop
@@ -221,7 +237,9 @@ class TkTextTag<TkObject
def destroy
tk_call_without_enc(@t.path, 'tag', 'delete', @id)
- TTagID_TBL[@tpath].delete(@id) if TTagID_TBL[@tpath]
+ TTagID_TBL.mutex.synchronize{
+ TTagID_TBL[@tpath].delete(@id) if TTagID_TBL[@tpath]
+ }
self
end
end
@@ -229,33 +247,48 @@ TktTag = TkTextTag
class TkTextNamedTag<TkTextTag
def self.new(parent, name, *args)
- if TTagID_TBL[parent.path] && TTagID_TBL[parent.path][name]
- tagobj = TTagID_TBL[parent.path][name]
- if args != []
- keys = args.pop
- if keys.kind_of?(Hash)
- tagobj.add(*args) if args != []
- tagobj.configure(keys)
- else
- args.push keys
- tagobj.add(*args)
- end
+ tagobj = nil
+ TTagID_TBL.mutex.synchronize{
+ if TTagID_TBL[parent.path] && TTagID_TBL[parent.path][name]
+ tagobj = TTagID_TBL[parent.path][name]
+ else
+ # super(parent, name, *args)
+ (tagobj = self.allocate).instance_eval{
+ @parent = @t = parent
+ @tpath = parent.path
+ @path = @id = name
+ TTagID_TBL[@id] = self
+ TTagID_TBL[@tpath] = {} unless TTagID_TBL[@tpath]
+ TTagID_TBL[@tpath][@id] = self unless TTagID_TBL[@tpath][@id]
+ @t._addtag @id, self
+ }
+ end
+ }
+
+ if args != []
+ keys = args.pop
+ if keys.kind_of?(Hash)
+ tagobj.add(*args) if args != []
+ tagobj.configure(keys)
+ else
+ args.push keys
+ tagobj.add(*args)
end
- return tagobj
- else
- super(parent, name, *args)
end
+
+ tagobj
end
def initialize(parent, name, *args)
+ # dummy:: not called by 'new' method
+
#unless parent.kind_of?(Tk::Text)
# fail ArgumentError, "expect Tk::Text for 1st argument"
#end
@parent = @t = parent
@tpath = parent.path
@path = @id = name
- TTagID_TBL[@tpath] = {} unless TTagID_TBL[@tpath]
- TTagID_TBL[@tpath][@id] = self unless TTagID_TBL[@tpath][@id]
+
#if mode
# tk_call @t.path, "addtag", @id, *args
#end
@@ -269,7 +302,7 @@ class TkTextNamedTag<TkTextTag
add(*args)
end
end
- @t._addtag id, self
+ @t._addtag @id, self
end
end
TktNamedTag = TkTextNamedTag
diff --git a/ext/tk/lib/tk/timer.rb b/ext/tk/lib/tk/timer.rb
index 47f2b79350..3588f0c480 100644
--- a/ext/tk/lib/tk/timer.rb
+++ b/ext/tk/lib/tk/timer.rb
@@ -11,7 +11,12 @@ class TkTimer
TkCommandNames = ['after'.freeze].freeze
- Tk_CBID = ['a'.freeze, '00000'.taint].freeze
+ (Tk_CBID = ['a'.freeze, '00000'.taint]).instance_eval{
+ @mutex = Mutex.new
+ def mutex; @mutex; end
+ freeze
+ }
+
Tk_CBTBL = {}.taint
TkCore::INTERP.add_tk_procs('rb_after', 'id', <<-'EOL')
@@ -96,9 +101,9 @@ class TkTimer
return self
end
@after_script = "rb_after #{@id}"
- @after_id = tk_call_without_enc('after', sleep, @after_script)
@current_args = args
@current_script = [sleep, @after_script]
+ @after_id = tk_call_without_enc('after', sleep, @after_script)
self
end
@@ -138,9 +143,11 @@ class TkTimer
end
def initialize(*args, &b)
- # @id = Tk_CBID.join('')
- @id = Tk_CBID.join(TkCore::INTERP._ip_id_)
- Tk_CBID[1].succ!
+ Tk_CBID.mutex.synchronize{
+ # @id = Tk_CBID.join('')
+ @id = Tk_CBID.join(TkCore::INTERP._ip_id_)
+ Tk_CBID[1].succ!
+ }
@wait_var = TkVariable.new(0)
diff --git a/ext/tk/lib/tk/ttk_selector.rb b/ext/tk/lib/tk/ttk_selector.rb
index f89b5c76be..72ed637a38 100644
--- a/ext/tk/lib/tk/ttk_selector.rb
+++ b/ext/tk/lib/tk/ttk_selector.rb
@@ -56,6 +56,15 @@ module Tk
@TOPLEVEL_ALIAS_TABLE[:Tile] = @TOPLEVEL_ALIAS_TABLE[:Ttk]
################################################
+ # register some Ttk widgets as default
+ # (Ttk is a standard library on Tcl/Tk8.5+)
+ @TOPLEVEL_ALIAS_TABLE[:Ttk].each{|sym, file|
+ unless Object.autoload?(sym) || Object.const_defined?(sym)
+ Object.autoload(sym, file)
+ end
+ }
+
+ ################################################
@TOPLEVEL_ALIAS_SETUP_PROC[:Tile] =
@TOPLEVEL_ALIAS_SETUP_PROC[:Ttk] = proc{|mod|
diff --git a/ext/tk/lib/tk/validation.rb b/ext/tk/lib/tk/validation.rb
index 0c5b5c61b9..1da38c776d 100644
--- a/ext/tk/lib/tk/validation.rb
+++ b/ext/tk/lib/tk/validation.rb
@@ -249,6 +249,22 @@ class TkValidateCommand
nil
]
+ # 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
+ }
+
_setup_subst_table(KEY_TBL, PROC_TBL);
#
diff --git a/ext/tk/lib/tk/variable.rb b/ext/tk/lib/tk/variable.rb
index 632f00cedf..f738a96ee7 100644
--- a/ext/tk/lib/tk/variable.rb
+++ b/ext/tk/lib/tk/variable.rb
@@ -16,7 +16,18 @@ class TkVariable
#TkVar_ID_TBL = {}
TkVar_CB_TBL = TkCore::INTERP.create_table
TkVar_ID_TBL = TkCore::INTERP.create_table
- Tk_VARIABLE_ID = ["v".freeze, "00000".taint].freeze
+ (Tk_VARIABLE_ID = ["v".freeze, "00000".taint]).instance_eval{
+ @mutex = Mutex.new
+ def mutex; @mutex; end
+ freeze
+ }
+ TkCore::INTERP.init_ip_env{
+ TkVar_CB_TBL.mutex.synchronize{ TkVar_CB_TBL.clear }
+ TkVar_ID_TBL.mutex.synchronize{ TkVar_ID_TBL.clear }
+ }
+
+ major, minor, type, type_name, patchlevel = TclTkLib.get_version
+ USE_OLD_TRACE_OPTION_STYLE = (major < 8) || (major == 8 && minor < 4)
#TkCore::INTERP.add_tk_procs('rb_var', 'args',
# "ruby [format \"TkVariable.callback %%Q!%s!\" $args]")
@@ -44,10 +55,10 @@ class TkVariable
def TkVariable.callback(id, name1, name2, op)
#name1,name2,op = tk_split_list(args)
#name1,name2,op = tk_split_simplelist(args)
- if TkVar_CB_TBL[id]
+ if cb_obj = TkVar_CB_TBL[id]
#_get_eval_string(TkVar_CB_TBL[name1].trace_callback(name2,op))
begin
- _get_eval_string(TkVar_CB_TBL[id].trace_callback(name2, op))
+ _get_eval_string(cb_obj.trace_callback(name2, op))
rescue SystemExit
exit(0)
rescue Interrupt
@@ -59,7 +70,11 @@ class TkVariable
"\n---< backtrace of Ruby side >-----\n" +
_toUTF8(e.backtrace.join("\n")) +
"\n---< backtrace of Tk side >-------"
- msg.instance_variable_set(:@encoding, 'utf-8')
+ 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" +
@@ -267,11 +282,15 @@ class TkVariable
def initialize(val="", type=nil)
# @id = Tk_VARIABLE_ID.join('')
begin
- @id = Tk_VARIABLE_ID.join(TkCore::INTERP._ip_id_)
- Tk_VARIABLE_ID[1].succ!
+ Tk_VARIABLE_ID.mutex.synchronize{
+ @id = Tk_VARIABLE_ID.join(TkCore::INTERP._ip_id_)
+ Tk_VARIABLE_ID[1].succ!
+ }
end until INTERP._invoke_without_enc('info', 'globals', @id).empty?
- TkVar_ID_TBL[@id] = self
+ TkVar_ID_TBL.mutex.synchronize{
+ TkVar_ID_TBL[@id] = self
+ }
@var = @id
@elem = nil
@@ -1263,56 +1282,101 @@ end
end
end
+ def _check_trace_opt(opts)
+ if opts.kind_of?(Array)
+ opt_str = opts.map{|s| s.to_s}.join(' ')
+ else
+ opt_str = opts.to_s
+ end
+
+ fail ArgumentError, 'null trace option' if opt_str.empty?
+
+ if opt_str =~ /[^arwu\s]/
+ # new format (Tcl/Tk8.4+?)
+ if opts.kind_of?(Array)
+ opt_ary = opts.map{|opt| opt.to_s.strip}
+ else
+ opt_ary = opt_str.split(/\s+|\|/)
+ opt_ary.delete('')
+ end
+ if USE_OLD_TRACE_OPTION_STYLE
+ opt_ary.uniq.map{|opt|
+ case opt
+ when 'array'
+ 'a'
+ when 'read'
+ 'r'
+ when 'write'
+ 'w'
+ when 'unset'
+ 'u'
+ else
+ fail ArgumentError, "unsupported trace option '#{opt}' on Tcl/Tk#{Tk::TCL_PATCHLEVEL}"
+ end
+ }.join
+ else
+ opt_ary
+ end
+ else
+ # old format
+ opt_ary = opt_str.delete('^arwu').split(//).uniq
+ if USE_OLD_TRACE_OPTION_STYLE
+ opt_ary.join
+ else
+ opt_ary.map{|c|
+ case c
+ when 'a'
+ 'array'
+ when 'r'
+ 'read'
+ when 'w'
+ 'write'
+ when 'u'
+ 'unset'
+ end
+ }
+ end
+ end
+ end
+ private :_check_trace_opt
+
def trace(opts, cmd = Proc.new)
- @trace_var = [] if @trace_var == nil
- #opts = ['r','w','u'].find_all{|c| opts.index(c)}.join('')
- opts = opts.to_s
- opts = ['r','w','u'].find_all{|c| opts.index(c)}.join('')
- @trace_var.unshift([opts,cmd])
+ opts = _check_trace_opt(opts)
+ (@trace_var ||= []).unshift([opts,cmd])
+
if @trace_opts == nil
TkVar_CB_TBL[@id] = self
- @trace_opts = opts.dup
- Tk.tk_call_without_enc('trace', 'variable', @id, @trace_opts,
- 'rb_var ' << @id)
-=begin
- if /^(8\.([4-9]|[1-9][0-9])|9\.|[1-9][0-9])/ =~ Tk::TCL_VERSION
- # TCL_VERSION >= 8.4
- Tk.tk_call_without_enc('trace', 'add', 'variable',
- @id, @trace_opts, 'rb_var')
+ @trace_opts = opts
+ if USE_OLD_TRACE_OPTION_STYLE
+ Tk.tk_call_without_enc('trace', 'variable',
+ @id, @trace_opts, 'rb_var ' << @id)
else
- # TCL_VERSION <= 8.3
- Tk.tk_call_without_enc('trace', 'variable', @id, @trace_opts, 'rb_var')
+ Tk.tk_call_without_enc('trace', 'add', 'variable',
+ @id, @trace_opts, 'rb_var ' << @id)
end
-=end
else
newopts = @trace_opts.dup
- #opts.each_byte{|c| newopts += c.chr unless newopts.index(c)}
- opts.each_byte{|c| newopts.concat(c.chr) unless newopts.index(c)}
- if newopts != @trace_opts
- Tk.tk_call_without_enc('trace', 'vdelete', @id, @trace_opts,
- 'rb_var ' << @id)
- @trace_opts.replace(newopts)
- Tk.tk_call_without_enc('trace', 'variable', @id, @trace_opts,
- 'rb_var ' << @id)
-=begin
- if /^(8\.([4-9]|[1-9][0-9])|9\.|[1-9][0-9])/ =~ Tk::TCL_VERSION
- # TCL_VERSION >= 8.4
- Tk.tk_call_without_enc('trace', 'remove', 'variable',
- @id, @trace_opts, 'rb_var')
- @trace_opts.replace(newopts)
- Tk.tk_call_without_enc('trace', 'add', 'variable',
- @id, @trace_opts, 'rb_var')
- else
- # TCL_VERSION <= 8.3
+ if USE_OLD_TRACE_OPTION_STYLE
+ opts.each_byte{|c| newopts.concat(c.chr) unless newopts.index(c.chr)}
+ if newopts != @trace_opts
Tk.tk_call_without_enc('trace', 'vdelete',
- @id, @trace_opts, 'rb_var')
+ @id, @trace_opts, 'rb_var ' << @id)
@trace_opts.replace(newopts)
Tk.tk_call_without_enc('trace', 'variable',
- @id, @trace_opts, 'rb_var')
+ @id, @trace_opts, 'rb_var ' << @id)
+ end
+ else
+ newopts |= opts
+ unless (newopts - @trace_opts).empty?
+ Tk.tk_call_without_enc('trace', 'remove', 'variable',
+ @id, @trace_opts, 'rb_var ' << @id)
+ @trace_opts.replace(newopts)
+ Tk.tk_call_without_enc('trace', 'add', 'variable',
+ @id, @trace_opts, 'rb_var ' << @id)
end
-=end
end
end
+
self
end
@@ -1321,65 +1385,54 @@ end
fail(RuntimeError,
"invalid for a TkVariable which denotes an element of Tcl's array")
end
- @trace_elem = {} if @trace_elem == nil
- @trace_elem[elem] = [] if @trace_elem[elem] == nil
- opts = opts.to_s
- opts = ['r','w','u'].find_all{|c| opts.index(c)}.join('')
- @trace_elem[elem].unshift([opts,cmd])
+
+ opts = _check_trace_opt(opts)
+
+ ((@trace_elem ||= {})[elem] ||= []).unshift([opts,cmd])
+
if @trace_opts == nil
TkVar_CB_TBL[@id] = self
- @trace_opts = opts.dup
- Tk.tk_call_without_enc('trace', 'variable', @id, @trace_opts,
- 'rb_var ' << @id)
-=begin
- if /^(8\.([4-9]|[1-9][0-9])|9\.|[1-9][0-9])/ =~ Tk::TCL_VERSION
- # TCL_VERSION >= 8.4
+ @trace_opts = opts
+ if USE_OLD_TRACE_OPTION_STYLE
Tk.tk_call_without_enc('trace', 'add', 'variable',
- @id, @trace_opts, 'rb_var')
+ @id, @trace_opts, 'rb_var ' << @id)
else
- # TCL_VERSION <= 8.3
Tk.tk_call_without_enc('trace', 'variable',
- @id, @trace_opts, 'rb_var')
+ @id, @trace_opts, 'rb_var ' << @id)
end
-=end
else
newopts = @trace_opts.dup
- # opts.each_byte{|c| newopts += c.chr unless newopts.index(c)}
- opts.each_byte{|c| newopts.concat(c.chr) unless newopts.index(c)}
- if newopts != @trace_opts
- Tk.tk_call_without_enc('trace', 'vdelete', @id, @trace_opts,
- 'rb_var ' << @id)
- @trace_opts.replace(newopts)
- Tk.tk_call_without_enc('trace', 'variable', @id, @trace_opts,
- 'rb_var ' << @id)
-=begin
- if /^(8\.([4-9]|[1-9][0-9])|9\.|[1-9][0-9])/ =~ Tk::TCL_VERSION
- # TCL_VERSION >= 8.4
- Tk.tk_call_without_enc('trace', 'remove', 'variable',
- @id, @trace_opts, 'rb_var')
- @trace_opts.replace(newopts)
- Tk.tk_call_without_enc('trace', 'add', 'variable',
- @id, @trace_opts, 'rb_var')
- else
- # TCL_VERSION <= 8.3
+ if USE_OLD_TRACE_OPTION_STYLE
+ opts.each_byte{|c| newopts.concat(c.chr) unless newopts.index(c.chr)}
+ if newopts != @trace_opts
Tk.tk_call_without_enc('trace', 'vdelete',
- @id, @trace_opts, 'rb_var')
+ @id, @trace_opts, 'rb_var ' << @id)
@trace_opts.replace(newopts)
Tk.tk_call_without_enc('trace', 'variable',
- @id, @trace_opts, 'rb_var')
+ @id, @trace_opts, 'rb_var ' << @id)
+ end
+ else
+ newopts |= opts
+ unless (newopts - @trace_opts).empty?
+ Tk.tk_call_without_enc('trace', 'remove', 'variable',
+ @id, @trace_opts, 'rb_var ' << @id)
+ @trace_opts.replace(newopts)
+ Tk.tk_call_without_enc('trace', 'add', 'variable',
+ @id, @trace_opts, 'rb_var ' << @id)
end
-=end
end
end
+
self
end
- def trace_vinfo
+ def trace_info
return [] unless @trace_var
@trace_var.dup
end
+ alias trace_vinfo trace_info
- def _trace_vinfo_for_element(elem)
+ def trace_info_for_element(elem)
if @elem
fail(RuntimeError,
"invalid for a TkVariable which denotes an element of Tcl's array")
@@ -1388,141 +1441,180 @@ end
return [] unless @trace_elem[elem]
@trace_elem[elem].dup
end
+ alias trace_vinfo_for_element trace_info_for_element
- def trace_vdelete(opts,cmd)
+ def trace_remove(opts,cmd)
return self unless @trace_var.kind_of? Array
- opts = opts.to_s
- opts = ['r','w','u'].find_all{|c| opts.index(c)}.join('')
+
+ opts = _check_trace_opt(opts)
+
idx = -1
- newopts = ''
- @trace_var.each_with_index{|e,i|
- if idx < 0 && e[0] == opts && e[1] == cmd
- idx = i
- next
- end
- # e[0].each_byte{|c| newopts += c.chr unless newopts.index(c)}
- e[0].each_byte{|c| newopts.concat(c.chr) unless newopts.index(c)}
- }
+ if USE_OLD_TRACE_OPTION_STYLE
+ newopts = ''
+ @trace_var.each_with_index{|e, i|
+ if idx < 0 && e[1] == cmd
+ diff = false
+ ['a', 'r', 'w', 'u'].each{|c|
+ break if (diff = e[0].index(c) ^ opts.index(c))
+ }
+ unless diff
+ #find
+ idx = i
+ next
+ end
+ end
+ e[0].each_byte{|c| newopts.concat(c.chr) unless newopts.index(c.chr)}
+ }
+ else
+ newopts = []
+ @trace_var.each_with_index{|e, i|
+ if idx < 0 && e[1] == cmd &&
+ e[0].size == opts.size && (e[0] - opts).empty?
+ # find
+ idx = i
+ next
+ end
+ newopts |= e[0]
+ }
+ end
+
if idx >= 0
@trace_var.delete_at(idx)
else
return self
end
- @trace_elem.each{|elem|
+ (@trace_elem ||= {}).each{|elem|
@trace_elem[elem].each{|e|
- # e[0].each_byte{|c| newopts += c.chr unless newopts.index(c)}
- e[0].each_byte{|c| newopts.concat(c.chr) unless newopts.index(c)}
+ if USE_OLD_TRACE_OPTION_STYLE
+ e[0].each_byte{|c| newopts.concat(c.chr) unless newopts.index(c.chr)}
+ else
+ newopts |= e[0]
+ end
}
}
- newopts = newopts.to_s
- newopts = ['r','w','u'].find_all{|c| newopts.index(c)}.join('')
- if newopts != @trace_opts
- Tk.tk_call_without_enc('trace', 'vdelete', @id, @trace_opts,
- 'rb_var ' << @id)
-=begin
- if /^(8\.([4-9]|[1-9][0-9])|9\.|[1-9][0-9])/ =~ Tk::TCL_VERSION
- # TCL_VERSION >= 8.4
- Tk.tk_call_without_enc('trace', 'remove', 'variable',
- @id, @trace_opts, 'rb_var')
- else
- # TCL_VERSION <= 8.3
+ if USE_OLD_TRACE_OPTION_STYLE
+ diff = false
+ @trace_opts.each_byte{|c| break if (diff = ! newopts.index(c))}
+ if diff
Tk.tk_call_without_enc('trace', 'vdelete',
- @id, @trace_opts, 'rb_var')
+ @id, @trace_opts, 'rb_var ' << @id)
+ @trace_opts.replace(newopts)
+ unless @trace_opts.empty?
+ Tk.tk_call_without_enc('trace', 'variable',
+ @id, @trace_opts, 'rb_var ' << @id)
+ end
end
-=end
- @trace_opts.replace(newopts)
- if @trace_opts != ''
- Tk.tk_call_without_enc('trace', 'variable', @id, @trace_opts,
- 'rb_var ' << @id)
-=begin
- if /^(8\.([4-9]|[1-9][0-9])|9\.|[1-9][0-9])/ =~ Tk::TCL_VERSION
- # TCL_VERSION >= 8.4
+ else
+ unless (@trace_opts - newopts).empty?
+ Tk.tk_call_without_enc('trace', 'remove', 'variable',
+ @id, @trace_opts, 'rb_var ' << @id)
+ @trace_opts.replace(newopts)
+ unless @trace_opts.empty?
Tk.tk_call_without_enc('trace', 'add', 'variable',
- @id, @trace_opts, 'rb_var')
- else
- # TCL_VERSION <= 8.3
- Tk.tk_call_without_enc('trace', 'variable',
- @id, @trace_opts, 'rb_var')
+ @id, @trace_opts, 'rb_var ' << @id)
end
-=end
end
end
self
end
+ alias trace_delete trace_remove
+ alias trace_vdelete trace_remove
- def trace_vdelete_for_element(elem,opts,cmd)
+ def trace_remove_for_element(elem,opts,cmd)
if @elem
fail(RuntimeError,
"invalid for a TkVariable which denotes an element of Tcl's array")
end
return self unless @trace_elem.kind_of? Hash
return self unless @trace_elem[elem].kind_of? Array
- opts = opts.to_s
- opts = ['r','w','u'].find_all{|c| opts.index(c)}.join('')
+
+ opts = _check_trace_opt(opts)
+
idx = -1
- @trace_elem[elem].each_with_index{|e,i|
- if idx < 0 && e[0] == opts && e[1] == cmd
- idx = i
- next
- end
- }
+ if USE_OLD_TRACE_OPTION_STYLE
+ @trace_elem[elem].each_with_index{|e, i|
+ if idx < 0 && e[1] == cmd
+ diff = false
+ ['a', 'r', 'w', 'u'].each{|c|
+ break if (diff = e[0].index(c) ^ opts.index(c))
+ }
+ unless diff
+ #find
+ idx = i
+ next
+ end
+ end
+ }
+ else
+ @trace_elem[elem].each_with_index{|e, i|
+ if idx < 0 && e[1] == cmd &&
+ e[0].size == opts.size && (e[0] - opts).empty?
+ # find
+ idx = i
+ next
+ end
+ }
+ end
+
if idx >= 0
@trace_elem[elem].delete_at(idx)
else
return self
end
- newopts = ''
- @trace_var.each{|e|
- # e[0].each_byte{|c| newopts += c.chr unless newopts.index(c)}
- e[0].each_byte{|c| newopts.concat(c.chr) unless newopts.index(c)}
- }
- @trace_elem.each{|elem|
- @trace_elem[elem].each{|e|
- # e[0].each_byte{|c| newopts += c.chr unless newopts.index(c)}
- e[0].each_byte{|c| newopts.concat(c.chr) unless newopts.index(c)}
+ if USE_OLD_TRACE_OPTION_STYLE
+ newopts = ''
+ @trace_var.each{|e|
+ e[0].each_byte{|c| newopts.concat(c.chr) unless newopts.index(c.chr)}
}
- }
+ @trace_elem.each{|elem|
+ @trace_elem[elem].each{|e|
+ e[0].each_byte{|c| newopts.concat(c.chr) unless newopts.index(c.chr)}
+ }
+ }
+ else
+ newopts = []
+ @trace_var.each{|e|
+ newopts |= e[0]
+ }
+ @trace_elem.each{|elem|
+ @trace_elem[elem].each{|e|
+ e[0].each_byte{|c| newopts.concat(c.chr) unless newopts.index(c.chr)}
+ }
+ }
+ end
- newopts = newopts.to_s
- newopts = ['r','w','u'].find_all{|c| newopts.index(c)}.join('')
- if newopts != @trace_opts
- Tk.tk_call_without_enc('trace', 'vdelete', @id, @trace_opts,
- 'rb_var ' << @id)
-=begin
- if /^(8\.([4-9]|[1-9][0-9])|9\.|[1-9][0-9])/ =~ Tk::TCL_VERSION
- # TCL_VERSION >= 8.4
- Tk.tk_call_without_enc('trace', 'remove', 'variable',
- @id, @trace_opts, 'rb_var')
- else
- # TCL_VERSION <= 8.3
+ if USE_OLD_TRACE_OPTION_STYLE
+ diff = false
+ @trace_opts.each_byte{|c| break if (diff = ! newopts.index(c))}
+ if diff
Tk.tk_call_without_enc('trace', 'vdelete',
- @id, @trace_opts, 'rb_var')
+ @id, @trace_opts, 'rb_var ' << @id)
+ @trace_opts.replace(newopts)
+ unless @trace_opts.empty?
+ Tk.tk_call_without_enc('trace', 'variable',
+ @id, @trace_opts, 'rb_var ' << @id)
+ end
end
-=end
- @trace_opts.replace(newopts)
- if @trace_opts != ''
- Tk.tk_call_without_enc('trace', 'variable', @id, @trace_opts,
- 'rb_var ' << @id)
-=begin
- if /^(8\.([4-9]|[1-9][0-9])|9\.|[1-9][0-9])/ =~ Tk::TCL_VERSION
- # TCL_VERSION >= 8.4
+ else
+ unless (@trace_opts - newopts).empty?
+ Tk.tk_call_without_enc('trace', 'remove', 'variable',
+ @id, @trace_opts, 'rb_var ' << @id)
+ @trace_opts.replace(newopts)
+ unless @trace_opts.empty?
Tk.tk_call_without_enc('trace', 'add', 'variable',
- @id, @trace_opts, 'rb_var')
- else
- # TCL_VERSION <= 8.3
- Tk.tk_call_without_enc('trace', 'variable', @id,
- @trace_opts, 'rb_var')
+ @id, @trace_opts, 'rb_var ' << @id)
end
-=end
end
end
self
end
+ alias trace_delete_for_element trace_remove_for_element
+ alias trace_vdelete_for_element trace_remove_for_element
end
class TkVarAccess<TkVariable
@@ -1532,12 +1624,23 @@ class TkVarAccess<TkVariable
return name
end
- if v = TkVar_ID_TBL[name]
- v.value = args[0] unless args.empty?
- return v
- end
+ name = name.to_s
+ v = nil
+ TkVar_ID_TBL.mutex.synchronize{
+ if v = TkVar_ID_TBL[name]
+ v.value = args[0] unless args.empty?
+ return v
+ else
+ (v = self.allocate).instance_eval{
+ @id = name
+ TkVar_ID_TBL[@id] = self
+ @var = @id
+ }
+ end
+ }
- super(name, *args)
+ v.instance_eval{ initialize(name, *args) }
+ v
end
def self.new_hash(name, *args)
@@ -1549,27 +1652,38 @@ class TkVarAccess<TkVariable
return name
end
- if v = TkVar_ID_TBL[name]
- unless v.is_hash?
- fail ArgumentError, "already exist as a scalar variable"
+ name = name.to_s
+ v = nil
+ TkVar_ID_TBL.mutex.synchronize{
+ if v = TkVar_ID_TBL[name]
+ unless v.is_hash?
+ fail ArgumentError, "already exist as a scalar variable"
+ end
+ v.value = args[0] unless args.empty?
+ return v
+ else
+ (v = self.allocate).instance_eval{
+ @id = name
+ TkVar_ID_TBL[@id] = self
+ @var = @id
+ }
end
- v.value = args[0] unless args.empty?
- return v
- end
+ }
INTERP._invoke_without_enc('global', name)
if args.empty? && INTERP._invoke_without_enc('array', 'exist', name) == '0'
- self.new(name, {}) # force creating
+ v.instance_eval{ initialize(name, {}) } # force creating
else
- self.new(name, *args)
+ v.instance_eval{ initialize(name, *args) }
end
+ v
end
def initialize(varname, val=nil)
- @id = varname
- TkVar_ID_TBL[@id] = self
+ # @id = varname
+ # TkVar_ID_TBL[@id] = self
- @var = @id
+ # @var = @id
@elem = nil
@def_default = false
diff --git a/ext/tk/lib/tk/virtevent.rb b/ext/tk/lib/tk/virtevent.rb
index d47e80aecd..ae31ac1f8f 100644
--- a/ext/tk/lib/tk/virtevent.rb
+++ b/ext/tk/lib/tk/virtevent.rb
@@ -9,10 +9,17 @@ class TkVirtualEvent<TkObject
TkCommandNames = ['event'.freeze].freeze
- TkVirtualEventID = ["VirtEvent".freeze, "00000".taint].freeze
+ (TkVirtualEventID = ["VirtEvent".freeze, "00000".taint]).instance_eval{
+ @mutex = Mutex.new
+ def mutex; @mutex; end
+ freeze
+ }
+
TkVirtualEventTBL = TkCore::INTERP.create_table
- TkCore::INTERP.init_ip_env{ TkVirtualEventTBL.clear }
+ TkCore::INTERP.init_ip_env{
+ TkVirtualEventTBL.mutex.synchronize{ TkVirtualEventTBL.clear }
+ }
class PreDefVirtEvent<self
def self.new(event, *sequences)
@@ -21,22 +28,30 @@ class TkVirtualEvent<TkObject
elsif event !~ /^<.*>$/
event = '<' + event + '>'
end
- if TkVirtualEvent::TkVirtualEventTBL.has_key?(event)
- TkVirtualEvent::TkVirtualEventTBL[event]
- else
- super(event, *sequences)
- end
+ TkVirtualEvent::TkVirtualEventTBL.mutex.synchronize{
+ if TkVirtualEvent::TkVirtualEventTBL.has_key?(event)
+ TkVirtualEvent::TkVirtualEventTBL[event]
+ else
+ # super(event, *sequences)
+ (obj = self.allocate).instance_eval{
+ initialize(event, *sequences)
+ TkVirtualEvent::TkVirtualEventTBL[@id] = self
+ }
+ end
+ }
end
def initialize(event, *sequences)
@path = @id = event
- TkVirtualEvent::TkVirtualEventTBL[@id] = self
- add(*sequences)
+ _add_sequences(sequences)
end
end
def TkVirtualEvent.getobj(event)
- obj = TkVirtualEventTBL[event]
+ obj = nil
+ TkVirtualEventTBL.mutex.synchronize{
+ obj = TkVirtualEventTBL[event]
+ }
if obj
obj
else
@@ -55,19 +70,31 @@ class TkVirtualEvent<TkObject
end
def initialize(*sequences)
- # @path = @id = '<' + TkVirtualEventID.join('') + '>'
- @path = @id = '<' + TkVirtualEventID.join(TkCore::INTERP._ip_id_) + '>'
- TkVirtualEventID[1].succ!
- add(*sequences)
+ TkVirtualEventID.mutex.synchronize{
+ # @path = @id = '<' + TkVirtualEventID.join('') + '>'
+ @path = @id = '<' + TkVirtualEventID.join(TkCore::INTERP._ip_id_) + '>'
+ TkVirtualEventID[1].succ!
+ }
+ _add_sequences(sequences)
end
- def add(*sequences)
- if sequences != []
+ def _add_sequences(seq_ary)
+ unless seq_ary.empty?
tk_call_without_enc('event', 'add', "<#{@id}>",
- *(sequences.collect{|seq|
+ *(seq_ary.collect{|seq|
"<#{tk_event_sequence(seq)}>"
}) )
- TkVirtualEventTBL[@id] = self
+ end
+ self
+ end
+ private :_add_sequences
+
+ def add(*sequences)
+ if sequences != []
+ _add_sequences(sequences)
+ TkVirtualEventTBL.mutex.synchronize{
+ TkVirtualEventTBL[@id] = self
+ }
end
self
end
@@ -75,20 +102,26 @@ class TkVirtualEvent<TkObject
def delete(*sequences)
if sequences == []
tk_call_without_enc('event', 'delete', "<#{@id}>")
- TkVirtualEventTBL.delete(@id)
+ TkVirtualEventTBL.mutex.synchronize{
+ TkVirtualEventTBL.delete(@id)
+ }
else
tk_call_without_enc('event', 'delete', "<#{@id}>",
*(sequences.collect{|seq|
"<#{tk_event_sequence(seq)}>"
}) )
- TkVirtualEventTBL.delete(@id) if info == []
+ if tk_call_without_enc('event','info',"<#{@id}>").empty?
+ TkVirtualEventTBL.mutex.synchronize{
+ TkVirtualEventTBL.delete(@id)
+ }
+ end
end
self
end
def info
tk_call_without_enc('event','info',"<#{@id}>").split(/\s+/).collect!{|seq|
- l = seq.scan(/<*[^<>]+>*/).collect!{|subseq|
+ lst = seq.scan(/<*[^<>]+>*/).collect!{|subseq|
case (subseq)
when /^<<[^<>]+>>$/
TkVirtualEvent.getobj(subseq[1..-2])
@@ -98,7 +131,7 @@ class TkVirtualEvent<TkObject
subseq.split('')
end
}.flatten
- (l.size == 1) ? l[0] : l
+ (lst.size == 1) ? lst[0] : lst
}
end
end
diff --git a/ext/tk/lib/tk/wm.rb b/ext/tk/lib/tk/wm.rb
index 1f432a3848..49dd4d73c2 100644
--- a/ext/tk/lib/tk/wm.rb
+++ b/ext/tk/lib/tk/wm.rb
@@ -5,273 +5,407 @@ require 'tk'
module Tk
module Wm
- include TkComm
+ #include TkComm
+ extend TkCore
TkCommandNames = ['wm'.freeze].freeze
TOPLEVEL_METHODCALL_OPTKEYS = {}
- def aspect(*args)
+ def Wm.aspect(win, *args)
if args.length == 0
- list(tk_call_without_enc('wm', 'aspect', path))
+ list(tk_call_without_enc('wm', 'aspect', win.epath))
else
args = args[0] if args.length == 1 && args[0].kind_of?(Array)
- tk_call('wm', 'aspect', path, *args)
- self
+ tk_call('wm', 'aspect', win.epath, *args)
+ win
end
end
+ def aspect(*args)
+ Wm.aspect(self, *args)
+ end
+ alias wm_aspect aspect
TOPLEVEL_METHODCALL_OPTKEYS['aspect'] = 'aspect'
- def attributes(slot=nil,value=None)
+ def Wm.attributes(win, slot=nil,value=TkComm::None)
if slot == nil
- lst = tk_split_list(tk_call('wm', 'attributes', path))
+ lst = tk_split_list(tk_call('wm', 'attributes', win.epath))
info = {}
while key = lst.shift
info[key[1..-1]] = lst.shift
end
info
elsif slot.kind_of? Hash
- tk_call('wm', 'attributes', path, *hash_kv(slot))
- self
- elsif value == None
- tk_call('wm', 'attributes', path, "-#{slot}")
+ tk_call('wm', 'attributes', win.epath, *hash_kv(slot))
+ win
+ elsif value == TkComm::None
+ tk_call('wm', 'attributes', win.epath, "-#{slot}")
else
- tk_call('wm', 'attributes', path, "-#{slot}", value)
- self
+ tk_call('wm', 'attributes', win.epath, "-#{slot}", value)
+ win
end
end
+ def attributes(slot=nil,value=TkComm::None)
+ Wm.attributes(self, slot, value)
+ end
+ alias wm_attributes attributes
TOPLEVEL_METHODCALL_OPTKEYS['attributes'] = 'attributes'
- def client(name=None)
- if name == None
- tk_call('wm', 'client', path)
+ def Wm.client(win, name=TkComm::None)
+ if name == TkComm::None
+ tk_call('wm', 'client', win.epath)
else
name = '' if name == nil
- tk_call('wm', 'client', path, name)
- self
+ tk_call('wm', 'client', win.epath, name)
+ win
end
end
+ def client(name=TkComm::None)
+ Wm.client(self, name)
+ end
+ alias wm_client client
TOPLEVEL_METHODCALL_OPTKEYS['client'] = 'client'
- def colormapwindows(*args)
+ def Wm.colormapwindows(win, *args)
if args.size == 0
- list(tk_call_without_enc('wm', 'colormapwindows', path))
+ list(tk_call_without_enc('wm', 'colormapwindows', win.epath))
else
args = args[0] if args.length == 1 && args[0].kind_of?(Array)
- tk_call_without_enc('wm', 'colormapwindows', path, *args)
- self
+ tk_call_without_enc('wm', 'colormapwindows', win.epath, *args)
+ win
end
end
+ def colormapwindows(*args)
+ Wm.colormapwindows(self, *args)
+ end
+ alias wm_colormapwindows colormapwindows
TOPLEVEL_METHODCALL_OPTKEYS['colormapwindows'] = 'colormapwindows'
- def wm_command(value=nil)
+ def Wm.command(win, value=nil)
if value
- tk_call('wm', 'command', path, value)
- self
+ tk_call('wm', 'command', epath, value)
+ win
else
- #procedure(tk_call('wm', 'command', path))
- tk_call('wm', 'command', path)
+ #procedure(tk_call('wm', 'command', epath))
+ tk_call('wm', 'command', epath)
end
end
+ def wm_command(value=nil)
+ Wm.command(self, value)
+ end
TOPLEVEL_METHODCALL_OPTKEYS['wm_command'] = 'wm_command'
- def deiconify(ex = true)
+ def Wm.deiconify(win, ex = true)
if ex
- tk_call_without_enc('wm', 'deiconify', path)
+ tk_call_without_enc('wm', 'deiconify', win.epath)
else
- self.iconify
+ Wm.iconify(win)
end
- self
+ win
end
+ def deiconify(ex = true)
+ Wm.deiconify(self, ex)
+ end
+ alias wm_deiconify deiconify
- def focusmodel(mode = nil)
+ def Wm.focusmodel(win, mode = nil)
if mode
- tk_call_without_enc('wm', 'focusmodel', path, mode)
- self
+ tk_call_without_enc('wm', 'focusmodel', win.epath, mode)
+ win
else
- tk_call_without_enc('wm', 'focusmodel', path)
+ tk_call_without_enc('wm', 'focusmodel', win.epath)
end
end
+ def focusmodel(mode = nil)
+ Wm.focusmodel(self, mode)
+ end
+ alias wm_focusmodel focusmodel
TOPLEVEL_METHODCALL_OPTKEYS['focusmodel'] = 'focusmodel'
+ def Wm.forget(win)
+ # Tcl/Tk 8.5+
+ # work with dockable frames
+ tk_call_without_enc('wm', 'forget', win.epath)
+ win
+ end
+ def wm_forget
+ Wm.forget(self)
+ end
+
+ def Wm.frame(win)
+ tk_call_without_enc('wm', 'frame', win.epath)
+ end
def frame
- tk_call_without_enc('wm', 'frame', path)
+ Wm.frame(self)
end
+ alias wm_frame frame
- def geometry(geom=nil)
+ def Wm.geometry(win, geom=nil)
if geom
- tk_call_without_enc('wm', 'geometry', path, geom)
- self
+ tk_call_without_enc('wm', 'geometry', win.epath, geom)
+ win
else
- tk_call_without_enc('wm', 'geometry', path)
+ tk_call_without_enc('wm', 'geometry', win.epath)
end
end
+ def geometry(geom=nil)
+ Wm.geometry(self, geom)
+ end
+ alias wm_geometry geometry
TOPLEVEL_METHODCALL_OPTKEYS['geometry'] = 'geometry'
- def wm_grid(*args)
+ def Wm.grid(win, *args)
if args.size == 0
- list(tk_call_without_enc('wm', 'grid', path))
+ list(tk_call_without_enc('wm', 'grid', win.epath))
else
args = args[0] if args.length == 1 && args[0].kind_of?(Array)
- tk_call_without_enc('wm', 'grid', path, *args)
- self
+ tk_call_without_enc('wm', 'grid', win.epath, *args)
+ win
end
end
+ def wm_grid(*args)
+ Wm.grid(self, *args)
+ end
TOPLEVEL_METHODCALL_OPTKEYS['wm_grid'] = 'wm_grid'
- def group(leader = nil)
+ def Wm.group(win, leader = nil)
if leader
- tk_call('wm', 'group', path, leader)
- self
+ tk_call('wm', 'group', win.epath, leader)
+ win
else
- window(tk_call('wm', 'group', path))
+ window(tk_call('wm', 'group', win.epath))
end
end
+ def group(leader = nil)
+ Wm.group(self, leader)
+ end
+ alias wm_group group
TOPLEVEL_METHODCALL_OPTKEYS['group'] = 'group'
- def iconbitmap(bmp=nil)
+ def Wm.iconbitmap(win, bmp=nil)
if bmp
- tk_call_without_enc('wm', 'iconbitmap', path, bmp)
- self
+ tk_call_without_enc('wm', 'iconbitmap', win.epath, bmp)
+ win
else
- image_obj(tk_call_without_enc('wm', 'iconbitmap', path))
+ image_obj(tk_call_without_enc('wm', 'iconbitmap', win.epath))
end
end
+ def iconbitmap(bmp=nil)
+ Wm.iconbitmap(self, bmp)
+ end
+ alias wm_iconbitmap iconbitmap
TOPLEVEL_METHODCALL_OPTKEYS['iconbitmap'] = 'iconbitmap'
- def iconphoto(*imgs)
+ def Wm.iconphoto(win, *imgs)
if imgs.empty?
- @wm_iconphoto = nil unless defined? @wm_iconphoto
- return @wm_iconphoto
+ win.instance_eval{
+ @wm_iconphoto = nil unless defined? @wm_iconphoto
+ return @wm_iconphoto
+ }
end
imgs = imgs[0] if imgs.length == 1 && imgs[0].kind_of?(Array)
- tk_call_without_enc('wm', 'iconphoto', path, *imgs)
- @wm_iconphoto = imgs
- self
+ tk_call_without_enc('wm', 'iconphoto', win.epath, *imgs)
+ win.instance_eval{ @wm_iconphoto = imgs }
+ win
+ end
+ def iconphoto(*imgs)
+ Wm.iconphoto(self, *imgs)
end
+ alias wm_iconphoto iconphoto
TOPLEVEL_METHODCALL_OPTKEYS['iconphoto'] = 'iconphoto'
- def iconphoto_default(*imgs)
+ def Wm.iconphoto_default(win, *imgs)
imgs = imgs[0] if imgs.length == 1 && imgs[0].kind_of?(Array)
- tk_call_without_enc('wm', 'iconphoto', path, '-default', *imgs)
- self
+ tk_call_without_enc('wm', 'iconphoto', win.epath, '-default', *imgs)
+ win
+ end
+ def iconphoto_default(*imgs)
+ Wm.iconphoto_default(self, *imgs)
end
+ alias wm_iconphoto_default iconphoto_default
- def iconify(ex = true)
+ def Wm.iconify(win, ex = true)
if ex
- tk_call_without_enc('wm', 'iconify', path)
+ tk_call_without_enc('wm', 'iconify', win.epath)
else
- self.deiconify
+ Wm.deiconify(win)
end
- self
+ win
+ end
+ def iconify(ex = true)
+ Wm.iconify(self, ex)
end
+ alias wm_iconify iconify
- def iconmask(bmp=nil)
+ def Wm.iconmask(win, bmp=nil)
if bmp
- tk_call_without_enc('wm', 'iconmask', path, bmp)
- self
+ tk_call_without_enc('wm', 'iconmask', win.epath, bmp)
+ win
else
- image_obj(tk_call_without_enc('wm', 'iconmask', path))
+ image_obj(tk_call_without_enc('wm', 'iconmask', win.epath))
end
end
+ def iconmask(bmp=nil)
+ Wm.iconmask(self, bmp)
+ end
+ alias wm_iconmask iconmask
TOPLEVEL_METHODCALL_OPTKEYS['iconmask'] = 'iconmask'
- def iconname(name=nil)
+ def Wm.iconname(win, name=nil)
if name
- tk_call('wm', 'iconname', path, name)
- self
+ tk_call('wm', 'iconname', win.epath, name)
+ win
else
- tk_call('wm', 'iconname', path)
+ tk_call('wm', 'iconname', win.epath)
end
end
+ def iconname(name=nil)
+ Wm.iconname(self, name)
+ end
+ alias wm_iconname iconname
TOPLEVEL_METHODCALL_OPTKEYS['iconname'] = 'iconname'
- def iconposition(*args)
+ def Wm.iconposition(win, *args)
if args.size == 0
- list(tk_call_without_enc('wm', 'iconposition', path))
+ list(tk_call_without_enc('wm', 'iconposition', win.epath))
else
args = args[0] if args.length == 1 && args[0].kind_of?(Array)
- tk_call_without_enc('wm', 'iconposition', path, *args)
- self
+ tk_call_without_enc('wm', 'iconposition', win.epath, *args)
+ win
end
end
+ def iconposition(*args)
+ Wm.iconposition(self, *args)
+ end
+ alias wm_iconposition iconposition
TOPLEVEL_METHODCALL_OPTKEYS['iconposition'] = 'iconposition'
- def iconwindow(win = nil)
- if win
- tk_call_without_enc('wm', 'iconwindow', path, win)
- self
+ def Wm.iconwindow(win, iconwin = nil)
+ if iconwin
+ tk_call_without_enc('wm', 'iconwindow', win.epath, iconwin)
+ win
else
- w = tk_call_without_enc('wm', 'iconwindow', path)
+ w = tk_call_without_enc('wm', 'iconwindow', win.epath)
(w == '')? nil: window(w)
end
end
+ def iconwindow(iconwin = nil)
+ Wm.iconwindow(self, iconwin)
+ end
+ alias wm_iconwindow iconwindow
TOPLEVEL_METHODCALL_OPTKEYS['iconwindow'] = 'iconwindow'
- def maxsize(*args)
+ def Wm.manage(win)
+ # Tcl/Tk 8.5+ feature
+ tk_call_without_enc('wm', 'manage', win.epath)
+ win
+ end
+ def wm_manage
+ Wm.manage(self)
+ end
+=begin
+ def Wm.manage(win, use_id = nil)
+ # Tcl/Tk 8.5+ feature
+ # --------------------------------------------------------------
+ # In the future release, I want to support to embed the 'win'
+ # into the container which has window-id 'use-id'.
+ # It may give users frexibility on controlling their GUI.
+ # However, it may be difficult for current Tcl/Tk (Tcl/Tk8.5.1),
+ # because it seems to require to modify Tcl/Tk's source code.
+ # --------------------------------------------------------------
+ if use_id
+ tk_call_without_enc('wm', 'manage', win.epath, '-use', use_id)
+ else
+ tk_call_without_enc('wm', 'manage', win.epath)
+ end
+ win
+ end
+=end
+
+ def Wm.maxsize(win, *args)
if args.size == 0
- list(tk_call_without_enc('wm', 'maxsize', path))
+ list(tk_call_without_enc('wm', 'maxsize', win.epath))
else
args = args[0] if args.length == 1 && args[0].kind_of?(Array)
- tk_call_without_enc('wm', 'maxsize', path, *args)
- self
+ tk_call_without_enc('wm', 'maxsize', win.epath, *args)
+ win
end
end
+ def maxsize(*args)
+ Wm.maxsize(self, *args)
+ end
+ alias wm_maxsize maxsize
TOPLEVEL_METHODCALL_OPTKEYS['maxsize'] = 'maxsize'
- def minsize(*args)
+ def Wm.minsize(win, *args)
if args.size == 0
- list(tk_call_without_enc('wm', 'minsize', path))
+ list(tk_call_without_enc('wm', 'minsize', win.epath))
else
args = args[0] if args.length == 1 && args[0].kind_of?(Array)
- tk_call_without_enc('wm', 'minsize', path, *args)
- self
+ tk_call_without_enc('wm', 'minsize', win.path, *args)
+ win
end
end
+ def minsize(*args)
+ Wm.minsize(self, *args)
+ end
+ alias wm_minsize minsize
TOPLEVEL_METHODCALL_OPTKEYS['minsize'] = 'minsize'
- def overrideredirect(mode=None)
- if mode == None
- bool(tk_call_without_enc('wm', 'overrideredirect', path))
+ def Wm.overrideredirect(win, mode=TkComm::None)
+ if mode == TkComm::None
+ bool(tk_call_without_enc('wm', 'overrideredirect', win.epath))
else
- tk_call_without_enc('wm', 'overrideredirect', path, mode)
- self
+ tk_call_without_enc('wm', 'overrideredirect', win.epath, mode)
+ win
end
end
+ def overrideredirect(mode=TkComm::None)
+ Wm.overrideredirect(self, mode=TkComm::None)
+ end
+ alias wm_overrideredirect overrideredirect
TOPLEVEL_METHODCALL_OPTKEYS['overrideredirect'] = 'overrideredirect'
- def positionfrom(who=None)
- if who == None
- r = tk_call_without_enc('wm', 'positionfrom', path)
+ def Wm.positionfrom(win, who=TkComm::None)
+ if who == TkComm::None
+ r = tk_call_without_enc('wm', 'positionfrom', win.epath)
(r == "")? nil: r
else
- tk_call_without_enc('wm', 'positionfrom', path, who)
- self
+ tk_call_without_enc('wm', 'positionfrom', win.epath, who)
+ win
end
end
+ def positionfrom(who=TkComm::None)
+ Wm.positionfrom(self, who)
+ end
+ alias wm_positionfrom positionfrom
TOPLEVEL_METHODCALL_OPTKEYS['positionfrom'] = 'positionfrom'
- def protocol(name=nil, cmd=nil, &b)
+ def Wm.protocol(win, name=nil, cmd=nil, &b)
if cmd
- tk_call_without_enc('wm', 'protocol', path, name, cmd)
- self
+ tk_call_without_enc('wm', 'protocol', win.epath, name, cmd)
+ win
elsif b
- tk_call_without_enc('wm', 'protocol', path, name, proc(&b))
- self
+ tk_call_without_enc('wm', 'protocol', win.epath, name, proc(&b))
+ win
elsif name
- result = tk_call_without_enc('wm', 'protocol', path, name)
+ result = tk_call_without_enc('wm', 'protocol', win.epath, name)
(result == "")? nil : tk_tcl2ruby(result)
else
- tk_split_simplelist(tk_call_without_enc('wm', 'protocol', path))
+ tk_split_simplelist(tk_call_without_enc('wm', 'protocol', win.epath))
end
end
+ def protocol(name=nil, cmd=nil, &b)
+ Wm.protocol(self, name, cmd, &b)
+ end
+ alias wm_protocol protocol
- def protocols(kv=nil)
+ def Wm.protocols(win, kv=nil)
unless kv
ret = {}
- self.protocol.each{|name|
- ret[name] = self.protocol(name)
+ Wm.protocol(win).each{|name|
+ ret[name] = Wm.protocol(win, name)
}
return ret
end
@@ -279,82 +413,140 @@ module Tk
unless kv.kind_of?(Hash)
fail ArgumentError, 'expect a hash of protocol=>command'
end
- kv.each{|k, v| self.protocol(k, v)}
- self
+ kv.each{|k, v| Wm.protocol(win, k, v)}
+ win
end
+ def protocols(kv=nil)
+ Wm.protocols(self, kv)
+ end
+ alias wm_protocols protocols
TOPLEVEL_METHODCALL_OPTKEYS['protocols'] = 'protocols'
- def resizable(*args)
+ def Wm.resizable(win, *args)
if args.length == 0
- list(tk_call_without_enc('wm', 'resizable', path)).collect{|e| bool(e)}
+ list(tk_call_without_enc('wm', 'resizable', win.epath)).map!{|e| bool(e)}
else
args = args[0] if args.length == 1 && args[0].kind_of?(Array)
- tk_call_without_enc('wm', 'resizable', path, *args)
- self
+ tk_call_without_enc('wm', 'resizable', win.epath, *args)
+ win
end
end
+ def resizable(*args)
+ Wm.resizable(self, *args)
+ end
+ alias wm_resizable resizable
TOPLEVEL_METHODCALL_OPTKEYS['resizable'] = 'resizable'
- def sizefrom(who=None)
- if who == None
- r = tk_call_without_enc('wm', 'sizefrom', path)
+ def Wm.sizefrom(win, who=TkComm::None)
+ if who == TkComm::None
+ r = tk_call_without_enc('wm', 'sizefrom', win.epath)
(r == "")? nil: r
else
- tk_call_without_enc('wm', 'sizefrom', path, who)
- self
+ tk_call_without_enc('wm', 'sizefrom', win.epath, who)
+ win
end
end
+ def sizefrom(who=TkComm::None)
+ Wm.sizefrom(self, who)
+ end
+ alias wm_sizefrom sizefrom
TOPLEVEL_METHODCALL_OPTKEYS['sizefrom'] = 'sizefrom'
+ def Wm.stackorder(win)
+ list(tk_call('wm', 'stackorder', win.epath))
+ end
def stackorder
- list(tk_call('wm', 'stackorder', path))
+ Wm.stackorder(self)
end
+ alias wm_stackorder stackorder
- def stackorder_isabove(win)
- bool(tk_call('wm', 'stackorder', path, 'isabove', win))
+ def Wm.stackorder_isabove(win, target)
+ bool(tk_call('wm', 'stackorder', win.epath, 'isabove', target))
+ end
+ def Wm.stackorder_is_above(win, target)
+ Wm.stackorder_isabove(win, target)
+ end
+ def stackorder_isabove(target)
+ Wm.stackorder_isabove(self, target)
end
+ alias stackorder_is_above stackorder_isabove
+ alias wm_stackorder_isabove stackorder_isabove
+ alias wm_stackorder_is_above stackorder_isabove
- def stackorder_isbelow(win)
- bool(tk_call('wm', 'stackorder', path, 'isbelow', win))
+ def Wm.stackorder_isbelow(win, target)
+ bool(tk_call('wm', 'stackorder', win.epath, 'isbelow', target))
end
+ def Wm.stackorder_is_below(win, target)
+ Wm.stackorder_isbelow(win, target)
+ end
+ def stackorder_isbelow(target)
+ Wm.stackorder_isbelow(self, target)
+ end
+ alias stackorder_is_below stackorder_isbelow
+ alias wm_stackorder_isbelow stackorder_isbelow
+ alias wm_stackorder_is_below stackorder_isbelow
- def state(st=nil)
+ def Wm.state(win, st=nil)
if st
- tk_call_without_enc('wm', 'state', path, st)
- self
+ tk_call_without_enc('wm', 'state', win.epath, st)
+ win
else
- tk_call_without_enc('wm', 'state', path)
+ tk_call_without_enc('wm', 'state', win.epath)
end
end
+ def state(st=nil)
+ Wm.state(self, st)
+ end
+ alias wm_state state
TOPLEVEL_METHODCALL_OPTKEYS['state'] = 'state'
- def title(str=nil)
+ def Wm.title(win, str=nil)
if str
- tk_call('wm', 'title', path, str)
- self
+ tk_call('wm', 'title', win.epath, str)
+ win
else
- tk_call('wm', 'title', path)
+ tk_call('wm', 'title', win.epath)
end
end
+ def title(str=nil)
+ Wm.title(self, str)
+ end
+ alias wm_title title
TOPLEVEL_METHODCALL_OPTKEYS['title'] = 'title'
- def transient(master=nil)
+ def Wm.transient(win, master=nil)
if master
- tk_call_without_enc('wm', 'transient', path, master)
- self
+ tk_call_without_enc('wm', 'transient', win.epath, master)
+ win
else
- window(tk_call_without_enc('wm', 'transient', path))
+ window(tk_call_without_enc('wm', 'transient', win.epath))
end
end
+ def transient(master=nil)
+ Wm.transient(self, master)
+ end
+ alias wm_transient transient
TOPLEVEL_METHODCALL_OPTKEYS['transient'] = 'transient'
- def withdraw(ex = true)
+ def Wm.withdraw(win, ex = true)
if ex
- tk_call_without_enc('wm', 'withdraw', path)
+ tk_call_without_enc('wm', 'withdraw', win.epath)
else
- self.deiconify
+ Wm.deiconify(win)
end
- self
+ win
end
+ def withdraw(ex = true)
+ Wm.withdraw(self, ex)
+ end
+ alias wm_withdraw withdraw
+ end
+
+ 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"
+ end
+ }
end
end
diff --git a/ext/tk/lib/tkextlib/SUPPORT_STATUS b/ext/tk/lib/tkextlib/SUPPORT_STATUS
index 15925cba72..cfbe274c86 100644
--- a/ext/tk/lib/tkextlib/SUPPORT_STATUS
+++ b/ext/tk/lib/tkextlib/SUPPORT_STATUS
@@ -83,7 +83,7 @@ BLT 2.4z http://sourceforge.net/projects/blt
TkTreeCtrl CVS/Hd(2005-12-02)
http://sourceforge.net/projects/tktreectrl ==> treectrl
-Tile 0.7.8
+Tile 0.8.0/8.5.1
http://sourceforge.net/projects/tktable ==> tile
diff --git a/ext/tk/lib/tkextlib/blt/bitmap.rb b/ext/tk/lib/tkextlib/blt/bitmap.rb
index 31cf8d4229..23c6d2d064 100644
--- a/ext/tk/lib/tkextlib/blt/bitmap.rb
+++ b/ext/tk/lib/tkextlib/blt/bitmap.rb
@@ -13,7 +13,16 @@ module Tk::BLT
TkCommandNames = ['::blt::bitmap'.freeze].freeze
BITMAP_ID_TBL = TkCore::INTERP.create_table
- BITMAP_ID = ['blt_bitmap_id'.freeze, '00000'.taint].freeze
+
+ (BITMAP_ID = ['blt_bitmap_id'.freeze, '00000'.taint]).instance_eval{
+ @mutex = Mutex.new
+ def mutex; @mutex; end
+ freeze
+ }
+
+ TkCore::INTERP.init_ip_env{
+ BITMAP_ID_TBL.mutex.synchronize{ BITMAP_ID_TBL.clear }
+ }
def self.data(name)
dat = tk_simple_list(tk_call('::blt::bitmap', 'data', name))
@@ -64,9 +73,13 @@ module Tk::BLT
if name
@id = name
else
- @id = BITMAP_ID.join(TkCore::INTERP._ip_id_)
- BITMAP_ID[1].succ!
- BITMAP_ID_TBL[@id] = self
+ BITMAP_ID.mutex.synchronize{
+ @id = BITMAP_ID.join(TkCore::INTERP._ip_id_)
+ BITMAP_ID[1].succ!
+ }
+ BITMAP_ID_TBL.mutex.synchronize{
+ BITMAP_ID_TBL[@id] = self
+ }
end
@path = @id
diff --git a/ext/tk/lib/tkextlib/blt/component.rb b/ext/tk/lib/tkextlib/blt/component.rb
index ad78a5430b..dd387634ee 100644
--- a/ext/tk/lib/tkextlib/blt/component.rb
+++ b/ext/tk/lib/tkextlib/blt/component.rb
@@ -327,13 +327,24 @@ module Tk::BLT
#################
class Axis < TkObject
- OBJ_ID = ['blt_chart_axis'.freeze, '00000'.taint].freeze
- OBJ_TBL={}
+ (OBJ_ID = ['blt_chart_axis'.freeze, '00000'.taint]).instance_eval{
+ @mutex = Mutex.new
+ def mutex; @mutex; end
+ freeze
+ }
+
+ AxisID_TBL = TkCore::INTERP.create_table
+
+ TkCore::INTERP.init_ip_env{
+ AxisID_TBL.mutex.synchronize{ AxisID_TBL.clear }
+ }
def self.id2obj(chart, id)
cpath = chart.path
- return id unless OBJ_TBL[cpath]
- OBJ_TBL[cpath][id]? OBJ_TBL[cpath][id]: id
+ AxisID_TBL.mutex.synchronize{
+ return id unless AxisID_TBL[cpath]
+ AxisID_TBL[cpath][id]? AxisID_TBL[cpath][id]: id
+ }
end
def self.new(chart, axis=nil, keys={})
@@ -341,12 +352,48 @@ module Tk::BLT
keys = axis
axis = nil
end
- OBJ_TBL[chart.path] = {} unless OBJ_TBL[chart.path]
- return OBJ_TBL[chart.path][axis] if axis && OBJ_TBL[chart.path][axis]
- super(chart, axis, keys)
+ if keys
+ keys = _symbolkey2str(keys)
+ not_create = keys.delete('without_creating')
+ else
+ not_create = false
+ end
+
+ obj = nil
+ AxisID_TBL.mutex.synchronize{
+ chart_path = chart.path
+ AxisID_TBL[chart_path] ||= {}
+ if axis && AxisID_TBL[chart_path][axis]
+ obj = AxisID_TBL[chart_path][axis]
+ else
+ (obj = self.allocate).instance_eval{
+ if axis
+ @axis = @id = axis.to_s
+ else
+ OBJ_ID.mutex.synchronize{
+ @axis = @id = OBJ_ID.join(TkCore::INTERP._ip_id_).freeze
+ OBJ_ID[1].succ!
+ }
+ end
+ @path = @id
+ @parent = @chart = chart
+ @cpath = @chart.path
+ Axis::AxisID_TBL[@cpath][@axis] = self
+ unless not_create
+ tk_call(@chart, 'axis', 'create', @axis, keys)
+ return obj
+ end
+ }
+ end
+ }
+
+ obj.configure(keys) if obj && ! keys.empty?
+ obj
end
def initialize(chart, axis=nil, keys={})
+ # dummy:: not called by 'new' method
+
if axis.kind_of?(Hash)
keys = axis
axis = nil
@@ -354,13 +401,15 @@ module Tk::BLT
if axis
@axis = @id = axis.to_s
else
- @axis = @id = OBJ_ID.join(TkCore::INTERP._ip_id_).freeze
- OBJ_ID[1].succ!
+ OBJ_ID.mutex.synchronize{
+ @axis = @id = OBJ_ID.join(TkCore::INTERP._ip_id_).freeze
+ OBJ_ID[1].succ!
+ }
end
@path = @id
@parent = @chart = chart
@cpath = @chart.path
- Axis::OBJ_TBL[@cpath][@axis] = self
+ # Axis::AxisID_TBL[@cpath][@axis] = self
keys = _symbolkey2str(keys)
unless keys.delete('without_creating')
# @chart.axis_create(@axis, keys)
@@ -438,17 +487,34 @@ module Tk::BLT
#################
class Crosshairs < TkObject
- OBJ_TBL={}
+ CrosshairsID_TBL = TkCore::INTERP.create_table
+
+ TkCore::INTERP.init_ip_env{
+ CrosshairsID_TBL.mutex.synchronize{ CrosshairsID_TBL.clear }
+ }
def self.new(chart, keys={})
- return OBJ_TBL[chart.path] if OBJ_TBL[chart.path]
- super(chart, keys)
+ obj = nil
+ CrosshairsID_TBL.mutex.synchronize{
+ unless (obj = CrosshairsID_TBL[chart.path])
+ (obj = self.allocate).instance_eval{
+ @parent = @chart = chart
+ @cpath = @chart.path
+ @path = @id = 'crosshairs'
+ Crosshairs::CrosshairsID_TBL[@cpath] = self
+ }
+ end
+ }
+ chart.crosshair_configure(keys) if obj && ! keys.empty?
+ obj
end
def initialize(chart, keys={})
+ # dummy:: not called by 'new' method
+
@parent = @chart = chart
@cpath = @chart.path
- Crosshairs::OBJ_TBL[@cpath] = self
+ # Crosshairs::CrosshairsID_TBL[@cpath] = self
@chart.crosshair_configure(keys) unless keys.empty?
@path = @id = 'crosshairs'
end
@@ -500,12 +566,18 @@ module Tk::BLT
ElementTypeName = 'element'
ElementTypeToClass = { ElementTypeName=>self }
+
ElementID_TBL = TkCore::INTERP.create_table
- TkCore::INTERP.init_ip_env{ ElementID_TBL.clear }
+ TkCore::INTERP.init_ip_env{
+ ElementID_TBL.mutex.synchronize{ ElementID_TBL.clear }
+ }
- OBJ_ID = ['blt_chart_element'.freeze, '00000'.taint].freeze
- OBJ_TBL={}
+ (OBJ_ID = ['blt_chart_element'.freeze, '00000'.taint]).instance_eval{
+ @mutex = Mutex.new
+ def mutex; @mutex; end
+ freeze
+ }
def Element.type2class(type)
ElementTypeToClass[type]
@@ -513,8 +585,10 @@ module Tk::BLT
def Element.id2obj(chart, id)
cpath = chart.path
- return id unless OBJ_TBL[cpath]
- OBJ_TBL[cpath][id]? OBJ_TBL[cpath][id]: id
+ ElementID_TBL.mutex.synchronize{
+ return id unless ElementID_TBL[cpath]
+ ElementID_TBL[cpath][id]? ElementID_TBL[cpath][id]: id
+ }
end
def self.new(chart, element=nil, keys={})
@@ -522,14 +596,49 @@ module Tk::BLT
keys = element
element = nil
end
- OBJ_TBL[chart.path] = {} unless OBJ_TBL[chart.path]
- if element && OBJ_TBL[chart.path][element]
- return OBJ_TBL[chart.path][element]
+ if keys
+ keys = _symbolkey2str(keys)
+ not_create = keys.delete('without_creating')
+ else
+ not_create = false
end
- super(chart, element, keys)
+
+ obj = nil
+ ElementID_TBL.mutex.synchronize{
+ chart_path = chart.path
+ ElementID_TBL[chart_path] ||= {}
+ if element && ElementID_TBL[chart_path][element]
+ obj = ElementID_TBL[chart_path][element]
+ else
+ (obj = self.allocate).instance_eval{
+ if element
+ @element = @id = element.to_s
+ else
+ OBJ_ID.mutex.synchronize{
+ @element = @id = OBJ_ID.join(TkCore::INTERP._ip_id_).freeze
+ OBJ_ID[1].succ!
+ }
+ end
+ @path = @id
+ @parent = @chart = chart
+ @cpath = @chart.path
+ @typename = self.class::ElementTypeName
+ Element::ElementID_TBL[@cpath][@element] = self
+ unless not_create
+ tk_call(@chart, @typename, 'create', @element, keys)
+ return obj
+ end
+ }
+ end
+ }
+
+ obj.configure(keys) if obj && ! keys.empty?
+ obj
end
def initialize(chart, element=nil, keys={})
+ # dummy:: not called by 'new' method
+
if element.kind_of?(Hash)
keys = element
element = nil
@@ -537,14 +646,16 @@ module Tk::BLT
if element
@element = @id = element.to_s
else
- @element = @id = OBJ_ID.join(TkCore::INTERP._ip_id_).freeze
- OBJ_ID[1].succ!
+ OBJ_ID.mutex.synchronize{
+ @element = @id = OBJ_ID.join(TkCore::INTERP._ip_id_).freeze
+ OBJ_ID[1].succ!
+ }
end
@path = @id
@parent = @chart = chart
@cpath = @chart.path
@typename = self.class::ElementTypeName
- Element::OBJ_TBL[@cpath][@element] = self
+ # Element::ElementID_TBL[@cpath][@element] = self
keys = _symbolkey2str(keys)
unless keys.delete('without_creating')
# @chart.element_create(@element, keys)
@@ -622,17 +733,33 @@ module Tk::BLT
#################
class GridLine < TkObject
- OBJ_TBL={}
+ GridLineID_TBL = TkCore::INTERP.create_table
+ TkCore::INTERP.init_ip_env{
+ GridLineID_TBL.mutex.synchronize{ GridLineID_TBL.clear }
+ }
def self.new(chart, keys={})
- return OBJ_TBL[chart.path] if OBJ_TBL[chart.path]
- super(chart, keys)
+ obj = nil
+ GridLineID_TBL.mutex.synchronize{
+ unless (obj = GridLineID_TBL[chart.path])
+ (obj = self.allocate).instance_eval{
+ @parent = @chart = chart
+ @cpath = @chart.path
+ @path = @id = 'grid'
+ GridLine::GridLineID_TBL[@cpath] = self
+ }
+ end
+ }
+ chart.gridline_configure(keys) if obj && ! keys.empty?
+ obj
end
def initialize(chart, keys={})
+ # dummy:: not called by 'new' method
+
@parent = @chart = chart
@cpath = @chart.path
- GridLine::OBJ_TBL[@cpath] = self
+ # GridLine::GridLineID_TBL[@cpath] = self
@chart.gridline_configure(keys) unless keys.empty?
@path = @id = 'grid'
end
@@ -676,18 +803,35 @@ module Tk::BLT
#################
class Legend < TkObject
- OBJ_TBL={}
+ LegendID_TBL = TkCore::INTERP.create_table
+
+ TkCore::INTERP.init_ip_env{
+ LegendID_TBL.mutex.synchronize{ LegendID_TBL.clear }
+ }
def self.new(chart, keys={})
- return OBJ_TBL[chart.path] if OBJ_TBL[chart.path]
- super(chart, keys)
+ obj = nil
+ LegenedID_TBL.mutex.synchronize{
+ unless (obj = LegenedID_TBL[chart.path])
+ (obj = self.allocate).instance_eval{
+ @parent = @chart = chart
+ @cpath = @chart.path
+ @path = @id = 'crosshairs'
+ Legend::LegenedID_TBL[@cpath] = self
+ }
+ end
+ }
+ chart.legend_configure(keys) if obj && ! keys.empty?
+ obj
end
def initialize(chart, keys={})
+ # dummy:: not called by 'new' method
+
@parent = @chart = chart
@cpath = @chart.path
- Crosshairs::OBJ_TBL[@cpath] = self
- @chart.crosshair_configure(keys) unless keys.empty?
+ # Legend::LegendID_TBL[@cpath] = self
+ @chart.legend_configure(keys) unless keys.empty?
@path = @id = 'legend'
end
@@ -729,13 +873,24 @@ module Tk::BLT
#################
class Pen < TkObject
- OBJ_ID = ['blt_chart_pen'.freeze, '00000'.taint].freeze
- OBJ_TBL={}
+ (OBJ_ID = ['blt_chart_pen'.freeze, '00000'.taint]).instance_eval{
+ @mutex = Mutex.new
+ def mutex; @mutex; end
+ freeze
+ }
+
+ PenID_TBL = TkCore::INTERP.create_table
+
+ TkCore::INTERP.init_ip_env{
+ PenID_TBL.mutex.synchronize{ PenID_TBL.clear }
+ }
def self.id2obj(chart, id)
cpath = chart.path
- return id unless OBJ_TBL[cpath]
- OBJ_TBL[cpath][id]? OBJ_TBL[cpath][id]: id
+ PenID_TBL.mutex.synchronize{
+ return id unless PenID_TBL[cpath]
+ PenID_TBL[cpath][id]? PenID_TBL[cpath][id]: id
+ }
end
def self.new(chart, pen=nil, keys={})
@@ -743,9 +898,43 @@ module Tk::BLT
keys = pen
pen = nil
end
- OBJ_TBL[chart.path] = {} unless OBJ_TBL[chart.path]
- return OBJ_TBL[chart.path][pen] if pen && OBJ_TBL[chart.path][pen]
- super(chart, pen, keys)
+ if keys
+ keys = _symbolkey2str(keys)
+ not_create = keys.delete('without_creating')
+ else
+ not_create = false
+ end
+
+ obj = nil
+ PenID_TBL.mutex.synchronize{
+ chart_path = chart.path
+ PenID_TBL[chart_path] ||= {}
+ if pen && PenID_TBL[chart_path][pen]
+ obj = PenID_TBL[chart_path][pen]
+ else
+ (obj = self.allocate).instance_eval{
+ if pen
+ @pen = @id = pen.to_s
+ else
+ OBJ_ID.mutex.synchronize{
+ @pen = @id = OBJ_ID.join(TkCore::INTERP._ip_id_).freeze
+ OBJ_ID[1].succ!
+ }
+ end
+ @path = @id
+ @parent = @chart = chart
+ @cpath = @chart.path
+ Pen::PenID_TBL[@cpath][@pen] = self
+ unless not_create
+ tk_call(@chart, 'pen', 'create', @pen, keys)
+ return obj
+ end
+ }
+ end
+ }
+
+ obj.configure(keys) if obj && ! keys.empty?
+ obj
end
def initialize(chart, pen=nil, keys={})
@@ -756,13 +945,15 @@ module Tk::BLT
if pen
@pen = @id = pen.to_s
else
- @pen = @id = OBJ_ID.join(TkCore::INTERP._ip_id_).freeze
- OBJ_ID[1].succ!
+ OBJ_ID.mutex.synchronize{
+ @pen = @id = OBJ_ID.join(TkCore::INTERP._ip_id_).freeze
+ OBJ_ID[1].succ!
+ }
end
@path = @id
@parent = @chart = chart
@cpath = @chart.path
- Pen::OBJ_TBL[@cpath][@pen] = self
+ Pen::PenID_TBL[@cpath][@pen] = self
keys = _symbolkey2str(keys)
unless keys.delete('without_creating')
# @chart.pen_create(@pen, keys)
@@ -805,17 +996,34 @@ module Tk::BLT
#################
class Postscript < TkObject
- OBJ_TBL={}
+ PostscriptID_TBL = TkCore::INTERP.create_table
+
+ TkCore::INTERP.init_ip_env{
+ PostscriptID_TBL.mutex.synchronize{ PostscriptID_TBL.clear }
+ }
def self.new(chart, keys={})
- return OBJ_TBL[chart.path] if OBJ_TBL[chart.path]
- super(chart, keys)
+ obj = nil
+ PostscriptID_TBL.mutex.synchronize{
+ unless (obj = PostscriptID_TBL[chart.path])
+ (obj = self.allocate).instance_eval{
+ @parent = @chart = chart
+ @cpath = @chart.path
+ @path = @id = 'postscript'
+ Postscript::PostscriptID_TBL[@cpath] = self
+ }
+ end
+ }
+ chart.postscript_configure(keys) if obj && ! keys.empty?
+ obj
end
def initialize(chart, keys={})
+ # dummy:: not called by 'new' method
+
@parent = @chart = chart
@cpath = @chart.path
- Postscript::OBJ_TBL[@cpath] = self
+ # Postscript::PostscriptID_TBL[@cpath] = self
@chart.postscript_configure(keys) unless keys.empty?
@path = @id = 'postscript'
end
@@ -870,7 +1078,9 @@ module Tk::BLT
MarkerTypeToClass = {}
MarkerID_TBL = TkCore::INTERP.create_table
- TkCore::INTERP.init_ip_env{ MarkerID_TBL.clear }
+ TkCore::INTERP.init_ip_env{
+ MarkerID_TBL.mutex.synchronize{ MarkerID_TBL.clear }
+ }
def Marker.type2class(type)
MarkerTypeToClass[type]
@@ -878,8 +1088,13 @@ module Tk::BLT
def Marker.id2obj(chart, id)
cpath = chart.path
- return id unless MarkerID_TBL[cpath]
- MarkerID_TBL[cpath][id]? MarkerID_TBL[cpath][id]: id
+ MarkerID_TBL.mutex.synchronize{
+ if MarkerID_TBL[cpath]
+ MarkerID_TBL[cpath][id]? MarkerID_TBL[cpath][id]: id
+ else
+ id
+ end
+ }
end
def self._parse_create_args(keys)
@@ -943,10 +1158,10 @@ module Tk::BLT
@parent = @chart = chart
@cpath = chart.path
@id = id
- unless Tk::BLT::PlotComponent::Marker::MarkerID_TBL[@cpath]
- Tk::BLT::PlotComponent::Marker::MarkerID_TBL[@cpath] = {}
- end
- Tk::BLT::PlotComponent::Marker::MarkerID_TBL[@cpath][@id] = self
+ Tk::BLT::PlotComponent::Marker::MarkerID_TBL.mutex.synchronize{
+ Tk::BLT::PlotComponent::Marker::MarkerID_TBL[@cpath] ||= {}
+ Tk::BLT::PlotComponent::Marker::MarkerID_TBL[@cpath][@id] = self
+ }
}
obj
end
@@ -956,10 +1171,10 @@ module Tk::BLT
@cpath = parent.path
@path = @id = create_self(*args) # an integer number as 'item id'
- unless Tk::BLT::PlotComponent::Marker::MarkerID_TBL[@cpath]
- Tk::BLT::PlotComponent::Marker::MarkerID_TBL[@cpath] = {}
- end
- Tk::BLT::PlotComponent::Marker::MarkerID_TBL[@cpath][@id] = self
+ Tk::BLT::PlotComponent::Marker::MarkerID_TBL.mutex.synchronize{
+ Tk::BLT::PlotComponent::Marker::MarkerID_TBL[@cpath] ||= {}
+ Tk::BLT::PlotComponent::Marker::MarkerID_TBL[@cpath][@id] = self
+ }
end
def create_self(*args)
self.class.create(@chart, *args) # return an integer as 'item id'
@@ -1037,14 +1252,14 @@ module Tk::BLT
#################
def __destroy_hook__
- Axis::OBJ_TBL.delete(@path)
- Crosshairs::OBJ_TBL.delete(@path)
- Element::OBJ_TBL.delete(@path)
- GridLine::OBJ_TBL.delete(@path)
- Legend::OBJ_TBL.delete(@path)
- Pen::OBJ_TBL.delete(@path)
- Postscript::OBJ_TBL.delete(@path)
- Marker::OBJ_TBL.delete(@path)
+ Axis::AxisID_TBL.delete(@path)
+ Crosshairs::CrosshairsID_TBL.delete(@path)
+ Element::ElementID_TBL.delete(@path)
+ GridLine::GridLineID_TBL.delete(@path)
+ Legend::LegendID_TBL.delete(@path)
+ Pen::PenID_TBL.delete(@path)
+ Postscript::PostscriptID_TBL.delete(@path)
+ Marker::MarkerID_TBL.delete(@path)
super()
end
diff --git a/ext/tk/lib/tkextlib/blt/dragdrop.rb b/ext/tk/lib/tkextlib/blt/dragdrop.rb
index 68fb9e591a..98b1a4832f 100644
--- a/ext/tk/lib/tkextlib/blt/dragdrop.rb
+++ b/ext/tk/lib/tkextlib/blt/dragdrop.rb
@@ -81,6 +81,22 @@ module Tk::BLT
nil
]
+ # 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
+ }
+
_setup_subst_table(KEY_TBL, PROC_TBL)
def self.ret_val(val)
@@ -107,6 +123,22 @@ module Tk::BLT
nil
]
+ # 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
+ }
+
_setup_subst_table(KEY_TBL, PROC_TBL)
def self.ret_val(val)
@@ -145,6 +177,22 @@ module Tk::BLT
nil
]
+ # 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
+ }
+
_setup_subst_table(KEY_TBL, PROC_TBL)
end
diff --git a/ext/tk/lib/tkextlib/blt/tabset.rb b/ext/tk/lib/tkextlib/blt/tabset.rb
index c26b6ee001..1a0f312c4c 100644
--- a/ext/tk/lib/tkextlib/blt/tabset.rb
+++ b/ext/tk/lib/tkextlib/blt/tabset.rb
@@ -12,14 +12,26 @@ module Tk::BLT
include TkTreatItemFont
TabID_TBL = TkCore::INTERP.create_table
- TabsetTab_ID = ['blt_tabset_tab'.freeze, '00000'.taint].freeze
- TkCore::INTERP.init_ip_env{ TabID_TBL.clear }
+ (TabsetTab_ID = ['blt_tabset_tab'.freeze, '00000'.taint]).instance_eval{
+ @mutex = Mutex.new
+ def mutex; @mutex; end
+ freeze
+ }
+
+ TkCore::INTERP.init_ip_env{
+ TabID_TBL.mutex.synchronize{ TabID_TBL.clear }
+ }
def self.id2obj(tabset, id)
tpath = tabset.path
- return id unless TabID_TBL[tpath]
- TabID_TBL[tpath][id]? TabID_TBL[tpath]: id
+ TabID_TBL.mutex.synchronize{
+ if TabID_TBL[tpath]
+ TabID_TBL[tpath][id]? TabID_TBL[tpath]: id
+ else
+ id
+ end
+ }
end
def self.new(parent, pos=nil, name=nil, keys={})
@@ -32,12 +44,20 @@ module Tk::BLT
keys = name
name = nil
end
-
- if name && TabID_TBL[parent.path] && TabID_TBL[parent.path][name]
- TabID_TBL[parent.path][name]
- else
- super(parent, pos, name, keys)
- end
+ obj = nil
+ TabID_TBL.mutex.synchronize{
+ if name && TabID_TBL[parent.path] && TabID_TBL[parent.path][name]
+ obj = TabID_TBL[parent.path][name]
+ obj.configure if keys && ! keys.empty?
+ else
+ (obj = self.allocate).instance_eval{
+ initialize(parent, pos, name, keys)
+ TabID_TBL[@tpath] = {} unless TabID_TBL[@tpath]
+ TabID_TBL[@tpath][@id] = self
+ }
+ end
+ }
+ obj
end
def initialize(parent, pos, name, keys)
@@ -45,9 +65,6 @@ module Tk::BLT
@tpath = parent.path
if name
@path = @id = name
- TabID_TBL[@tpath] = {} unless TabID_TBL[@tpath]
- TabID_TBL[@tpath][@id] = self
-
unless (list(tk_call(@tpath, 'tab', 'names', @id)).empty?)
if pos
idx = tk_call(@tpath, 'index', '-name', @id)
@@ -58,18 +75,18 @@ module Tk::BLT
end
end
tk_call(@tpath, 'tab', 'configure', @id, keys)
- return
+ else
+ pos = 'end' unless pos
+ tk_call(@tpath, 'insert', pos, @id, keys)
end
-
else
- @path = @id = TabsetTab_ID.join(TkCore::INTERP._ip_id_)
- TabID_TBL[@tpath] = {} unless TabID_TBL[@tpath]
- TabID_TBL[@tpath][@id] = self
- TabsetTab_ID[1].succ!
+ TabsetTab_ID.mutex.synchronize{
+ @path = @id = TabsetTab_ID.join(TkCore::INTERP._ip_id_)
+ TabsetTab_ID[1].succ!
+ }
+ pos = 'end' unless pos
+ tk_call(@tpath, 'insert', pos, @id, keys)
end
-
- pos = 'end' unless pos
- tk_call(@tpath, 'insert', pos, @id, keys)
end
#def bind(context, cmd=Proc.new, *args)
@@ -123,7 +140,9 @@ module Tk::BLT
def delete()
@t.delete(@id)
- TabID_TBL[@tpath].delete(@id)
+ TabID_TBL.mutex.synchronize{
+ TabID_TBL[@tpath].delete(@id)
+ }
self
end
@@ -184,7 +203,9 @@ module Tk::BLT
WidgetClassNames[WidgetClassName] = self
def __destroy_hook__
- Tk::BLT::Tabset::Tab::TabID_TBL.delete(@path)
+ Tk::BLT::Tabset::Tab::TabID_TBL.mutex.synchronize{
+ Tk::BLT::Tabset::Tab::TabID_TBL.delete(@path)
+ }
end
########################################
@@ -291,11 +312,15 @@ module Tk::BLT
def delete(first, last=None)
tk_send('delete', tagindex(first), tagindex(last))
if first.kind_of?(Tk::BLT::Tabset::Tab)
- TabID_TBL[@path].delete(first.id)
+ TabID_TBL.mutex.synchronize{
+ TabID_TBL[@path].delete(first.id)
+ }
end
# middle tabs of the range are unknown
if last.kind_of?(Tk::BLT::Tabset::Tab)
- TabID_TBL[@path].delete(last.id)
+ TabID_TBL.mutex.synchronize{
+ TabID_TBL[@path].delete(last.id)
+ }
end
self
end
diff --git a/ext/tk/lib/tkextlib/blt/tree.rb b/ext/tk/lib/tkextlib/blt/tree.rb
index 07dc7ef7e8..77b85f1717 100644
--- a/ext/tk/lib/tkextlib/blt/tree.rb
+++ b/ext/tk/lib/tkextlib/blt/tree.rb
@@ -12,53 +12,77 @@ module Tk::BLT
###################################
- class Node < TkObject
+ class Node < TkObject
TreeNodeID_TBL = TkCore::INTERP.create_table
- TkCore::INTERP.init_ip_env{ TreeNodeID_TBL.clear }
+
+ TkCore::INTERP.init_ip_env{
+ TreeNodeID_TBL.mutex.synchronize{ TreeNodeID_TBL.clear }
+ }
def self.id2obj(tree, id)
tpath = tree.path
- return id unless TreeNodeID_TBL[tpath]
- if TreeNodeID_TBL[tpath][id]
- TreeNodeID_TBL[tpath][id]
- else
- begin
- self.new(tree, nil, 'node'=>Integer(id))
- rescue
+ TreeNodeID_TBL.mutex.synchronize{
+ if TreeNodeID_TBL[tpath]
+ if TreeNodeID_TBL[tpath][id]
+ TreeNodeID_TBL[tpath][id]
+ else
+ begin
+ # self.new(tree, nil, 'node'=>Integer(id))
+ id = Integer(id)
+ if bool(tk_call(@tpath, 'exists', id))
+ (obj = self.allocate).instance_eval{
+ @parent = @tree = tree
+ @tpath = tpath
+ @path = @id = id
+ TreeNodeID_TBL[@tpath] = {} unless TreeNodeID_TBL[@tpath]
+ TreeNodeID_TBL[@tpath][@id] = self
+ }
+ obj
+ else
+ id
+ end
+ rescue
+ id
+ end
+ end
+ else
id
end
- end
+ }
end
def self.new(tree, parent, keys={})
keys = _symbolkey2str(keys)
tpath = tree.path
- if (id = keys['node']) && (obj = TreeNodeID_TBL[tpath][id])
- keys.delete('node')
- tk_call(tree.path, 'move', id, parent, keys) if parent
- return obj
- end
+ TreeNodeID_TBL.mutex.synchronize{
+ TreeNodeID_TBL[tpath] ||= {}
+ if (id = keys['node']) && (obj = TreeNodeID_TBL[tpath][id])
+ keys.delete('node')
+ tk_call(tree.path, 'move', id, parent, keys) if parent
+ return obj
+ end
- super(tree, parent, keys)
+ (obj = self.allocate).instance_eval{
+ initialize(tree, parent, keys)
+ TreeNodeID_TBL[tpath][@id] = self
+ }
+ obj
+ }
end
def initialize(tree, parent, keys={})
@parent = @tree = tree
@tpath = @parent.path
- parent = tk_call(@tpath, 'root') unless parent
-
if (id = keys['node']) && bool(tk_call(@tpath, 'exists', id))
@path = @id = id
keys.delete('node')
tk_call(@tpath, 'move', @id, parent, keys) if parent
else
+ parent = tk_call(@tpath, 'root') unless parent
@path = @id = tk_call(@tpath, 'insert', parent, keys)
end
-
- TreeNodeID_TBL[@tpath] = {} unless TreeNodeID_TBL[@tpath]
- TreeNodeID_TBL[@tpath][@id] = self
end
def id
@@ -243,17 +267,42 @@ module Tk::BLT
class Tag < TkObject
TreeTagID_TBL = TkCore::INTERP.create_table
- TkCore::INTERP.init_ip_env{ TreeTagID_TBL.clear }
- TreeTag_ID = ['blt_tree_tag'.freeze, '00000'.taint].freeze
+
+ TkCore::INTERP.init_ip_env{
+ TreeTagID_TBL.mutex.synchronize{ TreeTagID_TBL.clear }
+ }
+
+ (TreeTag_ID = ['blt_tree_tag'.freeze, '00000'.taint]).instance_eval{
+ @mutex = Mutex.new
+ def mutex; @mutex; end
+ freeze
+ }
def self.id2obj(tree, id)
tpath = tree.path
- return id unless TreeTagID_TBL[tpath]
- if TreeTagID_TBL[tpath][id]
- TreeTagID_TBL[tpath][id]
- else
- self.new(tree, id)
- end
+ TreeTagID_TBL.mutex.synchronize{
+ if TreeTagID_TBL[tpath]
+ if TreeTagID_TBL[tpath][id]
+ TreeTagID_TBL[tpath][id]
+ else
+ begin
+ # self.new(tree, id)
+ (obj = self.allocate).instance_eval{
+ @parent = @tree = tree
+ @tpath = @parent.path
+ @path = @id = id.dup.freeze if id
+ TreeTagID_TBL[@tpath] = {} unless TreeTagID_TBL[@tpath]
+ TreeTagID_TBL[@tpath][@id] = self
+ }
+ obj
+ rescue
+ id
+ end
+ end
+ else
+ id
+ end
+ }
end
def initialize(tree, tag_str = nil)
@@ -263,12 +312,15 @@ module Tk::BLT
if tag_str
@path = @id = tag_str.dup.freeze
else
- @path = @id = TreeTag_ID.join(TkCore::INTERP._ip_id_)
- TreeTagID_TBL[@id] = self
- TreeTag_ID[1].succ!
+ TreeTag_ID.mutex.synchronize{
+ @path = @id = TreeTag_ID.join(TkCore::INTERP._ip_id_)
+ TreeTag_ID[1].succ!
+ }
end
- TreeTagID_TBL[@tpath] = {} unless TreeTagID_TBL[@tpath]
- TreeTagID_TBL[@tpath][@id] = self
+ TreeTagID_TBL.mutex.synchronize{
+ TreeTagID_TBL[@tpath] = {} unless TreeTagID_TBL[@tpath]
+ TreeTagID_TBL[@tpath][@id] = self
+ }
end
def id
@@ -287,7 +339,9 @@ module Tk::BLT
def forget()
tk_call(@tpath, 'tag', 'forget', @id)
- TreeTagID_TBL[@tpath].delete(@id)
+ TreeTagID_TBL.mutex.synchronize{
+ TreeTagID_TBL[@tpath].delete(@id)
+ }
self
end
@@ -312,44 +366,63 @@ module Tk::BLT
class Notify < TkObject
NotifyID_TBL = TkCore::INTERP.create_table
- TkCore::INTERP.init_ip_env{ NotifyID_TBL.clear }
+
+ TkCore::INTERP.init_ip_env{
+ NotifyID_TBL.mutex.synchronize{ NotifyID_TBL.clear }
+ }
def self.id2obj(tree, id)
tpath = tree.path
- return id unless NotifyID_TBL[tpath]
- if NotifyID_TBL[tpath][id]
- NotifyID_TBL[tpath][id]
- else
- begin
- self.new([tree, id])
- rescue
- id
+ NotifyID_TBL.mutex.synchronize{
+ if NotifyID_TBL[tpath]
+ if NotifyID_TBL[tpath][id]
+ NotifyID_TBL[tpath][id]
+ else
+ (obj = self.allocate).instance_eval{
+ @parent = @tree = tree
+ @tpath = @parent.path
+ @path = @id = id
+ NotifyID_TBL[@tpath] ||= {}
+ NotifyID_TBL[@tpath][@id] = self
+ }
+ obj
+ end
+ else
+ return id
end
- end
+ }
end
def self.new(tree, *args, &b)
- if tree.kind_of?(Array)
- # not create
- if obj = NotifyID_TBL[tree[0].path][tree[1]]
+ NotifyID_TBL.mutex.synchronize{
+ if tree.kind_of?(Array)
+ # not create
+ tpath = tree[0].path
+ NotifyID_TBL[tpath] ||= {}
+ unless (obj = NotifyID_TBL[tpath][tree[1]])
+ (NotifyID_TBL[tpath][tree[1]] =
+ obj = self.allocate).instance_eval{
+ @parent = @tree = tree[0]
+ @tpath = @parent.path
+ @path = @id = tree[1]
+ }
+ end
return obj
- else
- return super(false, tree[0], tree[1])
end
- end
- super(true, tree, *args, &b)
+ (obj = self.allocate).instance_eval{
+ initialize(tree, *args, &b)
+ NotifyID_TBL[@tpath] ||= {}
+ NotifyID_TBL[@tpath][@id] = self
+ }
+ return obj
+ }
end
- def initialize(create, tree, *args, &b)
+ def initialize(tree, *args, &b)
@parent = @tree = tree
@tpath = @parent.path
- unless create
- @path = @id = args[0]
- return
- end
-
# if args[0].kind_of?(Proc) || args[0].kind_of?(Method)
if TkComm._callback_entry?(args[0])
cmd = args.shift
@@ -378,7 +451,9 @@ module Tk::BLT
def delete()
tk_call(@tpath, 'notify', 'delete', @id)
- NotifyID_TBL[tpath].delete(@id)
+ NotifyID_TBL.mutex.synchronize{
+ NotifyID_TBL[@tpath].delete(@id)
+ }
self
end
@@ -395,44 +470,69 @@ module Tk::BLT
class Trace < TkObject
TraceID_TBL = TkCore::INTERP.create_table
- TkCore::INTERP.init_ip_env{ TraceID_TBL.clear }
+
+ TkCore::INTERP.init_ip_env{
+ TraceID_TBL.mutex.synchronize{ TraceID_TBL.clear }
+ }
def self.id2obj(tree, id)
tpath = tree.path
- return id unless TraceID_TBL[tpath]
- if TraceID_TBL[tpath][id]
- TraceID_TBL[tpath][id]
- else
- begin
- self.new([tree, id])
- rescue
+ TraceID_TBL.mutex.synchronize{
+ if TraceID_TBL[tpath]
+ if TraceID_TBL[tpath][id]
+ TraceID_TBL[tpath][id]
+ else
+ begin
+ # self.new([tree, id])
+ (obj = self.allocate).instance_eval{
+ @parent = @tree = tree
+ @tpath = @parent.path
+ @path = @id = node # == traceID
+ TraceID_TBL[@tpath] ||= {}
+ TraceID_TBL[@tpath][@id] = self
+ }
+ obj
+ rescue
+ id
+ end
+ end
+ else
id
end
- end
+ }
end
def self.new(tree, *args, &b)
- if tree.kind_of?(Array)
- # not create
- if obj = TraceID_TBL[tree[0].path][tree[1]]
+ TraceID_TBL.mutex.synchronize{
+ if tree.kind_of?(Array)
+ # not create
+ tpath = tree[0].path
+ TraceID_TBL[tpath] ||= {}
+ unless (obj = TraceID_TBL[tpath][tree[1]])
+ (TraceID_TBL[tpath][tree[1]] =
+ obj = self.allocate).instance_eval{
+ @parent = @tree = tree
+ @tpath = @parent.path
+ @path = @id = tree[1] # == traceID
+ }
+ end
return obj
- else
- return super(false, tree[0], tree[1])
end
- end
- super(true, tree, *args, &b)
+ # super(true, tree, *args, &b)
+ (obj = self.allocate).instance_eval{
+ initialize(tree, *args, &b)
+ TraceID_TBL[@tpath] ||= {}
+ TraceID_TBL[@tpath][@id] = self
+ }
+ return obj
+ }
end
- def initialize(create, tree, node, key, opts, cmd=nil, &b)
+ def initialize(tree, node, key, opts, cmd=nil, &b)
@parent = @tree = tree
@tpath = @parent.path
- unless create
- @path = @id = node # == traceID
- return
- end
-
if !cmd
if b
cmd = Proc.new(&b)
@@ -459,7 +559,9 @@ module Tk::BLT
def delete()
tk_call(@tpath, 'trace', 'delete', @id)
- TraceID_TBL[tpath].delete(@id)
+ TraceID_TBL.mutex.synchronize{
+ TraceID_TBL[tpath].delete(@id)
+ }
self
end
@@ -475,7 +577,12 @@ module Tk::BLT
###################################
TreeID_TBL = TkCore::INTERP.create_table
- Tree_ID = ['blt_tree'.freeze, '00000'.taint].freeze
+
+ (Tree_ID = ['blt_tree'.freeze, '00000'.taint]).instance_eval{
+ @mutex = Mutex.new
+ def mutex; @mutex; end
+ freeze
+ }
def __keyonly_optkeys
{
@@ -498,7 +605,9 @@ module Tk::BLT
end
def self.id2obj(id)
- TreeID_TBL[id]? TreeID_TBL[id]: id
+ TreeID_TBL.mutex.synchronize{
+ TreeID_TBL[id]? TreeID_TBL[id]: id
+ }
end
def self.names(pat = None)
@@ -513,27 +622,45 @@ module Tk::BLT
end
def self.new(name = nil)
- return TreeID_TBL[name] if name && TreeID_TBL[name]
- super(name)
+ TreeID_TBL.mutex.synchronize{
+ if name && TreeID_TBL[name]
+ TreeID_TBL[name]
+ else
+ (obj = self.allocate).instance_eval{
+ initialize(name)
+ TreeID_TBL[@id] = self
+ }
+ obj
+ end
+ }
end
def initialzie(name = nil)
if name
@path = @id = name
else
- @path = @id = Tree_ID.join(TkCore::INTERP._ip_id_)
- TreeID_TBL[@id] = self
- Tree_ID[1].succ!
+ Tree_ID.mutex.synchronize{
+ @path = @id = Tree_ID.join(TkCore::INTERP._ip_id_)
+ Tree_ID[1].succ!
+ }
end
- TreeID_TBL[@id] = self
+
tk_call('::blt::tree', 'create', @id)
end
def __destroy_hook__
- Tk::BLT::Tree::Node::TreeNodeID_TBL.delete(@path)
- Tk::BLT::Tree::Tag::TreeTagID_TBL.delete(@path)
- Tk::BLT::Tree::Notify::NotifyID_TBL.delete(@path)
- Tk::BLT::Tree::Trace::TraceID_TBL.delete(@path)
+ Tk::BLT::Tree::Node::TreeNodeID_TBL.mutex.synchronize{
+ Tk::BLT::Tree::Node::TreeNodeID_TBL.delete(@path)
+ }
+ Tk::BLT::Tree::Tag::TreeTagID_TBL.mutex.synchronize{
+ Tk::BLT::Tree::Tag::TreeTagID_TBL.delete(@path)
+ }
+ Tk::BLT::Tree::Notify::NotifyID_TBL.mutex.synchronize{
+ Tk::BLT::Tree::Notify::NotifyID_TBL.delete(@path)
+ }
+ Tk::BLT::Tree::Trace::TraceID_TBL.mutex.synchronize{
+ Tk::BLT::Tree::Trace::TraceID_TBL.delete(@path)
+ }
end
def tagid(tag)
@@ -592,12 +719,14 @@ module Tk::BLT
def delete(*nodes)
tk_call('::blt::tree', 'delete', *(nodes.collect{|node| tagid(node)}))
- nodes.each{|node|
- if node.kind_of?(Tk::BLT::Tree::Node)
- Tk::BLT::Tree::Node::TreeNodeID_TBL[@path].delete(node.id)
- else
- Tk::BLT::Tree::Node::TreeNodeID_TBL[@path].delete(node.to_s)
- end
+ Tk::BLT::Tree::Node::TreeNodeID_TBL.mutex.synchronize{
+ nodes.each{|node|
+ if node.kind_of?(Tk::BLT::Tree::Node)
+ Tk::BLT::Tree::Node::TreeNodeID_TBL[@path].delete(node.id)
+ else
+ Tk::BLT::Tree::Node::TreeNodeID_TBL[@path].delete(node.to_s)
+ end
+ }
}
self
end
@@ -728,7 +857,9 @@ module Tk::BLT
id.delete
else
tk_call(@path, 'notify', 'delete', id)
- Tk::BLT::Tree::Notify::NotifyID_TBL[@path].delete(id.to_s)
+ Tk::BLT::Tree::Notify::NotifyID_TBL.mutex.synchronize{
+ Tk::BLT::Tree::Notify::NotifyID_TBL[@path].delete(id.to_s)
+ }
end
self
end
@@ -835,7 +966,9 @@ module Tk::BLT
def tag_forget(tag)
tag = tag.id if tag.kind_of?(Tk::BLT::Tree::Tag)
tk_call(@path, 'tag', 'forget', tag)
- TreeTagID_TBL[@path].delete(tag)
+ TreeTagID_TBL.mutex.synchronize{
+ TreeTagID_TBL[@path].delete(tag)
+ }
self
end
@@ -889,7 +1022,9 @@ module Tk::BLT
def trace_delete(*args)
args = args.collect{|id| tagid(id)}
tk_call(@path, 'trace', 'delete', *args)
- args.each{|id| Tk::BLT::Tree::Trace::TraceID_TBL[@path].delete(id.to_s)}
+ Tk::BLT::Tree::Trace::TraceID_TBL.mutex.synchronize{
+ args.each{|id| Tk::BLT::Tree::Trace::TraceID_TBL[@path].delete(id.to_s)}
+ }
self
end
diff --git a/ext/tk/lib/tkextlib/blt/treeview.rb b/ext/tk/lib/tkextlib/blt/treeview.rb
index 0343d28b9c..fc890614be 100644
--- a/ext/tk/lib/tkextlib/blt/treeview.rb
+++ b/ext/tk/lib/tkextlib/blt/treeview.rb
@@ -239,6 +239,22 @@ class Tk::BLT::Treeview
nil
]
+ # 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
+ }
+
_setup_subst_table(KEY_TBL, PROC_TBL);
def self.ret_val(val)
@@ -273,8 +289,12 @@ class Tk::BLT::Treeview
########################
def __destroy_hook__
- Tk::BLT::Treeview::Node::TreeNodeID_TBL.delete(@path)
- Tk::BLT::Treeview::Tag::TreeTagID_TBL.delete(@path)
+ Tk::BLT::Treeview::Node::TreeNodeID_TBL.mutex.synchronize{
+ Tk::BLT::Treeview::Node::TreeNodeID_TBL.delete(@path)
+ }
+ Tk::BLT::Treeview::Tag::TreeTagID_TBL.mutex.synchronize{
+ Tk::BLT::Treeview::Tag::TreeTagID_TBL.delete(@path)
+ }
end
def tagid(tag)
@@ -472,6 +492,22 @@ class Tk::BLT::Treeview
nil
]
+ # 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
+ }
+
_setup_subst_table(KEY_TBL, PROC_TBL);
def self.ret_val(val)
@@ -967,22 +1003,47 @@ class Tk::BLT::Treeview::Node < TkObject
include Tk::BLT::Treeview::TagOrID_Methods
TreeNodeID_TBL = TkCore::INTERP.create_table
- TreeNode_ID = ['blt_treeview_node'.freeze, '00000'.taint].freeze
- TkCore::INTERP.init_ip_env{ TreeNodeID_TBL.clear }
+ (TreeNode_ID = ['blt_treeview_node'.freeze, '00000'.taint]).instance_eval{
+ @mutex = Mutex.new
+ def mutex; @mutex; end
+ freeze
+ }
+
+ TkCore::INTERP.init_ip_env{
+ TreeNodeID_TBL.mutex.synchronize{ TreeNodeID_TBL.clear }
+ }
def self.id2obj(tree, id)
tpath = tree.path
- return id unless TreeNodeID_TBL[tpath]
- if TreeNodeID_TBL[tpath][id]
- TreeNodeID_TBL[tpath][id]
- else
- begin
- self.new(tree, nil, nil, 'node'=>Integer(id))
- rescue
+ TreeNodeID_TBL.mutex.synchronize{
+ if TreeNodeID_TBL[tpath]
+ if TreeNodeID_TBL[tpath][id]
+ TreeNodeID_TBL[tpath][id]
+ else
+ begin
+ # self.new(tree, nil, nil, 'node'=>Integer(id))
+ unless (tk_call(@tpath, 'get', id)).empty?
+ id = Integer(id)
+ (obj = self.allocate).instance_eval{
+ @parent = @tree = tree
+ @tpath = @parent.path
+ @path = @id = id
+ TreeNodeID_TBL[@tpath] ||= {}
+ TreeNodeID_TBL[@tpath][@id] = self
+ }
+ obj
+ else
+ id
+ end
+ rescue
+ id
+ end
+ end
+ else
id
end
- end
+ }
end
def self.new(tree, pos, parent=nil, keys={})
@@ -994,13 +1055,21 @@ class Tk::BLT::Treeview::Node < TkObject
keys = _symbolkey2str(keys)
tpath = tree.path
- if (id = keys['node']) && (obj = TreeNodeID_TBL[tpath][id])
- keys.delete('node')
- tk_call(tree.path, 'move', id, pos, parent) if parent
- return obj
- end
+ TreeNodeID_TBL.mutex.synchronize{
+ TreeNodeID_TBL[tpath] ||= {}
+ if (id = keys['node']) && (obj = TreeNodeID_TBL[tpath][id])
+ keys.delete('node')
+ tk_call(tree.path, 'move', id, pos, parent) if parent
+ return obj
+ end
- super(tree, pos, parent, keys)
+ #super(tree, pos, parent, keys)
+ (obj = self.allocate).instance_eval{
+ initialize(tree, pos, parent, keys)
+ TreeNodeID_TBL[tpath][@id] = self
+ }
+ obj
+ }
end
def initialize(tree, pos, parent, keys)
@@ -1008,11 +1077,18 @@ class Tk::BLT::Treeview::Node < TkObject
@tpath = @parent.path
if (id = keys['node'])
+ # if tk_call(@tpath, 'get', id).empty?
+ # fail RuntimeError, "not exist the node '#{id}'"
+ # end
@path = @id = id
tk_call(@tpath, 'move', @id, pos, tagid(parent)) if parent
+ configure(keys) if keys && ! keys.empty?
else
- name = TreeNode_ID.join(TkCore::INTERP._ip_id_).freeze
- TreeNode_ID[1].succ!
+ name = nil
+ TreeNode_ID.mutex.synchronize{
+ name = TreeNode_ID.join(TkCore::INTERP._ip_id_).freeze
+ TreeNode_ID[1].succ!
+ }
at = keys.delete['at']
@@ -1035,9 +1111,6 @@ class Tk::BLT::Treeview::Node < TkObject
end
@path = @id
end
-
- TreeNodeID_TBL[@tpath] = {} unless TreeNodeID_TBL[@tpath]
- TreeNodeID_TBL[@tpath][@id] = self
end
def id
@@ -1051,37 +1124,66 @@ class Tk::BLT::Treeview::Tag < TkObject
include Tk::BLT::Treeview::TagOrID_Methods
TreeTagID_TBL = TkCore::INTERP.create_table
- TreeTag_ID = ['blt_treeview_tag'.freeze, '00000'.taint].freeze
- TkCore::INTERP.init_ip_env{ TreeTagID_TBL.clear }
+ (TreeTag_ID = ['blt_treeview_tag'.freeze, '00000'.taint]).instance_eval{
+ @mutex = Mutex.new
+ def mutex; @mutex; end
+ freeze
+ }
- def self.id2obj(tree, id)
+ TkCore::INTERP.init_ip_env{
+ TreeTagID_TBL.mutex.synchronize{ TreeTagID_TBL.clear }
+ }
+
+ def self.id2obj(tree, name)
tpath = tree.path
- return id unless TreeTagID_TBL[tpath]
- if TreeTagID_TBL[tpath][id]
- TreeTagID_TBL[tpath][id]
- else
- begin
- self.new(tree, nil, nil, 'name'=>Integer(id))
- rescue
+ TreeTagID_TBL.mutex.synchronize{
+ if TreeTagID_TBL[tpath]
+ if TreeTagID_TBL[tpath][name]
+ TreeTagID_TBL[tpath][name]
+ else
+ #self.new(tree, name)
+ (obj = self.allocate).instance_eval{
+ @parent = @tree = tree
+ @tpath = @parent.path
+ @path = @id = name
+ TreeTagID_TBL[@tpath] = {} unless TreeTagID_TBL[@tpath]
+ TreeTagID_TBL[@tpath][@id] = self
+ }
+ obj
+ end
+ else
id
end
- end
+ }
end
def self.new_by_name(tree, name, *ids)
- if (obj = TreeTagID_TBL[tree.path][name])
- return obj
- end
- new([tree, name], ids)
+ TreeTagID_TBL.mutex.synchronize{
+ unless (obj = TreeTagID_TBL[tree.path][name])
+ (obj = self.allocate).instance_eval{
+ initialize(tree, name, ids)
+ TreeTagID_TBL[@tpath] = {} unless TreeTagID_TBL[@tpath]
+ TreeTagID_TBL[@tpath][@id] = self
+ }
+ end
+ obj
+ }
end
def self.new(tree, *ids)
- if tree.kind_of?(Array)
- super(tree[0], tree[1], ids)
- else
- super(tree, nil, ids)
- end
+ TreeTagID_TBL.mutex.synchronize{
+ (obj = self.allocate).instance_eval{
+ if tree.kind_of?(Array)
+ initialize(tree[0], tree[1], ids)
+ else
+ initialize(tree, nil, ids)
+ end
+ TreeTagID_TBL[@tpath] = {} unless TreeTagID_TBL[@tpath]
+ TreeTagID_TBL[@tpath][@id] = self
+ }
+ obj
+ }
end
def initialize(tree, name, ids)
@@ -1091,13 +1193,12 @@ class Tk::BLT::Treeview::Tag < TkObject
if name
@path = @id = name
else
- @path = @id = TreeTag_ID.join(TkCore::INTERP._ip_id_).freeze
- TreeTag_ID[1].succ!
+ TreeTag_ID.mutex.synchronize{
+ @path = @id = TreeTag_ID.join(TkCore::INTERP._ip_id_).freeze
+ TreeTag_ID[1].succ!
+ }
end
- TreeTagID_TBL[@tpath] = {} unless TreeTagID_TBL[@tpath]
- TreeTagID_TBL[@tpath][@id] = self
-
unless ids.empty?
tk_call(@tpath, 'tag', 'add', @id, *(ids.collect{|id| tagid(id)}))
end
diff --git a/ext/tk/lib/tkextlib/blt/vector.rb b/ext/tk/lib/tkextlib/blt/vector.rb
index 540b6b9102..76c12a24e8 100644
--- a/ext/tk/lib/tkextlib/blt/vector.rb
+++ b/ext/tk/lib/tkextlib/blt/vector.rb
@@ -23,14 +23,17 @@ module Tk::BLT
end
def self.names(pat=None)
- simplelist(tk_call('::blt::vector', 'names', pat)).collect{|name|
- if TkVar_ID_TBL[name]
- TkVar_ID_TBL[name]
- elsif name[0..1] == '::' && TkVar_ID_TBL[name[2..-1]]
- TkVar_ID_TBL[name[2..-1]]
- else
- name
- end
+ list = simplelist(tk_call('::blt::vector', 'names', pat))
+ TkVar_ID_TBL.mutex.synchronize{
+ list.collect{|name|
+ if TkVar_ID_TBL[name]
+ TkVar_ID_TBL[name]
+ elsif name[0..1] == '::' && TkVar_ID_TBL[name[2..-1]]
+ TkVar_ID_TBL[name[2..-1]]
+ else
+ name
+ end
+ }
}
end
@@ -53,7 +56,9 @@ module Tk::BLT
"#auto", *hash_kv(keys))
end
- TkVar_ID_TBL[@id] = self
+ TkVar_ID_TBL.mutex.synchronize{
+ TkVar_ID_TBL[@id] = self
+ }
@def_default = false
@default_val = nil
@@ -221,13 +226,21 @@ module Tk::BLT
class VectorAccess < Vector
def self.new(name)
- return TkVar_ID_TBL[name] if TkVar_ID_TBL[name]
- super(name, size=nil, keys={})
+ TkVar_ID_TBL.mutex.synchronize{
+ if TkVar_ID_TBL[name]
+ TkVar_ID_TBL[name]
+ else
+ (obj = self.allocate).instance_eval{
+ initialize(name)
+ TkVar_ID_TBL[@id] = self
+ }
+ obj
+ end
+ }
end
def initialize(vec_name)
@id = vec_name
- TkVar_ID_TBL[@id] = self
@def_default = false
@default_val = nil
diff --git a/ext/tk/lib/tkextlib/blt/watch.rb b/ext/tk/lib/tkextlib/blt/watch.rb
index ae5e50f126..2daf417e0b 100644
--- a/ext/tk/lib/tkextlib/blt/watch.rb
+++ b/ext/tk/lib/tkextlib/blt/watch.rb
@@ -13,11 +13,23 @@ module Tk::BLT
TkCommandNames = ['::blt::watch'.freeze].freeze
WATCH_ID_TBL = TkCore::INTERP.create_table
- BLT_WATCH_ID = ['blt_watch_id'.freeze, '00000'.taint].freeze
+
+ (BLT_WATCH_ID = ['blt_watch_id'.freeze, '00000'.taint]).instance_eval{
+ @mutex = Mutex.new
+ def mutex; @mutex; end
+ freeze
+ }
+
+ TkCore::INTERP.init_ip_env{
+ WATCH_ID_TBL.mutex.synchronize{ WATCH_ID_TBL.clear }
+ }
def self.names(state = None)
- tk_split_list(tk_call('::blt::watch', 'names', state)).collect{|name|
- WATCH_ID_TBL[name] || name
+ lst = tk_split_list(tk_call('::blt::watch', 'names', state))
+ WATCH_ID_TBL.mutex.synchronize{
+ lst.collect{|name|
+ WATCH_ID_TBL[name] || name
+ }
}
end
@@ -45,13 +57,17 @@ module Tk::BLT
if name
@id = name.to_s
else
- @id = BLT_WATCH_ID.join(TkCore::INTERP._ip_id_)
- BLT_WATCH_ID[1].succ!
+ BLT_WATCH_ID.mutex.synchronize{
+ @id = BLT_WATCH_ID.join(TkCore::INTERP._ip_id_)
+ BLT_WATCH_ID[1].succ!
+ }
end
@path = @id
- WATCH_ID_TBL[@id] = self
+ WATCH_ID_TBL.mutex.synchronize{
+ WATCH_ID_TBL[@id] = self
+ }
tk_call('::blt::watch', 'create', @id, *hash_kv(keys))
end
diff --git a/ext/tk/lib/tkextlib/bwidget/buttonbox.rb b/ext/tk/lib/tkextlib/bwidget/buttonbox.rb
index a8f23e8749..8d6d212189 100644
--- a/ext/tk/lib/tkextlib/bwidget/buttonbox.rb
+++ b/ext/tk/lib/tkextlib/bwidget/buttonbox.rb
@@ -40,7 +40,13 @@ class Tk::BWidget::ButtonBox
def add(keys={}, &b)
win = window(tk_send('add', *hash_kv(keys)))
- win.instance_eval(&b) if b
+ if b
+ if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!!
+ win.instance_exec(self, &b)
+ else
+ win.instance_eval(&b)
+ end
+ end
win
end
@@ -62,7 +68,13 @@ class Tk::BWidget::ButtonBox
def insert(idx, keys={}, &b)
win = window(tk_send('insert', tagid(idx), *hash_kv(keys)))
- win.instance_eval(&b) if b
+ if b
+ if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!!
+ win.instance_exec(self, &b)
+ else
+ win.instance_eval(&b)
+ end
+ end
win
end
diff --git a/ext/tk/lib/tkextlib/bwidget/combobox.rb b/ext/tk/lib/tkextlib/bwidget/combobox.rb
index 31f71c3aaf..1c58a4ccb0 100644
--- a/ext/tk/lib/tkextlib/bwidget/combobox.rb
+++ b/ext/tk/lib/tkextlib/bwidget/combobox.rb
@@ -25,7 +25,13 @@ class Tk::BWidget::ComboBox
def get_listbox(&b)
win = window(tk_send_without_enc('getlistbox'))
- win.instance_eval(&b) if b
+ if b
+ if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!!
+ win.instance_exec(self, &b)
+ else
+ win.instance_eval(&b)
+ end
+ end
win
end
diff --git a/ext/tk/lib/tkextlib/bwidget/dialog.rb b/ext/tk/lib/tkextlib/bwidget/dialog.rb
index ae5f0238a3..0ddee21d05 100644
--- a/ext/tk/lib/tkextlib/bwidget/dialog.rb
+++ b/ext/tk/lib/tkextlib/bwidget/dialog.rb
@@ -112,19 +112,37 @@ class Tk::BWidget::Dialog
def add(keys={}, &b)
win = window(tk_send('add', *hash_kv(keys)))
- win.instance_eval(&b) if b
+ if b
+ if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!!
+ win.instance_exec(self, &b)
+ else
+ win.instance_eval(&b)
+ end
+ end
win
end
def get_frame(&b)
win = window(tk_send('getframe'))
- win.instance_eval(&b) if b
+ if b
+ if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!!
+ win.instance_exec(self, &b)
+ else
+ win.instance_eval(&b)
+ end
+ end
win
end
def get_buttonbox(&b)
win = window(@path + '.bbox')
- win.instance_eval(&b) if b
+ if b
+ if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!!
+ win.instance_exec(self, &b)
+ else
+ win.instance_eval(&b)
+ end
+ end
win
end
diff --git a/ext/tk/lib/tkextlib/bwidget/labelframe.rb b/ext/tk/lib/tkextlib/bwidget/labelframe.rb
index f7b267eebb..dc221806e4 100644
--- a/ext/tk/lib/tkextlib/bwidget/labelframe.rb
+++ b/ext/tk/lib/tkextlib/bwidget/labelframe.rb
@@ -40,7 +40,13 @@ class Tk::BWidget::LabelFrame
end
def get_frame(&b)
win = window(tk_send_without_enc('getframe'))
- win.instance_eval(&b) if b
+ if b
+ if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!!
+ win.instance_exec(self, &b)
+ else
+ win.instance_eval(&b)
+ end
+ end
win
end
end
diff --git a/ext/tk/lib/tkextlib/bwidget/listbox.rb b/ext/tk/lib/tkextlib/bwidget/listbox.rb
index 1267500661..d8cd72fec2 100644
--- a/ext/tk/lib/tkextlib/bwidget/listbox.rb
+++ b/ext/tk/lib/tkextlib/bwidget/listbox.rb
@@ -211,14 +211,26 @@ class Tk::BWidget::ListBox::Item
include TkTreatTagFont
ListItem_TBL = TkCore::INTERP.create_table
- ListItem_ID = ['bw:item'.freeze, '00000'.taint].freeze
- TkCore::INTERP.init_ip_env{ ListItem_TBL.clear }
+ (ListItem_ID = ['bw:item'.freeze, '00000'.taint]).instance_eval{
+ @mutex = Mutex.new
+ def mutex; @mutex; end
+ freeze
+ }
+
+ TkCore::INTERP.init_ip_env{
+ ListItem_TBL.mutex.synchronize{ ListItem_TBL.clear }
+ }
def self.id2obj(lbox, id)
lpath = lbox.path
- return id unless ListItem_TBL[lpath]
- ListItem_TBL[lpath][id]? ListItem_TBL[lpath][id]: id
+ ListItem_TBL.mutex.synchronize{
+ if ListItem_TBL[lpath]
+ ListItem_TBL[lpath][id]? ListItem_TBL[lpath][id]: id
+ else
+ id
+ end
+ }
end
def initialize(lbox, *args)
@@ -250,13 +262,17 @@ class Tk::BWidget::ListBox::Item
if keys.key?('itemname')
@path = @id = keys.delete('itemname')
else
- @path = @id = ListItem_ID.join(TkCore::INTERP._ip_id_)
- ListItem_ID[1].succ!
+ ListItem_ID.mutex.synchronize{
+ @path = @id = ListItem_ID.join(TkCore::INTERP._ip_id_)
+ ListItem_ID[1].succ!
+ }
end
- ListItem_TBL[@id] = self
- ListItem_TBL[@lpath] = {} unless ListItem_TBL[@lpath]
- ListItem_TBL[@lpath][@id] = self
+ ListItem_TBL.mutex.synchronize{
+ ListItem_TBL[@id] = self
+ ListItem_TBL[@lpath] = {} unless ListItem_TBL[@lpath]
+ ListItem_TBL[@lpath][@id] = self
+ }
@listbox.insert(index, @id, keys)
end
diff --git a/ext/tk/lib/tkextlib/bwidget/mainframe.rb b/ext/tk/lib/tkextlib/bwidget/mainframe.rb
index c54e878557..de66eaf81e 100644
--- a/ext/tk/lib/tkextlib/bwidget/mainframe.rb
+++ b/ext/tk/lib/tkextlib/bwidget/mainframe.rb
@@ -41,37 +41,73 @@ class Tk::BWidget::MainFrame
def add_indicator(keys={}, &b)
win = window(tk_send('addindicator', *hash_kv(keys)))
- win.instance_eval(&b) if b
+ if b
+ if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!!
+ win.instance_exec(self, &b)
+ else
+ win.instance_eval(&b)
+ end
+ end
win
end
def add_toolbar(&b)
win = window(tk_send('addtoolbar'))
- win.instance_eval(&b) if b
+ if b
+ if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!!
+ win.instance_exec(self, &b)
+ else
+ win.instance_eval(&b)
+ end
+ end
win
end
def get_frame(&b)
win = window(tk_send('getframe'))
- win.instance_eval(&b) if b
+ if b
+ if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!!
+ win.instance_exec(self, &b)
+ else
+ win.instance_eval(&b)
+ end
+ end
win
end
def get_indicator(idx, &b)
win = window(tk_send('getindicator', idx))
- win.instance_eval(&b) if b
+ if b
+ if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!!
+ win.instance_exec(self, &b)
+ else
+ win.instance_eval(&b)
+ end
+ end
win
end
def get_menu(menu_id, &b)
win = window(tk_send('getmenu', menu_id))
- win.instance_eval(&b) if b
+ if b
+ if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!!
+ win.instance_exec(self, &b)
+ else
+ win.instance_eval(&b)
+ end
+ end
win
end
def get_toolbar(idx, &b)
win = window(tk_send('gettoolbar', idx))
- win.instance_eval(&b) if b
+ if b
+ if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!!
+ win.instance_exec(self, &b)
+ else
+ win.instance_eval(&b)
+ end
+ end
win
end
diff --git a/ext/tk/lib/tkextlib/bwidget/messagedlg.rb b/ext/tk/lib/tkextlib/bwidget/messagedlg.rb
index 9c946d0630..cc8a996f46 100644
--- a/ext/tk/lib/tkextlib/bwidget/messagedlg.rb
+++ b/ext/tk/lib/tkextlib/bwidget/messagedlg.rb
@@ -173,6 +173,9 @@ class Tk::BWidget::MessageDlg
end
def create
- num_or_str(tk_call(self.class::TkCommandNames[0], @path, *hash_kv(@keys)))
+ # return the index of the pressed button, or nil if it is destroyed
+ ret = num_or_str(tk_call(self.class::TkCommandNames[0],
+ @path, *hash_kv(@keys)))
+ (ret < 0)? nil: ret
end
end
diff --git a/ext/tk/lib/tkextlib/bwidget/notebook.rb b/ext/tk/lib/tkextlib/bwidget/notebook.rb
index 5146d4915d..423943619c 100644
--- a/ext/tk/lib/tkextlib/bwidget/notebook.rb
+++ b/ext/tk/lib/tkextlib/bwidget/notebook.rb
@@ -89,7 +89,13 @@ class Tk::BWidget::NoteBook
def add(page, &b)
win = window(tk_send('add', tagid(page)))
- win.instance_eval(&b) if b
+ if b
+ if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!!
+ win.instance_exec(self, &b)
+ else
+ win.instance_eval(&b)
+ end
+ end
win
end
@@ -105,7 +111,13 @@ class Tk::BWidget::NoteBook
def get_frame(page, &b)
win = window(tk_send('getframe', tagid(page)))
- win.instance_eval(&b) if b
+ if b
+ if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!!
+ win.instance_exec(self, &b)
+ else
+ win.instance_eval(&b)
+ end
+ end
win
end
@@ -115,7 +127,13 @@ class Tk::BWidget::NoteBook
def insert(index, page, keys={}, &b)
win = window(tk_send('insert', index, tagid(page), *hash_kv(keys)))
- win.instance_eval(&b) if b
+ if b
+ if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!!
+ win.instance_exec(self, &b)
+ else
+ win.instance_eval(&b)
+ end
+ end
win
end
diff --git a/ext/tk/lib/tkextlib/bwidget/pagesmanager.rb b/ext/tk/lib/tkextlib/bwidget/pagesmanager.rb
index fc01284be6..fbc2c11255 100644
--- a/ext/tk/lib/tkextlib/bwidget/pagesmanager.rb
+++ b/ext/tk/lib/tkextlib/bwidget/pagesmanager.rb
@@ -26,7 +26,13 @@ class Tk::BWidget::PagesManager
def add(page, &b)
win = window(tk_send('add', tagid(page)))
- win.instance_eval(&b) if b
+ if b
+ if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!!
+ win.instance_exec(self, &b)
+ else
+ win.instance_eval(&b)
+ end
+ end
win
end
@@ -42,7 +48,13 @@ class Tk::BWidget::PagesManager
def get_frame(page, &b)
win = window(tk_send('getframe', tagid(page)))
- win.instance_eval(&b) if b
+ if b
+ if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!!
+ win.instance_exec(self, &b)
+ else
+ win.instance_eval(&b)
+ end
+ end
win
end
diff --git a/ext/tk/lib/tkextlib/bwidget/panedwindow.rb b/ext/tk/lib/tkextlib/bwidget/panedwindow.rb
index 19982c6095..4d979fd523 100644
--- a/ext/tk/lib/tkextlib/bwidget/panedwindow.rb
+++ b/ext/tk/lib/tkextlib/bwidget/panedwindow.rb
@@ -25,7 +25,13 @@ class Tk::BWidget::PanedWindow
def get_frame(idx, &b)
win = window(tk_send_without_enc('getframe', idx))
- win.instance_eval(&b) if b
+ if b
+ if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!!
+ win.instance_exec(self, &b)
+ else
+ win.instance_eval(&b)
+ end
+ end
win
end
end
diff --git a/ext/tk/lib/tkextlib/bwidget/panelframe.rb b/ext/tk/lib/tkextlib/bwidget/panelframe.rb
index 13f8817d74..84bae0768b 100644
--- a/ext/tk/lib/tkextlib/bwidget/panelframe.rb
+++ b/ext/tk/lib/tkextlib/bwidget/panelframe.rb
@@ -36,7 +36,13 @@ class Tk::BWidget::PanelFrame
def get_frame(&b)
win = window(tk_send_without_enc('getframe'))
- win.instance_eval(&b) if b
+ if b
+ if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!!
+ win.instance_exec(self, &b)
+ else
+ win.instance_eval(&b)
+ end
+ end
win
end
diff --git a/ext/tk/lib/tkextlib/bwidget/progressdlg.rb b/ext/tk/lib/tkextlib/bwidget/progressdlg.rb
index fbf00f3b00..32600255d5 100644
--- a/ext/tk/lib/tkextlib/bwidget/progressdlg.rb
+++ b/ext/tk/lib/tkextlib/bwidget/progressdlg.rb
@@ -51,4 +51,8 @@ class Tk::BWidget::ProgressDlg
def value= (val)
@keys['variable'].value = val
end
+
+ def create
+ window(tk_call(self.class::TkCommandNames[0], @path, *hash_kv(@keys)))
+ end
end
diff --git a/ext/tk/lib/tkextlib/bwidget/scrollableframe.rb b/ext/tk/lib/tkextlib/bwidget/scrollableframe.rb
index a3986681a5..010c960ec5 100644
--- a/ext/tk/lib/tkextlib/bwidget/scrollableframe.rb
+++ b/ext/tk/lib/tkextlib/bwidget/scrollableframe.rb
@@ -23,7 +23,13 @@ class Tk::BWidget::ScrollableFrame
def get_frame(&b)
win = window(tk_send_without_enc('getframe'))
- win.instance_eval(&b) if b
+ if b
+ if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!!
+ win.instance_exec(self, &b)
+ else
+ win.instance_eval(&b)
+ end
+ end
win
end
diff --git a/ext/tk/lib/tkextlib/bwidget/scrolledwindow.rb b/ext/tk/lib/tkextlib/bwidget/scrolledwindow.rb
index e9e53235b7..3599fd8459 100644
--- a/ext/tk/lib/tkextlib/bwidget/scrolledwindow.rb
+++ b/ext/tk/lib/tkextlib/bwidget/scrolledwindow.rb
@@ -21,7 +21,13 @@ class Tk::BWidget::ScrolledWindow
def get_frame(&b)
win = window(tk_send_without_enc('getframe'))
- win.instance_eval(&b) if b
+ if b
+ if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!!
+ win.instance_exec(self, &b)
+ else
+ win.instance_eval(&b)
+ end
+ end
win
end
diff --git a/ext/tk/lib/tkextlib/bwidget/selectcolor.rb b/ext/tk/lib/tkextlib/bwidget/selectcolor.rb
index 742a84cd84..0f9014f8de 100644
--- a/ext/tk/lib/tkextlib/bwidget/selectcolor.rb
+++ b/ext/tk/lib/tkextlib/bwidget/selectcolor.rb
@@ -10,6 +10,11 @@ require 'tkextlib/bwidget/messagedlg'
module Tk
module BWidget
class SelectColor < Tk::BWidget::MessageDlg
+ class Dialog < Tk::BWidget::SelectColor
+ end
+ class Menubutton < Tk::Menubutton
+ end
+ MenuButton = Menubutton
end
end
end
@@ -43,3 +48,26 @@ class Tk::BWidget::SelectColor
tk_call('SelectColor::setcolor', idx, color)
end
end
+
+class Tk::BWidget::SelectColor::Dialog
+ def create_self(keys)
+ super(keys)
+ @keys['type'] = 'dialog'
+ end
+
+ def create
+ @keys['type'] = 'dialog' # 'dialog' type returns color
+ tk_call(Tk::BWidget::SelectColor::TkCommandNames[0],
+ @path, *hash_kv(@keys))
+ end
+end
+
+class Tk::BWidget::SelectColor::Menubutton
+ def create_self(keys)
+ keys = {} unless keys
+ keys = _symbolkey2str(keys)
+ keys['type'] = 'menubutton' # 'toolbar' type returns widget path
+ window(tk_call(Tk::BWidget::SelectColor::TkCommandNames[0],
+ @path, *hash_kv(keys)))
+ end
+end
diff --git a/ext/tk/lib/tkextlib/bwidget/selectfont.rb b/ext/tk/lib/tkextlib/bwidget/selectfont.rb
index 478787602a..e53eb3b5bc 100644
--- a/ext/tk/lib/tkextlib/bwidget/selectfont.rb
+++ b/ext/tk/lib/tkextlib/bwidget/selectfont.rb
@@ -66,7 +66,7 @@ class Tk::BWidget::SelectFont::Dialog
end
def create
- @keys['type'] = 'dialog'
+ @keys['type'] = 'dialog' # 'dialog' type returns font name
tk_call(Tk::BWidget::SelectFont::TkCommandNames[0], @path, *hash_kv(@keys))
end
end
@@ -79,7 +79,8 @@ class Tk::BWidget::SelectFont::Toolbar
def create_self(keys)
keys = {} unless keys
keys = _symbolkey2str(keys)
- keys['type'] = 'toolbar'
- tk_call(Tk::BWidget::SelectFont::TkCommandNames[0], @path, *hash_kv(keys))
+ keys['type'] = 'toolbar' # 'toolbar' type returns widget path
+ window(tk_call(Tk::BWidget::SelectFont::TkCommandNames[0],
+ @path, *hash_kv(keys)))
end
end
diff --git a/ext/tk/lib/tkextlib/bwidget/statusbar.rb b/ext/tk/lib/tkextlib/bwidget/statusbar.rb
index df16e4c0b7..39c678d37e 100644
--- a/ext/tk/lib/tkextlib/bwidget/statusbar.rb
+++ b/ext/tk/lib/tkextlib/bwidget/statusbar.rb
@@ -36,7 +36,13 @@ class Tk::BWidget::StatusBar
def get_frame(&b)
win = window(tk_send_without_enc('getframe'))
- win.instance_eval(&b) if b
+ if b
+ if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!!
+ win.instance_exec(self, &b)
+ else
+ win.instance_eval(&b)
+ end
+ end
win
end
diff --git a/ext/tk/lib/tkextlib/bwidget/titleframe.rb b/ext/tk/lib/tkextlib/bwidget/titleframe.rb
index f519490430..68534e66e9 100644
--- a/ext/tk/lib/tkextlib/bwidget/titleframe.rb
+++ b/ext/tk/lib/tkextlib/bwidget/titleframe.rb
@@ -21,7 +21,13 @@ class Tk::BWidget::TitleFrame
def get_frame(&b)
win = window(tk_send_without_enc('getframe'))
- win.instance_eval(&b) if b
+ if b
+ if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!!
+ win.instance_exec(self, &b)
+ else
+ win.instance_eval(&b)
+ end
+ end
win
end
end
diff --git a/ext/tk/lib/tkextlib/bwidget/tree.rb b/ext/tk/lib/tkextlib/bwidget/tree.rb
index e7178debe2..7a46db575e 100644
--- a/ext/tk/lib/tkextlib/bwidget/tree.rb
+++ b/ext/tk/lib/tkextlib/bwidget/tree.rb
@@ -263,14 +263,26 @@ class Tk::BWidget::Tree::Node
include TkTreatTagFont
TreeNode_TBL = TkCore::INTERP.create_table
- TreeNode_ID = ['bw:node'.freeze, '00000'.taint].freeze
- TkCore::INTERP.init_ip_env{ TreeNode_TBL.clear }
+ (TreeNode_ID = ['bw:node'.freeze, '00000'.taint]).instance_eval{
+ @mutex = Mutex.new
+ def mutex; @mutex; end
+ freeze
+ }
+
+ TkCore::INTERP.init_ip_env{
+ TreeNode_TBL.mutex.synchronize{ TreeNode_TBL.clear }
+ }
def self.id2obj(tree, id)
tpath = tree.path
- return id unless TreeNode_TBL[tpath]
- TreeNode_TBL[tpath][id]? TreeNode_TBL[tpath][id]: id
+ TreeNode_TBL.mutex.synchronize{
+ if TreeNode_TBL[tpath]
+ TreeNode_TBL[tpath][id]? TreeNode_TBL[tpath][id]: id
+ else
+ id
+ end
+ }
end
def initialize(tree, *args)
@@ -311,13 +323,17 @@ class Tk::BWidget::Tree::Node
if keys.key?('nodename')
@path = @id = keys.delete('nodename')
else
- @path = @id = TreeNode_ID.join(TkCore::INTERP._ip_id_)
- TreeNode_ID[1].succ!
+ TreeNode_ID.mutex.synchronize{
+ @path = @id = TreeNode_ID.join(TkCore::INTERP._ip_id_)
+ TreeNode_ID[1].succ!
+ }
end
- TreeNode_TBL[@id] = self
- TreeNode_TBL[@tpath] = {} unless TreeNode_TBL[@tpath]
- TreeNode_TBL[@tpath][@id] = self
+ TreeNode_TBL.mutex.synchronize{
+ TreeNode_TBL[@id] = self
+ TreeNode_TBL[@tpath] = {} unless TreeNode_TBL[@tpath]
+ TreeNode_TBL[@tpath][@id] = self
+ }
@tree.insert(index, parent, @id, keys)
end
diff --git a/ext/tk/lib/tkextlib/bwidget/widget.rb b/ext/tk/lib/tkextlib/bwidget/widget.rb
index 568e503a8b..34e51308a5 100644
--- a/ext/tk/lib/tkextlib/bwidget/widget.rb
+++ b/ext/tk/lib/tkextlib/bwidget/widget.rb
@@ -43,7 +43,13 @@ module Tk::BWidget::Widget
def self.create(klass, path, rename=None, &b)
win = window(tk_call('Widget::create', klass, path, rename))
- win.instance_eval(&b) if b
+ if b
+ if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!!
+ win.instance_exec(self, &b)
+ else
+ win.instance_eval(&b)
+ end
+ end
win
end
diff --git a/ext/tk/lib/tkextlib/itcl/incr_tcl.rb b/ext/tk/lib/tkextlib/itcl/incr_tcl.rb
index 07abf3a7bf..2b75d62eb9 100644
--- a/ext/tk/lib/tkextlib/itcl/incr_tcl.rb
+++ b/ext/tk/lib/tkextlib/itcl/incr_tcl.rb
@@ -40,16 +40,22 @@ module Tk
class ItclObject < TkObject
ITCL_CLASSNAME = ''.freeze
- ITCL_OBJ_ID = ['itclobj'.freeze, '00000'.taint].freeze
+ (ITCL_OBJ_ID = ['itclobj'.freeze, '00000'.taint]).instance_eval{
+ @mutex = Mutex.new
+ def mutex; @mutex; end
+ freeze
+ }
ITCL_OBJ_TBL = {}.taint
def initialize(*args)
if (@klass = self.class::ITCL_CLASSNAME).empty?
fail RuntimeError, 'unknown itcl class (abstract class?)'
end
- @id = Tk::Itcl::ItclObject::TCL_OBJ_ID.join(TkCore::INTERP._ip_id_)
+ Tk::Itcl::ItclObject::ITCL_OBJ_ID.mutex.synchronize{
+ @id = Tk::Itcl::ItclObject::TCL_OBJ_ID.join(TkCore::INTERP._ip_id_)
+ Tk::Itcl::ItclObject::ITCL_OBJ_ID[1].succ!
+ }
@path = @id
- Tk::Itcl::ItclObject::ITCL_OBJ_ID[1].succ!
end
def self.call_proc(name, *args)
diff --git a/ext/tk/lib/tkextlib/itk/incr_tk.rb b/ext/tk/lib/tkextlib/itk/incr_tk.rb
index c7b4e40af8..e06deb552c 100644
--- a/ext/tk/lib/tkextlib/itk/incr_tk.rb
+++ b/ext/tk/lib/tkextlib/itk/incr_tk.rb
@@ -145,9 +145,16 @@ module Tk
private :__config_cmd
ComponentID_TBL = TkCore::INTERP.create_table
- Itk_Component_ID = ['itk:component'.freeze, '00000'.taint].freeze
- TkCore::INTERP.init_ip_env{ ComponentID_TBL.clear }
+ (Itk_Component_ID = ['itk:component'.freeze, '00000'.taint]).instance_eval{
+ @mutex = Mutex.new
+ def mutex; @mutex; end
+ freeze
+ }
+
+ TkCore::INTERP.init_ip_env{
+ ComponentID_TBL.mutex.synchronize{ ComponentID_TBL.clear }
+ }
def self.id2obj(master, id)
if master.kind_of?(TkObject)
@@ -155,8 +162,13 @@ module Tk
else
master = master.to_s
end
- return id unless ComponentID_TBL.key?(master)
- (ComponentID_TBL[master].key?(id))? ComponentID_TBL[master][id]: id
+ ComponentID_TBL.mutex.synchronize{
+ if ComponentID_TBL.key?(master)
+ (ComponentID_TBL[master].key?(id))? ComponentID_TBL[master][id]: id
+ else
+ id
+ end
+ }
end
def self.new(master, component=nil)
@@ -171,17 +183,21 @@ module Tk
elsif component
component = component.to_s
else
- component = Itk_Component_ID.join(TkCore::INTERP._ip_id_)
- Itk_Component_ID[1].succ!
+ Itk_Component_ID.mutex.synchronize{
+ component = Itk_Component_ID.join(TkCore::INTERP._ip_id_)
+ Itk_Component_ID[1].succ!
+ }
end
- if ComponentID_TBL.key?(master)
- if ComponentID_TBL[master].key?(component)
- return ComponentID_TBL[master][component]
+ ComponentID_TBL.mutex.synchronize{
+ if ComponentID_TBL.key?(master)
+ if ComponentID_TBL[master].key?(component)
+ return ComponentID_TBL[master][component]
+ end
+ else
+ ComponentID_TBL[master] = {}
end
- else
- ComponentID_TBL[master] = {}
- end
+ }
super(master, component)
end
@@ -190,7 +206,9 @@ module Tk
@master = master
@component = component
- ComponentID_TBL[@master][@component] = self
+ ComponentID_TBL.mutex.synchronize{
+ ComponentID_TBL[@master][@component] = self
+ }
begin
@widget = window(tk_call(@master, 'component', @component))
diff --git a/ext/tk/lib/tkextlib/iwidgets/calendar.rb b/ext/tk/lib/tkextlib/iwidgets/calendar.rb
index 0152f8593a..236ca96f00 100644
--- a/ext/tk/lib/tkextlib/iwidgets/calendar.rb
+++ b/ext/tk/lib/tkextlib/iwidgets/calendar.rb
@@ -45,6 +45,23 @@ class Tk::Iwidgets::Calendar
class ValidateArgs < TkUtil::CallbackSubst
KEY_TBL = [ [?d, ?s, :date], nil ]
PROC_TBL = [ [?s, TkComm.method(:string) ], nil ]
+
+ # 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
+ }
+
_setup_subst_table(KEY_TBL, PROC_TBL);
def self.ret_val(val)
diff --git a/ext/tk/lib/tkextlib/iwidgets/entryfield.rb b/ext/tk/lib/tkextlib/iwidgets/entryfield.rb
index 6aa933ce06..1f9effb46e 100644
--- a/ext/tk/lib/tkextlib/iwidgets/entryfield.rb
+++ b/ext/tk/lib/tkextlib/iwidgets/entryfield.rb
@@ -42,6 +42,23 @@ class Tk::Iwidgets::Entryfield
[ ?w, TkComm.method(:window) ],
nil
]
+
+ # 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
+ }
+
_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 028f6ac0e7..4e7d8f8579 100644
--- a/ext/tk/lib/tkextlib/iwidgets/hierarchy.rb
+++ b/ext/tk/lib/tkextlib/iwidgets/hierarchy.rb
@@ -30,6 +30,23 @@ class Tk::Iwidgets::Hierarchy
class ValidateArgs < TkUtil::CallbackSubst
KEY_TBL = [ [?n, ?s, :node], nil ]
PROC_TBL = [ [?s, TkComm.method(:string) ], nil ]
+
+ # 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
+ }
+
_setup_subst_table(KEY_TBL, PROC_TBL);
def self.ret_val(val)
@@ -57,6 +74,22 @@ class Tk::Iwidgets::Hierarchy
nil
]
+ # 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
+ }
+
_setup_subst_table(KEY_TBL, PROC_TBL);
def self.ret_val(val)
@@ -78,6 +111,23 @@ class Tk::Iwidgets::Hierarchy
nil
]
PROC_TBL = [ [ ?s, TkComm.method(:string) ], nil ]
+
+ # 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
+ }
+
_setup_subst_table(KEY_TBL, PROC_TBL);
def self.ret_val(val)
diff --git a/ext/tk/lib/tkextlib/iwidgets/scrolledcanvas.rb b/ext/tk/lib/tkextlib/iwidgets/scrolledcanvas.rb
index 407c8f2aad..b07602e340 100644
--- a/ext/tk/lib/tkextlib/iwidgets/scrolledcanvas.rb
+++ b/ext/tk/lib/tkextlib/iwidgets/scrolledcanvas.rb
@@ -171,10 +171,16 @@ class Tk::Iwidgets::Scrolledcanvas
end
def delete(*args)
- if TkcItem::CItemID_TBL[self.path]
+ tbl = nil
+ TkcItem::CItemID_TBL.mutex.synchronize{
+ tbl = TkcItem::CItemID_TBL[self.path]
+ }
+ if tbl
find('withtag', *args).each{|item|
if item.kind_of?(TkcItem)
- TkcItem::CItemID_TBL[self.path].delete(item.id)
+ TkcItem::CItemID_TBL.mutex.synchronize{
+ tbl.delete(item.id)
+ }
end
}
end
diff --git a/ext/tk/lib/tkextlib/iwidgets/spinner.rb b/ext/tk/lib/tkextlib/iwidgets/spinner.rb
index 174b9bd506..126cfe7c95 100644
--- a/ext/tk/lib/tkextlib/iwidgets/spinner.rb
+++ b/ext/tk/lib/tkextlib/iwidgets/spinner.rb
@@ -37,6 +37,23 @@ class Tk::Iwidgets::Spinner
[ ?w, TkComm.method(:window) ],
nil
]
+
+ # 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
+ }
+
_setup_subst_table(KEY_TBL, PROC_TBL);
end
diff --git a/ext/tk/lib/tkextlib/tcllib/ico.rb b/ext/tk/lib/tkextlib/tcllib/ico.rb
index 3beeb11a4d..8c92926a4c 100644
--- a/ext/tk/lib/tkextlib/tcllib/ico.rb
+++ b/ext/tk/lib/tkextlib/tcllib/ico.rb
@@ -94,8 +94,10 @@ class Tk::Tcllib::ICO
if keys.key?('name')
@path = keys['name'].to_s
else
- @path = Tk_Image_ID.join(TkCore::INTERP._ip_id_)
- Tk_Image_ID[1].succ!
+ Tk_Image_ID.mutex.synchronize{
+ @path = Tk_Image_ID.join(TkCore::INTERP._ip_id_)
+ Tk_Image_ID[1].succ!
+ }
end
tk_call_without_enc('::ico::getIcon', file, index, '-name', @path,
'-format', 'image', *hash_kv(keys, true))
diff --git a/ext/tk/lib/tkextlib/tcllib/plotchart.rb b/ext/tk/lib/tkextlib/tcllib/plotchart.rb
index cde42c8a0a..06ab20f3e6 100644
--- a/ext/tk/lib/tkextlib/tcllib/plotchart.rb
+++ b/ext/tk/lib/tkextlib/tcllib/plotchart.rb
@@ -265,7 +265,9 @@ module Tk::Tcllib::Plotchart
private :_create_chart
def __destroy_hook__
- Tk::Tcllib::Plotchart::PlotSeries::SeriesID_TBL.delete(@path)
+ Tk::Tcllib::Plotchart::PlotSeries::SeriesID_TBL.mutex.synchronize{
+ Tk::Tcllib::Plotchart::PlotSeries::SeriesID_TBL.delete(@path)
+ }
end
def plot(series, x, y)
@@ -374,7 +376,9 @@ module Tk::Tcllib::Plotchart
private :_create_chart
def __destroy_hook__
- Tk::Tcllib::Plotchart::PlotSeries::SeriesID_TBL.delete(@path)
+ Tk::Tcllib::Plotchart::PlotSeries::SeriesID_TBL.mutex.synchronize{
+ Tk::Tcllib::Plotchart::PlotSeries::SeriesID_TBL.delete(@path)
+ }
end
def plot(series, radius, angle)
@@ -645,7 +649,9 @@ module Tk::Tcllib::Plotchart
private :_create_chart
def __destroy_hook__
- Tk::Tcllib::Plotchart::PlotSeries::SeriesID_TBL.delete(@path)
+ Tk::Tcllib::Plotchart::PlotSeries::SeriesID_TBL.mutex.synchronize{
+ Tk::Tcllib::Plotchart::PlotSeries::SeriesID_TBL.delete(@path)
+ }
end
def plot(series, dat, col=None)
@@ -834,23 +840,38 @@ module Tk::Tcllib::Plotchart
############################
class PlotSeries < TkObject
SeriesID_TBL = TkCore::INTERP.create_table
- Series_ID = ['series'.freeze, '00000'.taint].freeze
- TkCore::INTERP.init_ip_env{ SeriesID_TBL.clear }
+
+ (Series_ID = ['series'.freeze, '00000'.taint]).instance_eval{
+ @mutex = Mutex.new
+ def mutex; @mutex; end
+ freeze
+ }
+ TkCore::INTERP.init_ip_env{
+ SeriesID_TBL.mutex.synchronize{ SeriesID_TBL.clear }
+ }
def self.id2obj(chart, id)
path = chart.path
- return id unless SeriesID_TBL[path]
- SeriesID_TBL[path][id]? SeriesID_TBL[path][id]: id
+ SeriesID_TBL.mutex.synchronize{
+ if SeriesID_TBL[path]
+ SeriesID_TBL[path][id]? SeriesID_TBL[path][id]: id
+ else
+ id
+ end
+ }
end
def initialize(chart, keys=nil)
@parent = @chart_obj = chart
@ppath = @chart_obj.path
- @path = @series = @id = Series_ID.join(TkCore::INTERP._ip_id_)
- # SeriesID_TBL[@id] = self
- SeriesID_TBL[@ppath] = {} unless SeriesID_TBL[@ppath]
- SeriesID_TBL[@ppath][@id] = self
- Series_ID[1].succ!
+ Series_ID.mutex.synchronize{
+ @path = @series = @id = Series_ID.join(TkCore::INTERP._ip_id_)
+ Series_ID[1].succ!
+ }
+ SeriesID_TBL.mutex.synchronize{
+ SeriesID_TBL[@ppath] ||= {}
+ SeriesID_TBL[@ppath][@id] = self
+ }
dataconfig(keys) if keys.kind_of?(Hash)
end
diff --git a/ext/tk/lib/tkextlib/tcllib/tkpiechart.rb b/ext/tk/lib/tkextlib/tcllib/tkpiechart.rb
index 92dde65ce7..b366e0198b 100644
--- a/ext/tk/lib/tkextlib/tcllib/tkpiechart.rb
+++ b/ext/tk/lib/tkextlib/tcllib/tkpiechart.rb
@@ -125,7 +125,9 @@ module Tk::Tcllib::Tkpiechart
def delete
tk_call_without_enc('::stooop::delete', @tag_key)
- CItemID_TBL[@path].delete(@id) if CItemID_TBL[@path]
+ CItemID_TBL.mutex.synchronize{
+ CItemID_TBL[@path].delete(@id) if CItemID_TBL[@path]
+ }
self
end
@@ -184,8 +186,10 @@ module Tk::Tcllib::Tkpiechart
@id = "slices(#{@tag_key})"
@tag = TkcNamedTag.new(@pie.canvas, @id)
- CItemID_TBL[@path] = {} unless CItemID_TBL[@path]
- CItemID_TBL[@path][@id] = self
+ CItemID_TBL.mutex.synchronize{
+ CItemID_TBL[@path] = {} unless CItemID_TBL[@path]
+ CItemID_TBL[@path][@id] = self
+ }
end
def tag_key
@@ -200,7 +204,9 @@ module Tk::Tcllib::Tkpiechart
def delete
tk_call_without_enc('pie::deleteSlice', @pie.tag_key, @tag_key)
- CItemID_TBL[@path].delete(@id) if CItemID_TBL[@path]
+ CItemID_TBL.mutex.synchronize{
+ CItemID_TBL[@path].delete(@id) if CItemID_TBL[@path]
+ }
@pie._delete_slice(self)
self
end
diff --git a/ext/tk/lib/tkextlib/tile.rb b/ext/tk/lib/tkextlib/tile.rb
index b527935a60..02473d57a1 100644
--- a/ext/tk/lib/tkextlib/tile.rb
+++ b/ext/tk/lib/tkextlib/tile.rb
@@ -18,11 +18,8 @@ require 'tkextlib/tile/setup.rb'
# TkPackage.require('tile', '0.7')
if Tk::TK_MAJOR_VERSION > 8 ||
(Tk::TK_MAJOR_VERSION == 8 && Tk::TK_MINOR_VERSION >= 5)
- begin
- verstr = TkPackage.require('Ttk')
- rescue RuntimeError
- verstr = TkPackage.require('tile')
- end
+ TkPackage.require('tile') # for compatibility (version check of 'tile')
+ verstr = TkPackage.require('Ttk')
else
verstr = TkPackage.require('tile')
end
@@ -101,16 +98,97 @@ module Tk
end
def self.__Import_Tile_Widgets__!
+ warn 'Warning: "Tk::Tile::__Import_Tile_Widgets__!" is obsolete.' <<
+ ' To control default widget set, use "Tk.default_widget_set = :Ttk"'
Tk.tk_call('namespace', 'import', '-force', 'ttk::*')
end
- def self.load_images(imgdir, pat=TkComm::None)
- images = Hash[*TkComm.simplelist(Tk.tk_call('::tile::LoadImages',
- imgdir, pat))]
- images.keys.each{|k|
- images[k] = TkPhotoImage.new(:imagename=>images[k],
- :without_creating=>true)
+ def self.__define_LoadImages_proc_for_compatibility__!
+ # Ttk 8.5 (Tile 0.8) lost 'LoadImages' utility procedure.
+ # So, some old scripts doen't work, because those scripts use the
+ # procedure to define local styles.
+ # Of course, rewriting such Tcl/Tk scripts isn't difficult for
+ # Tcl/Tk users. However, it may be troublesome for Ruby/Tk users
+ # who use such Tcl/Tk scripts as it is.
+ # This method may help Ruby/Tk users who don't want to modify old
+ # Tcl/Tk scripts for the latest version of Ttk (Tile) extension.
+ # This method defines a comaptible 'LoadImages' procedure on the
+ # Tcl/Tk interpreter working under Ruby/Tk.
+ # Please give attention to use this method. It may conflict with
+ # some definitions on Tcl/Tk scripts.
+ klass_name = self.name
+ proc_name = 'LoadImages'
+ if Tk::Tile::USE_TTK_NAMESPACE
+ ns_list = ['::tile']
+ if Tk.info(:commands, "::ttk::#{proc_name}").empty?
+ ns_list << '::ttk'
+ end
+ else # Tk::Tile::USE_TILE_NAMESPACE
+ ns_list = ['::ttk']
+ if Tk.info(:commands, "::tile::#{proc_name}").empty?
+ ns_list << '::tile'
+ end
+ end
+
+ ns_list.each{|ns|
+ cmd = "#{ns}::#{proc_name}"
+ unless Tk.info(:commands, cmd).empty?
+ fail RuntimeError, "can't define '#{cmd}' command (already exist)"
+ end
+ TkNamespace.eval(ns){
+ TkCore::INTERP.add_tk_procs(proc_name, 'imgdir {patterns {*.gif}}',
+ <<-'EOS')
+ foreach pattern $patterns {
+ foreach file [glob -directory $imgdir $pattern] {
+ set img [file tail [file rootname $file]]
+ if {![info exists images($img)]} {
+ set images($img) [image create photo -file $file]
+ }
+ }
+ }
+ return [array get images]
+ EOS
+ }
}
+ end
+
+ def self.load_images(imgdir, pat=nil)
+ if Tk::Tile::TILE_SPEC_VERSION_ID < 8
+ if Tk::Tile::USE_TTK_NAMESPACE
+ cmd = '::ttk::LoadImages'
+ else # Tk::Tile::USE_TILE_NAMESPACE
+ cmd = '::tile::LoadImages'
+ end
+ pat ||= TkComm::None
+ images = Hash[*TkComm.simplelist(Tk.tk_call(cmd, imgdir, pat))]
+ images.keys.each{|k|
+ images[k] = TkPhotoImage.new(:imagename=>images[k],
+ :without_creating=>true)
+ }
+ else ## TILE_SPEC_VERSION_ID >= 8
+ pat ||= '*.gif'
+ if pat.kind_of?(Array)
+ pat_list = pat
+ else
+ pat_list = [ pat ]
+ end
+ Dir.chdir(imgdir){
+ pat_list.each{|pat|
+ Dir.glob(pat).each{|f|
+ img = File.basename(f, '.*')
+ unless TkComm.bool(Tk.info('exists', "images(#{img})"))
+ Tk.tk_call('set', "images(#{img})",
+ Tk.tk_call('image', 'create', 'photo', '-file', f))
+ end
+ }
+ }
+ }
+ images = Hash[*TkComm.simplelist(Tk.tk_call('array', 'get', 'images'))]
+ images.keys.each{|k|
+ images[k] = TkPhotoImage.new(:imagename=>images[k],
+ :without_creating=>true)
+ }
+ end
images
end
@@ -120,11 +198,20 @@ module Tk
end
module KeyNav
- def self.enableMnemonics(w)
- Tk.tk_call('::keynav::enableMnemonics', w)
- end
- def self.defaultButton(w)
- Tk.tk_call('::keynav::defaultButton', w)
+ if Tk::Tile::TILE_SPEC_VERSION_ID < 8
+ def self.enableMnemonics(w)
+ Tk.tk_call('::keynav::enableMnemonics', w)
+ end
+ def self.defaultButton(w)
+ Tk.tk_call('::keynav::defaultButton', w)
+ end
+ else # dummy
+ def self.enableMnemonics(w)
+ ""
+ end
+ def self.defaultButton(w)
+ ""
+ end
end
end
@@ -139,6 +226,12 @@ module Tk
Menu = 'TkMenuFont'
SmallCaption = 'TkSmallCaptionFont'
Icon = 'TkIconFont'
+
+ TkFont::SYSTEM_FONT_NAMES.add [
+ 'TkDefaultFont', 'TkTextFont', 'TkHeadingFont',
+ 'TkCaptionFont', 'TkTooltipFont', 'TkFixedFont',
+ 'TkMenuFont', 'TkSmallCaptionFont', 'TkIconFont'
+ ]
end
module ParseStyleLayout
@@ -177,7 +270,7 @@ module Tk
end
private :__val2ruby_optkeys
- def instate(state, script=nil, &b)
+ def ttk_instate(state, script=nil, &b)
if script
tk_send('instate', state, script)
elsif b
@@ -186,19 +279,30 @@ module Tk
bool(tk_send('instate', state))
end
end
+ alias tile_instate ttk_instate
- def state(state=nil)
+ def ttk_state(state=nil)
if state
tk_send('state', state)
else
list(tk_send('state'))
end
end
+ alias tile_state ttk_state
- def identify(x, y)
+ def ttk_identify(x, y)
ret = tk_send_without_enc('identify', x, y)
(ret.empty?)? nil: ret
end
+ alias tile_identify ttk_identify
+
+ # remove instate/state/identify method
+ # to avoid the conflict with widget options
+ if Tk.const_defined?(:USE_OBSOLETE_TILE_STATE_METHOD) && Tk::USE_OBSOLETE_TILE_STATE_METHOD
+ alias instate ttk_instate
+ alias state ttk_state
+ alias identify ttk_identify
+ end
end
######################################
diff --git a/ext/tk/lib/tkextlib/tile/style.rb b/ext/tk/lib/tkextlib/tile/style.rb
index e01011cb21..bf8acb34b0 100644
--- a/ext/tk/lib/tkextlib/tile/style.rb
+++ b/ext/tk/lib/tkextlib/tile/style.rb
@@ -19,8 +19,93 @@ end
class << Tk::Tile::Style
if Tk::Tile::TILE_SPEC_VERSION_ID < 8
TkCommandNames = ['style'.freeze].freeze
- else
+
+ # --- Tk::Tile::Style.__define_wrapper_proc_for_compatibility__! ---
+ # On Ttk (Tile) extension, 'style' command has imcompatible changes
+ # depend on the version of the extention. It requires modifying the
+ # Tcl/Tk scripts to define local styles. The rule for modification
+ # is a simple one. But, if users want to keep compatibility between
+ # versions of the extension, they will have to contrive to do that.
+ # It may be troublesome, especially for Ruby/Tk users.
+ # This method may help such work. This method make some definitions
+ # on the Tcl/Tk interpreter to work with different version of style
+ # command format. Please give attention to use this method. It may
+ # conflict with some definitions on Tcl/Tk scripts.
+ if Tk::Tile::TILE_SPEC_VERSION_ID < 7
+ def __define_wrapper_proc_for_compatibility__!
+ unless Tk.info(:commands, '::ttk::style').empty?
+ fail RuntimeError,
+ "can't define ':ttk::style' command (already exist)"
+ end
+ TkCore::INTERP.add_tk_procs('::ttk::style', 'args', <<-'EOS')
+ if [string equal [lrange $args 0 1] {element create}] {
+ if [string equal [lindex $args 3] image] {
+ set spec [lindex $args 4]
+ set map [lrange $spec 1 end]
+ if [llength $map] {
+ # return [eval [concat [list ::style element create [lindex $args 2] image [lindex $spec 0] -map $map] [lrange $args 5 end]]]
+ return [uplevel 1 [list ::style element create [lindex $args 2] image [lindex $spec 0] -map $map] [lrange $args 5 end]]
+ }
+ }
+ }
+ # return [eval "::style $args"]
+ return [uplevel 1 ::style $args]
+ EOS
+ #########################
+ end
+ else ### TILE_SPEC_VERSION_ID == 7
+ def __define_wrapper_proc_for_compatibility__!
+ unless Tk.info(:commands, '::ttk::style').empty?
+ fail RuntimeError,
+ "can't define ':ttk::style' command (already exist)"
+ end
+ TkCore::INTERP.add_tk_procs('::ttk::style', 'args', <<-'EOS')
+ if [string equal [lrange $args 0 1] {element create}] {
+ if [string equal [lindex $args 3] image] {
+ set spec [lindex $args 4]
+ set map [lrange $spec 1 end]
+ if [llength $map] {
+ # return [eval [concat [list ::style element create [lindex $args 2] image [lindex $spec 0] -map $map] [lrange $args 5 end]]]
+ return [uplevel 1 [list ::style element create [lindex $args 2] image [lindex $spec 0] -map $map] [lrange $args 5 end]]]
+ }
+ }
+ } elseif [string equal [lindex $args 0] default] {
+ # return [eval "::style [lreplace $args 0 0 configure]"]
+ return [uplevel 1 ::style [lreplace $args 0 0 configure]]
+ }
+ # return [eval "::style $args"]
+ return [uplevel 1 ::style $args]
+ EOS
+ #########################
+ end
+ end
+ else ### TILE_SPEC_VERSION_ID >= 8
TkCommandNames = ['::ttk::style'.freeze].freeze
+
+ def __define_wrapper_proc_for_compatibility__!
+ unless Tk.info(:commands, '::style').empty?
+ fail RuntimeError, "can't define '::style' command (already exist)"
+ end
+ TkCore::INTERP.add_tk_procs('::style', 'args', <<-'EOS')
+ if [string equal [lrange $args 0 1] {element create}] {
+ if [string equal [lindex $args 3] image] {
+ set name [lindex $args 4]
+ set opts [lrange $args 5 end]
+ set idx [lsearch $opts -map]
+ if {$idx >= 0 && [expr $idx % 2 == 0]} {
+ # return [eval [concat [list ::ttk::style element create [lindex $args 2] image [concat $name [lindex $opts [expr $idx + 1]]]] [lreplace $opts $idx [expr $idx + 1]]]]
+ return [uplevel 1 [list ::ttk::style element create [lindex $args 2] image [concat $name [lindex $opts [expr $idx + 1]]]] [lreplace $opts $idx [expr $idx + 1]]]
+ }
+ }
+ } elseif [string equal [lindex $args 0] default] {
+ # return [eval "::ttk::style [lreplace $args 0 0 configure]"]
+ return [uplevel 1 ::ttk::style [lreplace $args 0 0 configure]]
+ }
+ # return [eval "::ttk::style $args"]
+ return [uplevel 1 ::ttk::style $args]
+ EOS
+ #########################
+ end
end
def configure(style=nil, keys=nil)
@@ -98,7 +183,52 @@ class << Tk::Tile::Style
end
def element_create(name, type, *args)
- tk_call(TkCommandNames[0], 'element', 'create', name, type, *args)
+ if type == 'image' || type == :image
+ element_create_image(name, *args)
+ else
+ tk_call(TkCommandNames[0], 'element', 'create', name, type, *args)
+ end
+ end
+
+ def element_create_image(name, *args)
+ fail ArgumentError, 'Must supply a base image' unless (spec = args.shift)
+ if (opts = args.shift)
+ if opts.kind_of?(Hash)
+ opts = _symbolkey2str(opts)
+ else
+ fail ArgumentError, 'bad option'
+ end
+ end
+ fail ArgumentError, 'too many arguments' unless args.empty?
+
+ if spec.kind_of?(Array)
+ # probably, command format is tile 0.8+ (Tcl/Tk8.5+) style
+ if Tk::Tile::TILE_SPEC_VERSION_ID >= 8
+ if opts
+ tk_call(TkCommandNames[0],
+ 'element', 'create', name, 'image', spec, opts)
+ else
+ tk_call(TkCommandNames[0], 'element', 'create', name, 'image', spec)
+ end
+ else
+ fail ArgumentError, 'illegal arguments' if opts.key?('map')
+ base = spec.shift
+ opts['map'] = spec
+ tk_call(TkCommandNames[0],
+ 'element', 'create', name, 'image', base, opts)
+ end
+ else
+ # probably, command format is tile 0.7.8 or older style
+ if Tk::Tile::TILE_SPEC_VERSION_ID >= 8
+ spec = [spec, *(opts.delete('map'))] if opts.key?('map')
+ end
+ if opts
+ tk_call(TkCommandNames[0],
+ 'element', 'create', name, 'image', spec, opts)
+ else
+ tk_call(TkCommandNames[0], 'element', 'create', name, 'image', spec)
+ end
+ end
end
def element_names()
diff --git a/ext/tk/lib/tkextlib/tile/treeview.rb b/ext/tk/lib/tkextlib/tile/treeview.rb
index 36496ee0b9..7f31b9c233 100644
--- a/ext/tk/lib/tkextlib/tile/treeview.rb
+++ b/ext/tk/lib/tkextlib/tile/treeview.rb
@@ -381,7 +381,7 @@ module Tk::Tile::TreeviewConfig
when :item, 'item'
['width']
when :column, 'column'
- super(id[1])
+ super(id[1]) + ['minwidth']
when :tag, 'tag'
super(id[1])
when :heading, 'heading'
@@ -413,7 +413,7 @@ module Tk::Tile::TreeviewConfig
when :item, 'item'
['open']
when :column, 'column'
- super(id[1])
+ super(id[1]) + ['stretch']
when :tag, 'tag'
super(id[1])
when :heading, 'heading'
@@ -617,30 +617,43 @@ end
class Tk::Tile::Treeview::Item < TkObject
ItemID_TBL = TkCore::INTERP.create_table
- TkCore::INTERP.init_ip_env{ Tk::Tile::Treeview::Item::ItemID_TBL.clear }
+
+ TkCore::INTERP.init_ip_env{
+ Tk::Tile::Treeview::Item::ItemID_TBL.mutex.synchronize{
+ Tk::Tile::Treeview::Item::ItemID_TBL.clear
+ }
+ }
def self.id2obj(tree, id)
tpath = tree.path
- return id unless Tk::Tile::Treeview::Item::ItemID_TBL[tpath]
- (Tk::Tile::Treeview::Item::ItemID_TBL[tpath][id])? \
- Tk::Tile::Treeview::Item::ItemID_TBL[tpath][id]: id
+ Tk::Tile::Treeview::Item::ItemID_TBL.mutex.synchronize{
+ if Tk::Tile::Treeview::Item::ItemID_TBL[tpath]
+ (Tk::Tile::Treeview::Item::ItemID_TBL[tpath][id])? \
+ Tk::Tile::Treeview::Item::ItemID_TBL[tpath][id]: id
+ else
+ id
+ end
+ }
end
def self.assign(tree, id)
tpath = tree.path
- if Tk::Tile::Treeview::Item::ItemID_TBL[tpath] &&
- Tk::Tile::Treeview::Item::ItemID_TBL[tpath][id]
- return Tk::Tile::Treeview::Item::ItemID_TBL[tpath][id]
- end
+ obj = nil
+ Tk::Tile::Treeview::Item::ItemID_TBL.mutex.synchronize{
+ if Tk::Tile::Treeview::Item::ItemID_TBL[tpath] &&
+ Tk::Tile::Treeview::Item::ItemID_TBL[tpath][id]
+ return Tk::Tile::Treeview::Item::ItemID_TBL[tpath][id]
+ end
- obj = self.allocate
- obj.instance_eval{
- @parent = @t = tree
- @tpath = tpath
- @path = @id = id
+ obj = self.allocate
+ obj.instance_eval{
+ @parent = @t = tree
+ @tpath = tpath
+ @path = @id = id
+ }
+ Tk::Tile::Treeview::Item::ItemID_TBL[tpath] ||= {}
+ Tk::Tile::Treeview::Item::ItemID_TBL[tpath][id] = obj
}
- ItemID_TBL[tpath] = {} unless ItemID_TBL[tpath]
- Tk::Tile::Treeview::Item::ItemID_TBL[tpath][id] = obj
obj
end
@@ -669,8 +682,10 @@ class Tk::Tile::Treeview::Item < TkObject
@parent = @t = tree
@tpath = tree.path
@path = @id = _insert_item(@t, parent_item, idx, keys)
- ItemID_TBL[@tpath] = {} unless ItemID_TBL[@tpath]
- ItemID_TBL[@tpath][@id] = self
+ Tk::Tile::Treeview::Item::ItemID_TBL.mutex.synchronize{
+ ItemID_TBL[@tpath] = {} unless ItemID_TBL[@tpath]
+ ItemID_TBL[@tpath][@id] = self
+ }
end
def id
@id
@@ -804,22 +819,35 @@ end
class Tk::Tile::Treeview::Root < Tk::Tile::Treeview::Item
def self.new(tree, keys = {})
tpath = tree.path
- if Tk::Tile::Treeview::Item::ItemID_TBL[tpath] &&
- Tk::Tile::Treeview::Item::ItemID_TBL[tpath]['']
- Tk::Tile::Treeview::Item::ItemID_TBL[tpath]['']
- else
- super(tree, keys)
- end
+ obj = nil
+ Tk::Tile::Treeview::Item::ItemID_TBL.mutex.synchronize{
+ if Tk::Tile::Treeview::Item::ItemID_TBL[tpath] &&
+ Tk::Tile::Treeview::Item::ItemID_TBL[tpath]['']
+ obj = Tk::Tile::Treeview::Item::ItemID_TBL[tpath]['']
+ else
+ #super(tree, keys)
+ (obj = self.allocate).instance_eval{
+ @parent = @t = tree
+ @tpath = tree.path
+ @path = @id = ''
+ Tk::Tile::Treeview::Item::ItemID_TBL[@tpath] ||= {}
+ Tk::Tile::Treeview::Item::ItemID_TBL[@tpath][@id] = self
+ }
+ end
+ }
+ obj.configure(keys) if keys && ! keys.empty?
+ obj
end
def initialize(tree, keys = {})
+ # dummy:: not called by 'new' method
@parent = @t = tree
@tpath = tree.path
@path = @id = ''
- unless Tk::Tile::Treeview::Item::ItemID_TBL[@tpath]
- Tk::Tile::Treeview::Item::ItemID_TBL[@tpath] = {}
- end
- Tk::Tile::Treeview::Item::ItemID_TBL[@tpath][@id] = self
+ Tk::Tile::Treeview::Item::ItemID_TBL.mutex.synchronize{
+ Tk::Tile::Treeview::Item::ItemID_TBL[@tpath] ||= {}
+ Tk::Tile::Treeview::Item::ItemID_TBL[@tpath][@id] = self
+ }
end
end
@@ -829,24 +857,42 @@ class Tk::Tile::Treeview::Tag < TkObject
include TkTreatTagFont
TagID_TBL = TkCore::INTERP.create_table
- Tag_ID = ['tile_treeview_tag'.freeze, '00000'.taint].freeze
- TkCore::INTERP.init_ip_env{ Tk::Tile::Treeview::Tag::TagID_TBL.clear }
+ (Tag_ID = ['tile_treeview_tag'.freeze, '00000'.taint]).instance_eval{
+ @mutex = Mutex.new
+ def mutex; @mutex; end
+ freeze
+ }
+
+ TkCore::INTERP.init_ip_env{
+ Tk::Tile::Treeview::Tag::TagID_TBL.mutex.synchronize{
+ Tk::Tile::Treeview::Tag::TagID_TBL.clear
+ }
+ }
def self.id2obj(tree, id)
tpath = tree.path
- return id unless Tk::Tile::Treeview::Tag::TagID_TBL[tpath]
- (Tk::Tile::Treeview::Tag::TagID_TBL[tpath][id])? \
- Tk::Tile::Treeview::Tag::TagID_TBL[tpath][id]: id
+ Tk::Tile::Treeview::Tag::TagID_TBL.mutex.synchronize{
+ if Tk::Tile::Treeview::Tag::TagID_TBL[tpath]
+ (Tk::Tile::Treeview::Tag::TagID_TBL[tpath][id])? \
+ Tk::Tile::Treeview::Tag::TagID_TBL[tpath][id]: id
+ else
+ id
+ end
+ }
end
def initialize(tree, keys=nil)
@parent = @t = tree
@tpath = tree.path
- @path = @id = Tag_ID.join(TkCore::INTERP._ip_id_)
- TagID_TBL[@tpath] = {} unless TagID_TBL[@tpath]
- TagID_TBL[@tpath][@id] = self
- Tag_ID[1].succ!
+ Tag_ID.mutex.synchronize{
+ @path = @id = Tag_ID.join(TkCore::INTERP._ip_id_)
+ Tag_ID[1].succ!
+ }
+ TagID_TBL.mutex.synchronize{
+ TagID_TBL[@tpath] = {} unless TagID_TBL[@tpath]
+ TagID_TBL[@tpath][@id] = self
+ }
if keys && keys != None
tk_call_without_enc(@tpath, 'tag', 'configure', *hash_kv(keys, true))
end
@@ -919,8 +965,12 @@ class Tk::Tile::Treeview < TkWindow
WidgetClassNames[WidgetClassName] = self
def __destroy_hook__
- Tk::Tile::Treeview::Item::ItemID_TBL.delete(@path)
- Tk::Tile::Treeview::Tag::ItemID_TBL.delete(@path)
+ Tk::Tile::Treeview::Item::ItemID_TBL.mutex.synchronize{
+ Tk::Tile::Treeview::Item::ItemID_TBL.delete(@path)
+ }
+ Tk::Tile::Treeview::Tag::ItemID_TBL.mutex.synchronize{
+ Tk::Tile::Treeview::Tag::ItemID_TBL.delete(@path)
+ }
end
def self.style(*args)
diff --git a/ext/tk/lib/tkextlib/tkDND/tkdnd.rb b/ext/tk/lib/tkextlib/tkDND/tkdnd.rb
index a040532eb6..ea91d3d1f4 100644
--- a/ext/tk/lib/tkextlib/tkDND/tkdnd.rb
+++ b/ext/tk/lib/tkextlib/tkDND/tkdnd.rb
@@ -57,6 +57,22 @@ module Tk
nil
]
+ # 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
+ }
+
# setup tables
_setup_subst_table(KEY_TBL, PROC_TBL);
end
diff --git a/ext/tk/lib/tkextlib/tkHTML/htmlwidget.rb b/ext/tk/lib/tkextlib/tkHTML/htmlwidget.rb
index 8527f61df1..d893a83cf2 100644
--- a/ext/tk/lib/tkextlib/tkHTML/htmlwidget.rb
+++ b/ext/tk/lib/tkextlib/tkHTML/htmlwidget.rb
@@ -39,7 +39,10 @@ class Tk::HTML_Widget::ClippingWindow
WidgetClassNames[WidgetClassName] = self
HtmlClip_TBL = TkCore::INTERP.create_table
- TkCore::INTERP.init_ip_env{ HtmlClip_TBL.clear }
+
+ TkCore::INTERP.init_ip_env{
+ HtmlClip_TBL.mutex.synchronize{ HtmlClip_TBL.clear }
+ }
def self.new(parent, keys={})
if parent.kind_of?(Hash)
@@ -54,7 +57,9 @@ class Tk::HTML_Widget::ClippingWindow
else
ppath = ''
end
- return HtmlClip_TBL[ppath] if HtmlClip_TBL[ppath]
+ HtmlClip_TBL.mutex.synchronize{
+ return HtmlClip_TBL[ppath] if HtmlClip_TBL[ppath]
+ }
widgetname = keys.delete('widgetname')
if widgetname =~ /^(.*)\.[^.]+$/
@@ -62,7 +67,9 @@ class Tk::HTML_Widget::ClippingWindow
if ppath2[0] != ?.
ppath2 = ppath + '.' + ppath2
end
- return HtmlClip_TBL[ppath2] if HtmlClip_TBL[ppath2]
+ HtmlClip_TBL.mutex.synchronize{
+ return HtmlClip_TBL[ppath2] if HtmlClip_TBL[ppath2]
+ }
ppath = ppath2
end
@@ -79,7 +86,9 @@ class Tk::HTML_Widget::ClippingWindow
@parent = parent
@ppath = parent.path
@path = @id = @ppath + '.x'
- HtmlClip_TBL[@ppath] = self
+ HtmlClip_TBL.mutex.synchronize{
+ HtmlClip_TBL[@ppath] = self
+ }
end
def method_missing(m, *args, &b)
diff --git a/ext/tk/lib/tkextlib/tktable/tktable.rb b/ext/tk/lib/tkextlib/tktable/tktable.rb
index 4edaabc847..fb8a8b0f72 100644
--- a/ext/tk/lib/tkextlib/tktable/tktable.rb
+++ b/ext/tk/lib/tkextlib/tktable/tktable.rb
@@ -118,23 +118,39 @@ class Tk::TkTable::CellTag
include TkTreatTagFont
CellTagID_TBL = TkCore::INTERP.create_table
- CellTag_ID = ['tktbl:celltag'.freeze, '00000'.taint].freeze
- TkCore::INTERP.init_ip_env{ CellTagID_TBL.clear }
+ (CellTag_ID = ['tktbl:celltag'.freeze, '00000'.taint]).instance_eval{
+ @mutex = Mutex.new
+ def mutex; @mutex; end
+ freeze
+ }
+
+ TkCore::INTERP.init_ip_env{
+ CellTagID_TBL.mutex.synchronize{ CellTagID_TBL.clear }
+ }
def self.id2obj(table, id)
tpath = table.path
- return id unless CellTagID_TBL[tpath]
- CellTagID_TBL[tpath][id]? CellTagID_TBL[tpath][id] : id
+ CellTagID_TBL.mutex.synchronize{
+ if CellTagID_TBL[tpath]
+ CellTagID_TBL[tpath][id]? CellTagID_TBL[tpath][id] : id
+ else
+ id
+ end
+ }
end
def initialize(parent, keys=nil)
@parent = @t = parent
@tpath - parent.path
- @path = @id = CellTag_ID.join(TkCore::INTERP._ip_id_)
- CellTagID_TBL[@tpath] = {} unless CellTagID_TBL[@tpath]
- CellTagID_TBL[@tpath][@id] = self
- CellTag_ID[1].succ!
+ CellTag_ID.mutex.synchronize{
+ @path = @id = CellTag_ID.join(TkCore::INTERP._ip_id_)
+ CellTag_ID[1].succ!
+ }
+ CellTagID_TBL.mutex.synchronize{
+ CellTagID_TBL[@tpath] = {} unless CellTagID_TBL[@tpath]
+ CellTagID_TBL[@tpath][@id] = self
+ }
configure(keys) if keys
end
@@ -144,7 +160,9 @@ class Tk::TkTable::CellTag
def destroy
tk_call(@tpath, 'tag', 'delete', @id)
- CellTagID_TBL[@tpath].delete(@id) if CellTagID_TBL[@tpath]
+ CellTagID_TBL.mutex.synchronize{
+ CellTagID_TBL[@tpath].delete(@id) if CellTagID_TBL[@tpath]
+ }
self
end
alias delete destroy
@@ -189,22 +207,35 @@ end
class Tk::TkTable::NamedCellTag < Tk::TkTable::CellTag
def self.new(parent, name, keys=nil)
- if CellTagID_TBL[parent.path] && CellTagID_TBL[parent.path][name]
- cell = CellTagID_TBL[parent.path][name]
- cell.configure(keys) if keys
- return cell
- else
- super(parent, name, keys)
- end
+ obj = nil
+ CellTagID_TBL.mutex.synchronize{
+ if CellTagID_TBL[parent.path] && CellTagID_TBL[parent.path][name]
+ obj = CellTagID_TBL[parent.path][name]
+ else
+ #super(parent, name, keys)
+ (obj = self.allocate).instance_eval{
+ @parent = @t = parent
+ @tpath = parent.path
+ @path = @id = name
+ CellTagID_TBL[@tpath] = {} unless CellTagID_TBL[@tpath]
+ CellTagID_TBL[@tpath][@id] = self
+ }
+ end
+ }
+ obj.configure(keys) if keys && ! keys.empty?
+ obj
end
def initialize(parent, name, keys=nil)
+ # dummy:: not called by 'new' method
@parent = @t = parent
- @tpath - parent.path
+ @tpath = parent.path
@path = @id = name
- CellTagID_TBL[@tpath] = {} unless CellTagID_TBL[@tpath]
- CellTagID_TBL[@tpath][@id] = self
- configure(keys) if keys
+ CellTagID_TBL.mutex.synchronize{
+ CellTagID_TBL[@tpath] = {} unless CellTagID_TBL[@tpath]
+ CellTagID_TBL[@tpath][@id] = self
+ }
+ configure(keys) if keys && ! keys.empty?
end
end
@@ -220,7 +251,9 @@ class Tk::TkTable
include Tk::ValidateConfigure
def __destroy_hook__
- Tk::TkTable::CelTag::CellTagID_TBL.delete(@path)
+ Tk::TkTable::CelTag::CellTagID_TBL.mutex.synchronize{
+ Tk::TkTable::CelTag::CellTagID_TBL.delete(@path)
+ }
end
def __boolval_optkeys
@@ -258,6 +291,22 @@ class Tk::TkTable
nil
]
+ # 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
+ }
+
_setup_subst_table(KEY_TBL, PROC_TBL);
def self.ret_val(val)
@@ -291,6 +340,22 @@ class Tk::TkTable
nil
]
+ # 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
+ }
+
_setup_subst_table(KEY_TBL, PROC_TBL);
def self.ret_val(val)
@@ -322,6 +387,22 @@ class Tk::TkTable
nil
]
+ # 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
+ }
+
_setup_subst_table(KEY_TBL, PROC_TBL);
def self.ret_val(val)
@@ -356,6 +437,22 @@ class Tk::TkTable
nil
]
+ # 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
+ }
+
_setup_subst_table(KEY_TBL, PROC_TBL);
end
@@ -746,15 +843,17 @@ class Tk::TkTable
end
def tagid2obj(tagid)
- if Tk::TkTable::CellTag::CellTagID_TBL.key?(@path)
- if Tk::TkTable::CellTag::CellTagID_TBL[@path].key?(tagid)
- Tk::TkTable::CellTag::CellTagID_TBL[@path][tagid]
+ Tk::TkTable::CellTag::CellTagID_TBL.mutex.synchronize{
+ if Tk::TkTable::CellTag::CellTagID_TBL.key?(@path)
+ if Tk::TkTable::CellTag::CellTagID_TBL[@path].key?(tagid)
+ Tk::TkTable::CellTag::CellTagID_TBL[@path][tagid]
+ else
+ tagid
+ end
else
tagid
end
- else
- tagid
- end
+ }
end
def tag_cell(tag, *cells)
@@ -775,13 +874,15 @@ class Tk::TkTable
end
def tag_delete(tag)
tk_send('tag', 'delete', tagid(tag))
- if Tk::TkTable::CellTag::CellTagID_TBL[@path]
- if tag.kind_of? Tk::TkTable::CellTag
- Tk::TkTable::CellTag::CellTagID_TBL[@path].delete(tag.id)
- else
- Tk::TkTable::CellTag::CellTagID_TBL[@path].delete(tag)
+ Tk::TkTable::CellTag::CellTagID_TBL.mutex.synchronize{
+ if Tk::TkTable::CellTag::CellTagID_TBL[@path]
+ if tag.kind_of? Tk::TkTable::CellTag
+ Tk::TkTable::CellTag::CellTagID_TBL[@path].delete(tag.id)
+ else
+ Tk::TkTable::CellTag::CellTagID_TBL[@path].delete(tag)
+ end
end
- end
+ }
self
end
def tag_exist?(tag)
diff --git a/ext/tk/lib/tkextlib/treectrl/tktreectrl.rb b/ext/tk/lib/tkextlib/treectrl/tktreectrl.rb
index 12f7cffabf..b72b157dcd 100644
--- a/ext/tk/lib/tkextlib/treectrl/tktreectrl.rb
+++ b/ext/tk/lib/tkextlib/treectrl/tktreectrl.rb
@@ -137,6 +137,22 @@ class Tk::TreeCtrl::NotifyEvent
nil
]
+ # 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
+ }
+
# 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
@@ -544,10 +560,18 @@ class Tk::TreeCtrl
#########################
def __destroy_hook__
- Tk::TreeCtrl::Column::TreeCtrlColumnID_TBL.delete(@path)
- Tk::TreeCtrl::Element::TreeCtrlElementID_TBL.delete(@path)
- Tk::TreeCtrl::Item::TreeCtrlItemID_TBL.delete(@path)
- Tk::TreeCtrl::Style::TreeCtrlStyleID_TBL.delete(@path)
+ Tk::TreeCtrl::Column::TreeCtrlColumnID_TBL.mutex.synchronize{
+ Tk::TreeCtrl::Column::TreeCtrlColumnID_TBL.delete(@path)
+ }
+ Tk::TreeCtrl::Element::TreeCtrlElementID_TBL.mutex.synchronize{
+ Tk::TreeCtrl::Element::TreeCtrlElementID_TBL.delete(@path)
+ }
+ Tk::TreeCtrl::Item::TreeCtrlItemID_TBL.mutex.synchronize{
+ Tk::TreeCtrl::Item::TreeCtrlItemID_TBL.delete(@path)
+ }
+ Tk::TreeCtrl::Style::TreeCtrlStyleID_TBL.mutex.synchronize{
+ Tk::TreeCtrl::Style::TreeCtrlStyleID_TBL.delete(@path)
+ }
end
#########################
@@ -638,9 +662,11 @@ class Tk::TreeCtrl
end
def column_delete(idx)
- if Tk::TreeCtrl::Column::TreeCtrlColumnID_TBL[self.path]
- Tk::TreeCtrl::Column::TreeCtrlColumnID_TBL[self.path].delete(idx)
- end
+ Tk::TreeCtrl::Column::TreeCtrlColumnID_TBL.mutex.synchronize{
+ if Tk::TreeCtrl::Column::TreeCtrlColumnID_TBL[self.path]
+ Tk::TreeCtrl::Column::TreeCtrlColumnID_TBL[self.path].delete(idx)
+ end
+ }
tk_send('column', 'delete', idx)
self
end
@@ -750,11 +776,13 @@ class Tk::TreeCtrl
end
def element_delete(*elems)
- if Tk::TreeCtrl::Element::TreeCtrlElementID_TBL[self.path]
- elems.each{|elem|
- Tk::TreeCtrl::Element::TreeCtrlElementID_TBL[self.path].delete(elem)
- }
- end
+ Tk::TreeCtrl::Element::TreeCtrlElementID_TBL.mutex.synchronize{
+ if Tk::TreeCtrl::Element::TreeCtrlElementID_TBL[self.path]
+ elems.each{|elem|
+ Tk::TreeCtrl::Element::TreeCtrlElementID_TBL[self.path].delete(elem)
+ }
+ end
+ }
tk_send('element', 'delete', *elems)
self
end
@@ -885,22 +913,25 @@ class Tk::TreeCtrl
def _erase_children(item)
item_children(item).each{|i| _erase_children(i)}
+ # table is already locked
Tk::TreeCtrl::Item::TreeCtrlItemID_TBL[self.path].delete(item)
end
private :_erase_children
def item_delete(first, last=None)
- if Tk::TreeCtrl::Item::TreeCtrlItemID_TBL[self.path]
- if first == 'all' || first == :all || last == 'all' || last == :all
- Tk::TreeCtrl::Item::TreeCtrlItemID_TBL[self.path].clear
- elsif last == None
- _erase_children(first)
- else
- self.range(first, last).each{|id|
- _erase_children(id)
- }
+ Tk::TreeCtrl::Item::TreeCtrlItemID_TBL.mutex.synchronize{
+ if Tk::TreeCtrl::Item::TreeCtrlItemID_TBL[self.path]
+ if first == 'all' || first == :all || last == 'all' || last == :all
+ Tk::TreeCtrl::Item::TreeCtrlItemID_TBL[self.path].clear
+ elsif last == None
+ _erase_children(first)
+ else
+ self.range(first, last).each{|id|
+ _erase_children(id)
+ }
+ end
end
- end
+ }
tk_send('item', 'delete', first, last)
self
end
@@ -1520,11 +1551,13 @@ class Tk::TreeCtrl
end
def style_delete(*args)
- if Tk::TreeCtrl::Style::TreeCtrlStyleID_TBL[self.path]
- args.each{|sty|
- Tk::TreeCtrl::Style::TreeCtrlStyleID_TBL[self.path].delete(sty)
- }
- end
+ Tk::TreeCtrl::Style::TreeCtrlStyleID_TBL.mutex.synchronize{
+ if Tk::TreeCtrl::Style::TreeCtrlStyleID_TBL[self.path]
+ args.each{|sty|
+ Tk::TreeCtrl::Style::TreeCtrlStyleID_TBL[self.path].delete(sty)
+ }
+ end
+ }
tk_send('style', 'delete', *args)
self
end
@@ -1608,15 +1641,29 @@ end
class Tk::TreeCtrl::Column < TkObject
TreeCtrlColumnID_TBL = TkCore::INTERP.create_table
- TreeCtrlColumnID = ['treectrl_column'.freeze, '00000'.taint].freeze
- TkCore::INTERP.init_ip_env{Tk::TreeCtrl::Column::TreeCtrlColumnID_TBL.clear}
+ (TreeCtrlColumnID = ['treectrl_column'.freeze, '00000'.taint]).instance_eval{
+ @mutex = Mutex.new
+ def mutex; @mutex; end
+ freeze
+ }
+
+ TkCore::INTERP.init_ip_env{
+ Tk::TreeCtrl::Column::TreeCtrlColumnID_TBL.mutex.synchronize{
+ Tk::TreeCtrl::Column::TreeCtrlColumnID_TBL.clear
+ }
+ }
def self.id2obj(tree, id)
tpath = tree.path
- return id unless Tk::TreeCtrl::Column::TreeCtrlColumnID_TBL[tpath]
- Tk::TreeCtrl::Column::TreeCtrlColumnID_TBL[tpath][id]? \
- Tk::TreeCtrl::Column::TreeCtrlColumnID_TBL[tpath][id] : id
+ Tk::TreeCtrl::Column::TreeCtrlColumnID_TBL.mutex.synchronize{
+ if Tk::TreeCtrl::Column::TreeCtrlColumnID_TBL[tpath]
+ Tk::TreeCtrl::Column::TreeCtrlColumnID_TBL[tpath][id]? \
+ Tk::TreeCtrl::Column::TreeCtrlColumnID_TBL[tpath][id] : id
+ else
+ id
+ end
+ }
end
def initialize(parent, keys={})
@@ -1625,17 +1672,19 @@ class Tk::TreeCtrl::Column < TkObject
keys = _symbolkey2str(keys)
- @path = @id =
- keys.delete('tag') ||
- Tk::TreeCtrl::Column::TreeCtrlColumnID.join(TkCore::INTERP._ip_id_)
+ Tk::TreeCtrl::Column::TreeCtrlColumnID.mutex.synchronize{
+ @path = @id =
+ keys.delete('tag') ||
+ Tk::TreeCtrl::Column::TreeCtrlColumnID.join(TkCore::INTERP._ip_id_)
+ Tk::TreeCtrl::Column::TreeCtrlColumnID[1].succ!
+ }
keys['tag'] = @id
- unless Tk::TreeCtrl::Column::TreeCtrlColumnID_TBL[@tpath]
- Tk::TreeCtrl::Column::TreeCtrlColumnID_TBL[@tpath] = {}
- end
- Tk::TreeCtrl::Column::TreeCtrlColumnID_TBL[@tpath][@id] = self
- Tk::TreeCtrl::Column::TreeCtrlColumnID[1].succ!
+ Tk::TreeCtrl::Column::TreeCtrlColumnID_TBL.mutex.synchronize{
+ Tk::TreeCtrl::Column::TreeCtrlColumnID_TBL[@tpath] ||= {}
+ Tk::TreeCtrl::Column::TreeCtrlColumnID_TBL[@tpath][@id] = self
+ }
@tree.column_create(keys)
end
@@ -1692,11 +1741,18 @@ end
class Tk::TreeCtrl::Element < TkObject
TreeCtrlElementID_TBL = TkCore::INTERP.create_table
- TreeCtrlElementID = ['treectrl_element'.freeze, '00000'.taint].freeze
+
+ (TreeCtrlElementID = ['treectrl_element'.freeze, '00000'.taint]).instance_eval{
+ @mutex = Mutex.new
+ def mutex; @mutex; end
+ freeze
+ }
TreeCtrlElemTypeToClass = {}
TkCore::INTERP.init_ip_env{
- Tk::TreeCtrl::Element::TreeCtrlElementID_TBL.clear
+ Tk::TreeCtrl::Element::TreeCtrlElementID_TBL.mutex.synchronize{
+ Tk::TreeCtrl::Element::TreeCtrlElementID_TBL.clear
+ }
}
def self.type2class(type)
@@ -1705,22 +1761,30 @@ class Tk::TreeCtrl::Element < TkObject
def self.id2obj(tree, id)
tpath = tree.path
- return id unless Tk::TreeCtrl::Element::TreeCtrlElementID_TBL[tpath]
- Tk::TreeCtrl::Element::TreeCtrlElementID_TBL[tpath][id]? \
+ Tk::TreeCtrl::Element::TreeCtrlElementID_TBL.mutex.synchronize{
+ if Tk::TreeCtrl::Element::TreeCtrlElementID_TBL[tpath]
+ Tk::TreeCtrl::Element::TreeCtrlElementID_TBL[tpath][id]? \
Tk::TreeCtrl::Element::TreeCtrlElementID_TBL[tpath][id] : id
+ else
+ id
+ end
+ }
end
def initialize(parent, type, keys=nil)
@tree = parent
@tpath = parent.path
@type = type.to_s
- @path = @id =
- Tk::TreeCtrl::Element::TreeCtrlElementID.join(TkCore::INTERP._ip_id_)
- unless Tk::TreeCtrl::Element::TreeCtrlElementID_TBL[@tpath]
- Tk::TreeCtrl::Element::TreeCtrlElementID_TBL[@tpath] = {}
- end
- Tk::TreeCtrl::Element::TreeCtrlElementID_TBL[@tpath][@id] = self
- Tk::TreeCtrl::Element::TreeCtrlElementID[1].succ!
+ Tk::TreeCtrl::Element::TreeCtrlElementID.mutex.synchronize{
+ @path = @id =
+ Tk::TreeCtrl::Element::TreeCtrlElementID.join(TkCore::INTERP._ip_id_)
+ Tk::TreeCtrl::Element::TreeCtrlElementID[1].succ!
+ }
+
+ Tk::TreeCtrl::Element::TreeCtrlElementID_TBL.mutex.synchronize{
+ Tk::TreeCtrl::Element::TreeCtrlElementID_TBL[@tpath] ||= {}
+ Tk::TreeCtrl::Element::TreeCtrlElementID_TBL[@tpath][@id] = self
+ }
@tree.element_create(@id, @type, keys)
end
@@ -1800,13 +1864,22 @@ end
class Tk::TreeCtrl::Item < TkObject
TreeCtrlItemID_TBL = TkCore::INTERP.create_table
- TkCore::INTERP.init_ip_env{Tk::TreeCtrl::Item::TreeCtrlItemID_TBL.clear}
+ TkCore::INTERP.init_ip_env{
+ Tk::TreeCtrl::Item::TreeCtrlItemID_TBL.mutex.synchronize{
+ Tk::TreeCtrl::Item::TreeCtrlItemID_TBL.clear
+ }
+ }
def self.id2obj(tree, id)
tpath = tree.path
- return id unless Tk::TreeCtrl::Item::TreeCtrlItemID_TBL[tpath]
- Tk::TreeCtrl::Item::TreeCtrlItemID_TBL[tpath][id]? \
- Tk::TreeCtrl::Item::TreeCtrlItemID_TBL[tpath][id] : id
+ Tk::TreeCtrl::Item::TreeCtrlItemID_TBL.mutex.synchronize{
+ if Tk::TreeCtrl::Item::TreeCtrlItemID_TBL[tpath]
+ Tk::TreeCtrl::Item::TreeCtrlItemID_TBL[tpath][id]? \
+ Tk::TreeCtrl::Item::TreeCtrlItemID_TBL[tpath][id] : id
+ else
+ id
+ end
+ }
end
def initialize(parent, keys={})
@@ -1814,10 +1887,10 @@ class Tk::TreeCtrl::Item < TkObject
@tpath = parent.path
@path = @id = @tree.item_create(keys)
- unless Tk::TreeCtrl::Item::TreeCtrlItemID_TBL[@tpath]
- Tk::TreeCtrl::Item::TreeCtrlItemID_TBL[@tpath] = {}
- end
- Tk::TreeCtrl::Item::TreeCtrlItemID_TBL[@tpath][@id] = self
+ Tk::TreeCtrl::Item::TreeCtrlItemID_TBL.mutex.synchronize{
+ Tk::TreeCtrl::Item::TreeCtrlItemID_TBL[@tpath] ||= {}
+ Tk::TreeCtrl::Item::TreeCtrlItemID_TBL[@tpath][@id] = self
+ }
end
def id
@@ -2088,27 +2161,45 @@ end
class Tk::TreeCtrl::Style < TkObject
TreeCtrlStyleID_TBL = TkCore::INTERP.create_table
- TreeCtrlStyleID = ['treectrl_style'.freeze, '00000'.taint].freeze
- TkCore::INTERP.init_ip_env{ Tk::TreeCtrl::Style::TreeCtrlStyleID_TBL.clear }
+ (TreeCtrlStyleID = ['treectrl_style'.freeze, '00000'.taint]).instance_eval{
+ @mutex = Mutex.new
+ def mutex; @mutex; end
+ freeze
+ }
+
+ TkCore::INTERP.init_ip_env{
+ Tk::TreeCtrl::Style::TreeCtrlStyleID_TBL.mutex.synchronize{
+ Tk::TreeCtrl::Style::TreeCtrlStyleID_TBL.clear
+ }
+ }
def self.id2obj(tree, id)
tpath = tree.path
- return id unless Tk::TreeCtrl::Style::TreeCtrlStyleID_TBL[tpath]
- Tk::TreeCtrl::Style::TreeCtrlStyleID_TBL[tpath][id]? \
- Tk::TreeCtrl::Style::TreeCtrlStyleID_TBL[tpath][id] : id
+ Tk::TreeCtrl::Style::TreeCtrlStyleID_TBL.mutex.synchronize{
+ if Tk::TreeCtrl::Style::TreeCtrlStyleID_TBL[tpath]
+ Tk::TreeCtrl::Style::TreeCtrlStyleID_TBL[tpath][id]? \
+ Tk::TreeCtrl::Style::TreeCtrlStyleID_TBL[tpath][id] : id
+ else
+ id
+ end
+ }
end
def initialize(parent, keys=nil)
@tree = parent
@tpath = parent.path
- @path = @id =
- Tk::TreeCtrl::Style::TreeCtrlStyleID.join(TkCore::INTERP._ip_id_)
- unless Tk::TreeCtrl::Style::TreeCtrlStyleID_TBL[@tpath]
- Tk::TreeCtrl::Style::TreeCtrlStyleID_TBL[@tpath] = {}
- end
- Tk::TreeCtrl::Style::TreeCtrlStyleID_TBL[@tpath][@id] = self
- Tk::TreeCtrl::Style::TreeCtrlStyleID[1].succ!
+
+ Tk::TreeCtrl::Style::TreeCtrlStyleID.mutex.synchronize{
+ @path = @id =
+ Tk::TreeCtrl::Style::TreeCtrlStyleID.join(TkCore::INTERP._ip_id_)
+ Tk::TreeCtrl::Style::TreeCtrlStyleID[1].succ!
+ }
+
+ Tk::TreeCtrl::Style::TreeCtrlStyleID_TBL.mutex.synchronize{
+ Tk::TreeCtrl::Style::TreeCtrlStyleID_TBL[@tpath] ||= {}
+ Tk::TreeCtrl::Style::TreeCtrlStyleID_TBL[@tpath][@id] = self
+ }
@tree.style_create(@id, keys)
end
diff --git a/ext/tk/lib/tkextlib/version.rb b/ext/tk/lib/tkextlib/version.rb
index c7816fd4a5..3542c79dbe 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 = '2007-05-26'.freeze
+ Tkextlib_RELEASE_DATE = '2008-03-29'.freeze
end
diff --git a/ext/tk/lib/tkextlib/vu/pie.rb b/ext/tk/lib/tkextlib/vu/pie.rb
index 78f3fa54da..1975803db1 100644
--- a/ext/tk/lib/tkextlib/vu/pie.rb
+++ b/ext/tk/lib/tkextlib/vu/pie.rb
@@ -116,13 +116,26 @@ end
class Tk::Vu::PieSlice
SliceID_TBL = TkCore::INTERP.create_table
- Pie_Slice_ID = ['vu:pie'.freeze, '00000'.taint].freeze
- TkCore::INTERP.init_ip_env{ SliceID_TBL.clear }
+
+ (Pie_Slice_ID = ['vu:pie'.freeze, '00000'.taint]).instance_eval{
+ @mutex = Mutex.new
+ def mutex; @mutex; end
+ freeze
+ }
+
+ TkCore::INTERP.init_ip_env{
+ SliceID_TBL.mutex.synchronize{ SliceID_TBL.clear }
+ }
def self.id2obj(pie, id)
pie_path = pie.path
- return id unless SliceID_TBL[pie_path]
- SliceID_TBL[pie_path][id]? SliceID_TBL[pie_path][id]: id
+ SliceID_TBL.mutex.synchronize{
+ if SliceID_TBL[pie_path]
+ SliceID_TBL[pie_path][id]? SliceID_TBL[pie_path][id]: id
+ else
+ id
+ end
+ }
end
def initialize(parent, *args)
@@ -131,10 +144,14 @@ class Tk::Vu::PieSlice
end
@parent = @pie = parent
@ppath = parent.path
- @path = @id = Pie_Slice_ID.join(TkCore::INTERP._ip_id_)
- SliceID_TBL[@ppath] = {} unless SliceID_TBL[@ppath]
- SliceID_TBL[@ppath][@id] = self
- Pie_Slice_ID[1].succ!
+ Pie_Slice_ID.mutex.synchronize{
+ @path = @id = Pie_Slice_ID.join(TkCore::INTERP._ip_id_)
+ Pie_Slice_ID[1].succ!
+ }
+ SliceID_TBL.mutex.synchronize{
+ SliceID_TBL[@ppath] = {} unless SliceID_TBL[@ppath]
+ SliceID_TBL[@ppath][@id] = self
+ }
if args[-1].kind_of?(Hash)
keys = args.unshift
@@ -209,22 +226,48 @@ end
class Tk::Vu::NamedPieSlice
def self.new(parent, name, *args)
- if SliceID_TBL[parent.path] && SliceID_TBL[parent.path][name]
- return SliceID_TBL[parent.path][name]
- else
- super(parent, name, *args)
- end
+ obj = nil
+ SliceID_TBL.mutex.synchronize{
+ if SliceID_TBL[parent.path] && SliceID_TBL[parent.path][name]
+ obj = SliceID_TBL[parent.path][name]
+ else
+ #super(parent, name, *args)
+ unless parent.kind_of?(Tk::Vu::Pie)
+ fail ArgumentError, "expect a Tk::Vu::Pie instance for 1st argument"
+ end
+ obj = self.allocate
+ obj.instance_eval{
+ @parent = @pie = parent
+ @ppath = parent.path
+ @path = @id = name.to_s
+ SliceID_TBL[@ppath] = {} unless SliceID_TBL[@ppath]
+ SliceID_TBL[@ppath][@id] = self
+ }
+ end
+ }
+ obj.instance_eval{
+ if args[-1].kind_of?(Hash)
+ keys = args.unshift
+ end
+ @pie.set(@id, *args)
+ configure(keys)
+ }
+
+ obj
end
def initialize(parent, name, *args)
+ # dummy:: not called by 'new' method
unless parent.kind_of?(Tk::Vu::Pie)
fail ArgumentError, "expect a Tk::Vu::Pie instance for 1st argument"
end
@parent = @pie = parent
@ppath = parent.path
@path = @id = name.to_s
- SliceID_TBL[@ppath] = {} unless SliceID_TBL[@ppath]
- SliceID_TBL[@ppath][@id] = self
+ SliceID_TBL.mutex.synchronize{
+ SliceID_TBL[@ppath] = {} unless SliceID_TBL[@ppath]
+ SliceID_TBL[@ppath][@id] = self
+ }
if args[-1].kind_of?(Hash)
keys = args.unshift
diff --git a/ext/tk/lib/tkextlib/winico/winico.rb b/ext/tk/lib/tkextlib/winico/winico.rb
index c53a3ff48c..30fb9682d5 100644
--- a/ext/tk/lib/tkextlib/winico/winico.rb
+++ b/ext/tk/lib/tkextlib/winico/winico.rb
@@ -34,10 +34,15 @@ end
class Tk::Winico
WinicoID_TBL = TkCore::INTERP.create_table
- TkCore::INTERP.init_ip_env{ WinicoID_TBL.clear }
+
+ TkCore::INTERP.init_ip_env{
+ WinicoID_TBL.mutex.synchronize{ WinicoID_TBL.clear }
+ }
def self.id2obj(id)
- (WinicoID_TBL.key?(id))? WinicoID_TBL[id] : id
+ WinicoID_TBL.mutex.synchronize{
+ (WinicoID_TBL.key?(id))? WinicoID_TBL[id] : id
+ }
end
def self.info
@@ -81,7 +86,9 @@ class Tk::Winico
"must be given proper information from where loading icons"
end
@path = @id
- WinicoID_TBL[@id] = self
+ WinicoID_TBL.mutex.synchronize{
+ WinicoID_TBL[@id] = self
+ }
end
def id
@@ -96,7 +103,9 @@ class Tk::Winico
def delete
tk_call('winico', 'delete', @id)
- WinicoID_TBL.delete(@id)
+ WinicoID_TBL.mutex.synchronize{
+ WinicoID_TBL.delete(@id)
+ }
self
end
alias destroy delete
@@ -126,15 +135,37 @@ class Tk::Winico
[ ?n, TkComm.method(:number) ],
[ ?s, TkComm.method(:string) ],
[ ?x, proc{|id|
- if Tk::Winico::WinicoID_TBL.key?(id)
- Tk::Winico::WinicoID_TBL[id]
- else
- Tk::Winico.new(nil, nil, id)
- end
+ Tk::Winico::WinicoID_TBL.mutex.synchronize{
+ if Tk::Winico::WinicoID_TBL.key?(id)
+ obj = Tk::Winico::WinicoID_TBL[id]
+ else
+ # Tk::Winico.new(nil, nil, id)
+ obj = Tk::Winico.allocate
+ obj.instance_eval{ @path = @id = id }
+ Tk::Winico::WinicoID_TBL[id] = obj
+ end
+ obj
+ }
} ],
nil
]
+ # 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
+ }
+
_setup_subst_table(KEY_TBL, PROC_TBL);
def self.ret_val(val)
diff --git a/ext/tk/sample/binstr_usage.rb b/ext/tk/sample/binstr_usage.rb
index 91692856f9..be8399ba51 100644
--- a/ext/tk/sample/binstr_usage.rb
+++ b/ext/tk/sample/binstr_usage.rb
@@ -16,7 +16,7 @@ to avoid such troubles. Please see the source code of this sample. \
A Tk::BinaryString instance is used to create the image for the center button.
EOM
-ImgFile=['images','tcllogo.gif'].join(File::Separator)
+ImgFile=[File.dirname(__FILE__), 'images','tcllogo.gif'].join(File::Separator)
ph1 = TkPhotoImage.new(:file=>ImgFile)
p ph1.configinfo
@@ -28,12 +28,18 @@ ph2 = TkPhotoImage.new(:data=>b_str)
p ph2.configinfo
p ph2.data(:grayscale=>true)
-ph3 = TkPhotoImage.new()
-ph3.put(ph2.data(:grayscale=>true))
+ph3 = TkPhotoImage.new(:palette=>256)
+ph3.put(ph2.data)
+
+ph4 = TkPhotoImage.new()
+ph4.put(ph2.data(:grayscale=>true))
+
+#p [b_str.encoding, b_str.rb_encoding]
f = TkFrame.new.pack
TkButton.new(:parent=>f, :image=>ph1, :command=>proc{exit}).pack(:side=>:left)
TkButton.new(:parent=>f, :image=>ph2, :command=>proc{exit}).pack(:side=>:left)
TkButton.new(:parent=>f, :image=>ph3, :command=>proc{exit}).pack(:side=>:left)
+TkButton.new(:parent=>f, :image=>ph4, :command=>proc{exit}).pack(:side=>:left)
Tk.mainloop
diff --git a/ext/tk/sample/demos-en/arrow.rb b/ext/tk/sample/demos-en/arrow.rb
index b62e1966eb..4a589a0892 100644
--- a/ext/tk/sample/demos-en/arrow.rb
+++ b/ext/tk/sample/demos-en/arrow.rb
@@ -77,11 +77,19 @@ def arrowSetup(c)
'arrow'=>'both', 'arrowshape'=>v.smallTips)
TkcText.new(c, v.x2-5*v.b, tmp+5, 'text'=>v.b, 'anchor'=>'n')
- TkcText.new(c, v.x1, 310, 'text'=>"'width'=>#{v.width}", 'anchor'=>'w',
- 'font'=>'-*-Helvetica-Medium-R-Normal--*-180-*-*-*-*-*-*')
- TkcText.new(c, v.x1, 330,
- 'text'=>"'arrowshape'=>[#{v.a}, #{v.b}, #{v.c}]", 'anchor'=>'w',
- 'font'=>'-*-Helvetica-Medium-R-Normal--*-180-*-*-*-*-*-*')
+ if $tk_version =~ /^4.*/
+ TkcText.new(c, v.x1, 310, 'text'=>"'width'=>#{v.width}", 'anchor'=>'w',
+ 'font'=>'-*-Helvetica-Medium-R-Normal--*-180-*-*-*-*-*-*')
+ TkcText.new(c, v.x1, 330,
+ 'text'=>"'arrowshape'=>[#{v.a}, #{v.b}, #{v.c}]",'anchor'=>'w',
+ 'font'=>'-*-Helvetica-Medium-R-Normal--*-180-*-*-*-*-*-*')
+ else
+ TkcText.new(c, v.x1, 310, 'text'=>"'width'=>#{v.width}", 'anchor'=>'w',
+ 'font'=>'Helvetica 18')
+ TkcText.new(c, v.x1, 330,
+ 'text'=>"'arrowshape'=>[#{v.a}, #{v.b}, #{v.c}]",
+ 'anchor'=>'w', 'font'=>'Helvetica 18')
+ end
v.count += 1
end
diff --git a/ext/tk/sample/demos-en/bind.rb b/ext/tk/sample/demos-en/bind.rb
index b7e7122c57..5d6ec84edb 100644
--- a/ext/tk/sample/demos-en/bind.rb
+++ b/ext/tk/sample/demos-en/bind.rb
@@ -43,11 +43,11 @@ def tag_binding_for_bind_demo(tag, enter_style, leave_style)
end
# text
-TkText.new($bind_demo){|t|
+txt = TkText.new($bind_demo){|t|
#
setgrid 'true'
- width 60
- height 24
+ #width 60
+ #height 24
font $font
wrap 'word'
TkScrollbar.new($bind_demo) {|s|
@@ -120,3 +120,6 @@ TkText.new($bind_demo){|t|
TkTextMarkInsert.new(t, '0.0')
configure('state','disabled')
}
+
+txt.width 60
+txt.width 24
diff --git a/ext/tk/sample/demos-en/ctext.rb b/ext/tk/sample/demos-en/ctext.rb
index dbb5e32638..8c10880ed6 100644
--- a/ext/tk/sample/demos-en/ctext.rb
+++ b/ext/tk/sample/demos-en/ctext.rb
@@ -56,19 +56,28 @@ $ctext_canvas = TkCanvas.new($ctext_demo, 'relief'=>'flat',
$ctext_canvas.pack('side'=>'top', 'expand'=>'yes', 'fill'=>'both')
# font
-textFont = '-*-Helvetica-Medium-R-Normal--*-240-*-*-*-*-*-*'
+if $tk_version =~ /^4.*/
+ textFont = '-*-Helvetica-Medium-R-Normal--*-240-*-*-*-*-*-*'
+else
+ textFont = 'Helvetica 24'
+end
# canvas
TkcRectangle.new($ctext_canvas, 245, 195, 255, 205,
'outline'=>'black', 'fill'=>'red')
+ctag_text_param = {
+ 'text'=>"This is just a string of text to demonstrate the text facilities of canvas widgets. Bindings have been been defined to support editing (see above).",
+ 'width'=>440, 'anchor'=>'n', 'justify'=>'left'
+}
+if $tk_version =~ /^4.*/
+ ctag_text_param['font'] = '-*-Helvetica-Medium-R-Normal--*-240-*-*-*-*-*-*'
+else
+ ctag_text_param['font'] = 'Helvetica 24'
+end
+
$ctag_text = TkcTag.new($ctext_canvas)
-$ctag_text.withtag(TkcText.new($ctext_canvas, 250, 200,
- 'text'=>"This is just a string of text to demonstrate the text facilities of canvas widgets. Bindings have been been defined to support editing (see above).",
- 'width'=>440, 'anchor'=>'n',
- 'font'=>'-*-Helvetica-Medium-R-Normal--*-240-*-*-*-*-*-*',
- 'kanjifont'=>'-*--24-*-jisx0208.1983-0',
- 'justify'=>'left') )
+$ctag_text.withtag(TkcText.new($ctext_canvas, 250, 200, ctag_text_param))
$ctag_text.bind('1', proc{|x,y| textB1Press $ctext_canvas,x,y}, "%x %y")
$ctag_text.bind('B1-Motion', proc{|x,y| textB1Move $ctext_canvas,x,y}, "%x %y")
@@ -110,9 +119,14 @@ mkTextConfig $ctext_canvas, x+60, y+60, 'anchor', 'nw', color
item = TkcRectangle.new($ctext_canvas, x+40, y+40, x+50, y+50,
'outline'=>'black', 'fill'=>'red')
item.bind('1', proc{$ctag_text.configure 'anchor', 'center'})
-TkcText.new($ctext_canvas, x+45, y-5, 'text'=>'Text Position', 'anchor'=>'s',
- 'font'=>'-*-times-medium-r-normal--*-240-*-*-*-*-*-*',
- 'fill'=>'brown')
+if $tk_version =~ /^4.*/
+ TkcText.new($ctext_canvas, x+45, y-5, 'text'=>'Text Position',
+ 'font'=>'-*-times-medium-r-normal--*-240-*-*-*-*-*-*',
+ 'anchor'=>'s', 'fill'=>'brown')
+else
+ TkcText.new($ctext_canvas, x+45, y-5, 'text'=>'Text Position',
+ 'font'=>'Times 24', 'anchor'=>'s', 'fill'=>'brown')
+end
# Lastly, create some items that allow the text's justification to be
# changed.
@@ -123,9 +137,14 @@ color = 'SeaGreen2'
mkTextConfig $ctext_canvas, x, y, 'justify', 'left', color
mkTextConfig $ctext_canvas, x+30, y, 'justify', 'center', color
mkTextConfig $ctext_canvas, x+60, y, 'justify', 'right', color
-TkcText.new($ctext_canvas, x+45, y-5, 'text'=>'Justification', 'anchor'=>'s',
- 'font'=>'-*-times-medium-r-normal--*-240-*-*-*-*-*-*',
- 'fill'=>'brown')
+if $tk_version =~ /^4.*/
+ TkcText.new($ctext_canvas, x+45, y-5, 'text'=>'Justification',
+ 'font'=>'-*-times-medium-r-normal--*-240-*-*-*-*-*-*',
+ 'anchor'=>'s', 'fill'=>'brown')
+else
+ TkcText.new($ctext_canvas, x+45, y-5, 'text'=>'Justification',
+ 'font'=>'Times 24', 'anchor'=>'s', 'fill'=>'brown')
+end
$ctext_canvas.itembind('config', 'Enter', proc{textEnter $ctext_canvas})
$ctext_canvas.itembind('config', 'Leave',
diff --git a/ext/tk/sample/demos-en/hello b/ext/tk/sample/demos-en/hello
index f06eabe518..5e86ad7e3e 100644
--- a/ext/tk/sample/demos-en/hello
+++ b/ext/tk/sample/demos-en/hello
@@ -1,9 +1,9 @@
#!/usr/bin/env ruby
require 'tk'
-unless /^8\.[1-9]/ =~ Tk::TCL_VERSION && !Tk::JAPANIZED_TK
- require 'tkencoding'
-end
+#unless /^8\.[1-9]/ =~ Tk::TCL_VERSION && !Tk::JAPANIZED_TK
+# require 'tkencoding'
+#end
TkButton.new(nil,
'text'=>"Hello Ruby world!",
diff --git a/ext/tk/sample/demos-en/hscale.rb b/ext/tk/sample/demos-en/hscale.rb
index 14e395b61a..743c4b4852 100644
--- a/ext/tk/sample/demos-en/hscale.rb
+++ b/ext/tk/sample/demos-en/hscale.rb
@@ -62,7 +62,6 @@ TkFrame.new($hscale_demo) {|frame|
scale.set 75
}.pack('side'=>'top', 'fill'=>'x')
-
def setWidth(w, width)
width = width + 21
x2 = width - 30
@@ -72,3 +71,4 @@ def setWidth(w, width)
w.coords 'poly',20,15,20,35,x2,35,x2,45,width,25,x2,5,x2,15,20,15
w.coords 'line',20,15,20,35,x2,35,x2,45,width,25,x2,5,x2,15,20,15
end
+
diff --git a/ext/tk/sample/demos-en/items.rb b/ext/tk/sample/demos-en/items.rb
index 8ab7668a07..23191b59b9 100644
--- a/ext/tk/sample/demos-en/items.rb
+++ b/ext/tk/sample/demos-en/items.rb
@@ -94,8 +94,13 @@ TkcLine.new(cvs, '0c', '16c', '30c', '16c', 'width'=>2)
TkcLine.new(cvs, '10c', '0c', '10c', '24c', 'width'=>2)
TkcLine.new(cvs, '20c', '0c', '20c', '24c', 'width'=>2)
-font1 = '-Adobe-Helvetica-Medium-R-Normal--*-120-*-*-*-*-*-*'
-font2 = '-Adobe-Helvetica-Bold-R-Normal--*-240-*-*-*-*-*-*'
+if $tk_version =~ /^4.*/
+ font1 = '-Adobe-Helvetica-Medium-R-Normal--*-120-*-*-*-*-*-*'
+ font2 = '-Adobe-Helvetica-Bold-R-Normal--*-240-*-*-*-*-*-*'
+else
+ font1 = 'Helvetica 12'
+ font2 = 'Helvetica 24 bold'
+end
if TkWinfo.depth($root).to_i > 1
blue = 'DeepSkyBlue3'
red = 'red'
diff --git a/ext/tk/sample/demos-en/patch_1.1c1 b/ext/tk/sample/demos-en/patch_1.1c1
deleted file mode 100644
index d3952e71eb..0000000000
--- a/ext/tk/sample/demos-en/patch_1.1c1
+++ /dev/null
@@ -1,93 +0,0 @@
---- /usr/src/ruby-1.1c1/lib/tkcanvas.rb Tue Jul 21 18:18:02 1998
-+++ tkcanvas.rb Fri Jul 24 20:38:24 1998
-@@ -310,7 +310,7 @@
- || key == 'latinfont' || key == 'asciifont' )
- tagfont_configure(tagid(tagOrId), {key=>value})
- else
-- tk_call 'itemconfigure', tagid(tagOrId), "-#{key}", value
-+ tk_send 'itemconfigure', tagid(tagOrId), "-#{key}", value
- end
- end
- end
---- /usr/src/ruby-1.1c1/lib/tkfont.rb Fri Jul 17 23:43:28 1998
-+++ tkfont.rb Fri Jul 24 17:46:22 1998
-@@ -42,7 +42,7 @@
- r | []
-
- when /^8\.*/
-- list(tk_call('font', 'names'))
-+ tk_split_simplelist(tk_call('font', 'names'))
-
- end
- end
-@@ -89,10 +89,14 @@
- if fnt == []
- TkFont.new(nil, nil).call_font_configure(path, *(args + [{}]))
- else
-- compound = Hash[*list(tk_call('font', 'configure',
-- fnt))].collect{|key,value|
-- [key[1..-1], value]
-- }.assoc('compound')[1]
-+ begin
-+ compound = Hash[*list(tk_call('font', 'configure',
-+ fnt))].collect{|key,value|
-+ [key[1..-1], value]
-+ }.assoc('compound')[1]
-+ rescue
-+ compound = []
-+ end
- if compound == []
- TkFont.new(fnt, DEFAULT_KANJI_FONT_NAME) \
- .call_font_configure(path, *(args + [{}]))
-@@ -156,14 +160,19 @@
- elsif font.kind_of? Array
- finfo = {}
- finfo['family'] = font[0].to_s
-- if font[1] && font[1] != '0' && font[1] =~ /^(|\+|-)([0-9]+)$/
-- if $1 == '-'
-- finfo['pixels'] = font[1].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'] = font[1].to_s
-+ finfo['points'] = '13'
- end
- end
-- finfo[2..-1].each{|style|
-+ font[2..-1].each{|style|
- case (style)
- when 'normal'
- finfo['weight'] = style
-@@ -199,16 +208,19 @@
- elsif font.kind_of? Array
- finfo = {}
- finfo['family'] = font[0].to_s
-- if font[1] && font[1] != '0' && font[1] =~ /^(|\+|-)([0-9]+)$/
-- if $1 == '-'
-- finfo['pixels'] = $2
-+ 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'] = $2
-+ finfo['points'] = '13'
- end
-- else
-- finfo['points'] = '13'
- end
-- finfo[2..-1].each{|style|
-+ font[2..-1].each{|style|
- case (style)
- when 'normal'
- finfo['weight'] = style
diff --git a/ext/tk/sample/demos-en/rolodex-j b/ext/tk/sample/demos-en/rolodex-j
deleted file mode 100644
index 27e2bc9da0..0000000000
--- a/ext/tk/sample/demos-en/rolodex-j
+++ /dev/null
@@ -1,323 +0,0 @@
-#!/usr/bin/env ruby
-#
-# rolodex --
-# このスクリプトは Tom LaStrange の rolodex の一部です。
-#
-# Copyright (C) 1998 by Takaaki Tateishi <ttate@jaist.ac.jp>
-# Time-stamp: "03/08/02 14:02:04 nagai"
-#
-
-require "tk"
-
-Tk.encoding = "euc-jp"
-$font = TkFont.new('k14')
-
-def show_help(topic,x=0,y=0)
- if( topic.is_a?(TkWindow) )
- w = TkWinfo.containing(x,y)
- if( w.is_a?(TkWindow) )
- if( TkWinfo.exist?(w) )
- topic = w
- end
- end
- end
-
- if( $helpTopics.include?(topic) )
- msg = $helpTopics[topic]
- else
- msg = "このトピックについてのヘルプはまだ使用できません"
- end
- TkDialog.new("title"=>"Rolodex Help",
- "message"=>"「#{topic}」\n\n#{msg}",
- "font"=>$font,
- "default_button"=>0,
- "buttons"=>["OK"])
-end
-
-def fillCard
- clearAction
- $root.frame.entry[1].insert(0, "立石 孝彰")
- $root.frame.entry[2].insert(0, "923-1292 石川県")
- $root.frame.entry[3].insert(0, "辰口町 旭台 1-1")
- $root.frame.entry[4].insert(0, "北陸先端科学技術大学院大学")
- $root.frame.entry[5].insert(0,"private")
- $root.frame.entry[6].insert(0,"***-***-****")
- $root.frame.entry[7].insert(0,"***-***-****")
-end
-
-def addAction
- for i in 1..7
- STDERR.print format("%-12s %s\n",
- RolodexFrame::LABEL[i],
- $root.frame.entry[i].value)
- end
-end
-
-def clearAction
- for i in 1..7
- $root.frame.entry[i].delete(0,"end")
- end
-end
-
-def fileAction
- TkDialog.new("title"=>"File Selection",
- "message"=>"これはファイル選択ダイアログのダミーです。\n",
- "font"=>$font,
- "default_button"=>0,
- "buttons"=>["OK"])
- STDERR.print "dummy file name\n"
-end
-
-def deleteAction
- result = TkDialog.new("title"=>"Confirm Action",
- "message"=>"よろしいですか?",
- "font"=>$font,
- "default_button"=>0,
- "buttons"=>["キャンセル"])
- if( result.value == 0 )
- clearAction
- end
-end
-
-
-class RolodexFrame < TkFrame
- attr_reader :entry, :label
-
- LABEL = ["","名前:","住所","","","電話(自宅):","電話(会社):","Fax:"]
-
- def initialize(parent=nil,keys=nil)
- super(parent,keys)
- self["relief"] = "flat"
- @i = []
- @label = []
- @entry = []
- for i in 1..7
- @i[i] = TkFrame.new(self)
- @i[i].pack("side"=>"top",
- "pady"=>2,
- "anchor"=>"e")
- @label[i] = TkLabel.new(@i[i],
- "text"=>LABEL[i],
- "anchor"=>"e",
- "font" => $font)
- @entry[i] = TkEntry.new(@i[i],
- "width"=>30,
- "relief"=>"sunken",
- "font" => $font)
- @entry[i].pack("side"=>"right")
- @label[i].pack("side"=>"right")
- end
- end
-end
-
-class RolodexButtons < TkFrame
- attr_reader :clear, :add, :search, :delete
-
- def initialize(parent,keys=nil)
- super(parent,keys)
- @clear = TkButton.new(self,
- "text" => "クリアー",
- "font" => $font)
- @add = TkButton.new(self,
- "text" => "追加",
- "font" => $font)
- @search = TkButton.new(self,
- "text" => "検索",
- "font" => $font)
- @delete = TkButton.new(self,
- "text" => "消去",
- "font" => $font)
- for w in [@clear,@add,@search,@delete]
- w.pack("side"=>"left", "padx"=>2)
- end
- end
-end
-
-class RolodexMenuFrame < TkFrame
- attr_reader :file_menu, :help_menu, :file, :help
-
- def initialize(parent,keys=nil)
- super(parent,keys)
- configure("relief"=>"raised",
- "borderwidth"=>1)
-
- @file = TkMenubutton.new(self,
- "text"=> "ファイル",
- "font"=> $font,
- "underline"=>0)
- @file_menu = TkMenu.new(@file)
- @file_menu.add("command",
- "label" => "読み込み ...",
- "font" => $font,
- "command" => proc{fileAction},
- "underline" => 0)
- @file_menu.add("command",
- "label" => "終了",
- "font" => $font,
- "command" => proc{$root.destroy},
- "underline" => 0)
- @file.menu(@file_menu)
- @file.pack("side"=>"left")
-
- @help = TkMenubutton.new(self,
- "text"=> "ヘルプ",
- "font"=> $font,
- "underline"=>0)
- @help_menu = TkMenu.new(@help)
- @help_menu.add("command",
- "label"=> "コンテキストについて",
- "font" => $font,
- "command"=>proc{show_help("コンテキスト")},
- "underline"=>3)
- @help_menu.add("command",
- "label"=> "ヘルプについて",
- "font" => $font,
- "command"=>proc{show_help("ヘルプ")},
- "underline"=>3)
- @help_menu.add("command",
- "label"=> "ウィンドウについて",
- "font" => $font,
- "command"=>proc{show_help("ウィンドウ")},
- "underline"=>3)
- @help_menu.add("command",
- "label"=> "キー操作について",
- "font" => $font,
- "command"=>proc{show_help("キー操作")},
- "underline"=>3)
- @help_menu.add("command",
- "label"=> "バージョン情報",
- "font" => $font,
- "command"=>proc{show_help("バージョン情報")},
- "underline"=>3)
- @help.menu(@help_menu)
- @help.pack("side"=>"right")
- end
-end
-
-class Rolodex < TkRoot
- attr_reader :frame, :buttons, :menu
-
- def initialize(*args)
- super(*args)
- @frame = RolodexFrame.new(self)
- @frame.pack("side"=>"top",
- "fill"=>"y",
- "anchor"=>"center")
- @buttons = RolodexButtons.new(self)
- @buttons.pack("side"=>"bottom",
- "pady"=>2,
- "anchor"=>"center")
- @menu = RolodexMenuFrame.new(self)
- @menu.pack("before"=>@frame,
- "side"=>"top",
- "fill"=>"x")
- end
-end
-
-$root = Rolodex.new
-
-$root.buttons.delete.configure("command"=>proc{deleteAction})
-$root.buttons.add.configure("command"=>proc{addAction})
-$root.buttons.clear.configure("command"=>proc{clearAction})
-$root.buttons.search.configure("command"=>proc{addAction; fillCard})
-
-$root.buttons.clear.configure("text"=> "クリアー Ctrl+C", "font" => $font)
-$root.bind("Control-c",proc{clearAction})
-
-$root.buttons.add.configure("text"=> "追加 Ctrl+A", "font" => $font)
-$root.bind("Control-a",proc{addAction})
-
-$root.buttons.search.configure("text"=> "検索 Ctrl+S", "font" => $font)
-$root.bind("Control-s",proc{addAction; fillCard})
-
-$root.buttons.delete.configure("text"=> "消去 Ctrl+D", "font" => $font)
-$root.bind("Control-d",proc{deleteAction})
-
-$root.menu.file_menu.entryconfigure(1, "accel"=>"Ctrl+F")
-$root.bind("Control-f",proc{fileAction})
-
-$root.menu.file_menu.entryconfigure(2, "accel"=>"Ctrl+Q")
-$root.bind("Control-q",proc{$root.destroy})
-
-$root.frame.entry[1].focus
-
-$root.bind("Any-F1",
- proc{|event| show_help(event.widget, event.x_root, event.y_root)})
-$root.bind("Any-Help",
- proc{|event| show_help(event.widget, event.x_root, event.y_root)})
-
-
-$helpTopics = {}
-
-$helpTopics[$root.menu.file] = <<EOF
-これは「ファイル」メニューです。「読み込み」や「終了」などを
-行なうことができます。
-EOF
-
-$helpTopics[$root.menu.file_menu.index(0)] = <<EOF
-ファイルの読み込みを行なうときに使います。
-EOF
-
-$helpTopics[$root.menu.file_menu.index(1)] = <<EOF
-アプリケーションを終了するときに使います。
-EOF
-
-$helpTopics[$root.frame.entry[1]] = <<EOF
-名前を記入するエントリです。
-EOF
-
-$helpTopics[$root.frame.entry[2]] = <<EOF
-住所を記入するエントリです。
-EOF
-
-$helpTopics[$root.frame.entry[3]] = <<EOF
-住所を記入するエントリです。
-EOF
-
-$helpTopics[$root.frame.entry[4]] = <<EOF
-住所を記入するエントリです。
-EOF
-
-$helpTopics[$root.frame.entry[5]] = <<EOF
-自宅の電話番号を記入するエントリです。公開\
-したくないときは private と記入します。
-EOF
-
-$helpTopics[$root.frame.entry[6]] = <<EOF
-会社の電話番号を記入するエントリです。
-EOF
-
-$helpTopics[$root.frame.entry[7]] = <<EOF
-FAX番号を記入するエントリです。
-EOF
-
-$helpTopics["コンテキスト"] = <<EOF
-Ruby/Tkではgrabの機構がないためこのアプリケーションでは\
-コンテキストヘルプはサポートされていません。
-しかし同じような効果をbindとマウスの位置のWedgetを知る\
-ことで得ることができます。
-EOF
-
-$helpTopics["ヘルプ"] = <<EOF
-マウスをウィンドウにあわせてF1キーを押すことによって\
-そのヘルプを見ることができます。
-EOF
-
-$helpTopics["ウィンドウ"] = <<EOF
-このウィンドウはダミーです。
-EOF
-
-$helpTopics["キー操作"] = <<EOF
-Ctrl+A: 追加
-Ctrl+C: クリアー
-Ctrl+D: 消去
-Ctrl+F: ファイル選択
-Ctrl+Q: 終了
-Ctrl+S: 検索
-EOF
-
-$helpTopics["バージョン情報"] = <<EOF
-バージョンは 1.0.1e です。
-EOF
-
-Tk.mainloop
diff --git a/ext/tk/sample/demos-en/search.rb b/ext/tk/sample/demos-en/search.rb
index 3d3b4aecc8..3749423bbc 100644
--- a/ext/tk/sample/demos-en/search.rb
+++ b/ext/tk/sample/demos-en/search.rb
@@ -140,7 +140,7 @@ $search_text = TkText.new($search_demo, 'setgrid'=>true, 'wrap'=>'word') {|t|
pack('side'=>'right', 'fill'=>'y')
}
pack('expand'=>'yes', 'fill'=>'both')
-}
+}
# Set up display styles for text highlighting.
@@ -173,8 +173,13 @@ type a string in the lower entry and type <Return> or click on \
\"Load File\". This will cause all of the instances of the string to \
be tagged with the tag \"search\", and it will arrange for the tag\'s \
display attributes to change to make all of the strings blink.")
+$search_text.insert('end', "\
+The current directory to load a file is \"#{Dir.pwd}\".\
+")
$search_text.set_insert '0.0'
$search_fileName.value = ''
$search_searchString.value = ''
+$search_text.width = 60
+$search_text.height = 20
diff --git a/ext/tk/sample/demos-en/style.rb b/ext/tk/sample/demos-en/style.rb
index 5ed11aa459..8606893c9b 100644
--- a/ext/tk/sample/demos-en/style.rb
+++ b/ext/tk/sample/demos-en/style.rb
@@ -40,9 +40,10 @@ TkFrame.new($style_demo) {|frame|
TkText.new($style_demo){|t|
#
setgrid 'true'
- width 70
- height 32
+ #width 70
+ #height 32
wrap 'word'
+ font $font
TkScrollbar.new($style_demo) {|s|
pack('side'=>'right', 'fill'=>'y')
command proc{|*args| t.yview(*args)}
@@ -51,11 +52,20 @@ TkText.new($style_demo){|t|
pack('expand'=>'yes', 'fill'=>'both')
#
- style_tag_bold = TkTextTag.new(t, 'font'=>'-*-Courier-Bold-O-Normal--*-120-*-*-*-*-*-*')
- style_tag_big = TkTextTag.new(t, 'font'=>'-*-Courier-Bold-R-Normal--*-140-*-*-*-*-*-*', 'kanjifont'=>$msg_kanji_font)
+ family = 'Courier'
+
+ if $tk_version =~ /^4.*/
+ style_tag_bold = TkTextTag.new(t, 'font'=>'-*-Courier-Bold-O-Normal--*-120-*-*-*-*-*-*')
+ style_tag_big = TkTextTag.new(t, 'font'=>'-*-Courier-Bold-R-Normal--*-140-*-*-*-*-*-*', 'kanjifont'=>$msg_kanji_font)
style_tag_verybig = TkTextTag.new(t, 'font'=>'-*-Helvetica-Bold-R-Normal--*-240-*-*-*-*-*-*')
-# style_tag_small = TkTextTag.new(t, 'font'=>'-Adobe-Helvetica-Bold-R-Normal-*-100-*', 'kanjifont'=>$kanji_font)
+ # style_tag_small = TkTextTag.new(t, 'font'=>'-Adobe-Helvetica-Bold-R-Normal-*-100-*', 'kanjifont'=>$kanji_font)
style_tag_small = TkTextTag.new(t, 'font'=>'-Adobe-Helvetica-Bold-R-Normal-*-100-*')
+ else
+ style_tag_bold = TkTextTag.new(t, 'font'=>[family, 12, :bold, :italic])
+ style_tag_big = TkTextTag.new(t, 'font'=>[family, 14, :bold])
+ style_tag_verybig = TkTextTag.new(t, 'font'=>['Helvetica', 24, :bold])
+ style_tag_small = TkTextTag.new(t, 'font'=>['Times 8 bold'])
+ end
###
# case($tk_version)
# when /^4.*/
@@ -109,8 +119,13 @@ TkText.new($style_demo){|t|
style_tag_overstrike = TkTextTag.new(t, 'overstrike'=>'on')
style_tag_right = TkTextTag.new(t, 'justify'=>'right')
style_tag_center = TkTextTag.new(t, 'justify'=>'center')
- style_tag_super = TkTextTag.new(t, 'offset'=>'4p', 'font'=>'-Adobe-Courier-Medium-R-Normal--*-100-*-*-*-*-*-*')
- style_tag_sub = TkTextTag.new(t, 'offset'=>'-2p', 'font'=>'-Adobe-Courier-Medium-R-Normal--*-100-*-*-*-*-*-*')
+ if $tk_version =~ /^4.*/
+ style_tag_super = TkTextTag.new(t, 'offset'=>'4p', 'font'=>'-Adobe-Courier-Medium-R-Normal--*-100-*-*-*-*-*-*')
+ style_tag_sub = TkTextTag.new(t, 'offset'=>'-2p', 'font'=>'-Adobe-Courier-Medium-R-Normal--*-100-*-*-*-*-*-*')
+ else
+ style_tag_super = TkTextTag.new(t, 'offset'=>'4p', 'font'=>[family, 10])
+ style_tag_sub = TkTextTag.new(t, 'offset'=>'-2p', 'font'=>[family, 10])
+ end
style_tag_margins = TkTextTag.new(t, 'lmargin1'=>'12m', 'lmargin2'=>'6m',
'rmargin'=>'10m')
style_tag_spacing = TkTextTag.new(t, 'spacing1'=>'10p', 'spacing2'=>'2p',
@@ -132,7 +147,8 @@ available display styles are:
insert('end', " You can choose any X font, ")
insert('end', "large", style_tag_verybig)
insert('end', " or ")
- insert('end', "small.\n")
+ insert('end', "small", style_tag_small)
+ insert('end', ".\n")
insert('end', "\n2. Color.", style_tag_big)
insert('end', " You can change either the ")
insert('end', "background", style_tag_color1)
@@ -209,3 +225,5 @@ available display styles are:
}
+txt.width 70
+txt.height 32
diff --git a/ext/tk/sample/demos-en/textpeer.rb b/ext/tk/sample/demos-en/textpeer.rb
new file mode 100644
index 0000000000..d98ef170b4
--- /dev/null
+++ b/ext/tk/sample/demos-en/textpeer.rb
@@ -0,0 +1,72 @@
+#
+# text widget peering demo (called by 'widget')
+#
+# based on Tcl/Tk8.5.0 widget demos
+
+if defined?($textpeer_demo) && $textpeer_demo
+ $textpeer_demo.destroy
+ $textpeer_demo = nil
+end
+
+# demo toplevel widget
+$textpeer_demo = TkToplevel.new {|w|
+ title("Text Wdget Peering Demonstration")
+ iconname("textpeer")
+ positionWindow(w)
+}
+
+count = [0]
+
+## Define a widget that we peer from; it won't ever actually be shown though
+first = TkText.new($textpeer_demo, :widgetname=>"text#{count[0] += 1}")
+first.insert :end,"This is a coupled pair of text widgets; they are peers to "
+first.insert :end,"each other. They have the same underlying data model, but "
+first.insert :end,"can show different locations, have different current edit "
+first.insert :end,"locations, and have different selections. You can also "
+first.insert :end,"create additional peers of any of these text widgets using "
+first.insert :end,"the Make Peer button beside the text widget to clone, and "
+first.insert :end,"delete a particular peer widget using the Delete Peer "
+first.insert :end,"button."
+
+## Procedures to make and kill clones; most of this is just so that the demo
+## looks nice...
+def makeClone(count, win, txt)
+ cnt = (count[0] += 1)
+ peer = TkText::Peer.new(txt, win, :widgetname=>"text#{cnt}")
+ sbar = TkScrollbar.new(win, :widgetname=>"sb#{cnt}")
+ peer.yscrollbar sbar
+ b1 = TkButton.new(win, :widgetname=>"clone#{cnt}", :text=>'Make Peer',
+ :command=>proc{makeClone(count, win, peer)})
+ b2 = TkButton.new(win, :widgetname=>"kill#{cnt}", :text=>'Delete Peer',
+ :command=>proc{killClone(win, cnt)})
+ row = cnt * 2
+ TkGrid.configure(peer, sbar, b1, :sticky=>'nsew', :row=>row)
+ TkGrid.configure('^', '^', b2, :sticky=>'nsew', :row=>(row+=1))
+ TkGrid.configure(b1, b2, :sticky=>'new')
+ TkGrid.rowconfigure(win, b2, :weight=>1)
+end
+
+def killClone(win, cnt)
+ Tk.destroy("#{win.path}.text#{cnt}", "#{win.path}.sb#{cnt}",
+ "#{win.path}.clone#{cnt}", "#{win.path}.kill#{cnt}")
+end
+
+## Now set up the GUI
+makeClone(count, $textpeer_demo, first)
+makeClone(count, $textpeer_demo, first)
+first.destroy
+
+## See Code / Dismiss buttons
+TkFrame.new($textpeer_demo){|f|
+ TkButton.new(f, :text=>'Dismiss', :width=>15, :command=>proc{
+ $textpeer_demo.destroy
+ $textpeer_demo = nil
+ }).pack(:side=>:left, :expand=>true)
+
+ TkButton.new(f, :text=>'See Code', :width=>15, :command=>proc{
+ showCode 'textpeer'
+ }).pack(:side=>:left, :expand=>true)
+
+ TkGrid.configure(f, '-', '-', :sticky=>'ew', :row=>5000)
+}
+TkGrid.columnconfigure($textpeer_demo, 0, :weight=>1)
diff --git a/ext/tk/sample/demos-en/twind.rb b/ext/tk/sample/demos-en/twind.rb
index 24a4bcf706..f29e49f35a 100644
--- a/ext/tk/sample/demos-en/twind.rb
+++ b/ext/tk/sample/demos-en/twind.rb
@@ -206,7 +206,11 @@ def textWindPlot (t)
cursor 'top_left_arrow'
}
- font = '-Adobe-Helvetica-Medium-R-Normal--*-180-*-*-*-*-*-*'
+ if $tk_version =~ /^4.*/
+ font = '-Adobe-Helvetica-Medium-R-Normal--*-180-*-*-*-*-*-*'
+ else
+ font = 'Helvetica 18'
+ end
TkcLine.new($twind_plot, 100, 250, 400, 250, 'width'=>2)
TkcLine.new($twind_plot, 100, 250, 100, 50, 'width'=>2)
diff --git a/ext/tk/sample/demos-en/vscale.rb b/ext/tk/sample/demos-en/vscale.rb
index 636b85813b..c0170467d5 100644
--- a/ext/tk/sample/demos-en/vscale.rb
+++ b/ext/tk/sample/demos-en/vscale.rb
@@ -66,7 +66,6 @@ TkFrame.new($vscale_demo) {|frame|
scale.set 75
}.pack
-
def setHeight(w, height)
height = height + 21
y2 = height - 30
diff --git a/ext/tk/sample/demos-en/widget b/ext/tk/sample/demos-en/widget
index 3c50582211..391d8532b6 100644
--- a/ext/tk/sample/demos-en/widget
+++ b/ext/tk/sample/demos-en/widget
@@ -21,7 +21,8 @@ require 'tk'
#----------------------------------------------------------------
# widget demo directory
-$demo_dir = File.dirname($0)
+# $demo_dir = File.dirname($0)
+$demo_dir = File.dirname(__FILE__)
# root
$root = TkRoot.new{title "Ruby/Tk Widget Demonstration"}
@@ -164,12 +165,17 @@ else
textFrame.pack('expand'=>'yes', 'fill'=>'both')
statusBar = TkFrame.new($root) {|f|
+ if $tk_version =~ /^4.*/
+ statusfont = '-*-Helvetica-Medium-R-Normal--*-120-*-*-*-*-*-*'
+ else
+ statusfont = 'Helvetica 10'
+ end
$statusBarLabel = \
TkLabel.new(f, 'text'=>" ", 'relief'=>'sunken', 'bd'=>1, 'anchor'=>'w',
- 'font'=>'-*-Helvetica-Medium-R-Normal--*-120-*-*-*-*-*-*') \
+ 'font'=>statusfont) \
.pack('side'=>'left', 'padx'=>2, 'expand'=>'yes', 'fill'=>'both')
TkLabel.new(f, 'width'=>8, 'relief'=>'sunken', 'bd'=>1, 'anchor'=>'w',
- 'font'=>'-*-Helvetica-Medium-R-Normal--*-120-*-*-*-*-*-*') \
+ 'font'=>statusfont) \
.pack('side'=>'left', 'padx'=>2)
}.pack('side'=>'bottom', 'fill'=>'x', 'pady'=>2)
end
@@ -178,7 +184,11 @@ end
# section titles and demo descriptions. Also define the bindings for
# tags.
-tag_title = TkTextTag.new(txt, 'font'=>'-*-Helvetica-Bold-R-Normal--*-180-*-*-*-*-*-*')
+if $tk_version =~ /^4.*/
+ tag_title = TkTextTag.new(txt, 'font'=>'-*-Helvetica-Bold-R-Normal--*-180-*-*-*-*-*-*')
+else
+ tag_title = TkTextTag.new(txt, 'font'=>'Helvetica 18 bold')
+end
# We put some "space" characters to the left and right of each demo description
# so that the descriptions are highlighted only when the mouse cursor
@@ -331,6 +341,8 @@ txt.insert('end', "5. A text widget with embedded windows. (if supported)\n", ta
txt.insert('end', " \n ", tag_demospace)
txt.insert('end', "6. A search tool built with a text widget.\n", tag_demo, "demo-search")
txt.insert('end', " \n ", tag_demospace)
+txt.insert('end', "7. Peering text widgets. (if supported)\n", tag_demo, "demo-textpeer")
+txt.insert('end', " \n ", tag_demospace)
txt.insert('end', "\n")
txt.insert('end', "Canvases\n", tag_title)
@@ -445,7 +457,11 @@ def showVars1(parent, *args)
text "Variable values:"
width 20
anchor 'center'
- font '-Adobe-helvetica-medium-r-normal--*-180-*-*-*-*-*-*'
+ if $tk_version =~ /^4.*/
+ font '-Adobe-helvetica-medium-r-normal--*-180-*-*-*-*-*-*'
+ else
+ font 'Helvetica 14'
+ end
}.pack('side'=>'top', 'fill'=>'x')
len = 1
args.each{|vnam,vbody|
@@ -592,7 +608,9 @@ end
private :_null_binding
def eval_samplecode(code)
- Thread.new{ _null_binding.pseudo_toplevel_eval{ eval(code) } }.run
+ #eval(code)
+ #_null_binding.pseudo_toplevel_eval{ eval(code) }
+ Thread.new{ _null_binding.pseudo_toplevel_eval{ eval(code) } }
Tk.update
end
@@ -896,7 +914,7 @@ end
#
def aboutBox
Tk.messageBox('icon'=>'info', 'type'=>'ok', 'title'=>'About Widget Demo',
- 'message'=>"Ruby/Tk widget demonstration Ver.1.6.0-en\n\n" +
+ 'message'=>"Ruby/Tk widget demonstration Ver.1.6.3-en\n\n" +
"based on demos of Tk8.1 -- 8.5 " +
"( Copyright:: " +
"(c) 1996-1997 Sun Microsystems, Inc. / " +
diff --git a/ext/tk/sample/demos-jp/arrow.rb b/ext/tk/sample/demos-jp/arrow.rb
index 43c6eef4eb..b2c1067027 100644
--- a/ext/tk/sample/demos-jp/arrow.rb
+++ b/ext/tk/sample/demos-jp/arrow.rb
@@ -74,11 +74,19 @@ def arrowSetup(c)
'arrow'=>'both', 'arrowshape'=>v.smallTips)
TkcText.new(c, v.x2-5*v.b, tmp+5, 'text'=>v.b, 'anchor'=>'n')
- TkcText.new(c, v.x1, 310, 'text'=>"'width'=>#{v.width}", 'anchor'=>'w',
- 'font'=>'-*-Helvetica-Medium-R-Normal--*-180-*-*-*-*-*-*')
- TkcText.new(c, v.x1, 330,
- 'text'=>"'arrowshape'=>[#{v.a}, #{v.b}, #{v.c}]", 'anchor'=>'w',
- 'font'=>'-*-Helvetica-Medium-R-Normal--*-180-*-*-*-*-*-*')
+ if $tk_version =~ /^4.*/
+ TkcText.new(c, v.x1, 310, 'text'=>"'width'=>#{v.width}", 'anchor'=>'w',
+ 'font'=>'-*-Helvetica-Medium-R-Normal--*-180-*-*-*-*-*-*')
+ TkcText.new(c, v.x1, 330,
+ 'text'=>"'arrowshape'=>[#{v.a}, #{v.b}, #{v.c}]",'anchor'=>'w',
+ 'font'=>'-*-Helvetica-Medium-R-Normal--*-180-*-*-*-*-*-*')
+ else
+ TkcText.new(c, v.x1, 310, 'text'=>"'width'=>#{v.width}", 'anchor'=>'w',
+ 'font'=>'Helvetica 18')
+ TkcText.new(c, v.x1, 330,
+ 'text'=>"'arrowshape'=>[#{v.a}, #{v.b}, #{v.c}]",
+ 'anchor'=>'w', 'font'=>'Helvetica 18')
+ end
v.count += 1
end
diff --git a/ext/tk/sample/demos-jp/bind.rb b/ext/tk/sample/demos-jp/bind.rb
index 87b39721d1..3b6f6242c2 100644
--- a/ext/tk/sample/demos-jp/bind.rb
+++ b/ext/tk/sample/demos-jp/bind.rb
@@ -41,11 +41,11 @@ def tag_binding_for_bind_demo(tag, enter_style, leave_style)
end
# text 生成
-TkText.new($bind_demo){|t|
+txt = TkText.new($bind_demo){|t|
# 生成
setgrid 'true'
- width 60
- height 24
+ #width 60
+ #height 24
font $font
wrap 'word'
TkScrollbar.new($bind_demo) {|s|
@@ -118,3 +118,6 @@ TkText.new($bind_demo){|t|
TkTextMarkInsert.new(t, '0.0')
configure('state','disabled')
}
+
+txt.width 60
+txt.width 24
diff --git a/ext/tk/sample/demos-jp/ctext.rb b/ext/tk/sample/demos-jp/ctext.rb
index 35d43febbc..f5daf7ca05 100644
--- a/ext/tk/sample/demos-jp/ctext.rb
+++ b/ext/tk/sample/demos-jp/ctext.rb
@@ -53,19 +53,28 @@ $ctext_canvas = TkCanvas.new($ctext_demo, 'relief'=>'flat',
$ctext_canvas.pack('side'=>'top', 'expand'=>'yes', 'fill'=>'both')
# font 設定
-textFont = '-*-Helvetica-Medium-R-Normal--*-240-*-*-*-*-*-*'
+if $tk_version =~ /^4.*/
+ textFont = '-*-Helvetica-Medium-R-Normal--*-240-*-*-*-*-*-*'
+else
+ textFont = 'Helvetica 24'
+end
# canvas 設定
TkcRectangle.new($ctext_canvas, 245, 195, 255, 205,
'outline'=>'black', 'fill'=>'red')
+ctag_text_param = {
+ 'text'=>"これはキャンバスwidgetのテキスト機能をデモするための文字列です。\n上で述べたような編集を可能とするためのバインディングを施しています。",
+ 'width'=>440, 'anchor'=>'n', 'justify'=>'left'
+}
+if $tk_version =~ /^4.*/
+ ctag_text_param['font'] = '-*-Helvetica-Medium-R-Normal--*-240-*-*-*-*-*-*'
+ ctag_text_param['kanjifont'] = '-*-r-*--24-*-jisx0208.1983-0'
+else
+ ctag_text_param['font'] = 'Helvetica 24'
+end
$ctag_text = TkcTag.new($ctext_canvas)
-$ctag_text.withtag(TkcText.new($ctext_canvas, 250, 200,
- 'text'=>"これはキャンバスwidgetのテキスト機能をデモするための文字列です。\n上で述べたような編集を可能とするためのバインディングを施しています。",
- 'width'=>440, 'anchor'=>'n',
- 'font'=>'-*-Helvetica-Medium-R-Normal--*-240-*-*-*-*-*-*',
- 'kanjifont'=>'-*-r-*--24-*-jisx0208.1983-0',
- 'justify'=>'left') )
+$ctag_text.withtag(TkcText.new($ctext_canvas, 250, 200, ctag_text_param))
$ctag_text.bind('1', proc{|x,y| textB1Press $ctext_canvas,x,y}, "%x %y")
$ctag_text.bind('B1-Motion', proc{|x,y| textB1Move $ctext_canvas,x,y}, "%x %y")
@@ -107,9 +116,14 @@ mkTextConfig $ctext_canvas, x+60, y+60, 'anchor', 'nw', color
item = TkcRectangle.new($ctext_canvas, x+40, y+40, x+50, y+50,
'outline'=>'black', 'fill'=>'red')
item.bind('1', proc{$ctag_text.configure 'anchor', 'center'})
-TkcText.new($ctext_canvas, x+45, y-5, 'text'=>'Text Position', 'anchor'=>'s',
- 'font'=>'-*-times-medium-r-normal--*-240-*-*-*-*-*-*',
- 'fill'=>'brown')
+if $tk_version =~ /^4.*/
+ TkcText.new($ctext_canvas, x+45, y-5, 'text'=>'Text Position',
+ 'font'=>'-*-times-medium-r-normal--*-240-*-*-*-*-*-*',
+ 'anchor'=>'s', 'fill'=>'brown')
+else
+ TkcText.new($ctext_canvas, x+45, y-5, 'text'=>'Text Position',
+ 'font'=>'Times 24', 'anchor'=>'s', 'fill'=>'brown')
+end
# Lastly, create some items that allow the text's justification to be
# changed.
@@ -120,9 +134,14 @@ color = 'SeaGreen2'
mkTextConfig $ctext_canvas, x, y, 'justify', 'left', color
mkTextConfig $ctext_canvas, x+30, y, 'justify', 'center', color
mkTextConfig $ctext_canvas, x+60, y, 'justify', 'right', color
-TkcText.new($ctext_canvas, x+45, y-5, 'text'=>'Justification', 'anchor'=>'s',
- 'font'=>'-*-times-medium-r-normal--*-240-*-*-*-*-*-*',
- 'fill'=>'brown')
+if $tk_version =~ /^4.*/
+ TkcText.new($ctext_canvas, x+45, y-5, 'text'=>'Justification',
+ 'font'=>'-*-times-medium-r-normal--*-240-*-*-*-*-*-*',
+ 'anchor'=>'s', 'fill'=>'brown')
+else
+ TkcText.new($ctext_canvas, x+45, y-5, 'text'=>'Justification',
+ 'font'=>'Times 24', 'anchor'=>'s', 'fill'=>'brown')
+end
$ctext_canvas.itembind('config', 'Enter', proc{textEnter $ctext_canvas})
$ctext_canvas.itembind('config', 'Leave',
diff --git a/ext/tk/sample/demos-jp/hscale.rb b/ext/tk/sample/demos-jp/hscale.rb
index 690479d6d1..b636f0579f 100644
--- a/ext/tk/sample/demos-jp/hscale.rb
+++ b/ext/tk/sample/demos-jp/hscale.rb
@@ -66,7 +66,6 @@ TkFrame.new($hscale_demo) {|frame|
scale.set 75
}.pack('side'=>'top', 'fill'=>'x')
-
def setWidth(w, width)
width = width + 21
x2 = width - 30
diff --git a/ext/tk/sample/demos-jp/items.rb b/ext/tk/sample/demos-jp/items.rb
index d538fac75f..c173d3b57f 100644
--- a/ext/tk/sample/demos-jp/items.rb
+++ b/ext/tk/sample/demos-jp/items.rb
@@ -92,8 +92,13 @@ TkcLine.new(cvs, '0c', '16c', '30c', '16c', 'width'=>2)
TkcLine.new(cvs, '10c', '0c', '10c', '24c', 'width'=>2)
TkcLine.new(cvs, '20c', '0c', '20c', '24c', 'width'=>2)
-font1 = '-Adobe-Helvetica-Medium-R-Normal--*-120-*-*-*-*-*-*'
-font2 = '-Adobe-Helvetica-Bold-R-Normal--*-240-*-*-*-*-*-*'
+if $tk_version =~ /^4.*/
+ font1 = '-Adobe-Helvetica-Medium-R-Normal--*-120-*-*-*-*-*-*'
+ font2 = '-Adobe-Helvetica-Bold-R-Normal--*-240-*-*-*-*-*-*'
+else
+ font1 = 'Helvetica 12'
+ font2 = 'Helvetica 24 bold'
+end
if TkWinfo.depth($root).to_i > 1
blue = 'DeepSkyBlue3'
red = 'red'
diff --git a/ext/tk/sample/demos-jp/plot.rb b/ext/tk/sample/demos-jp/plot.rb
index 09a3446836..dbca3e971c 100644
--- a/ext/tk/sample/demos-jp/plot.rb
+++ b/ext/tk/sample/demos-jp/plot.rb
@@ -42,7 +42,11 @@ $plot_buttons = TkFrame.new($plot_demo) {|frame|
$plot_buttons.pack('side'=>'bottom', 'fill'=>'x', 'pady'=>'2m')
# font 設定
-plotFont = '-*-Helvetica-Medium-R-Normal--*-180-*-*-*-*-*-*'
+ if $tk_version =~ /^4.*/
+ plotFont = '-*-Helvetica-Medium-R-Normal--*-180-*-*-*-*-*-*'
+ else
+ font = 'Helvetica 18'
+ end
# canvas 設定
$plot_canvas = TkCanvas.new($plot_demo,'relief'=>'raised','width'=>450,'height'=>300)
diff --git a/ext/tk/sample/demos-jp/search.rb b/ext/tk/sample/demos-jp/search.rb
index adb72fd809..d3692e2455 100644
--- a/ext/tk/sample/demos-jp/search.rb
+++ b/ext/tk/sample/demos-jp/search.rb
@@ -169,9 +169,14 @@ $search_text.insert('1.0', "\
エントリに文字列を入力し、<リターン> を押すか「反転」ボタンを押してく \
ださい。するとファイル中の、検索文字列と一致する部分に全て \"search_Tag\" \
というタグがつけられ、タグの表示属性としてその文字列が点滅するように \
-設定されます。")
+設定されます。\n")
+$search_text.insert('end', "\
+ファイル読み込みのカレントディレクトリは \"#{Dir.pwd}\" です。\
+")
$search_text.set_insert '0.0'
$search_fileName.value = ''
$search_searchString.value = ''
+$search_text.width = 60
+$search_text.height = 20
diff --git a/ext/tk/sample/demos-jp/style.rb b/ext/tk/sample/demos-jp/style.rb
index 50855a549a..c8c7850156 100644
--- a/ext/tk/sample/demos-jp/style.rb
+++ b/ext/tk/sample/demos-jp/style.rb
@@ -9,6 +9,7 @@ if defined?($style_demo) && $style_demo
$style_demo = nil
end
+
# demo 用の toplevel widget を生成
$style_demo = TkToplevel.new {|w|
title("Text Demonstration - Display Styles")
@@ -16,6 +17,7 @@ $style_demo = TkToplevel.new {|w|
positionWindow(w)
}
+
# frame 生成
TkFrame.new($style_demo) {|frame|
TkButton.new(frame) {
@@ -34,13 +36,15 @@ TkFrame.new($style_demo) {|frame|
}.pack('side'=>'left', 'expand'=>'yes')
}.pack('side'=>'bottom', 'fill'=>'x', 'pady'=>'2m')
+
# text 生成
-TkText.new($style_demo){|t|
+txt = TkText.new($style_demo){|t|
# 生成
setgrid 'true'
- width 70
- height 32
+ #width 70
+ #height 32
wrap 'word'
+ font $font
TkScrollbar.new($style_demo) {|s|
pack('side'=>'right', 'fill'=>'y')
command proc{|*args| t.yview(*args)}
@@ -49,11 +53,20 @@ TkText.new($style_demo){|t|
pack('expand'=>'yes', 'fill'=>'both')
# テキストタグ設定 (フォント関連)
- style_tag_bold = TkTextTag.new(t, 'font'=>'-*-Courier-Bold-O-Normal--*-120-*-*-*-*-*-*')
- style_tag_big = TkTextTag.new(t, 'font'=>'-*-Courier-Bold-R-Normal--*-140-*-*-*-*-*-*', 'kanjifont'=>$msg_kanji_font)
+ family = 'Courier'
+
+ if $tk_version =~ /^4.*/
+ style_tag_bold = TkTextTag.new(t, 'font'=>'-*-Courier-Bold-O-Normal--*-120-*-*-*-*-*-*')
+ style_tag_big = TkTextTag.new(t, 'font'=>'-*-Courier-Bold-R-Normal--*-140-*-*-*-*-*-*', 'kanjifont'=>$msg_kanji_font)
style_tag_verybig = TkTextTag.new(t, 'font'=>'-*-Helvetica-Bold-R-Normal--*-240-*-*-*-*-*-*')
-# style_tag_small = TkTextTag.new(t, 'font'=>'-Adobe-Helvetica-Bold-R-Normal-*-100-*', 'kanjifont'=>$kanji_font)
+ # style_tag_small = TkTextTag.new(t, 'font'=>'-Adobe-Helvetica-Bold-R-Normal-*-100-*', 'kanjifont'=>$kanji_font)
style_tag_small = TkTextTag.new(t, 'font'=>'-Adobe-Helvetica-Bold-R-Normal-*-100-*')
+ else
+ style_tag_bold = TkTextTag.new(t, 'font'=>[family, 12, :bold, :italic])
+ style_tag_big = TkTextTag.new(t, 'font'=>[family, 14, :bold])
+ style_tag_verybig = TkTextTag.new(t, 'font'=>['Helvetica', 24, :bold])
+ style_tag_small = TkTextTag.new(t, 'font'=>['Times 8 bold'])
+ end
###
# case($tk_version)
# when /^4.*/
@@ -107,8 +120,13 @@ TkText.new($style_demo){|t|
style_tag_overstrike = TkTextTag.new(t, 'overstrike'=>'on')
style_tag_right = TkTextTag.new(t, 'justify'=>'right')
style_tag_center = TkTextTag.new(t, 'justify'=>'center')
- style_tag_super = TkTextTag.new(t, 'offset'=>'4p', 'font'=>'-Adobe-Courier-Medium-R-Normal--*-100-*-*-*-*-*-*')
- style_tag_sub = TkTextTag.new(t, 'offset'=>'-2p', 'font'=>'-Adobe-Courier-Medium-R-Normal--*-100-*-*-*-*-*-*')
+ if $tk_version =~ /^4.*/
+ style_tag_super = TkTextTag.new(t, 'offset'=>'4p', 'font'=>'-Adobe-Courier-Medium-R-Normal--*-100-*-*-*-*-*-*')
+ style_tag_sub = TkTextTag.new(t, 'offset'=>'-2p', 'font'=>'-Adobe-Courier-Medium-R-Normal--*-100-*-*-*-*-*-*')
+ else
+ style_tag_super = TkTextTag.new(t, 'offset'=>'4p', 'font'=>[family, 10])
+ style_tag_sub = TkTextTag.new(t, 'offset'=>'-2p', 'font'=>[family, 10])
+ end
style_tag_margins = TkTextTag.new(t, 'lmargin1'=>'12m', 'lmargin2'=>'6m',
'rmargin'=>'10m')
style_tag_spacing = TkTextTag.new(t, 'spacing1'=>'10p', 'spacing2'=>'2p',
@@ -247,3 +265,5 @@ spacing3')
}
+txt.width 70
+txt.height 32
diff --git a/ext/tk/sample/demos-jp/textpeer.rb b/ext/tk/sample/demos-jp/textpeer.rb
new file mode 100644
index 0000000000..9b2b57a698
--- /dev/null
+++ b/ext/tk/sample/demos-jp/textpeer.rb
@@ -0,0 +1,78 @@
+# -*- coding: euc-jp -*-
+#
+# text widget peering demo (called by 'widget')
+#
+# based on Tcl/Tk8.5.0 widget demos
+
+if defined?($textpeer_demo) && $textpeer_demo
+ $textpeer_demo.destroy
+ $textpeer_demo = nil
+end
+
+# demo toplevel widget
+$textpeer_demo = TkToplevel.new {|w|
+ title("Text Wdget Peering Demonstration")
+ iconname("textpeer")
+ positionWindow(w)
+}
+
+count = [0]
+
+## Define a widget that we peer from; it won't ever actually be shown though
+first = TkText.new($textpeer_demo, :widgetname=>"text#{count[0] += 1}")
+first.insert :end,"このデモは一つの組を成したテキストウィジェットを示します。"
+first.insert :end,"それらのテキストウィジェットは対等(ピア;peer)の関係に"
+first.insert :end,"なっています。"
+first.insert :end,"それらは、基盤となるデータモデルは共通のものを持ちますが、"
+first.insert :end,"画面表示位置、編集位置、選択範囲(selection)については"
+first.insert :end,"独立に持つことができます。"
+first.insert :end,"各テキストウィジェットの脇にある"
+first.insert :end,"「ピア(peer)の作成」ボタンを使えば、"
+first.insert :end,"新たなピアを追加することが可能です。"
+first.insert :end,"また「ピア(peer)の消去」ボタンを使えば、"
+first.insert :end,"特定のピアウィジェットを消去することもできます。"
+
+## Procedures to make and kill clones; most of this is just so that the demo
+## looks nice...
+def makeClone(count, win, txt)
+ cnt = (count[0] += 1)
+ peer = TkText::Peer.new(txt, win, :widgetname=>"text#{cnt}")
+ sbar = TkScrollbar.new(win, :widgetname=>"sb#{cnt}")
+ peer.yscrollbar sbar
+ b1 = TkButton.new(win, :widgetname=>"clone#{cnt}",
+ :text=>'ピア(peer)の作成',
+ :command=>proc{makeClone(count, win, peer)})
+ b2 = TkButton.new(win, :widgetname=>"kill#{cnt}",
+ :text=>'ピア(peer)の消去',
+ :command=>proc{killClone(win, cnt)})
+ row = cnt * 2
+ TkGrid.configure(peer, sbar, b1, :sticky=>'nsew', :row=>row)
+ TkGrid.configure('^', '^', b2, :sticky=>'nsew', :row=>(row+=1))
+ TkGrid.configure(b1, b2, :sticky=>'new')
+ TkGrid.rowconfigure(win, b2, :weight=>1)
+end
+
+def killClone(win, cnt)
+ Tk.destroy("#{win.path}.text#{cnt}", "#{win.path}.sb#{cnt}",
+ "#{win.path}.clone#{cnt}", "#{win.path}.kill#{cnt}")
+end
+
+## Now set up the GUI
+makeClone(count, $textpeer_demo, first)
+makeClone(count, $textpeer_demo, first)
+first.destroy
+
+## See Code / Dismiss buttons
+TkFrame.new($textpeer_demo){|f|
+ TkButton.new(f, :text=>'閉じる', :width=>15, :command=>proc{
+ $textpeer_demo.destroy
+ $textpeer_demo = nil
+ }).pack(:side=>:left, :expand=>true)
+
+ TkButton.new(f, :text=>'コード参照', :width=>15, :command=>proc{
+ showCode 'textpeer'
+ }).pack(:side=>:left, :expand=>true)
+
+ TkGrid.configure(f, '-', '-', :sticky=>'ew', :row=>5000)
+}
+TkGrid.columnconfigure($textpeer_demo, 0, :weight=>1)
diff --git a/ext/tk/sample/demos-jp/twind.rb b/ext/tk/sample/demos-jp/twind.rb
index 166a44cdb2..d0fa8ca49e 100644
--- a/ext/tk/sample/demos-jp/twind.rb
+++ b/ext/tk/sample/demos-jp/twind.rb
@@ -207,7 +207,11 @@ def textWindPlot (t)
cursor 'top_left_arrow'
}
- font = '-Adobe-Helvetica-Medium-R-Normal--*-180-*-*-*-*-*-*'
+ if $tk_version =~ /^4.*/
+ font = '-Adobe-Helvetica-Medium-R-Normal--*-180-*-*-*-*-*-*'
+ else
+ font = 'Helvetica 18'
+ end
TkcLine.new($twind_plot, 100, 250, 400, 250, 'width'=>2)
TkcLine.new($twind_plot, 100, 250, 100, 50, 'width'=>2)
diff --git a/ext/tk/sample/demos-jp/vscale.rb b/ext/tk/sample/demos-jp/vscale.rb
index eb0cea250d..990ca43215 100644
--- a/ext/tk/sample/demos-jp/vscale.rb
+++ b/ext/tk/sample/demos-jp/vscale.rb
@@ -67,7 +67,6 @@ TkFrame.new($vscale_demo) {|frame|
scale.set 75
}.pack
-
def setHeight(w, height)
height = height + 21
y2 = height - 30
@@ -77,3 +76,4 @@ def setHeight(w, height)
w.coords 'poly',15,20,35,20,35,y2,45,y2,25,height,5,y2,15,y2,15,20
w.coords 'line',15,20,35,20,35,y2,45,y2,25,height,5,y2,15,y2,15,20
end
+
diff --git a/ext/tk/sample/demos-jp/widget b/ext/tk/sample/demos-jp/widget
index 7982a6651e..3eea4c7887 100644
--- a/ext/tk/sample/demos-jp/widget
+++ b/ext/tk/sample/demos-jp/widget
@@ -5,7 +5,7 @@
if RUBY_VERSION < '1.9.0' ### !!!!!!!!!!!!!!
$KCODE = 'euc'
else
- $TK_ENCODING = 'EUC-JP'
+ DEFAULT_TK_ENCODING = 'EUC-JP'
end
# tk 関係ライブラリの読み込み
@@ -13,7 +13,8 @@ require 'tk'
# require 'tkafter'
# widget demo directory 位置の獲得
-$demo_dir = File.dirname($0)
+# $demo_dir = File.dirname($0)
+$demo_dir = File.dirname(__FILE__)
# root の生成
$root = TkRoot.new{title "Ruby/Tk Widget Demonstration"}
@@ -45,18 +46,17 @@ when /^4.*/
# $msg_kanji_font=TkFont.new('Helvetica 16', 'Gothic 16 bold')
when /^8.*/
- $font = TkFont.new('Helvetica -12')
- $kanji_font = TkFont.new('Helvetica -12', 'Mincho -12')
+ $font = TkFont.new('Helvetica 12')
+ $kanji_font = TkFont.new('Helvetica 12', 'Mincho 12')
TkOption.add('*kanjiFont', knjfont, 'startupFile')
- $msg_kanji_font=TkFont.new('Helvetica 16', 'Gothic 16 bold')
+ $msg_kanji_font=TkFont.new('Helvetica 18 bold', 'Gothic 18 bold')
else
- $font = TkFont.new('-*-Helvetica-Medium-R-Normal--*-140-*-*-*-*-*-*', nil)
+ $font = TkFont.new('Helvetica 14', nil)
knjfont = '-*--16-*-jisx0208.1983-0'
- $kanji_font = TkFont.new('-*-Helvetica-Medium-R-Normal--*-140-*-*-*-*-*-*',
- knjfont)
+ $kanji_font = TkFont.new('Helvetic 14', knj)
TkOption.add('*kanjiFont', knjfont, 'startupFile')
- $msg_kanji_font=TkFont.new('-*-Helvetica-Medium-R-Normal--*-140-*-*-*-*-*-*',
+ $msg_kanji_font=TkFont.new('Helvetica 14',
'-*--24-*-jisx0208.1983-0')
end
#######
@@ -185,18 +185,27 @@ else
textFrame.pack('expand'=>'yes', 'fill'=>'both')
statusBar = TkFrame.new($root) {|f|
+ if $tk_version =~ /^4.*/
+ statusfont = '-*-Helvetica-Medium-R-Normal--*-120-*-*-*-*-*-*'
+ else
+ statusfont = 'Helvetica 10'
+ end
$statusBarLabel = \
TkLabel.new(f, 'text'=>" ", 'relief'=>'sunken', 'bd'=>1, 'anchor'=>'w',
- 'font'=>'-*-Helvetica-Medium-R-Normal--*-120-*-*-*-*-*-*') \
+ 'font'=>statusfont) \
.pack('side'=>'left', 'padx'=>2, 'expand'=>'yes', 'fill'=>'both')
TkLabel.new(f, 'width'=>8, 'relief'=>'sunken', 'bd'=>1, 'anchor'=>'w',
- 'font'=>'-*-Helvetica-Medium-R-Normal--*-120-*-*-*-*-*-*') \
+ 'font'=>statusfont) \
.pack('side'=>'left', 'padx'=>2)
}.pack('side'=>'bottom', 'fill'=>'x', 'pady'=>2)
end
# テキストタグ設定
-tag_title = TkTextTag.new(txt, 'font'=>'-*-Helvetica-Bold-R-Normal--*-180-*-*-*-*-*-*')
+if $tk_version =~ /^4.*/
+ tag_title = TkTextTag.new(txt, 'font'=>'-*-Helvetica-Bold-R-Normal--*-180-*-*-*-*-*-*')
+else
+ tag_title = TkTextTag.new(txt, 'font'=>'Helvetica 18 bold')
+end
#tag_kanji_title = TkTextTag.new(txt, 'kanjifont'=>$msg_kanji_font)
#tag_middle = TkTextTag.new(txt, 'kanjifont'=>$kanji_font)
tag_kanji_title = TkTextTag.new(txt, 'font'=>$msg_kanji_font)
@@ -372,6 +381,8 @@ txt.insert('end', "5. ウィンドウを埋め込んだテキスト (機能に対応したバージョンの
txt.insert('end', " \n ", tag_demospace)
txt.insert('end', "6. 検索\n", tag_demo, "demo-search")
txt.insert('end', " \n ", tag_demospace)
+txt.insert('end', "7. テキストウィジェットの対等化(peering) (機能に対応したバージョンのTkが必要)\n", tag_demo, "demo-textpeer")
+txt.insert('end', " \n ", tag_demospace)
txt.insert('end', "\n")
#txt.insert('end', "キャンバス\n", tag_middle)
@@ -492,7 +503,11 @@ def showVars1(parent, *args)
text "変数値:"
width 20
anchor 'center'
- font '-Adobe-helvetica-medium-r-normal--*-180-*-*-*-*-*-*'
+ if $tk_version =~ /^4.*/
+ font '-Adobe-helvetica-medium-r-normal--*-180-*-*-*-*-*-*'
+ else
+ font 'Helvetica 14'
+ end
}.pack('side'=>'top', 'fill'=>'x')
len = 1
args.each{|vnam,vbody|
@@ -639,7 +654,9 @@ end
private :_null_binding
def eval_samplecode(code)
- Thread.new{ _null_binding.pseudo_toplevel_eval{ eval(code) } }.run
+ #eval(code)
+ #_null_binding.pseudo_toplevel_eval{ eval(code) }
+ Thread.new{ _null_binding.pseudo_toplevel_eval{ eval(code) } }
Tk.update
end
@@ -931,7 +948,7 @@ end
#
def aboutBox
Tk.messageBox('icon'=>'info', 'type'=>'ok', 'title'=>'About Widget Demo',
- 'message'=>"Ruby/Tk ウィジェットデモ Ver.1.6.0-jp\n\n" +
+ 'message'=>"Ruby/Tk ウィジェットデモ Ver.1.6.3-jp\n\n" +
"based on demos of Tk8.1 -- 8.5 " +
"( Copyright:: " +
"(c) 1996-1997 Sun Microsystems, Inc. / " +
diff --git a/ext/tk/sample/encstr_usage.rb b/ext/tk/sample/encstr_usage.rb
index 4285ec861c..b22c2504ac 100644
--- a/ext/tk/sample/encstr_usage.rb
+++ b/ext/tk/sample/encstr_usage.rb
@@ -11,7 +11,7 @@ t1 = TkText.new(:height=>5).pack
t2 = TkText.new(:height=>5).pack
t3 = TkText.new(:height=>5).pack
-src_str = IO.readlines('iso2022-kr.txt').join
+src_str = IO.readlines(File.join(File.dirname(__FILE__),'iso2022-kr.txt')).join
t1.insert('end',
"use neither Tk::EncodedString class nor Tk.encoding= method\n\n")
@@ -23,7 +23,8 @@ t2.insert('end',
t2.insert('end', enc_str)
Tk.encoding = 'iso2022-kr'
-t3.insert('end', "use Tk.encoding = 'iso2022-kr'\n\n")
+t3.insert('end', "use Tk.encoding = 'iso2022-kr' (Tk.force_default_encoding? == #{Tk.force_default_encoding?})\n\n")
+
t3.insert('end', src_str)
Tk.mainloop
diff --git a/ext/tk/sample/irbtkw.rbw b/ext/tk/sample/irbtkw.rbw
index f6a35be6ed..3fb6dde626 100644
--- a/ext/tk/sample/irbtkw.rbw
+++ b/ext/tk/sample/irbtkw.rbw
@@ -4,7 +4,7 @@
#
# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
#
-release = '2006/11/06'
+release = '2008/03/08'
require 'tk'
begin
@@ -15,10 +15,32 @@ end
require 'irb'
+if TkCore::WITH_ENCODING
+else
+ # $KCODE setup
+ case Tk.encoding
+ when 'shiftjis', 'cp932'
+ $KCODE='SJIS'
+ when 'euc-jp'
+ $KCODE='EUC'
+ when 'utf-8', 'unicode'
+ $KCODE='UTF8'
+ else
+ # unknown
+ end
+end
+
# console setup
top = TkToplevel.new(:title=>'IRB console')
top.protocol(:WM_DELETE_WINDOW){ Tk.exit }
+case (Tk.windowingsystem)
+when 'win32'
+ fnt = ['MS Gothic', '-12']
+else
+ fnt = ['courier', '-12']
+end
+
console = TkTextIO.new(top, :mode=>:console,
:width=>80).pack(:side=>:left,
:expand=>true, :fill=>:both)
diff --git a/ext/tk/sample/tkextlib/tile/demo.rb b/ext/tk/sample/tkextlib/tile/demo.rb
index b604410da4..1a9c029701 100644
--- a/ext/tk/sample/tkextlib/tile/demo.rb
+++ b/ext/tk/sample/tkextlib/tile/demo.rb
@@ -20,6 +20,12 @@ def version?(ver)
TkPackage.vcompare(Tk::Tile.package_version, ver) >= 0
end
+# define Tcl/Tk procedures for compatibility
+Tk::Tile.__define_LoadImages_proc_for_compatibility__!
+Tk::Tile::Style.__define_wrapper_proc_for_compatibility__!
+
+Tk::Tile::Style.theme_create('step')
+
Tk.load_tclscript(File.join(demodir, 'toolbutton.tcl'))
Tk.load_tclscript(File.join(demodir, 'repeater.tcl'))
@@ -55,7 +61,7 @@ $V = TkVariable.new_hash(:THEME => 'default',
:CHOICE => 2)
# Add in any available loadable themes.
-TkPackage.names.find_all{|n| n =~ /^tile::theme::/}.each{|pkg|
+TkPackage.names.find_all{|n| n =~ /^(tile|ttk)::theme::/}.each{|pkg|
name = pkg.split('::')[-1]
unless $THEMELIST.assoc(name)
$THEMELIST << [name, Tk.tk_call('string', 'totitle', name)]
@@ -66,7 +72,8 @@ TkPackage.names.find_all{|n| n =~ /^tile::theme::/}.each{|pkg|
$RUBY_THEMELIST = []
begin
load(File.join(demodir, 'themes', 'kroc.rb'), true)
-rescue
+rescue => e
+raise e
$RUBY_THEMELIST << ['kroc-rb', 'Kroc (by Ruby)', false]
else
$RUBY_THEMELIST << ['kroc-rb', 'Kroc (by Ruby)', true]
@@ -79,8 +86,8 @@ def makeThemeControl(parent)
:variable=>$V.ref(:THEME),
:command=>proc{setTheme(theme)})
b.grid(:sticky=>:ew)
- unless (TkPackage.names.find{|n| n == "tile::theme::#{theme}"})
- b.state(:disabled)
+ unless (TkPackage.names.find{|n| n =~ /(tile|ttk)::theme::#{theme}/})
+ b.ttk_state(:disabled)
end
}
$RUBY_THEMELIST.each{|theme, name, available|
@@ -88,7 +95,7 @@ def makeThemeControl(parent)
:variable=>$V.ref(:THEME),
:command=>proc{setTheme(theme)})
b.grid(:sticky=>:ew)
- b.state(:disabled) unless available
+ b.ttk_state(:disabled) unless available
}
c
end
@@ -98,7 +105,7 @@ def makeThemeMenu(parent)
$THEMELIST.each{|theme, name|
m.add(:radiobutton, :label=>name, :variable=>$V.ref(:THEME),
:value=>theme, :command=>proc{setTheme(theme)})
- unless (TkPackage.names.find{|n| n == "tile::theme::#{theme}"})
+ unless (TkPackage.names.find{|n| n =~ /(tile|ttk)::theme::#{theme}/})
m.entryconfigure(:end, :state=>:disabled)
end
}
@@ -111,8 +118,10 @@ def makeThemeMenu(parent)
end
def setTheme(theme)
- if (TkPackage.names.find{|n| n == "tile::theme::#{theme}"})
- TkPackage.require("tile::theme::#{theme}")
+ if (pkg = TkPackage.names.find{|n| n =~ /(tile|ttk)::theme::#{theme}/})
+ unless Tk::Tile::Style.theme_names.find{|n| n == theme}
+ TkPackage.require(pkg)
+ end
end
Tk::Tile::Style.theme_use(theme)
end
@@ -675,7 +684,7 @@ values = %w(list abc def ghi jkl mno pqr stu vwx yz)
combo, :values=>values, :textvariable=>$V.ref(:COMBO))
cb.pack(:side=>:top, :padx=>2, :pady=>2, :expand=>false, :fill=>:x)
if i == 1
- cb.state :readonly
+ cb.ttk_state :readonly
begin
cb.current = 3 # ignore if unsupported (tile0.4)
rescue
@@ -922,11 +931,11 @@ end
def updateStates
$states_list.each{|st|
begin
- $State[st] = $Widget.window.instate(st)
+ $State[st] = $Widget.window.ttk_instate(st)
rescue
- $states_btns[st].state('disabled')
+ $states_btns[st].ttk_state('disabled')
else
- $states_btns[st].state('!disabled')
+ $states_btns[st].ttk_state('!disabled')
end
}
end
@@ -934,9 +943,9 @@ end
def changeState(st)
if $Widget.value != ''
if $State.bool_element(st)
- $Widget.window.state(st)
+ $Widget.window.ttk_state(st)
else
- $Widget.window.state("!#{st}")
+ $Widget.window.ttk_state("!#{st}")
end
end
end
diff --git a/ext/tk/sample/tkextlib/tile/themes/blue/pkgIndex.tcl b/ext/tk/sample/tkextlib/tile/themes/blue/pkgIndex.tcl
index 19ddda7c73..4facac70d8 100644
--- a/ext/tk/sample/tkextlib/tile/themes/blue/pkgIndex.tcl
+++ b/ext/tk/sample/tkextlib/tile/themes/blue/pkgIndex.tcl
@@ -1,6 +1,6 @@
# Package index for tile demo pixmap themes.
if {[file isdirectory [file join $dir blue]]} {
- package ifneeded tile::theme::blue 0.0.1 \
+ package ifneeded tile::theme::blue 0.7 \
[list source [file join $dir blue.tcl]]
}
diff --git a/ext/tk/sample/tkextlib/tile/themes/kroc.rb b/ext/tk/sample/tkextlib/tile/themes/kroc.rb
index f67ce7a897..27006d847f 100644
--- a/ext/tk/sample/tkextlib/tile/themes/kroc.rb
+++ b/ext/tk/sample/tkextlib/tile/themes/kroc.rb
@@ -95,8 +95,35 @@ def kroc_rb_settings
#
# Elements:
#
- if TkPackage.vcompare(Tk::Tile.package_version, '0.5') >= 0
+ if Tk::Tile::TILE_SPEC_VERSION_ID >= 8
+ Tk::Tile::Style.element_create('Button.button',
+ :image,
+ [ $images['button-n'],
+ :pressed, $images['button-p'],
+ :active, $images['button-h'],
+ ], :border=>3, :sticky=>:ew)
+
+ Tk::Tile::Style.element_create('Checkbutton.indicator',
+ :image,
+ [ $images['check-nu'],
+ [:pressed, :selected],$images['check-nc'],
+ :pressed, $images['check-nu'],
+ [:active, :selected], $images['check-hc'],
+ :active, $images['check-hu'],
+ :selected, $images['check-nc'],
+ ], :sticky=>:w)
+ Tk::Tile::Style.element_create('Radiobutton.indicator',
+ :image,
+ [ $images['radio-nu'],
+ [:pressed,:selected],$images['radio-nc'],
+ :pressed, $images['radio-nu'],
+ [:active,:selected], $images['radio-hc'],
+ :active, $images['radio-hu'],
+ :selected, $images['radio-nc'],
+ ], :sticky=>:w)
+
+ elsif TkPackage.vcompare(Tk::Tile.package_version, '0.5') >= 0
Tk::Tile::Style.element_create('Button.button',
:image, $images['button-n'],
:map=>[
@@ -125,7 +152,6 @@ def kroc_rb_settings
], :sticky=>:w)
else # tile 0.4 or earlier
-
Tk::Tile::Style.element_create('Button.button', :pixmap,
:images=>[
:pressed, $images['button-p'],
diff --git a/ext/tk/sample/tkextlib/tile/toolbutton.tcl b/ext/tk/sample/tkextlib/tile/toolbutton.tcl
index 2656fff6d8..4e08034e31 100644
--- a/ext/tk/sample/tkextlib/tile/toolbutton.tcl
+++ b/ext/tk/sample/tkextlib/tile/toolbutton.tcl
@@ -4,18 +4,6 @@
# Demonstration of custom widget styles.
#
-set tile_ver [package require tile]
-if {[package vcompare $tile_ver 0.8] >= 0} {
- set style ::ttk::style
-} {
- set style style
-}
-if {[package vcompare $tile_ver 0.7] >= 0} {
- set conf_subcmd configure
-} {
- set conf_subcmd default
-}
-
#
# ~ BACKGROUND
#
@@ -54,8 +42,7 @@ if {[package vcompare $tile_ver 0.7] >= 0} {
# style; see demo.tcl.)
#
-#$style theme settings "step" {
-$style theme settings "alt" {
+style theme settings "step" {
#
# First, we use [style layout] to define what elements to
@@ -64,7 +51,7 @@ $style theme settings "alt" {
# and a label. (See also the TScrollbar layout definition
# in demos/blue.tcl for a more complicated layout spec.)
#
- $style layout Toolbutton {
+ style layout Toolbutton {
Toolbutton.background
Toolbutton.border -children {
Toolbutton.padding -children {
@@ -81,7 +68,7 @@ $style theme settings "alt" {
# For many options (like -background), the defaults
# inherited from the parent style are sufficient.
#
- $style $conf_subcmd Toolbutton -width 0 -padding 1 -relief flat -borderwidth 2
+ style default Toolbutton -width 0 -padding 1 -relief flat -borderwidth 2
#
# Finally, use [style map] to specify state-specific
@@ -91,7 +78,7 @@ $style theme settings "alt" {
# over the widget). Each state-value pair is checked
# in order, and the first matching state takes precedence.
#
- $style map Toolbutton -relief {
+ style map Toolbutton -relief {
disabled flat
selected sunken
pressed sunken
@@ -106,19 +93,19 @@ $style theme settings "alt" {
# design decisions from an aesthetic standpoint.)
#
if {![catch {package require tile::theme::blue}]} {
-$style theme settings "blue" {
+style theme settings "blue" {
#
# Default values:
#
- $style $conf_subcmd Toolbutton \
+ style default Toolbutton \
-width 0 -relief flat -borderwidth 2 \
-background #6699CC -foreground #000000 ;
#
# Configure state-specific values for -relief, as before:
#
- $style map Toolbutton -relief {
+ style map Toolbutton -relief {
disabled flat
selected sunken
pressed sunken
@@ -129,8 +116,8 @@ $style theme settings "blue" {
# Adjust the -padding at the same time, to enhance
# the raised/sunken illusion:
#
- $style $conf_subcmd Toolbutton -padding 4
- $style map Toolbutton -padding {
+ style default Toolbutton -padding 4
+ style map Toolbutton -padding {
disabled {4}
selected {6 6 2 2}
pressed {6 6 2 2}
@@ -141,7 +128,7 @@ $style theme settings "blue" {
# ... and change the foreground and background colors
# when the mouse cursor is over the widget:
#
- $style map Toolbutton -background {
+ style map Toolbutton -background {
active #008800
} -foreground {
active #FFFFFF
diff --git a/ext/tk/sample/tkrttimer.rb b/ext/tk/sample/tkrttimer.rb
index 531f4a8d5a..0abd4ecbd2 100644
--- a/ext/tk/sample/tkrttimer.rb
+++ b/ext/tk/sample/tkrttimer.rb
@@ -17,8 +17,17 @@ TkLabel.new(f2, :text=>'use TkRTTimer class').pack
label2 = TkLabel.new(:parent=>f2, :relief=>:raised,
:width=>10).pack(:fill=>:both)
-TkLabel.new(:text=>'Interval setting of each timer is 10 ms.',
- :padx=>10, :pady=>5).pack
+TkLabel.new(:padx=>10, :pady=>5, :justify=>'left', :text=><<EOT).pack
+Interval setting of each timer object is 10 ms.
+Each timer object counts up the value on each callback
+(the value is not the clock data).
+The count of the TkTimer object is delayed by execution
+time of callbacks and inaccuracy of interval.
+On the other hand, the count of the TkRTTimer object is
+not delayed. Its callback interval is not accurate too.
+But it can compute error correction about the time when
+a callback should start.
+EOT
# define the procedure repeated by the TkTimer object
tick = proc{|aobj| #<== TkTimer object
diff --git a/ext/tk/sample/tksleep_sample.rb b/ext/tk/sample/tksleep_sample.rb
new file mode 100644
index 0000000000..23f6eca54e
--- /dev/null
+++ b/ext/tk/sample/tksleep_sample.rb
@@ -0,0 +1,29 @@
+require 'tk'
+
+v = TkVariable.new(0)
+l = TkLabel.new(:textvariable=>v).pack(:pady=>[1, 10])
+
+a = TkButton.new(:text=>"button A :: proc{p ['AAA', v.value]}").pack(:fill=>:x, :pady=>[1, 15], :padx=>15)
+a.command{p ['AAA', v.value]}
+
+TkLabel.new(:text=>'Callback of the button B returns LIFO order').pack
+b = TkButton.new(:text=>"button B :: proc{n = v.value; p ['B:start', n]; Tk.sleep(10000); p ['B:end', n]}").pack(:fill=>:x, :pady=>[1, 15], :padx=>15)
+b.command{n = v.value; p ['B:start', n]; Tk.sleep(10000); p ['B:end', n]}
+
+TkLabel.new(:text=>'Callback of the button C returns FIFO order').pack
+c = TkButton.new(:text=>"button C :: proc{n = v.value; Thread.new{p ['C:start', n]; Tk.sleep(10000); p ['C:end', n]}}").pack(:fill=>:x, :pady=>[1, 15], :padx=>15)
+c.command{n = v.value; Thread.new{p ['C:start', n]; Tk.sleep(10000); p ['C:end', n]}}
+
+TkLabel.new(:text=>'Callback of the button D blocks eventloop (no respond to event)').pack
+d = TkButton.new(:text=>"button D :: proc{n = v.value; p ['D:start', n]; sleep(10); p ['D:end', n]}").pack(:fill=>:x, :pady=>[1,15], :padx=>15)
+d.command{n = v.value; p ['D:start', n]; sleep(10); p ['D:end', n]}
+
+TkLabel.new(:text=>'Callback of the button E is another way to avoid eventloop blocking').pack
+e = TkButton.new(:text=>"button E :: proc{n = v.value; Thread.new{p ['D:start', n]; sleep(10); p ['D:end', n]}}").pack(:fill=>:x, :pady=>[1,15], :padx=>15)
+e.command{n = v.value; Thread.new{p ['D:start', n]; sleep(10); p ['D:end', n]}}
+
+TkButton.new(:text=>'QUIT', :command=>proc{exit}).pack
+
+TkTimer.new(500, -1){v.numeric += 1}.start
+
+Tk.mainloop
diff --git a/ext/tk/sample/ttk_wrapper.rb b/ext/tk/sample/ttk_wrapper.rb
new file mode 100644
index 0000000000..30ae0ece53
--- /dev/null
+++ b/ext/tk/sample/ttk_wrapper.rb
@@ -0,0 +1,154 @@
+#!/usr/bin/env ruby
+#
+# ttk_wrapper.rb -- use Ttk widgets as default on old Ruby/Tk scripts
+#
+# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)
+#
+version = '0.1'
+#
+##########################################################################
+# parse commandline arguments
+##########################################################################
+require 'optparse'
+opt = OptionParser.new("Usage: #{$0} [options] rubytk_script" << "\n " <<
+ "Ruby/Tk script wrapper. Use Ttk widgets as default.")
+opt.version = version
+
+OPTS = {}
+OPTS[:themedir] = []
+OPTS[:rb_theme] = []
+OPTS[:theme] = 'default'
+
+opt.on('-l', '--list', 'list available theme names'){|v| OPTS[:list] = true}
+opt.on('-t', '--theme theme', 'theme name'){|v| OPTS[:theme] = v}
+opt.on('-d', '--themedir themes_dir', 'directory of theme definitions'){|v|
+ OPTS[:themedir] << v
+}
+opt.on('-r', '--rubytheme rb_theme', 'theme definition file (ruby script)'){|v|
+ OPTS[:rb_theme] << v
+}
+opt.on('-v', '--verbose', 'print verbose messages'){|v| OPTS[:verbose] = true}
+
+opt.parse!(ARGV)
+
+
+##########################################################################
+# load Ttk (Tile) extension
+##########################################################################
+require 'tk'
+
+begin
+ require 'tkextlib/tile'
+ Tk.default_widget_set = :Ttk
+rescue LoadError
+ if OPTS[:verbose]
+ print "warning: fail to load 'Ttk' extension. use standard widgets.\n"
+ end
+end
+
+if OPTS[:verbose]
+ print "current default widget set is '#{Tk.default_widget_set}'\n"
+end
+
+
+##########################################################################
+# use themes defined on the demo of Ttk (Tile) extension
+##########################################################################
+demodir = File.dirname(__FILE__)
+demo_themesdir = File.expand_path(File.join(demodir, 'tkextlib', 'tile', 'themes'))
+
+Tk::AUTO_PATH.lappend(*OPTS[:themedir]) unless OPTS[:themedir].empty?
+Tk::AUTO_PATH.lappend('.', demodir, demo_themesdir)
+
+OPTS[:themedir] << demo_themesdir
+print "theme-dirs: #{OPTS[:themedir].inspect}\n" if OPTS[:verbose]
+
+OPTS[:themedir].each{|themesdir|
+ if File.directory?(themesdir)
+ Dir.foreach(themesdir){|name|
+ next if name == '.' || name == '..'
+ path = File.join(themesdir, name)
+ Tk::AUTO_PATH.lappend(path) if File.directory?(path)
+ }
+ end
+}
+
+# This forces an update of the available packages list. It's required
+# for package names to find the themes in demos/themes/*.tcl
+Tk.ip_eval("#{TkPackage.unknown_proc} Tcl #{TkPackage.provide('Tcl')}")
+
+# load themes written in Ruby.
+themes_by_ruby = [File.join(demo_themesdir, 'kroc.rb')]
+themes_by_ruby.concat OPTS[:rb_theme]
+print "ruby-themes: #{themes_by_ruby.inspect}\n" if OPTS[:verbose]
+
+themes_by_ruby.each{|f|
+ begin
+ load(f, true)
+ rescue LoadError
+ print "fail to load \"#{f}\"\n" if OPTS[:verbose]
+ end
+}
+
+
+##########################################################################
+# define Tcl/Tk procedures for compatibility.
+# those are required when want to use themes included
+# in "sample/tkextlib/tile/demo.rb".
+##########################################################################
+Tk::Tile.__define_LoadImages_proc_for_compatibility__!
+Tk::Tile::Style.__define_wrapper_proc_for_compatibility__!
+
+
+##########################################################################
+# ignore unsupported options of Ttk widgets
+##########################################################################
+TkConfigMethod.__set_IGNORE_UNKNOWN_CONFIGURE_OPTION__! true
+TkItemConfigMethod.__set_IGNORE_UNKNOWN_CONFIGURE_OPTION__! true
+
+
+##########################################################################
+# define utility method
+##########################################################################
+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)
+end
+
+
+##########################################################################
+# make theme name list
+##########################################################################
+ThemesList = Tk::Tile::Style.theme_names
+TkPackage.names.find_all{|n| n =~ /^(tile|ttk)::theme::/}.each{|pkg|
+ ThemesList << pkg.split('::')[-1]
+}
+ThemesList.uniq!
+
+
+##########################################################################
+# set theme of widget style
+##########################################################################
+if OPTS[:list] || OPTS[:verbose]
+ print "supported theme names: #{ThemesList}\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]
+
+
+##########################################################################
+# load script
+##########################################################################
+if (script = File.expand_path(ARGV.shift))
+ print "load script \"#{script}\"\n" if OPTS[:verbose]
+ load(script)
+else
+ print "Error: no script is given.\n"
+ print opt.help
+ exit(1)
+end
diff --git a/ext/tk/stubs.c b/ext/tk/stubs.c
index d0aaf61f31..6d3b330f0e 100644
--- a/ext/tk/stubs.c
+++ b/ext/tk/stubs.c
@@ -1,5 +1,11 @@
+/************************************************
+
+ stubs.c - Tcl/Tk stubs support
+
+************************************************/
+
+#include "ruby.h"
#include "stubs.h"
-#include "ruby/ruby.h"
#include <tcl.h>
#include <tk.h>
@@ -86,7 +92,12 @@ static DL_HANDLE tcl_dll = (DL_HANDLE)0;
static DL_HANDLE tk_dll = (DL_HANDLE)0;
int
+#ifdef RUBY_VM
ruby_open_tcl_dll(char *appname)
+#else
+ruby_open_tcl_dll(appname)
+ char *appname;
+#endif
{
void (*p_Tcl_FindExecutable)(const char *);
int n;
@@ -168,7 +179,12 @@ ruby_open_tk_dll()
}
int
+#ifdef RUBY_VM
ruby_open_tcltk_dll(char *appname)
+#else
+ruby_open_tcltk_dll(appname)
+ char *appname;
+#endif
{
return( ruby_open_tcl_dll(appname) || ruby_open_tk_dll() );
}
@@ -187,7 +203,12 @@ tk_stubs_init_p()
Tcl_Interp *
+#ifdef RUBY_VM
ruby_tcl_create_ip_and_stubs_init(int *st)
+#else
+ruby_tcl_create_ip_and_stubs_init(st)
+ int *st;
+#endif
{
Tcl_Interp *tcl_ip;
@@ -269,7 +290,12 @@ ruby_tcl_stubs_init()
}
int
+#ifdef RUBY_VM
ruby_tk_stubs_init(Tcl_Interp *tcl_ip)
+#else
+ruby_tk_stubs_init(tcl_ip)
+ Tcl_Interp *tcl_ip;
+#endif
{
Tcl_ResetResult(tcl_ip);
@@ -304,7 +330,12 @@ ruby_tk_stubs_init(Tcl_Interp *tcl_ip)
}
int
+#ifdef RUBY_VM
ruby_tk_stubs_safeinit(Tcl_Interp *tcl_ip)
+#else
+ruby_tk_stubs_safeinit(tcl_ip)
+ Tcl_Interp *tcl_ip;
+#endif
{
Tcl_ResetResult(tcl_ip);
@@ -390,7 +421,12 @@ static int open_tcl_dll = 0;
static int call_tk_stubs_init = 0;
int
+#ifdef RUBY_VM
ruby_open_tcl_dll(char *appname)
+#else
+ruby_open_tcl_dll(appname)
+ char *appname;
+#endif
{
if (appname) {
Tcl_FindExecutable(appname);
@@ -402,7 +438,8 @@ ruby_open_tcl_dll(char *appname)
return TCLTK_STUBS_OK;
}
-int ruby_open_tk_dll()
+int
+ruby_open_tk_dll()
{
if (!open_tcl_dll) {
/* ruby_open_tcl_dll(RSTRING_PTR(rb_argv0)); */
@@ -412,7 +449,13 @@ int ruby_open_tk_dll()
return TCLTK_STUBS_OK;
}
-int ruby_open_tcltk_dll(char *appname)
+int
+#ifdef RUBY_VM
+ruby_open_tcltk_dll(char *appname)
+#else
+ruby_open_tcltk_dll(appname)
+ char *appname;
+#endif
{
return( ruby_open_tcl_dll(appname) || ruby_open_tk_dll() );
}
@@ -430,7 +473,12 @@ tk_stubs_init_p()
}
Tcl_Interp *
+#ifdef RUBY_VM
ruby_tcl_create_ip_and_stubs_init(int *st)
+#else
+ruby_tcl_create_ip_and_stubs_init(st)
+ int *st;
+#endif
{
Tcl_Interp *tcl_ip;
@@ -458,7 +506,12 @@ ruby_tcl_stubs_init()
}
int
+#ifdef RUBY_VM
ruby_tk_stubs_init(Tcl_Interp *tcl_ip)
+#else
+ruby_tk_stubs_init(tcl_ip)
+ Tcl_Interp *tcl_ip;
+#endif
{
if (Tk_Init(tcl_ip) == TCL_ERROR)
return FAIL_Tk_Init;
@@ -474,7 +527,12 @@ ruby_tk_stubs_init(Tcl_Interp *tcl_ip)
}
int
+#ifdef RUBY_VM
ruby_tk_stubs_safeinit(Tcl_Interp *tcl_ip)
+#else
+ruby_tk_stubs_safeinit(tcl_ip)
+ Tcl_Interp *tcl_ip;
+#endif
{
#if TCL_MAJOR_VERSION >= 8
if (Tk_SafeInit(tcl_ip) == TCL_ERROR)
diff --git a/ext/tk/tcltklib.c b/ext/tk/tcltklib.c
index df70e67c9d..18e0fd76fb 100644
--- a/ext/tk/tcltklib.c
+++ b/ext/tk/tcltklib.c
@@ -4,10 +4,20 @@
* Oct. 24, 1997 Y. Matsumoto
*/
-#define TCLTKLIB_RELEASE_DATE "2007-12-21"
+#define TCLTKLIB_RELEASE_DATE "2008-03-29"
-#include "ruby/ruby.h"
+#include "ruby.h"
+
+#ifdef RUBY_VM
+/* #include "ruby/ruby.h" */
#include "ruby/signal.h"
+#include "ruby/encoding.h"
+#else
+/* #include "ruby.h" */
+#include "rubysig.h"
+#include "version.h"
+#endif
+
#undef EXTERN /* avoid conflict with tcl.h of tcl8.2 or before */
#include <stdio.h>
#ifdef HAVE_STDARG_PROTOTYPES
@@ -29,6 +39,24 @@
#define TCL_FINAL_RELEASE 2
#endif
+static struct {
+ int major;
+ int minor;
+ int patchlevel;
+ int type;
+} tcltk_version = {0, 0, 0, 0};
+
+static void
+set_tcltk_version()
+{
+ if (tcltk_version.major) return;
+
+ Tcl_GetVersion(&(tcltk_version.major),
+ &(tcltk_version.minor),
+ &(tcltk_version.patchlevel),
+ &(tcltk_version.type));
+}
+
#if TCL_MAJOR_VERSION >= 8
# ifndef CONST84
# if TCL_MAJOR_VERSION == 8 && TCL_MINOR_VERSION <= 4 /* Tcl8.0.x -- 8.4b1 */
@@ -82,6 +110,26 @@ static void ip_finalize _((Tcl_Interp*));
static int at_exit = 0;
+#ifdef RUBY_VM
+static VALUE cRubyEncoding;
+
+/* encoding */
+static int ENCODING_INDEX_UTF8;
+static int ENCODING_INDEX_BINARY;
+#endif
+static VALUE ENCODING_NAME_UTF8;
+static VALUE ENCODING_NAME_BINARY;
+
+static VALUE create_dummy_encoding_for_tk_core _((VALUE, VALUE, VALUE));
+static VALUE create_dummy_encoding_for_tk _((VALUE, VALUE));
+static int update_encoding_table _((VALUE, VALUE, VALUE));
+static VALUE encoding_table_get_name_core _((VALUE, VALUE, VALUE));
+static VALUE encoding_table_get_obj_core _((VALUE, VALUE, VALUE));
+static VALUE encoding_table_get_name _((VALUE, VALUE));
+static VALUE encoding_table_get_obj _((VALUE, VALUE));
+static VALUE create_encoding_table _((VALUE));
+static VALUE ip_get_encoding_table _((VALUE));
+
/* for callback break & continue */
static VALUE eTkCallbackReturn;
@@ -100,6 +148,9 @@ static VALUE tcltkip_class;
static ID ID_at_enc;
static ID ID_at_interp;
+static ID ID_encoding_name;
+static ID ID_encoding_table;
+
static ID ID_stop_p;
static ID ID_alive_p;
static ID ID_kill;
@@ -123,9 +174,30 @@ static VALUE ip_invoke _((int, VALUE*, VALUE));
static VALUE tk_funcall _((VALUE(), int, VALUE*, VALUE));
+/* Tcl's object type */
+#if TCL_MAJOR_VERSION >= 8
+static char *Tcl_ObjTypeName_ByteArray = "bytearray";
+static Tcl_ObjType *Tcl_ObjType_ByteArray;
+
+static char *Tcl_ObjTypeName_String = "string";
+static Tcl_ObjType *Tcl_ObjType_String;
+
+#if TCL_MAJOR_VERSION > 8 || (TCL_MAJOR_VERSION == 8 && TCL_MINOR_VERSION >= 1)
+#define IS_TCL_BYTEARRAY(obj) ((obj)->typePtr == Tcl_ObjType_ByteArray)
+#define IS_TCL_STRING(obj) ((obj)->typePtr == Tcl_ObjType_String)
+#define IS_TCL_VALID_STRING(obj) ((obj)->bytes != (char*)NULL)
+#endif
+#endif
+
/* safe Tcl_Eval and Tcl_GlobalEval */
static int
+#ifdef RUBY_VM
tcl_eval(Tcl_Interp *interp, const char *cmd)
+#else
+tcl_eval(interp, cmd)
+ Tcl_Interp *interp;
+ const char *cmd; /* don't have to be writable */
+#endif
{
char *buf = strdup(cmd);
int ret;
@@ -140,7 +212,13 @@ tcl_eval(Tcl_Interp *interp, const char *cmd)
#define Tcl_Eval tcl_eval
static int
+#ifdef RUBY_VM
tcl_global_eval(Tcl_Interp *interp, const char *cmd)
+#else
+tcl_global_eval(interp, cmd)
+ Tcl_Interp *interp;
+ const char *cmd; /* don't have to be writable */
+#endif
{
char *buf = strdup(cmd);
int ret;
@@ -311,13 +389,24 @@ call_queue_mark(struct call_queue *q)
static VALUE eventloop_thread;
+#ifdef RUBY_VM
+Tcl_ThreadId tk_eventloop_thread_id; /* native thread ID of Tcl interpreter */
+#endif
static VALUE eventloop_stack;
static int window_event_mode = ~(TCL_WINDOW_EVENTS | TCL_IDLE_EVENTS);
static VALUE watchdog_thread;
Tcl_Interp *current_interp;
-
+
+/* thread control strategy */
+#define CONTROL_BY_STATUS_OF_RB_THREAD_WAIT_FOR_VALUE 0
+#define USE_TOGGLE_WINDOW_MODE_FOR_IDLE 0
+#define DO_THREAD_SCHEDULE_AT_CALLBACK_DONE 1
+
+#if CONTROL_BY_STATUS_OF_RB_THREAD_WAIT_FOR_VALUE
+static int have_rb_thread_waited_for_value = 0;
+#endif
/*
* 'event_loop_max' is a maximum events which the eventloop processes in one
@@ -326,12 +415,27 @@ Tcl_Interp *current_interp;
* 'timer_tick' is a limit of one term of thread scheduling.
* If 'timer_tick' == 0, then not use the timer for thread scheduling.
*/
-#define DEFAULT_EVENT_LOOP_MAX 800/*counts*/
-#define DEFAULT_NO_EVENT_TICK 10/*counts*/
-#define DEFAULT_NO_EVENT_WAIT 20/*milliseconds ( 1 -- 999 ) */
-#define WATCHDOG_INTERVAL 10/*milliseconds ( 1 -- 999 ) */
-#define DEFAULT_TIMER_TICK 0/*milliseconds ( 0 -- 999 ) */
-#define NO_THREAD_INTERRUPT_TIME 100/*milliseconds ( 1 -- 999 ) */
+#ifdef RUBY_VM
+#define DEFAULT_EVENT_LOOP_MAX 800/*counts*/
+#define DEFAULT_NO_EVENT_TICK 10/*counts*/
+#define DEFAULT_NO_EVENT_WAIT 10/*milliseconds ( 1 -- 999 ) */
+#define WATCHDOG_INTERVAL 10/*milliseconds ( 1 -- 999 ) */
+#define DEFAULT_TIMER_TICK 0/*milliseconds ( 0 -- 999 ) */
+#define NO_THREAD_INTERRUPT_TIME 100/*milliseconds ( 1 -- 999 ) */
+#if CONTROL_BY_STATUS_OF_RB_THREAD_WAIT_FOR_VALUE
+#define DEFAULT_HAS_WAIT_THREAD_TICK 50/*counts*/
+#endif
+#else /* ! RUBY_VM */
+#define DEFAULT_EVENT_LOOP_MAX 800/*counts*/
+#define DEFAULT_NO_EVENT_TICK 10/*counts*/
+#define DEFAULT_NO_EVENT_WAIT 20/*milliseconds ( 1 -- 999 ) */
+#define WATCHDOG_INTERVAL 10/*milliseconds ( 1 -- 999 ) */
+#define DEFAULT_TIMER_TICK 0/*milliseconds ( 0 -- 999 ) */
+#define NO_THREAD_INTERRUPT_TIME 100/*milliseconds ( 1 -- 999 ) */
+#if CONTROL_BY_STATUS_OF_RB_THREAD_WAIT_FOR_VALUE
+#define DEFAULT_HAS_WAIT_THREAD_TICK 50/*counts*/
+#endif
+#endif
static int event_loop_max = DEFAULT_EVENT_LOOP_MAX;
static int no_event_tick = DEFAULT_NO_EVENT_TICK;
@@ -339,6 +443,9 @@ static int no_event_wait = DEFAULT_NO_EVENT_WAIT;
static int timer_tick = DEFAULT_TIMER_TICK;
static int req_timer_tick = DEFAULT_TIMER_TICK;
static int run_timer_flag = 0;
+#if CONTROL_BY_STATUS_OF_RB_THREAD_WAIT_FOR_VALUE
+static int has_wait_thread_tick = DEFAULT_HAS_WAIT_THREAD_TICK;
+#endif
static int event_loop_wait_event = 0;
static int event_loop_abort_on_exc = 1;
@@ -567,7 +674,7 @@ struct tcltkip {
Tcl_Namespace *default_ns; /* default namespace */
#endif
#ifdef RUBY_VM
- Tcl_ThreadId tk_thread_id; /* default namespace */
+ Tcl_ThreadId tk_thread_id; /* native thread ID of Tcl interpreter */
#endif
int has_orig_exit; /* has original 'exit' command ? */
Tcl_CmdInfo orig_exit_info; /* command info of original 'exit' command */
@@ -604,9 +711,9 @@ deleted_ip(ptr)
#endif
) {
DUMP1("ip is deleted");
- return Qtrue;
+ return 1;
}
- return Qfalse;
+ return 0;
}
/* increment/decrement reference count of tcltkip */
@@ -770,6 +877,7 @@ tcltkip_init_tk(interp)
/* treat excetiopn on Tcl side */
static VALUE rbtk_pending_exception;
static int rbtk_eventloop_depth = 0;
+static int rbtk_internal_eventloop_handler = 0;
static int
@@ -779,7 +887,9 @@ pending_exception_check0()
if (!NIL_P(exc) && rb_obj_is_kind_of(exc, rb_eException)) {
DUMP1("find a pending exception");
- if (rbtk_eventloop_depth > 0) {
+ if (rbtk_eventloop_depth > 0
+ || rbtk_internal_eventloop_handler > 0
+ ) {
return 1; /* pending */
} else {
rbtk_pending_exception = Qnil;
@@ -812,7 +922,9 @@ pending_exception_check1(thr_crit_bup, ptr)
if (!NIL_P(exc) && rb_obj_is_kind_of(exc, rb_eException)) {
DUMP1("find a pending exception");
- if (rbtk_eventloop_depth > 0) {
+ if (rbtk_eventloop_depth > 0
+ || rbtk_internal_eventloop_handler > 0
+ ) {
return 1; /* pending */
} else {
rbtk_pending_exception = Qnil;
@@ -870,8 +982,11 @@ call_original_exit(ptr, state)
if (info->isNativeObjectProc) {
Tcl_Obj **argv;
- // argv = (Tcl_Obj **)ALLOC_N(Tcl_Obj *, 3); /* XXXXXXXXXX */
+ /* argv = (Tcl_Obj **)ALLOC_N(Tcl_Obj *, 3); */ /* XXXXXXXXXX */
argv = (Tcl_Obj **)ckalloc(sizeof(Tcl_Obj *) * 3);
+#if 0 /* use Tcl_Preserve/Release */
+ Tcl_Preserve((ClientData)argv); /* XXXXXXXX */
+#endif
argv[0] = Tcl_NewStringObj("exit", 4);
argv[1] = state_obj;
argv[2] = (Tcl_Obj *)NULL;
@@ -879,13 +994,24 @@ call_original_exit(ptr, state)
ptr->return_value
= (*(info->objProc))(info->objClientData, ptr->ip, 2, argv);
- free(argv);
+#if 0 /* use Tcl_EventuallyFree */
+ Tcl_EventuallyFree((ClientData)argv, TCL_DYNAMIC); /* XXXXXXXX */
+#else
+#if 0 /* use Tcl_Preserve/Release */
+ Tcl_Release((ClientData)argv); /* XXXXXXXX */
+#endif
+ /* free(argv); */
+ ckfree((char*)argv);
+#endif
} else {
/* string interface */
char **argv;
- //argv = (char **)ALLOC_N(char *, 3); /* XXXXXXXXXX */
- argv = (char **)ckalloc(sizeof(char *) * 3);
+ /* argv = (char **)ALLOC_N(char *, 3); */ /* XXXXXXXXXX */
+ argv = (char **)ckalloc(sizeof(char *) * 3);
+#if 0 /* use Tcl_Preserve/Release */
+ Tcl_Preserve((ClientData)argv); /* XXXXXXXX */
+#endif
argv[0] = "exit";
/* argv[1] = Tcl_GetString(state_obj); */
argv[1] = Tcl_GetStringFromObj(state_obj, (int*)NULL);
@@ -894,7 +1020,15 @@ call_original_exit(ptr, state)
ptr->return_value = (*(info->proc))(info->clientData, ptr->ip,
2, (CONST84 char **)argv);
- free(argv);
+#if 0 /* use Tcl_EventuallyFree */
+ Tcl_EventuallyFree((ClientData)argv, TCL_DYNAMIC); /* XXXXXXXX */
+#else
+#if 0 /* use Tcl_Preserve/Release */
+ Tcl_Release((ClientData)argv); /* XXXXXXXX */
+#endif
+ /* free(argv); */
+ ckfree((char*)argv);
+#endif
}
Tcl_DecrRefCount(state_obj);
@@ -903,7 +1037,11 @@ call_original_exit(ptr, state)
{
/* string interface */
char **argv;
- argv = (char **)ALLOC_N(char *, 3);
+ /* argv = (char **)ALLOC_N(char *, 3); */
+ argv = (char **)ckalloc(sizeof(char *) * 3);
+#if 0 /* use Tcl_Preserve/Release */
+ Tcl_Preserve((ClientData)argv); /* XXXXXXXX */
+#endif
argv[0] = "exit";
argv[1] = RSTRING_PTR(rb_fix2str(INT2NUM(state), 10));
argv[2] = (char *)NULL;
@@ -911,7 +1049,15 @@ call_original_exit(ptr, state)
ptr->return_value = (*(info->proc))(info->clientData, ptr->ip,
2, argv);
- free(argv);
+#if 0 /* use Tcl_EventuallyFree */
+ Tcl_EventuallyFree((ClientData)argv, TCL_DYNAMIC); /* XXXXXXXX */
+#else
+#if 0 /* use Tcl_Preserve/Release */
+ Tcl_Release((ClientData)argv); /* XXXXXXXX */
+#endif
+ /* free(argv); */
+ ckfree(argv);
+#endif
}
#endif
@@ -954,6 +1100,21 @@ _timer_for_tcl(clientData)
/* tick_counter += event_loop_max; */
}
+#ifdef RUBY_VM
+#if USE_TOGGLE_WINDOW_MODE_FOR_IDLE
+static int
+toggle_eventloop_window_mode_for_idle()
+{
+ if (window_event_mode & TCL_IDLE_EVENTS) {
+ window_event_mode &= ~TCL_IDLE_EVENTS;
+ return 1;
+ } else {
+ window_event_mode |= TCL_IDLE_EVENTS;
+ return 0;
+ }
+}
+#endif
+#endif
static VALUE
set_eventloop_window_mode(self, mode)
@@ -1262,8 +1423,10 @@ ip_evloop_abort_on_exc_set(self, val)
}
static VALUE
-lib_num_of_mainwindows(self)
+lib_num_of_mainwindows_core(self, argc, argv)
VALUE self;
+ int argc; /* dummy */
+ VALUE *argv; /* dummy */
{
if (tk_stubs_init_p()) {
return INT2FIX(Tk_GetNumMainWindows());
@@ -1272,7 +1435,37 @@ lib_num_of_mainwindows(self)
}
}
+static VALUE
+lib_num_of_mainwindows(self)
+ VALUE self;
+{
+ return tk_funcall(lib_num_of_mainwindows_core, 0, (VALUE*)NULL, self);
+}
+
+
+#ifdef RUBY_VM /* Ruby 1.9+ !!! */
+static VALUE
+call_DoOneEvent_core(flag_val)
+ VALUE flag_val;
+{
+ int flag;
+
+ flag = FIX2INT(flag_val);
+ if (Tcl_DoOneEvent(flag)) {
+ return Qtrue;
+ } else {
+ return Qfalse;
+ }
+}
+
+static VALUE
+call_DoOneEvent(flag_val)
+ VALUE flag_val;
+{
+ return tk_funcall(call_DoOneEvent_core, 0, (VALUE*)NULL, flag_val);
+}
+#else /* Ruby 1.8- */
static VALUE
call_DoOneEvent(flag_val)
VALUE flag_val;
@@ -1286,6 +1479,8 @@ call_DoOneEvent(flag_val)
return Qfalse;
}
}
+#endif
+
static VALUE
eventloop_sleep(dummy)
@@ -1296,29 +1491,78 @@ eventloop_sleep(dummy)
t.tv_sec = (time_t)0;
t.tv_usec = (time_t)(no_event_wait*1000.0);
-#if 0
#ifdef HAVE_NATIVETHREAD
+#ifdef RUBY_VM
+#if 0
if (!ruby_native_thread_p()) {
rb_bug("cross-thread violation on eventloop_sleep()");
}
#endif
+#else
+ if (!is_ruby_native_thread()) {
+ rb_bug("cross-thread violation on eventloop_sleep()");
+ }
+#endif
#endif
DUMP2("eventloop_sleep: rb_thread_wait_for() at thread : %lx", rb_thread_current());
rb_thread_wait_for(t);
DUMP2("eventloop_sleep: finish at thread : %lx", rb_thread_current());
-#if 0
#ifdef HAVE_NATIVETHREAD
+#ifdef RUBY_VM
+#if 0
if (!ruby_native_thread_p()) {
rb_bug("cross-thread violation on eventloop_sleep()");
}
#endif
+#else
+ if (!is_ruby_native_thread()) {
+ rb_bug("cross-thread violation on eventloop_sleep()");
+ }
+#endif
#endif
return Qnil;
}
+#define USE_EVLOOP_THREAD_ALONE_CHECK_FLAG 0
+
+#if USE_EVLOOP_THREAD_ALONE_CHECK_FLAG
+static int
+get_thread_alone_check_flag()
+{
+#ifdef RUBY_VM
+ return 0;
+#else
+ set_tcltk_version();
+
+ if (tcltk_version.major < 8) {
+ /* Tcl/Tk 7.x */
+ return 1;
+ } else if (tcltk_version.major == 8) {
+ if (tcltk_version.minor < 5) {
+ /* Tcl/Tk 8.0 - 8.4 */
+ return 1;
+ } else if (tcltk_version.minor == 5) {
+ if (tcltk_version.type < TCL_FINAL_RELEASE) {
+ /* Tcl/Tk 8.5a? - 8.5b? */
+ return 1;
+ } else {
+ /* Tcl/Tk 8.5.x */
+ return 0;
+ }
+ } else {
+ /* Tcl/Tk 8.6 - 8.9 ?? */
+ return 0;
+ }
+ } else {
+ /* Tcl/Tk 9+ ?? */
+ return 0;
+ }
+#endif
+}
+#endif
static int
lib_eventloop_core(check_root, update_flag, check_var, interp)
@@ -1334,7 +1578,9 @@ lib_eventloop_core(check_root, update_flag, check_var, interp)
int thr_crit_bup;
int status;
int depth = rbtk_eventloop_depth;
-
+#if USE_EVLOOP_THREAD_ALONE_CHECK_FLAG
+ int thread_alone_check_flag = 1;
+#endif
if (update_flag) DUMP1("update loop start!!");
@@ -1353,9 +1599,14 @@ lib_eventloop_core(check_root, update_flag, check_var, interp)
timer_token = (Tcl_TimerToken)NULL;
}
+#if USE_EVLOOP_THREAD_ALONE_CHECK_FLAG
+ /* version check */
+ thread_alone_check_flag = get_thread_alone_check_flag();
+#endif
+
for(;;) {
-#ifdef RUBY_VM
- if (0) {
+#if USE_EVLOOP_THREAD_ALONE_CHECK_FLAG
+ if (thread_alone_check_flag && rb_thread_alone()) {
#else
if (rb_thread_alone()) {
#endif
@@ -1365,8 +1616,8 @@ lib_eventloop_core(check_root, update_flag, check_var, interp)
if (update_flag) {
event_flag = update_flag | TCL_DONT_WAIT; /* for safety */
} else {
- // event_flag = TCL_ALL_EVENTS;
- event_flag = TCL_FILE_EVENTS | TCL_TIMER_EVENTS | TCL_DONT_WAIT;
+ event_flag = TCL_ALL_EVENTS;
+ /* event_flag = TCL_ALL_EVENTS | TCL_DONT_WAIT; */
}
if (timer_tick == 0 && update_flag == 0) {
@@ -1393,11 +1644,19 @@ lib_eventloop_core(check_root, update_flag, check_var, interp)
if (status) {
switch (status) {
case TAG_RAISE:
+#ifdef RUBY_VM
if (NIL_P(rb_errinfo())) {
+#else
+ if (NIL_P(ruby_errinfo)) {
+#endif
rbtk_pending_exception
= rb_exc_new2(rb_eException, "unknown exception");
} else {
+#ifdef RUBY_VM
rbtk_pending_exception = rb_errinfo();
+#else
+ rbtk_pending_exception = ruby_errinfo;
+#endif
if (!NIL_P(rbtk_pending_exception)) {
if (rbtk_eventloop_depth == 0) {
@@ -1412,10 +1671,18 @@ lib_eventloop_core(check_root, update_flag, check_var, interp)
break;
case TAG_FATAL:
+#ifdef RUBY_VM
if (NIL_P(rb_errinfo())) {
+#else
+ if (NIL_P(ruby_errinfo)) {
+#endif
rb_exc_raise(rb_exc_new2(rb_eFatal, "FATAL"));
} else {
+#ifdef RUBY_VM
rb_exc_raise(rb_errinfo());
+#else
+ rb_exc_raise(ruby_errinfo);
+#endif
}
}
}
@@ -1514,6 +1781,17 @@ lib_eventloop_core(check_root, update_flag, check_var, interp)
st = RTEST(rb_protect(call_DoOneEvent,
INT2FIX(event_flag & window_event_mode),
&status));
+#if USE_TOGGLE_WINDOW_MODE_FOR_IDLE
+ if (!st) {
+ if (toggle_eventloop_window_mode_for_idle()) {
+ /* idle-mode -> event-mode*/
+ tick_counter = 0;
+ } else {
+ /* event-mode -> idle-mode */
+ tick_counter = event_loop_max;
+ }
+ }
+#endif
}
#else
/* st = Tcl_DoOneEvent(event_flag); */
@@ -1523,12 +1801,20 @@ lib_eventloop_core(check_root, update_flag, check_var, interp)
if (status) {
switch (status) {
case TAG_RAISE:
+#ifdef RUBY_VM
if (NIL_P(rb_errinfo())) {
+#else
+ if (NIL_P(ruby_errinfo)) {
+#endif
rbtk_pending_exception
= rb_exc_new2(rb_eException,
"unknown exception");
} else {
+#ifdef RUBY_VM
rbtk_pending_exception = rb_errinfo();
+#else
+ rbtk_pending_exception = ruby_errinfo;
+#endif
if (!NIL_P(rbtk_pending_exception)) {
if (rbtk_eventloop_depth == 0) {
@@ -1543,10 +1829,18 @@ lib_eventloop_core(check_root, update_flag, check_var, interp)
break;
case TAG_FATAL:
+#ifdef RUBY_VM
if (NIL_P(rb_errinfo())) {
+#else
+ if (NIL_P(ruby_errinfo)) {
+#endif
rb_exc_raise(rb_exc_new2(rb_eFatal, "FATAL"));
} else {
+#ifdef RUBY_VM
rb_exc_raise(rb_errinfo());
+#else
+ rb_exc_raise(ruby_errinfo);
+#endif
}
}
}
@@ -1579,6 +1873,13 @@ lib_eventloop_core(check_root, update_flag, check_var, interp)
return 0;
}
+#if CONTROL_BY_STATUS_OF_RB_THREAD_WAIT_FOR_VALUE
+ if (have_rb_thread_waited_for_value) {
+ tick_counter += no_event_tick;
+ have_rb_thread_waited_for_value = 0;
+ }
+#endif
+
if (st) {
tick_counter++;
} else {
@@ -1590,19 +1891,26 @@ lib_eventloop_core(check_root, update_flag, check_var, interp)
tick_counter += no_event_tick;
/* rb_thread_wait_for(t); */
-#if 0
+
rb_protect(eventloop_sleep, Qnil, &status);
-#endif
if (status) {
switch (status) {
case TAG_RAISE:
+#ifdef RUBY_VM
if (NIL_P(rb_errinfo())) {
+#else
+ if (NIL_P(ruby_errinfo)) {
+#endif
rbtk_pending_exception
= rb_exc_new2(rb_eException,
"unknown exception");
} else {
+#ifdef RUBY_VM
rbtk_pending_exception = rb_errinfo();
+#else
+ rbtk_pending_exception = ruby_errinfo;
+#endif
if (!NIL_P(rbtk_pending_exception)) {
if (rbtk_eventloop_depth == 0) {
@@ -1617,11 +1925,19 @@ lib_eventloop_core(check_root, update_flag, check_var, interp)
break;
case TAG_FATAL:
+#ifdef RUBY_VM
if (NIL_P(rb_errinfo())) {
+#else
+ if (NIL_P(ruby_errinfo)) {
+#endif
rb_exc_raise(rb_exc_new2(rb_eFatal,
"FATAL"));
} else {
+#ifdef RUBY_VM
rb_exc_raise(rb_errinfo());
+#else
+ rb_exc_raise(ruby_errinfo);
+#endif
}
}
}
@@ -1676,12 +1992,16 @@ lib_eventloop_core(check_root, update_flag, check_var, interp)
}
}
- DUMP1("thread scheduling");
- rb_thread_schedule();
+ DUMP1("thread scheduling");
+ rb_thread_schedule();
}
DUMP1("trap check & thread scheduling");
- if (update_flag == 0) ; // TODO: CHECK_INTS
+#ifdef RUBY_VM
+ /* if (update_flag == 0) CHECK_INTS; */ /*XXXXXXXXXXXXX TODO !!!! */
+#else
+ if (update_flag == 0) CHECK_INTS;
+#endif
}
return 1;
@@ -1728,19 +2048,35 @@ lib_eventloop_main(args)
switch (status) {
case TAG_RAISE:
+#ifdef RUBY_VM
if (NIL_P(rb_errinfo())) {
+#else
+ if (NIL_P(ruby_errinfo)) {
+#endif
rbtk_pending_exception
= rb_exc_new2(rb_eException, "unknown exception");
} else {
+#ifdef RUBY_VM
rbtk_pending_exception = rb_errinfo();
+#else
+ rbtk_pending_exception = ruby_errinfo;
+#endif
}
return Qnil;
case TAG_FATAL:
+#ifdef RUBY_VM
if (NIL_P(rb_errinfo())) {
+#else
+ if (NIL_P(ruby_errinfo)) {
+#endif
rbtk_pending_exception = rb_exc_new2(rb_eFatal, "FATAL");
} else {
+#ifdef RUBY_VM
rbtk_pending_exception = rb_errinfo();
+#else
+ rbtk_pending_exception = ruby_errinfo;
+#endif
}
return Qnil;
}
@@ -1764,6 +2100,7 @@ lib_eventloop_ensure(args)
rb_thread_critical = ptr->thr_crit_bup;
free(ptr);
+ /* ckfree((char*)ptr); */
return Qnil;
}
@@ -1793,9 +2130,16 @@ lib_eventloop_ensure(args)
}
}
+#ifdef RUBY_VM
+ if (NIL_P(eventloop_thread)) {
+ tk_eventloop_thread_id = (Tcl_ThreadId) 0;
+ }
+#endif
+
rb_thread_critical = ptr->thr_crit_bup;
free(ptr);
+ /* ckfree((char*)ptr);*/
DUMP2("finish current eventloop %lx", current_evloop);
return Qnil;
@@ -1810,10 +2154,14 @@ lib_eventloop_launcher(check_root, update_flag, check_var, interp)
{
volatile VALUE parent_evloop = eventloop_thread;
struct evloop_params *args = ALLOC(struct evloop_params);
+ /* struct evloop_params *args = (struct evloop_params *)ckalloc(sizeof(struct evloop_params)); */
tcl_stubs_check();
eventloop_thread = rb_thread_current();
+#ifdef RUBY_VM
+ tk_eventloop_thread_id = Tcl_GetCurrentThread();
+#endif
if (parent_evloop == eventloop_thread) {
DUMP2("eventloop: recursive call on %lx", parent_evloop);
@@ -1964,6 +2312,9 @@ lib_watchdog_ensure(arg)
VALUE arg;
{
eventloop_thread = Qnil; /* stop eventloops */
+#ifdef RUBY_VM
+ tk_eventloop_thread_id = (Tcl_ThreadId) 0;
+#endif
return Qnil;
}
@@ -1975,6 +2326,11 @@ lib_mainloop_watchdog(argc, argv, self)
{
VALUE check_rootwidget;
+#ifdef RUBY_VM
+ rb_raise(rb_eNotImpError,
+ "eventloop_watchdog is not implemented on Ruby VM.");
+#endif
+
if (rb_scan_args(argc, argv, "01", &check_rootwidget) == 0) {
check_rootwidget = Qtrue;
} else if (RTEST(check_rootwidget)) {
@@ -2068,11 +2424,11 @@ lib_thread_callback(argc, argv, self)
proc = rb_block_proc();
}
- //q = (struct thread_call_proc_arg *)ALLOC(struct thread_call_proc_arg);
- q = (struct thread_call_proc_arg *)ckalloc(sizeof(struct thread_call_proc_arg));
+ q = (struct thread_call_proc_arg *)ALLOC(struct thread_call_proc_arg);
+ /* q = (struct thread_call_proc_arg *)ckalloc(sizeof(struct thread_call_proc_arg)); */
q->proc = proc;
- //q->done = (int*)ALLOC(int);
- q->done = (int*)ckalloc(sizeof(int));
+ q->done = (int*)ALLOC(int);
+ /* q->done = (int*)ckalloc(sizeof(int)); */
*(q->done) = 0;
/* create call-proc thread */
@@ -2091,16 +2447,23 @@ lib_thread_callback(argc, argv, self)
ret = rb_protect(_thread_call_proc_value, th, &status);
}
- //free(q->done);
- //free(q);
- ckfree((char*)q->done);
- ckfree((char*)q);
+ free(q->done);
+ free(q);
+ /* ckfree((char*)q->done); */
+ /* ckfree((char*)q); */
if (NIL_P(rbtk_pending_exception)) {
+#ifdef RUBY_VM
/* return rb_errinfo(); */
if (status) {
rb_exc_raise(rb_errinfo());
}
+#else
+ /* return ruby_errinfo; */
+ if (status) {
+ rb_exc_raise(ruby_errinfo);
+ }
+#endif
} else {
VALUE exc = rbtk_pending_exception;
rbtk_pending_exception = Qnil;
@@ -2225,8 +2588,11 @@ ip_set_exc_message(interp, exc)
}
/* to avoid a garbled error message dialog */
- // buf = ALLOC_N(char, (RSTRING_LEN(msg))+1);
- buf = ckalloc(sizeof(char)*((RSTRING_LEN(msg))+1));
+ /* buf = ALLOC_N(char, (RSTRING(msg)->len)+1);*/
+ /* memcpy(buf, RSTRING(msg)->ptr, RSTRING(msg)->len);*/
+ /* buf[RSTRING(msg)->len] = 0; */
+ buf = ALLOC_N(char, RSTRING_LEN(msg)+1);
+ /* buf = ckalloc(sizeof(char)*((RSTRING_LEN(msg))+1)); */
memcpy(buf, RSTRING_PTR(msg), RSTRING_LEN(msg));
buf[RSTRING_LEN(msg)] = 0;
@@ -2237,8 +2603,8 @@ ip_set_exc_message(interp, exc)
Tcl_AppendResult(interp, Tcl_DStringValue(&dstr), (char*)NULL);
DUMP2("error message:%s", Tcl_DStringValue(&dstr));
Tcl_DStringFree(&dstr);
- //free(buf);
- ckfree(buf);
+ free(buf);
+ /* ckfree(buf); */
#else /* TCL_VERSION <= 8.0 */
Tcl_AppendResult(interp, RSTRING_PTR(msg), (char*)NULL);
@@ -2307,58 +2673,104 @@ tcl_protect_core(interp, proc, data) /* should not raise exception */
goto error;
error:
str = rb_str_new2("LocalJumpError: ");
+#ifdef RUBY_VM
rb_str_append(str, rb_obj_as_string(rb_errinfo()));
+#else
+ rb_str_append(str, rb_obj_as_string(ruby_errinfo));
+#endif
exc = rb_exc_new3(type, str);
break;
case TAG_RETRY:
+#ifdef RUBY_VM
if (NIL_P(rb_errinfo())) {
+#else
+ if (NIL_P(ruby_errinfo)) {
+#endif
DUMP1("rb_protect: retry");
exc = rb_exc_new2(eTkCallbackRetry, "retry jump error");
} else {
+#ifdef RUBY_VM
exc = rb_errinfo();
+#else
+ exc = ruby_errinfo;
+#endif
}
break;
case TAG_REDO:
+#ifdef RUBY_VM
if (NIL_P(rb_errinfo())) {
+#else
+ if (NIL_P(ruby_errinfo)) {
+#endif
DUMP1("rb_protect: redo");
exc = rb_exc_new2(eTkCallbackRedo, "redo jump error");
} else {
+#ifdef RUBY_VM
exc = rb_errinfo();
+#else
+ exc = ruby_errinfo;
+#endif
}
break;
case TAG_RAISE:
+#ifdef RUBY_VM
if (NIL_P(rb_errinfo())) {
+#else
+ if (NIL_P(ruby_errinfo)) {
+#endif
exc = rb_exc_new2(rb_eException, "unknown exception");
} else {
+#ifdef RUBY_VM
exc = rb_errinfo();
+#else
+ exc = ruby_errinfo;
+#endif
}
break;
case TAG_FATAL:
+#ifdef RUBY_VM
if (NIL_P(rb_errinfo())) {
+#else
+ if (NIL_P(ruby_errinfo)) {
+#endif
exc = rb_exc_new2(rb_eFatal, "FATAL");
} else {
+#ifdef RUBY_VM
exc = rb_errinfo();
+#else
+ exc = ruby_errinfo;
+#endif
}
break;
case TAG_THROW:
+#ifdef RUBY_VM
if (NIL_P(rb_errinfo())) {
+#else
+ if (NIL_P(ruby_errinfo)) {
+#endif
DUMP1("rb_protect: throw");
exc = rb_exc_new2(eTkCallbackThrow, "throw jump error");
} else {
+#ifdef RUBY_VM
exc = rb_errinfo();
+#else
+ exc = ruby_errinfo;
+#endif
}
break;
default:
buf = ALLOC_N(char, 256);
+ /* buf = ckalloc(sizeof(char) * 256); */
sprintf(buf, "unknown loncaljmp status %d", status);
exc = rb_exc_new2(rb_eException, buf);
free(buf);
+ /* ckfree(buf); */
break;
}
@@ -2455,12 +2867,18 @@ tcl_protect(interp, proc, data)
int old_trapflag = rb_trap_immediate;
int code;
-#if 0
#ifdef HAVE_NATIVETHREAD
+#ifdef RUBY_VM
+#if 0
if (!ruby_native_thread_p()) {
rb_bug("cross-thread violation on tcl_protect()");
}
#endif
+#else
+ if (!is_ruby_native_thread()) {
+ rb_bug("cross-thread violation on tcl_protect()");
+ }
+#endif
#endif
rb_trap_immediate = 0;
@@ -2523,6 +2941,7 @@ ip_ruby_eval(clientData, interp, argc, argv)
str = Tcl_GetStringFromObj(argv[1], &len);
arg = ALLOC_N(char, len + 1);
+ /* arg = ckalloc(sizeof(char) * (len + 1)); */
memcpy(arg, str, len);
arg[len] = 0;
@@ -2540,6 +2959,7 @@ ip_ruby_eval(clientData, interp, argc, argv)
#if TCL_MAJOR_VERSION >= 8
free(arg);
+ /* ckfree(arg); */
#endif
return code;
@@ -2564,6 +2984,96 @@ ip_ruby_cmd_core(arg)
return ret;
}
+#define SUPPORT_NESTED_CONST_AS_IP_RUBY_CMD_RECEIVER 1
+
+static VALUE
+ip_ruby_cmd_receiver_const_get(name)
+ char *name;
+{
+ volatile VALUE klass = rb_cObject;
+ char *head, *tail;
+ int state;
+
+#if SUPPORT_NESTED_CONST_AS_IP_RUBY_CMD_RECEIVER
+ klass = rb_eval_string_protect(name, &state);
+ if (state) {
+ return Qnil;
+ } else {
+ return klass;
+ }
+#else
+ return rb_const_get(klass, rb_intern(name));
+#endif
+
+ /* TODO!!!!!! */
+ /* support nest of classes/modules */
+
+ /* return rb_eval_string(name); */
+ /* return rb_eval_string_protect(name, &state); */
+
+#if 0 /* doesn't work!! (fail to autoload?) */
+ /* duplicate */
+ head = name = strdup(name);
+
+ /* has '::' at head ? */
+ if (*head == ':') head += 2;
+ tail = head;
+
+ /* search */
+ while(*tail) {
+ if (*tail == ':') {
+ *tail = '\0';
+ klass = rb_const_get(klass, rb_intern(head));
+ tail += 2;
+ head = tail;
+ } else {
+ tail++;
+ }
+ }
+
+ free(name);
+ return rb_const_get(klass, rb_intern(head));
+#endif
+}
+
+static VALUE
+ip_ruby_cmd_receiver_get(str)
+ char *str;
+{
+ volatile VALUE receiver;
+ volatile VALUE klass = rb_cObject;
+ int state;
+
+ if (str[0] == ':' || ('A' <= str[0] && str[0] <= 'Z')) {
+ /* class | module | constant */
+#if SUPPORT_NESTED_CONST_AS_IP_RUBY_CMD_RECEIVER
+ receiver = ip_ruby_cmd_receiver_const_get(str);
+#else
+ receiver = rb_protect(ip_ruby_cmd_receiver_const_get, (VALUE)str, &state);
+ if (state) return Qnil;
+#endif
+ } else if (str[0] == '$') {
+ /* global variable */
+ receiver = rb_gv_get(str);
+ } else {
+ /* global variable omitted '$' */
+ char *buf;
+ int len;
+
+ len = strlen(str);
+ buf = ALLOC_N(char, len + 2);
+ /* buf = ckalloc(sizeof(char) * (len + 2)); */
+ buf[0] = '$';
+ memcpy(buf + 1, str, len);
+ buf[len + 1] = 0;
+ receiver = rb_gv_get(buf);
+ free(buf);
+ /* ckfree(buf); */
+ }
+
+ return receiver;
+}
+
/* ruby_cmd receiver method arg ... */
static int
#if TCL_MAJOR_VERSION >= 8
@@ -2611,6 +3121,7 @@ ip_ruby_cmd(clientData, interp, argc, argv)
/* allocate */
arg = ALLOC(struct cmd_body_arg);
+ /* arg = (struct cmd_body_arg *)ckalloc(sizeof(struct cmd_body_arg)); */
/* get arguments from Tcl objects */
thr_crit_bup = rb_thread_critical;
@@ -2624,24 +3135,8 @@ ip_ruby_cmd(clientData, interp, argc, argv)
str = argv[1];
#endif
DUMP2("receiver:%s",str);
- if (str[0] == ':' || ('A' <= str[0] && str[0] <= 'Z')) {
- /* class | module | constant */
- receiver = rb_const_get(rb_cObject, rb_intern(str));
- } else if (str[0] == '$') {
- /* global variable */
- receiver = rb_gv_get(str);
- } else {
- /* global variable omitted '$' */
- char *buf;
-
- len = strlen(str);
- buf = ALLOC_N(char, len + 2);
- buf[0] = '$';
- memcpy(buf + 1, str, len);
- buf[len + 1] = 0;
- receiver = rb_gv_get(buf);
- free(buf);
- }
+ /* receiver = rb_protect(ip_ruby_cmd_receiver_get, (VALUE)str, &code); */
+ receiver = ip_ruby_cmd_receiver_get(str);
if (NIL_P(receiver)) {
#if 0
rb_raise(rb_eArgError,
@@ -2666,14 +3161,26 @@ ip_ruby_cmd(clientData, interp, argc, argv)
/* get args */
args = rb_ary_new2(argc - 2);
+#ifdef RUBY_VM
+#else
+ RARRAY(args)->len = 0;
+#endif
for(i = 3; i < argc; i++) {
#if TCL_MAJOR_VERSION >= 8
str = Tcl_GetStringFromObj(argv[i], &len);
DUMP2("arg:%s",str);
+#ifdef RUBY_VM
rb_ary_push(args, rb_tainted_str_new(str, len));
+#else
+ RARRAY(args)->ptr[RARRAY(args)->len++] = rb_tainted_str_new(str, len);
+#endif
#else /* TCL_MAJOR_VERSION < 8 */
DUMP2("arg:%s",argv[i]);
+#ifdef RUBY_VM
rb_ary_push(args, rb_tainted_str_new2(argv[i]));
+#else
+ RARRAY(args)->ptr[RARRAY(args)->len++] = rb_tainted_str_new2(argv[i]);
+#endif
#endif
}
@@ -2688,6 +3195,7 @@ ip_ruby_cmd(clientData, interp, argc, argv)
code = tcl_protect(interp, ip_ruby_cmd_core, (VALUE)arg);
free(arg);
+ /* ckfree((char*)arg); */
return code;
}
@@ -2864,12 +3372,18 @@ ip_rbUpdateCommand(clientData, interp, objc, objv)
"IP is deleted");
return TCL_ERROR;
}
-#if 0
#ifdef HAVE_NATIVETHREAD
+#ifdef RUBY_VM
+#if 0
if (!ruby_native_thread_p()) {
rb_bug("cross-thread violation on ip_ruby_eval()");
}
#endif
+#else
+ if (!is_ruby_native_thread()) {
+ rb_bug("cross-thread violation on ip_ruby_eval()");
+ }
+#endif
#endif
if (objc == 1) {
@@ -3013,10 +3527,16 @@ ip_rb_threadUpdateCommand(clientData, interp, objc, objv)
"IP is deleted");
return TCL_ERROR;
}
-#if 0
#ifdef HAVE_NATIVETHREAD
+#ifdef RUBY_VM
+#if 0
if (!ruby_native_thread_p()) {
- rb_bug("cross-thread violation on ip_ruby_eval()");
+ rb_bug("cross-thread violation on ip_rb_threadUpdateCommand()");
+ }
+#endif
+#else
+ if (!is_ruby_native_thread()) {
+ rb_bug("cross-thread violation on ip_rb_threadUpdateCommand()");
}
#endif
#endif
@@ -3080,8 +3600,11 @@ ip_rb_threadUpdateCommand(clientData, interp, objc, objv)
DUMP1("pass argument check");
- param = (struct th_update_param *)Tcl_Alloc(sizeof(struct th_update_param));
- Tcl_Preserve(param);
+ /* param = (struct th_update_param *)Tcl_Alloc(sizeof(struct th_update_param)); */
+ param = (struct th_update_param *)ckalloc(sizeof(struct th_update_param));
+#if 0 /* use Tcl_Preserve/Release */
+ Tcl_Preserve((ClientData)param);
+#endif
param->thread = current_thread;
param->done = 0;
@@ -3093,8 +3616,15 @@ ip_rb_threadUpdateCommand(clientData, interp, objc, objv)
rb_thread_stop();
}
- Tcl_Release(param);
- Tcl_Free((char *)param);
+#if 0 /* use Tcl_EventuallyFree */
+ Tcl_EventuallyFree((ClientData)param, TCL_DYNAMIC); /* XXXXXXXX */
+#else
+#if 0 /* use Tcl_Preserve/Release */
+ Tcl_Release((ClientData)param);
+#endif
+ /* Tcl_Free((char *)param); */
+ ckfree((char *)param);
+#endif
DUMP1("finish Ruby's 'thread_update'");
return TCL_OK;
@@ -3192,10 +3722,16 @@ ip_rbVwaitCommand(clientData, interp, objc, objv)
#endif
Tcl_Preserve(interp);
-#if 0
#ifdef HAVE_NATIVETHREAD
+#ifdef RUBY_VM
+#if 0
if (!ruby_native_thread_p()) {
- rb_bug("cross-thread violation on ip_ruby_eval()");
+ rb_bug("cross-thread violation on ip_rbVwaitCommand()");
+ }
+#endif
+#else
+ if (!is_ruby_native_thread()) {
+ rb_bug("cross-thread violation on ip_rbVwaitCommand()");
}
#endif
#endif
@@ -3588,6 +4124,7 @@ ip_rbTkWaitCommand(clientData, interp, objc, objv)
thr_crit_bup = rb_thread_critical;
rb_thread_critical = Qtrue;
+ /* This function works on the Tk eventloop thread only. */
if (!tk_stubs_init_p() || Tk_MainWindow(interp) == (Tk_Window)NULL) {
window = NULL;
} else {
@@ -3595,7 +4132,7 @@ ip_rbTkWaitCommand(clientData, interp, objc, objv)
}
if (window == NULL) {
- Tcl_AppendResult(interp, "tkwait: ",
+ Tcl_AppendResult(interp, ": tkwait: ",
"no main-window (not Tk application?)",
(char*)NULL);
rb_thread_critical = thr_crit_bup;
@@ -3684,7 +4221,8 @@ ip_rbTkWaitCommand(clientData, interp, objc, objv)
case TKWAIT_WINDOW:
thr_crit_bup = rb_thread_critical;
rb_thread_critical = Qtrue;
-
+
+ /* This function works on the Tk eventloop thread only. */
if (!tk_stubs_init_p() || Tk_MainWindow(interp) == (Tk_Window)NULL) {
window = NULL;
} else {
@@ -3696,7 +4234,7 @@ ip_rbTkWaitCommand(clientData, interp, objc, objv)
#endif
if (window == NULL) {
- Tcl_AppendResult(interp, "tkwait: ",
+ Tcl_AppendResult(interp, ": tkwait: ",
"no main-window (not Tk application?)",
(char*)NULL);
rb_thread_critical = thr_crit_bup;
@@ -3902,8 +4440,11 @@ ip_rb_threadVwaitCommand(clientData, interp, objc, objv)
thr_crit_bup = rb_thread_critical;
rb_thread_critical = Qtrue;
- param = (struct th_vwait_param *)Tcl_Alloc(sizeof(struct th_vwait_param));
- Tcl_Preserve(param);
+ /* param = (struct th_vwait_param *)Tcl_Alloc(sizeof(struct th_vwait_param)); */
+ param = (struct th_vwait_param *)ckalloc(sizeof(struct th_vwait_param));
+#if 0 /* use Tcl_Preserve/Release */
+ Tcl_Preserve((ClientData)param);
+#endif
param->thread = current_thread;
param->done = 0;
@@ -3921,8 +4462,15 @@ ip_rb_threadVwaitCommand(clientData, interp, objc, objv)
rb_thread_critical = thr_crit_bup;
if (ret != TCL_OK) {
- Tcl_Release(param);
- Tcl_Free((char *)param);
+#if 0 /* use Tcl_EventuallyFree */
+ Tcl_EventuallyFree((ClientData)param, TCL_DYNAMIC); /* XXXXXXXX */
+#else
+#if 0 /* use Tcl_Preserve/Release */
+ Tcl_Release((ClientData)param);
+#endif
+ /* Tcl_Free((char *)param); */
+ ckfree((char *)param);
+#endif
#if TCL_MAJOR_VERSION >= 8
Tcl_DecrRefCount(objv[1]);
@@ -3945,8 +4493,15 @@ ip_rb_threadVwaitCommand(clientData, interp, objc, objv)
rb_threadVwaitProc, (ClientData) param);
}
- Tcl_Release(param);
- Tcl_Free((char *)param);
+#if 0 /* use Tcl_EventuallyFree */
+ Tcl_EventuallyFree((ClientData)param, TCL_DYNAMIC); /* XXXXXXXX */
+#else
+#if 0 /* use Tcl_Preserve/Release */
+ Tcl_Release((ClientData)param);
+#endif
+ /* Tcl_Free((char *)param); */
+ ckfree((char *)param);
+#endif
rb_thread_critical = thr_crit_bup;
@@ -4087,8 +4642,11 @@ ip_rb_threadTkWaitCommand(clientData, interp, objc, objv)
nameString = objv[2];
#endif
- param = (struct th_vwait_param *)Tcl_Alloc(sizeof(struct th_vwait_param));
- Tcl_Preserve(param);
+ /* param = (struct th_vwait_param *)Tcl_Alloc(sizeof(struct th_vwait_param)); */
+ param = (struct th_vwait_param *)ckalloc(sizeof(struct th_vwait_param));
+#if 0 /* use Tcl_Preserve/Release */
+ Tcl_Preserve((ClientData)param);
+#endif
param->thread = current_thread;
param->done = 0;
@@ -4112,8 +4670,15 @@ ip_rb_threadTkWaitCommand(clientData, interp, objc, objv)
rb_thread_critical = thr_crit_bup;
if (ret != TCL_OK) {
+#if 0 /* use Tcl_EventuallyFree */
+ Tcl_EventuallyFree((ClientData)param, TCL_DYNAMIC); /* XXXXXXXX */
+#else
+#if 0 /* use Tcl_Preserve/Release */
Tcl_Release(param);
- Tcl_Free((char *)param);
+#endif
+ /* Tcl_Free((char *)param); */
+ ckfree((char *)param);
+#endif
#if TCL_MAJOR_VERSION >= 8
Tcl_DecrRefCount(objv[2]);
@@ -4150,21 +4715,42 @@ ip_rb_threadTkWaitCommand(clientData, interp, objc, objv)
thr_crit_bup = rb_thread_critical;
rb_thread_critical = Qtrue;
+#if 0 /* variable 'tkwin' must keep the token of MainWindow */
if (!tk_stubs_init_p() || Tk_MainWindow(interp) == (Tk_Window)NULL) {
window = NULL;
} else {
window = Tk_NameToWindow(interp, nameString, tkwin);
}
+#else
+ if (!tk_stubs_init_p() || tkwin == (Tk_Window)NULL) {
+ window = NULL;
+ } else {
+ /* Tk_NameToWindow() returns right token on non-eventloop thread */
+ Tcl_CmdInfo info;
+ if (Tcl_GetCommandInfo(interp, ".", &info)) { /* check root */
+ window = Tk_NameToWindow(interp, nameString, tkwin);
+ } else {
+ window = NULL;
+ }
+ }
+#endif
if (window == NULL) {
- Tcl_AppendResult(interp, "thread_tkwait: ",
+ Tcl_AppendResult(interp, ": thread_tkwait: ",
"no main-window (not Tk application?)",
(char*)NULL);
rb_thread_critical = thr_crit_bup;
+#if 0 /* use Tcl_EventuallyFree */
+ Tcl_EventuallyFree((ClientData)param, TCL_DYNAMIC); /* XXXXXXXX */
+#else
+#if 0 /* use Tcl_Preserve/Release */
Tcl_Release(param);
- Tcl_Free((char *)param);
+#endif
+ /* Tcl_Free((char *)param); */
+ ckfree((char *)param);
+#endif
#if TCL_MAJOR_VERSION >= 8
Tcl_DecrRefCount(objv[2]);
@@ -4213,8 +4799,15 @@ ip_rb_threadTkWaitCommand(clientData, interp, objc, objv)
Tcl_Release(window);
+#if 0 /* use Tcl_EventuallyFree */
+ Tcl_EventuallyFree((ClientData)param, TCL_DYNAMIC); /* XXXXXXXX */
+#else
+#if 0 /* use Tcl_Preserve/Release */
Tcl_Release(param);
- Tcl_Free((char *)param);
+#endif
+ /* Tcl_Free((char *)param); */
+ ckfree((char *)param);
+#endif
#if TCL_MAJOR_VERSION >= 8
Tcl_DecrRefCount(objv[2]);
@@ -4239,25 +4832,46 @@ ip_rb_threadTkWaitCommand(clientData, interp, objc, objv)
thr_crit_bup = rb_thread_critical;
rb_thread_critical = Qtrue;
+#if 0 /* variable 'tkwin' must keep the token of MainWindow */
if (!tk_stubs_init_p() || Tk_MainWindow(interp) == (Tk_Window)NULL) {
window = NULL;
} else {
window = Tk_NameToWindow(interp, nameString, tkwin);
}
+#else
+ if (!tk_stubs_init_p() || tkwin == (Tk_Window)NULL) {
+ window = NULL;
+ } else {
+ /* Tk_NameToWindow() returns right token on non-eventloop thread */
+ Tcl_CmdInfo info;
+ if (Tcl_GetCommandInfo(interp, ".", &info)) { /* check root */
+ window = Tk_NameToWindow(interp, nameString, tkwin);
+ } else {
+ window = NULL;
+ }
+ }
+#endif
#if TCL_MAJOR_VERSION >= 8
Tcl_DecrRefCount(objv[2]);
#endif
if (window == NULL) {
- Tcl_AppendResult(interp, "thread_tkwait: ",
+ Tcl_AppendResult(interp, ": thread_tkwait: ",
"no main-window (not Tk application?)",
(char*)NULL);
rb_thread_critical = thr_crit_bup;
+#if 0 /* use Tcl_EventuallyFree */
+ Tcl_EventuallyFree((ClientData)param, TCL_DYNAMIC); /* XXXXXXXX */
+#else
+#if 0 /* use Tcl_Preserve/Release */
Tcl_Release(param);
- Tcl_Free((char *)param);
+#endif
+ /* Tcl_Free((char *)param); */
+ ckfree((char *)param);
+#endif
Tcl_Release(tkwin);
Tcl_Release(interp);
@@ -4296,8 +4910,15 @@ ip_rb_threadTkWaitCommand(clientData, interp, objc, objv)
break;
} /* end of 'switch' statement */
- Tcl_Release(param);
- Tcl_Free((char *)param);
+#if 0 /* use Tcl_EventuallyFree */
+ Tcl_EventuallyFree((ClientData)param, TCL_DYNAMIC); /* XXXXXXXX */
+#else
+#if 0 /* use Tcl_Preserve/Release */
+ Tcl_Release((ClientData)param);
+#endif
+ /* Tcl_Free((char *)param); */
+ ckfree((char *)param);
+#endif
/*
* Clear out the interpreter's result, since it may have been set
@@ -4541,6 +5162,18 @@ ip_finalize(ip)
#if 1
DUMP1("destroy root widget");
if (tk_stubs_init_p() && Tk_MainWindow(ip) != (Tk_Window)NULL) {
+ /*
+ * On Ruby VM, this code piece may be not called, because
+ * Tk_MainWindow() returns NULL on a native thread except
+ * the thread which initialize Tk environment.
+ * Of course, that is a problem. But maybe not so serious.
+ * All widgets are destroyed when the Tcl interp is deleted.
+ * At then, Ruby may raise exceptions on the delete hook
+ * callbacks which registered for the deleted widgets, and
+ * may fail to clear objects which depends on the widgets.
+ * Although it is the problem, it is possibly avoidable by
+ * rescuing exceptions and the finalize hook of the interp.
+ */
DUMP1("call Tk_DestroyWindow");
ruby_debug = Qfalse;
ruby_verbose = Qnil;
@@ -4602,13 +5235,15 @@ ip_free(ptr)
DUMP2("slave IP(%lx) should not be deleted",
(unsigned long)ptr->ip);
free(ptr);
+ /* ckfree((char*)ptr); */
rb_thread_critical = thr_crit_bup;
return;
}
if (ptr->ip == (Tcl_Interp*)NULL) {
DUMP1("ip_free is called for deleted IP");
- free(ptr);
+ /* free(ptr); */
+ ckfree((char*)ptr);
rb_thread_critical = thr_crit_bup;
return;
}
@@ -4619,6 +5254,7 @@ ip_free(ptr)
ptr->ip = (Tcl_Interp*)NULL;
free(ptr);
+ /* ckfree((char*)ptr); */
rb_thread_critical = thr_crit_bup;
}
@@ -4740,7 +5376,11 @@ ip_rbNamespaceObjCmd(clientData, interp, objc, objv)
int i;
char **argv;
- argv = (char **)Tcl_Alloc(sizeof(char *) * (objc + 1));
+ /* argv = (char **)Tcl_Alloc(sizeof(char *) * (objc + 1)); */
+ argv = (char **)ckalloc(sizeof(char *) * (objc + 1));
+#if 0 /* use Tcl_Preserve/Release */
+ Tcl_Preserve((ClientData)argv); /* XXXXXXXX */
+#endif
for(i = 0; i < objc; i++) {
/* argv[i] = Tcl_GetString(objv[i]); */
@@ -4751,7 +5391,15 @@ ip_rbNamespaceObjCmd(clientData, interp, objc, objv)
ret = (*(info.proc))(info.clientData, interp,
objc, (CONST84 char **)argv);
- Tcl_Free((char*)argv);
+#if 0 /* use Tcl_EventuallyFree */
+ Tcl_EventuallyFree((ClientData)argv, TCL_DYNAMIC); /* XXXXXXXX */
+#else
+#if 0 /* use Tcl_Preserve/Release */
+ Tcl_Release((ClientData)argv); /* XXXXXXXX */
+#endif
+ /* Tcl_Free((char*)argv); */
+ ckfree((char*)argv);
+#endif
}
DUMP2("namespace wrapper exit depth == %d", rbtk_eventloop_depth);
@@ -4822,15 +5470,25 @@ ip_init(argc, argv, self)
Tk_Window mainWin = (Tk_Window)NULL;
/* security check */
+#ifdef RUBY_VM
if (rb_safe_level() >= 4) {
+#else
+ if (ruby_safe_level >= 4) {
+#endif
rb_raise(rb_eSecurityError,
"Cannot create a TclTkIp object at level %d",
- rb_safe_level());
+#ifdef RUBY_VM
+ rb_safe_level()
+#else
+ ruby_safe_level
+#endif
+ );
}
/* create object */
Data_Get_Struct(self, struct tcltkip, ptr);
ptr = ALLOC(struct tcltkip);
+ /* ptr = (struct tcltkip *)ckalloc(sizeof(struct tcltkip)); */
DATA_PTR(self) = ptr;
#ifdef RUBY_VM
ptr->tk_thread_id = 0;
@@ -4943,7 +5601,8 @@ ip_init(argc, argv, self)
#endif
#ifdef RUBY_VM
- ptr->tk_thread_id = Tcl_GetCurrentThread();
+ /* set Tk thread ID */
+ ptr->tk_thread_id = Tcl_GetCurrentThread();
#endif
/* get main window */
mainWin = Tk_MainWindow(ptr->ip);
@@ -5008,7 +5667,7 @@ ip_init(argc, argv, self)
if (mainWin != (Tk_Window)NULL) {
Tk_Release((ClientData)mainWin);
}
-
+
return self;
}
@@ -5020,6 +5679,7 @@ ip_create_slave_core(interp, argc, argv)
{
struct tcltkip *master = get_ip(interp);
struct tcltkip *slave = ALLOC(struct tcltkip);
+ /* struct tcltkip *slave = (struct tcltkip *)ckalloc(sizeof(struct tcltkip)); */
VALUE safemode;
VALUE name;
int safe;
@@ -5062,6 +5722,10 @@ ip_create_slave_core(interp, argc, argv)
#endif
/* create slave-ip */
+#ifdef RUBY_VM
+ /* slave->tk_thread_id = 0; */
+ slave->tk_thread_id = master->tk_thread_id; /* == current thread */
+#endif
slave->ref_count = 0;
slave->allow_ruby_exit = 0;
slave->return_value = 0;
@@ -5350,6 +6014,12 @@ ip_allow_ruby_exit_set(self, val)
"insecure operation on a safe interpreter");
}
+ /*
+ * Because of cross-threading, the following line may fail to find
+ * the MainWindow, even if the Tcl/Tk interpreter has one or more.
+ * But it has no problem. Current implementation of both type of
+ * the "exit" command don't need maiinWin token.
+ */
mainWin = (tk_stubs_init_p())? Tk_MainWindow(ptr->ip): (Tk_Window)NULL;
if (RTEST(val)) {
@@ -5446,8 +6116,10 @@ ip_is_deleted_p(self)
}
static VALUE
-ip_has_mainwindow_p(self)
+ip_has_mainwindow_p_core(self, argc, argv)
VALUE self;
+ int argc; /* dummy */
+ VALUE *argv; /* dummy */
{
struct tcltkip *ptr = get_ip(self);
@@ -5460,6 +6132,14 @@ ip_has_mainwindow_p(self)
}
}
+static VALUE
+ip_has_mainwindow_p(self)
+ VALUE self;
+{
+ return tk_funcall(ip_has_mainwindow_p_core, 0, (VALUE*)NULL, self);
+}
+
+
/*** ruby string <=> tcl object ***/
#if TCL_MAJOR_VERSION >= 8
static VALUE
@@ -5469,12 +6149,16 @@ get_str_from_obj(obj)
int len, binary = 0;
const char *s;
volatile VALUE str;
+#if TCL_MAJOR_VERSION > 8 || (TCL_MAJOR_VERSION == 8 && TCL_MINOR_VERSION >= 4)
+ int len2;
+ const char *s2;
+#endif
#if TCL_MAJOR_VERSION == 8 && TCL_MINOR_VERSION == 0
s = Tcl_GetStringFromObj(obj, &len);
#else
-#if 0
- /* TCL_VERSION >= 8.1 */
+#if TCL_MAJOR_VERSION == 8 && TCL_MINOR_VERSION <= 3
+ /* TCL_VERSION 8.1 -- 8.3 */
if (Tcl_GetCharLength(obj) != Tcl_UniCharLen(Tcl_GetUnicode(obj))) {
/* possibly binary string */
s = Tcl_GetByteArrayFromObj(obj, &len);
@@ -5483,29 +6167,30 @@ get_str_from_obj(obj)
/* possibly text string */
s = Tcl_GetStringFromObj(obj, &len);
}
-#else
-#if TCL_MAJOR_VERSION == 8 && TCL_MINOR_VERSION <= 4
- if (Tcl_GetCharLength(obj) != Tcl_UniCharLen(Tcl_GetUnicode(obj))) {
- /* possibly binary string */
- s = Tcl_GetByteArrayFromObj(obj, &len);
- binary = 1;
+#else /* TCL_VERSION >= 8.4 */
+ if (IS_TCL_BYTEARRAY(obj)) {
+ s = Tcl_GetByteArrayFromObj(obj, &len);
+ binary = 1;
} else {
- /* possibly text string */
- s = Tcl_GetStringFromObj(obj, &len);
- }
-#else /* TCL_VERSION >= 8.5 */
- /* TODO: Known BUG:
- Tcl_GetByteArrayFromObj() returns "alloc: invalid block" */
- if (Tcl_GetCharLength(obj) != Tcl_UniCharLen(Tcl_GetUnicode(obj))) {
- /* possibly binary string */
- binary = 1;
+ s = Tcl_GetStringFromObj(obj, &len);
}
- s = Tcl_GetStringFromObj(obj, &len);
-#endif
+
#endif
#endif
str = s ? rb_str_new(s, len) : rb_str_new2("");
- if (binary) rb_ivar_set(str, ID_at_enc, rb_str_new2("binary"));
+ if (binary) {
+#ifdef RUBY_VM
+ rb_enc_associate_index(str, ENCODING_INDEX_BINARY);
+#endif
+ rb_ivar_set(str, ID_at_enc, ENCODING_NAME_BINARY);
+#if TCL_MAJOR_VERSION > 8 || (TCL_MAJOR_VERSION == 8 && TCL_MINOR_VERSION >= 1)
+ } else {
+#ifdef RUBY_VM
+ rb_enc_associate_index(str, ENCODING_INDEX_UTF8);
+#endif
+ rb_ivar_set(str, ID_at_enc, ENCODING_NAME_UTF8);
+#endif
+ }
return str;
}
@@ -5529,6 +6214,11 @@ get_obj_from_str(str)
/* text string */
return Tcl_NewStringObj(s, RSTRING_LEN(str));
}
+#ifdef RUBY_VM
+ } else if (rb_enc_get_index(str) == ENCODING_INDEX_BINARY) {
+ /* binary string */
+ return Tcl_NewByteArrayObj(s, RSTRING_LEN(str));
+#endif
} else if (strlen(s) != RSTRING_LEN(str)) {
/* probably binary string */
return Tcl_NewByteArrayObj(s, RSTRING_LEN(str));
@@ -5589,6 +6279,7 @@ call_queue_handler(evPtr, flags)
DUMP2("call_queue_handler thread : %lx", rb_thread_current());
DUMP2("added by thread : %lx", q->thread);
+
if (*(q->done)) {
DUMP1("processed by another event-loop");
return 0;
@@ -5606,10 +6297,13 @@ call_queue_handler(evPtr, flags)
return 1;
}
+ /* incr internal handler mark */
+ rbtk_internal_eventloop_handler++;
+
/* check safe-level */
if (rb_safe_level() != q->safe_level) {
- /* q_dat = Data_Wrap_Struct(rb_cData,0,0,q); */
- q_dat = Data_Wrap_Struct(rb_cData,call_queue_mark,0,q);
+ /* q_dat = Data_Wrap_Struct(rb_cData,0,-1,q); */
+ q_dat = Data_Wrap_Struct(rb_cData,call_queue_mark,-1,q);
ret = rb_funcall(rb_proc_new(callq_safelevel_handler, q_dat),
ID_call, 0);
rb_gc_force_recycle(q_dat);
@@ -5622,6 +6316,9 @@ call_queue_handler(evPtr, flags)
/* set result */
RARRAY_PTR(q->result)[0] = ret;
+ /* decr internal handler mark */
+ rbtk_internal_eventloop_handler--;
+
/* complete */
*(q->done) = -1;
@@ -5629,8 +6326,16 @@ call_queue_handler(evPtr, flags)
if (RTEST(rb_funcall(q->thread, ID_alive_p, 0, 0))) {
DUMP2("back to caller (caller thread:%lx)", q->thread);
DUMP2(" (current thread:%lx)", rb_thread_current());
+#if CONTROL_BY_STATUS_OF_RB_THREAD_WAIT_FOR_VALUE
+ have_rb_thread_waited_for_value = 1;
+ rb_thread_wakeup(q->thread);
+#else
rb_thread_run(q->thread);
+#endif
DUMP1("finish back to caller");
+#if DO_THREAD_SCHEDULE_AT_CALLBACK_DONE
+ rb_thread_schedule();
+#endif
} else {
DUMP2("caller is dead (caller thread:%lx)", q->thread);
DUMP2(" (current thread:%lx)", rb_thread_current());
@@ -5648,32 +6353,39 @@ tk_funcall(func, argc, argv, obj)
VALUE obj;
{
struct call_queue *callq;
-#ifdef RUBY_VM
struct tcltkip *ptr;
-#endif
int *alloc_done;
int thr_crit_bup;
+ int is_tk_evloop_thread;
volatile VALUE current = rb_thread_current();
volatile VALUE ip_obj = obj;
volatile VALUE result;
volatile VALUE ret;
-
- if (!NIL_P(ip_obj) && deleted_ip(get_ip(ip_obj))) {
- return Qnil;
+ if (!NIL_P(ip_obj) && rb_obj_is_kind_of(ip_obj, tcltkip_class)) {
+ ptr = get_ip(ip_obj);
+ if (deleted_ip(ptr)) return Qnil;
+ } else {
+ ptr = (struct tcltkip *)NULL;
}
#ifdef RUBY_VM
- ptr = get_ip(ip_obj);
+ if (ptr) {
+ /* on Tcl interpreter */
+ is_tk_evloop_thread = (ptr->tk_thread_id == (Tcl_ThreadId) 0
+ || ptr->tk_thread_id == Tcl_GetCurrentThread());
+ } else {
+ /* on Tcl/Tk library */
+ is_tk_evloop_thread = (tk_eventloop_thread_id == (Tcl_ThreadId) 0
+ || tk_eventloop_thread_id == Tcl_GetCurrentThread());
+ }
+#else
+ is_tk_evloop_thread = 1;
#endif
- if (
-#ifdef RUBY_VM
- (ptr->tk_thread_id == 0 || ptr->tk_thread_id == Tcl_GetCurrentThread())
- &&
-#endif
- (NIL_P(eventloop_thread) || current == eventloop_thread)
- ) {
+ if (is_tk_evloop_thread
+ && (NIL_P(eventloop_thread) || current == eventloop_thread)
+ ) {
if (NIL_P(eventloop_thread)) {
DUMP2("tk_funcall from thread:%lx but no eventloop", current);
} else {
@@ -5693,18 +6405,29 @@ tk_funcall(func, argc, argv, obj)
/* allocate memory (argv cross over thread : must be in heap) */
if (argv) {
- VALUE *temp = ALLOC_N(VALUE, argc);
+ /* VALUE *temp = ALLOC_N(VALUE, argc); */
+ VALUE *temp = (VALUE*)ckalloc(sizeof(VALUE) * argc);
+#if 0 /* use Tcl_Preserve/Release */
+ Tcl_Preserve((ClientData)temp); /* XXXXXXXX */
+#endif
MEMCPY(temp, argv, VALUE, argc);
argv = temp;
}
/* allocate memory (keep result) */
- alloc_done = (int*)ALLOC(int);
+ /* alloc_done = (int*)ALLOC(int); */
+ alloc_done = (int*)ckalloc(sizeof(int));
+#if 0 /* use Tcl_Preserve/Release */
+ Tcl_Preserve((ClientData)alloc_done); /* XXXXXXXX */
+#endif
*alloc_done = 0;
/* allocate memory (freed by Tcl_ServiceEvent) */
- callq = (struct call_queue *)Tcl_Alloc(sizeof(struct call_queue));
+ /* callq = (struct call_queue *)Tcl_Alloc(sizeof(struct call_queue)); */
+ callq = (struct call_queue *)ckalloc(sizeof(struct call_queue));
+#if 1 /* use Tcl_Preserve/Release */
Tcl_Preserve(callq);
+#endif
/* allocate result obj */
result = rb_ary_new3(1, Qnil);
@@ -5723,9 +6446,13 @@ tk_funcall(func, argc, argv, obj)
/* add the handler to Tcl event queue */
DUMP1("add handler");
#ifdef RUBY_VM
- if (ptr->tk_thread_id) {
+ if (ptr && ptr->tk_thread_id) {
Tcl_ThreadQueueEvent(ptr->tk_thread_id, &(callq->ev), TCL_QUEUE_HEAD);
Tcl_ThreadAlert(ptr->tk_thread_id);
+ } else if (tk_eventloop_thread_id) {
+ Tcl_ThreadQueueEvent(tk_eventloop_thread_id,
+ &(callq->ev), TCL_QUEUE_HEAD);
+ Tcl_ThreadAlert(tk_eventloop_thread_id);
} else {
Tcl_QueueEvent(&(callq->ev), TCL_QUEUE_HEAD);
}
@@ -5739,22 +6466,47 @@ tk_funcall(func, argc, argv, obj)
DUMP2("wait for handler (current thread:%lx)", current);
while(*alloc_done >= 0) {
DUMP2("*** wait for handler (current thread:%lx)", current);
- rb_thread_stop();
+ rb_thread_stop();
DUMP2("*** wakeup (current thread:%lx)", current);
}
DUMP2("back from handler (current thread:%lx)", current);
/* get result & free allocated memory */
ret = RARRAY_PTR(result)[0];
- free(alloc_done);
- if (argv) free(argv);
+#if 0 /* use Tcl_EventuallyFree */
+ Tcl_EventuallyFree((ClientData)alloc_done, TCL_DYNAMIC); /* XXXXXXXX */
+#else
+#if 0 /* use Tcl_Preserve/Release */
+ Tcl_Release((ClientData)alloc_done); /* XXXXXXXX */
+#endif
+ /* free(alloc_done); */
+ ckfree((char*)alloc_done);
+#endif
+ /* if (argv) free(argv); */
+ if (argv) {
+ /* if argv != NULL, alloc as 'temp' */
+#if 0 /* use Tcl_EventuallyFree */
+ Tcl_EventuallyFree((ClientData)argv, TCL_DYNAMIC); /* XXXXXXXX */
+#else
+#if 0 /* use Tcl_Preserve/Release */
+ Tcl_Release((ClientData)argv); /* XXXXXXXX */
+#endif
+ ckfree((char*)argv);
+#endif
+ }
+#if 1 /* use Tcl_Preserve/Release */
Tcl_Release(callq);
+#else
+ ckfree((char*)callq);
+#endif
/* exception? */
if (rb_obj_is_kind_of(ret, rb_eException)) {
DUMP1("raise exception");
- rb_exc_raise(ret);
+ /* rb_exc_raise(ret); */
+ rb_exc_raise(rb_exc_new3(rb_obj_class(ret),
+ rb_funcall(ret, ID_to_s, 0, 0)));
}
DUMP1("exit tk_funcall");
@@ -5825,19 +6577,35 @@ ip_eval_real(self, cmd_str, cmd_len)
ret = rb_protect(call_tcl_eval, (VALUE)&inf, &status);
switch(status) {
case TAG_RAISE:
+#ifdef RUBY_VM
if (NIL_P(rb_errinfo())) {
+#else
+ if (NIL_P(ruby_errinfo)) {
+#endif
rbtk_pending_exception = rb_exc_new2(rb_eException,
"unknown exception");
} else {
+#ifdef RUBY_VM
rbtk_pending_exception = rb_errinfo();
+#else
+ rbtk_pending_exception = ruby_errinfo;
+#endif
}
break;
case TAG_FATAL:
+#ifdef RUBY_VM
if (NIL_P(rb_errinfo())) {
+#else
+ if (NIL_P(ruby_errinfo)) {
+#endif
rbtk_pending_exception = rb_exc_new2(rb_eFatal, "FATAL");
} else {
+#ifdef RUBY_VM
rbtk_pending_exception = rb_errinfo();
+#else
+ rbtk_pending_exception = ruby_errinfo;
+#endif
}
}
#endif
@@ -5960,17 +6728,26 @@ eval_queue_handler(evPtr, flags)
return 1;
}
+ /* incr internal handler mark */
+ rbtk_internal_eventloop_handler++;
+
/* check safe-level */
if (rb_safe_level() != q->safe_level) {
-#if 0
#ifdef HAVE_NATIVETHREAD
- if (!ruby_native_thread_p()) {
- rb_bug("cross-thread violation on eval_queue_handler()");
- }
+#ifdef RUBY_VM
+#if 0
+ if (!ruby_native_thread_p()) {
+ rb_bug("cross-thread violation on eval_queue_handler()");
+ }
+#endif
+#else
+ if (!is_ruby_native_thread()) {
+ rb_bug("cross-thread violation on eval_queue_handler()");
+ }
#endif
#endif
- /* q_dat = Data_Wrap_Struct(rb_cData,0,0,q); */
- q_dat = Data_Wrap_Struct(rb_cData,eval_queue_mark,0,q);
+ /* q_dat = Data_Wrap_Struct(rb_cData,0,-1,q); */
+ q_dat = Data_Wrap_Struct(rb_cData,eval_queue_mark,-1,q);
ret = rb_funcall(rb_proc_new(evq_safelevel_handler, q_dat),
ID_call, 0);
rb_gc_force_recycle(q_dat);
@@ -5981,6 +6758,9 @@ eval_queue_handler(evPtr, flags)
/* set result */
RARRAY_PTR(q->result)[0] = ret;
+ /* decr internal handler mark */
+ rbtk_internal_eventloop_handler--;
+
/* complete */
*(q->done) = -1;
@@ -5988,8 +6768,16 @@ eval_queue_handler(evPtr, flags)
if (RTEST(rb_funcall(q->thread, ID_alive_p, 0, 0))) {
DUMP2("back to caller (caller thread:%lx)", q->thread);
DUMP2(" (current thread:%lx)", rb_thread_current());
+#if CONTROL_BY_STATUS_OF_RB_THREAD_WAIT_FOR_VALUE
+ have_rb_thread_waited_for_value = 1;
+ rb_thread_wakeup(q->thread);
+#else
rb_thread_run(q->thread);
+#endif
DUMP1("finish back to caller");
+#if DO_THREAD_SCHEDULE_AT_CALLBACK_DONE
+ rb_thread_schedule();
+#endif
} else {
DUMP2("caller is dead (caller thread:%lx)", q->thread);
DUMP2(" (current thread:%lx)", rb_thread_current());
@@ -6051,16 +6839,27 @@ ip_eval(self, str)
rb_thread_critical = Qtrue;
/* allocate memory (protected from Tcl_ServiceEvent) */
- alloc_done = (int*)ALLOC(int);
+ /* alloc_done = (int*)ALLOC(int); */
+ alloc_done = (int*)ckalloc(sizeof(int));
+#if 0 /* use Tcl_Preserve/Release */
+ Tcl_Preserve((ClientData)alloc_done); /* XXXXXXXX */
+#endif
*alloc_done = 0;
- eval_str = ALLOC_N(char, RSTRING_LEN(str) + 1);
+ /* eval_str = ALLOC_N(char, RSTRING_LEN(str) + 1); */
+ eval_str = ckalloc(sizeof(char) * (RSTRING_LEN(str) + 1));
+#if 0 /* use Tcl_Preserve/Release */
+ Tcl_Preserve((ClientData)eval_str); /* XXXXXXXX */
+#endif
memcpy(eval_str, RSTRING_PTR(str), RSTRING_LEN(str));
eval_str[RSTRING_LEN(str)] = 0;
/* allocate memory (freed by Tcl_ServiceEvent) */
- evq = (struct eval_queue *)Tcl_Alloc(sizeof(struct eval_queue));
+ /* evq = (struct eval_queue *)Tcl_Alloc(sizeof(struct eval_queue)); */
+ evq = (struct eval_queue *)ckalloc(sizeof(struct eval_queue));
+#if 1 /* use Tcl_Preserve/Release */
Tcl_Preserve(evq);
+#endif
/* allocate result obj */
result = rb_ary_new3(1, Qnil);
@@ -6096,7 +6895,7 @@ ip_eval(self, str)
DUMP2("wait for handler (current thread:%lx)", current);
while(*alloc_done >= 0) {
DUMP2("*** wait for handler (current thread:%lx)", current);
- rb_thread_stop();
+ rb_thread_stop();
DUMP2("*** wakeup (current thread:%lx)", current);
}
DUMP2("back from handler (current thread:%lx)", current);
@@ -6104,12 +6903,35 @@ ip_eval(self, str)
/* get result & free allocated memory */
ret = RARRAY_PTR(result)[0];
- free(alloc_done);
- free(eval_str);
+#if 0 /* use Tcl_EventuallyFree */
+ Tcl_EventuallyFree((ClientData)alloc_done, TCL_DYNAMIC); /* XXXXXXXX */
+#else
+#if 0 /* use Tcl_Preserve/Release */
+ Tcl_Release((ClientData)alloc_done); /* XXXXXXXX */
+#endif
+ /* free(alloc_done); */
+ ckfree((char*)alloc_done);
+#endif
+#if 0 /* use Tcl_EventuallyFree */
+ Tcl_EventuallyFree((ClientData)eval_str, TCL_DYNAMIC); /* XXXXXXXX */
+#else
+#if 0 /* use Tcl_Preserve/Release */
+ Tcl_Release((ClientData)eval_str); /* XXXXXXXX */
+#endif
+ /* free(eval_str); */
+ ckfree(eval_str);
+#endif
+#if 1 /* use Tcl_Preserve/Release */
Tcl_Release(evq);
+#else
+ ckfree((char*)evq);
+#endif
if (rb_obj_is_kind_of(ret, rb_eException)) {
- rb_exc_raise(ret);
+ DUMP1("raise exception");
+ /* rb_exc_raise(ret); */
+ rb_exc_raise(rb_exc_new3(rb_obj_class(ret),
+ rb_funcall(ret, ID_to_s, 0, 0)));
}
return ret;
@@ -6264,7 +7086,12 @@ lib_toUTF8_core(ip_obj, src, encodename)
if (NIL_P(encodename)) {
if (TYPE(str) == T_STRING) {
volatile VALUE enc;
+
+#ifdef RUBY_VM
+ enc = rb_funcall(rb_obj_encoding(str), ID_to_s, 0, 0);
+#else
enc = rb_attr_get(str, ID_at_enc);
+#endif
if (NIL_P(enc)) {
if (NIL_P(ip_obj)) {
encoding = (Tcl_Encoding)NULL;
@@ -6283,6 +7110,10 @@ lib_toUTF8_core(ip_obj, src, encodename)
} else {
StringValue(enc);
if (strcmp(RSTRING_PTR(enc), "binary") == 0) {
+#ifdef RUBY_VM
+ rb_enc_associate_index(str, ENCODING_INDEX_BINARY);
+#endif
+ rb_ivar_set(str, ID_at_enc, ENCODING_NAME_BINARY);
rb_thread_critical = thr_crit_bup;
return str;
}
@@ -6296,6 +7127,14 @@ lib_toUTF8_core(ip_obj, src, encodename)
}
} else {
StringValue(encodename);
+ if (strcmp(RSTRING_PTR(encodename), "binary") == 0) {
+#ifdef RUBY_VM
+ rb_enc_associate_index(str, ENCODING_INDEX_BINARY);
+#endif
+ rb_ivar_set(str, ID_at_enc, ENCODING_NAME_BINARY);
+ rb_thread_critical = thr_crit_bup;
+ return str;
+ }
encoding = Tcl_GetEncoding(interp, RSTRING_PTR(encodename));
if (encoding == (Tcl_Encoding)NULL) {
/*
@@ -6312,7 +7151,8 @@ lib_toUTF8_core(ip_obj, src, encodename)
rb_thread_critical = thr_crit_bup;
return str;
}
- buf = ALLOC_N(char,RSTRING_LEN(str)+1);
+ buf = ALLOC_N(char, RSTRING_LEN(str)+1);
+ /* buf = ckalloc(sizeof(char) * (RSTRING_LEN(str)+1)); */
memcpy(buf, RSTRING_PTR(str), RSTRING_LEN(str));
buf[RSTRING_LEN(str)] = 0;
@@ -6324,7 +7164,10 @@ lib_toUTF8_core(ip_obj, src, encodename)
/* str = rb_tainted_str_new2(Tcl_DStringValue(&dstr)); */
/* str = rb_str_new2(Tcl_DStringValue(&dstr)); */
str = rb_str_new(Tcl_DStringValue(&dstr), Tcl_DStringLength(&dstr));
- rb_ivar_set(str, ID_at_enc, rb_tainted_str_new2("utf-8"));
+#ifdef RUBY_VM
+ rb_enc_associate_index(str, ENCODING_INDEX_UTF8);
+#endif
+ rb_ivar_set(str, ID_at_enc, ENCODING_NAME_UTF8);
if (taint_flag) OBJ_TAINT(str);
if (encoding != (Tcl_Encoding)NULL) {
@@ -6333,6 +7176,7 @@ lib_toUTF8_core(ip_obj, src, encodename)
Tcl_DStringFree(&dstr);
free(buf);
+ /* ckfree(buf); */
rb_thread_critical = thr_crit_bup;
#endif
@@ -6411,9 +7255,20 @@ lib_fromUTF8_core(ip_obj, src, encodename)
if (!NIL_P(enc)) {
StringValue(enc);
if (strcmp(RSTRING_PTR(enc), "binary") == 0) {
+#ifdef RUBY_VM
+ rb_enc_associate_index(str, ENCODING_INDEX_BINARY);
+#endif
+ rb_ivar_set(str, ID_at_enc, ENCODING_NAME_BINARY);
rb_thread_critical = thr_crit_bup;
return str;
}
+#ifdef RUBY_VM
+ } else if (rb_enc_get_index(str) == ENCODING_INDEX_BINARY) {
+ rb_enc_associate_index(str, ENCODING_INDEX_BINARY);
+ rb_ivar_set(str, ID_at_enc, ENCODING_NAME_BINARY);
+ rb_thread_critical = thr_crit_bup;
+ return str;
+#endif
}
}
@@ -6446,7 +7301,10 @@ lib_fromUTF8_core(ip_obj, src, encodename)
RSTRING_LEN(str)),
&len);
str = rb_tainted_str_new(s, len);
- rb_ivar_set(str, ID_at_enc, rb_tainted_str_new2("binary"));
+#ifdef RUBY_VM
+ rb_enc_associate_index(str, ENCODING_INDEX_BINARY);
+#endif
+ rb_ivar_set(str, ID_at_enc, ENCODING_NAME_BINARY);
rb_thread_critical = thr_crit_bup;
return str;
@@ -6471,7 +7329,8 @@ lib_fromUTF8_core(ip_obj, src, encodename)
return rb_tainted_str_new2("");
}
- buf = ALLOC_N(char,strlen(RSTRING_PTR(str))+1);
+ buf = ALLOC_N(char, RSTRING_LEN(str)+1);
+ /* buf = ckalloc(sizeof(char) * (RSTRING_LEN(str)+1)); */
memcpy(buf, RSTRING_PTR(str), RSTRING_LEN(str));
buf[RSTRING_LEN(str)] = 0;
@@ -6483,6 +7342,19 @@ lib_fromUTF8_core(ip_obj, src, encodename)
/* str = rb_tainted_str_new2(Tcl_DStringValue(&dstr)); */
/* str = rb_str_new2(Tcl_DStringValue(&dstr)); */
str = rb_str_new(Tcl_DStringValue(&dstr), Tcl_DStringLength(&dstr));
+#ifdef RUBY_VM
+ if (interp) {
+ /* can access encoding_table of TclTkIp */
+ /* -> try to use encoding_table */
+ VALUE tbl = ip_get_encoding_table(ip_obj);
+ VALUE encobj = encoding_table_get_obj(tbl, encodename);
+ rb_enc_associate_index(str, rb_to_encoding_index(encobj));
+ } else {
+ /* cannot access encoding_table of TclTkIp */
+ /* -> try to find on Ruby Encoding */
+ rb_enc_associate_index(str, rb_enc_find_index(RSTRING_PTR(encodename)));
+ }
+#endif
rb_ivar_set(str, ID_at_enc, encodename);
if (taint_flag) OBJ_TAINT(str);
@@ -6493,6 +7365,7 @@ lib_fromUTF8_core(ip_obj, src, encodename)
Tcl_DStringFree(&dstr);
free(buf);
+ /* ckfree(buf); */
rb_thread_critical = thr_crit_bup;
#endif
@@ -6550,11 +7423,19 @@ lib_UTF_backslash_core(self, str, all_bs)
thr_crit_bup = rb_thread_critical;
rb_thread_critical = Qtrue;
- src_buf = ALLOC_N(char,RSTRING_LEN(str)+1);
+ /* src_buf = ALLOC_N(char, RSTRING_LEN(str)+1); */
+ src_buf = ckalloc(sizeof(char) * (RSTRING_LEN(str)+1));
+#if 0 /* use Tcl_Preserve/Release */
+ Tcl_Preserve((ClientData)src_buf); /* XXXXXXXX */
+#endif
memcpy(src_buf, RSTRING_PTR(str), RSTRING_LEN(str));
src_buf[RSTRING_LEN(str)] = 0;
- dst_buf = ALLOC_N(char,RSTRING_LEN(str)+1);
+ /* dst_buf = ALLOC_N(char, RSTRING_LEN(str)+1); */
+ dst_buf = ckalloc(sizeof(char) * (RSTRING_LEN(str)+1));
+#if 0 /* use Tcl_Preserve/Release */
+ Tcl_Preserve((ClientData)dst_buf); /* XXXXXXXX */
+#endif
ptr = src_buf;
while(RSTRING_LEN(str) > ptr - src_buf) {
@@ -6568,9 +7449,29 @@ lib_UTF_backslash_core(self, str, all_bs)
str = rb_str_new(dst_buf, dst_len);
if (taint_flag) OBJ_TAINT(str);
+#ifdef RUBY_VM
+ rb_enc_associate_index(str, ENCODING_INDEX_UTF8);
+#endif
+ rb_ivar_set(str, ID_at_enc, ENCODING_NAME_UTF8);
- free(src_buf);
- free(dst_buf);
+#if 0 /* use Tcl_EventuallyFree */
+ Tcl_EventuallyFree((ClientData)src_buf, TCL_DYNAMIC); /* XXXXXXXX */
+#else
+#if 0 /* use Tcl_Preserve/Release */
+ Tcl_Release((ClientData)src_buf); /* XXXXXXXX */
+#endif
+ /* free(src_buf); */
+ ckfree(src_buf);
+#endif
+#if 0 /* use Tcl_EventuallyFree */
+ Tcl_EventuallyFree((ClientData)dst_buf, TCL_DYNAMIC); /* XXXXXXXX */
+#else
+#if 0 /* use Tcl_Preserve/Release */
+ Tcl_Release((ClientData)dst_buf); /* XXXXXXXX */
+#endif
+ /* free(dst_buf); */
+ ckfree(dst_buf);
+#endif
rb_thread_critical = thr_crit_bup;
#endif
@@ -6661,8 +7562,11 @@ invoke_tcl_proc(arg)
#if TCL_MAJOR_VERSION >= 8
if (!inf->cmdinfo.isNativeObjectProc) {
/* string interface */
- // argv = (char **)ALLOC_N(char *, argc+1); /* XXXXXXXXXX */
+ /* argv = (char **)ALLOC_N(char *, argc+1);*/ /* XXXXXXXXXX */
argv = (char **)ckalloc(sizeof(char *)*(argc+1));
+#if 0 /* use Tcl_Preserve/Release */
+ Tcl_Preserve((ClientData)argv); /* XXXXXXXX */
+#endif
for (i = 0; i < argc; ++i) {
argv[i] = Tcl_GetStringFromObj(inf->objv[i], &len);
}
@@ -6675,7 +7579,6 @@ invoke_tcl_proc(arg)
/* Invoke the C procedure */
#if TCL_MAJOR_VERSION >= 8
if (inf->cmdinfo.isNativeObjectProc) {
- int ret_val;
inf->ptr->return_value
= (*(inf->cmdinfo.objProc))(inf->cmdinfo.objClientData,
inf->ptr->ip, inf->objc, inf->objv);
@@ -6688,8 +7591,15 @@ invoke_tcl_proc(arg)
= (*(inf->cmdinfo.proc))(inf->cmdinfo.clientData, inf->ptr->ip,
argc, (CONST84 char **)argv);
- //free(argv);
+#if 0 /* use Tcl_EventuallyFree */
+ Tcl_EventuallyFree((ClientData)argv, TCL_DYNAMIC); /* XXXXXXXX */
+#else
+#if 0 /* use Tcl_Preserve/Release */
+ Tcl_Release((ClientData)argv); /* XXXXXXXX */
+#endif
+ /* free(argv); */
ckfree((char*)argv);
+#endif
#else /* TCL_MAJOR_VERSION < 8 */
inf->ptr->return_value
@@ -6745,6 +7655,9 @@ ip_invoke_core(interp, argc, argv)
cmd = argv[0];
#endif
+ /* get the data struct */
+ ptr = get_ip(interp);
+
/* ip is deleted? */
if (deleted_ip(ptr)) {
return rb_tainted_str_new2("");
@@ -6794,15 +7707,22 @@ ip_invoke_core(interp, argc, argv)
unknown_flag = 1;
#if TCL_MAJOR_VERSION >= 8
- //unknown_objv = (Tcl_Obj **)ALLOC_N(Tcl_Obj *, objc+2);
+ /* unknown_objv = (Tcl_Obj **)ALLOC_N(Tcl_Obj *, objc+2); */
unknown_objv = (Tcl_Obj **)ckalloc(sizeof(Tcl_Obj *) * (objc+2));
+#if 0 /* use Tcl_Preserve/Release */
+ Tcl_Preserve((ClientData)unknown_objv); /* XXXXXXXX */
+#endif
unknown_objv[0] = Tcl_NewStringObj("::unknown", 9);
Tcl_IncrRefCount(unknown_objv[0]);
memcpy(unknown_objv + 1, objv, sizeof(Tcl_Obj *)*objc);
unknown_objv[++objc] = (Tcl_Obj*)NULL;
objv = unknown_objv;
#else
- unknown_argv = (char **)ALLOC_N(char *, argc+2);
+ /* unknown_argv = (char **)ALLOC_N(char *, argc+2); */
+ unknown_argv = (char **)ckalloc(sizeof(char *) * (argc+2));
+#if 0 /* use Tcl_Preserve/Release */
+ Tcl_Preserve((ClientData)unknown_argv); /* XXXXXXXX */
+#endif
unknown_argv[0] = strdup("unknown");
memcpy(unknown_argv + 1, argv, sizeof(char *)*argc);
unknown_argv[++argc] = (char *)NULL;
@@ -6831,19 +7751,35 @@ ip_invoke_core(interp, argc, argv)
ret = rb_protect(invoke_tcl_proc, (VALUE)&inf, &status);
switch(status) {
case TAG_RAISE:
+#ifdef RUBY_VM
if (NIL_P(rb_errinfo())) {
+#else
+ if (NIL_P(ruby_errinfo)) {
+#endif
rbtk_pending_exception = rb_exc_new2(rb_eException,
"unknown exception");
} else {
+#ifdef RUBY_VM
rbtk_pending_exception = rb_errinfo();
+#else
+ rbtk_pending_exception = ruby_errinfo;
+#endif
}
break;
case TAG_FATAL:
+#ifdef RUBY_VM
if (NIL_P(rb_errinfo())) {
+#else
+ if (NIL_P(ruby_errinfo)) {
+#endif
rbtk_pending_exception = rb_exc_new2(rb_eFatal, "FATAL");
} else {
+#ifdef RUBY_VM
rbtk_pending_exception = rb_errinfo();
+#else
+ rbtk_pending_exception = ruby_errinfo;
+#endif
}
}
@@ -6855,8 +7791,11 @@ ip_invoke_core(interp, argc, argv)
int i;
/* string interface */
- //argv = (char **)ALLOC_N(char *, argc+1);
+ /* argv = (char **)ALLOC_N(char *, argc+1); */
argv = (char **)ckalloc(sizeof(char *) * (argc+1));
+#if 0 /* use Tcl_Preserve/Release */
+ Tcl_Preserve((ClientData)argv); /* XXXXXXXX */
+#endif
for (i = 0; i < argc; ++i) {
argv[i] = Tcl_GetStringFromObj(objv[i], &len);
}
@@ -6885,8 +7824,15 @@ ip_invoke_core(interp, argc, argv)
ptr->return_value = (*info.proc)(info.clientData, ptr->ip,
argc, (CONST84 char **)argv);
- //free(argv);
- ckfree(argv);
+#if 0 /* use Tcl_EventuallyFree */
+ Tcl_EventuallyFree((ClientData)argv, TCL_DYNAMIC); /* XXXXXXXX */
+#else
+#if 0 /* use Tcl_Preserve/Release */
+ Tcl_Release((ClientData)argv); /* XXXXXXXX */
+#endif
+ /* free(argv); */
+ ckfree((char*)argv);
+#endif
#else /* TCL_MAJOR_VERSION < 8 */
ptr->return_value = (*info.proc)(info.clientData, ptr->ip,
@@ -6899,10 +7845,27 @@ ip_invoke_core(interp, argc, argv)
if (unknown_flag) {
#if TCL_MAJOR_VERSION >= 8
Tcl_DecrRefCount(objv[0]);
- free(objv);
+#if 0 /* use Tcl_EventuallyFree */
+ Tcl_EventuallyFree((ClientData)objv, TCL_DYNAMIC); /* XXXXXXXX */
+#else
+#if 0 /* use Tcl_Preserve/Release */
+ Tcl_Release((ClientData)objv); /* XXXXXXXX */
+#endif
+ /* free(objv); */
+ ckfree((char*)objv);
+#endif
#else
free(argv[0]);
- free(argv);
+ /* ckfree(argv[0]); */
+#if 0 /* use Tcl_EventuallyFree */
+ Tcl_EventuallyFree((ClientData)argv, TCL_DYNAMIC); /* XXXXXXXX */
+#else
+#if 0 /* use Tcl_Preserve/Release */
+ Tcl_Release((ClientData)argv); /* XXXXXXXX */
+#endif
+ /* free(argv); */
+ ckfree((char*)argv);
+#endif
#endif
}
@@ -6957,8 +7920,11 @@ alloc_invoke_arguments(argc, argv)
/* memory allocation */
#if TCL_MAJOR_VERSION >= 8
- //av = ALLOC_N(Tcl_Obj *, argc+1); /* XXXXXXXXXX */
+ /* av = ALLOC_N(Tcl_Obj *, argc+1);*/ /* XXXXXXXXXX */
av = (Tcl_Obj**)ckalloc(sizeof(Tcl_Obj *)*(argc+1));
+#if 0 /* use Tcl_Preserve/Release */
+ Tcl_Preserve((ClientData)av); /* XXXXXXXX */
+#endif
for (i = 0; i < argc; ++i) {
av[i] = get_obj_from_str(argv[i]);
Tcl_IncrRefCount(av[i]);
@@ -6967,7 +7933,11 @@ alloc_invoke_arguments(argc, argv)
#else /* TCL_MAJOR_VERSION < 8 */
/* string interface */
- av = ALLOC_N(char *, argc+1);
+ /* av = ALLOC_N(char *, argc+1); */
+ av = (char**)ckalloc(sizeof(char *) * (argc+1));
+#if 0 /* use Tcl_Preserve/Release */
+ Tcl_Preserve((ClientData)av); /* XXXXXXXX */
+#endif
for (i = 0; i < argc; ++i) {
av[i] = strdup(StringValuePtr(argv[i]));
}
@@ -6998,9 +7968,24 @@ free_invoke_arguments(argc, av)
#endif
}
#if TCL_MAJOR_VERSION >= 8
+#if 0 /* use Tcl_EventuallyFree */
+ Tcl_EventuallyFree((ClientData)av, TCL_DYNAMIC); /* XXXXXXXX */
+#else
+#if 0 /* use Tcl_Preserve/Release */
+ Tcl_Release((ClientData)av); /* XXXXXXXX */
+#endif
ckfree((char*)av);
+#endif
#else /* TCL_MAJOR_VERSION < 8 */
- free(av);
+#if 0 /* use Tcl_EventuallyFree */
+ Tcl_EventuallyFree((ClientData)av, TCL_DYNAMIC); /* XXXXXXXX */
+#else
+#if 0 /* use Tcl_Preserve/Release */
+ Tcl_Release((ClientData)av); /* XXXXXXXX */
+#endif
+ /* free(av); */
+ ckfree((char*)av);
+#endif
#endif
}
@@ -7064,6 +8049,7 @@ invoke_queue_handler(evPtr, flags)
struct invoke_queue *q = (struct invoke_queue *)evPtr;
volatile VALUE ret;
volatile VALUE q_dat;
+ struct tcltkip *ptr;
DUMP2("do_invoke_queue_handler : evPtr = %p", evPtr);
DUMP2("invoke queue_thread : %lx", rb_thread_current());
@@ -7079,10 +8065,20 @@ invoke_queue_handler(evPtr, flags)
/* process it */
*(q->done) = 1;
+ /* deleted ipterp ? */
+ ptr = get_ip(q->interp);
+ if (deleted_ip(ptr)) {
+ /* deleted IP --> ignore */
+ return 1;
+ }
+
+ /* incr internal handler mark */
+ rbtk_internal_eventloop_handler++;
+
/* check safe-level */
if (rb_safe_level() != q->safe_level) {
/* q_dat = Data_Wrap_Struct(rb_cData,0,0,q); */
- q_dat = Data_Wrap_Struct(rb_cData,invoke_queue_mark,0,q);
+ q_dat = Data_Wrap_Struct(rb_cData,invoke_queue_mark,-1,q);
ret = rb_funcall(rb_proc_new(ivq_safelevel_handler, q_dat),
ID_call, 0);
rb_gc_force_recycle(q_dat);
@@ -7095,6 +8091,9 @@ invoke_queue_handler(evPtr, flags)
/* set result */
RARRAY_PTR(q->result)[0] = ret;
+ /* decr internal handler mark */
+ rbtk_internal_eventloop_handler--;
+
/* complete */
*(q->done) = -1;
@@ -7102,8 +8101,16 @@ invoke_queue_handler(evPtr, flags)
if (RTEST(rb_funcall(q->thread, ID_alive_p, 0, 0))) {
DUMP2("back to caller (caller thread:%lx)", q->thread);
DUMP2(" (current thread:%lx)", rb_thread_current());
+#if CONTROL_BY_STATUS_OF_RB_THREAD_WAIT_FOR_VALUE
+ have_rb_thread_waited_for_value = 1;
+ rb_thread_wakeup(q->thread);
+#else
rb_thread_run(q->thread);
+#endif
DUMP1("finish back to caller");
+#if DO_THREAD_SCHEDULE_AT_CALLBACK_DONE
+ rb_thread_schedule();
+#endif
} else {
DUMP2("caller is dead (caller thread:%lx)", q->thread);
DUMP2(" (current thread:%lx)", rb_thread_current());
@@ -7143,8 +8150,8 @@ ip_invoke_with_position(argc, argv, obj, position)
#ifdef RUBY_VM
ptr = get_ip(ip_obj);
-#endif
DUMP2("status: ptr->tk_thread_id %d", ptr->tk_thread_id);
+#endif
DUMP2("status: Tcl_GetCurrentThread %d", Tcl_GetCurrentThread());
DUMP2("status: eventloopt_thread %lx", eventloop_thread);
@@ -7167,6 +8174,8 @@ ip_invoke_with_position(argc, argv, obj, position)
return result;
}
+ DUMP2("invoke from thread %lx (NOT current eventloop)", current);
+
thr_crit_bup = rb_thread_critical;
rb_thread_critical = Qtrue;
@@ -7174,13 +8183,19 @@ ip_invoke_with_position(argc, argv, obj, position)
av = alloc_invoke_arguments(argc, argv);
/* allocate memory (keep result) */
- //alloc_done = (int*)ALLOC(int);
+ /* alloc_done = (int*)ALLOC(int); */
alloc_done = (int*)ckalloc(sizeof(int));
+#if 0 /* use Tcl_Preserve/Release */
+ Tcl_Preserve((ClientData)alloc_done); /* XXXXXXXX */
+#endif
*alloc_done = 0;
/* allocate memory (freed by Tcl_ServiceEvent) */
+ /* ivq = (struct invoke_queue *)Tcl_Alloc(sizeof(struct invoke_queue)); */
ivq = (struct invoke_queue *)ckalloc(sizeof(struct invoke_queue));
- Tcl_Preserve(ivq);
+#if 1 /* use Tcl_Preserve/Release */
+ Tcl_Preserve((ClientData)ivq); /* XXXXXXXX */
+#endif
/* allocate result obj */
result = rb_ary_new3(1, Qnil);
@@ -7213,16 +8228,31 @@ ip_invoke_with_position(argc, argv, obj, position)
/* wait for the handler to be processed */
DUMP2("wait for handler (current thread:%lx)", current);
while(*alloc_done >= 0) {
- rb_thread_stop();
+ rb_thread_stop();
}
DUMP2("back from handler (current thread:%lx)", current);
/* get result & free allocated memory */
- ret = RARRAY_PTR(result)[0];
- //free(alloc_done);
+ ret = RARRAY(result)->ptr[0];
+#if 0 /* use Tcl_EventuallyFree */
+ Tcl_EventuallyFree((ClientData)alloc_done, TCL_DYNAMIC); /* XXXXXXXX */
+#else
+#if 0 /* use Tcl_Preserve/Release */
+ Tcl_Release((ClientData)alloc_done); /* XXXXXXXX */
+#endif
+ /* free(alloc_done); */
ckfree((char*)alloc_done);
+#endif
+#if 0 /* use Tcl_EventuallyFree */
+ Tcl_EventuallyFree((ClientData)ivq, TCL_DYNAMIC); /* XXXXXXXX */
+#else
+#if 1 /* use Tcl_Preserve/Release */
Tcl_Release(ivq);
+#else
+ ckfree((char*)ivq);
+#endif
+#endif
/* free allocated memory */
free_invoke_arguments(argc, av);
@@ -7230,9 +8260,12 @@ ip_invoke_with_position(argc, argv, obj, position)
/* exception? */
if (rb_obj_is_kind_of(ret, rb_eException)) {
DUMP1("raise exception");
- rb_exc_raise(ret);
+ /* rb_exc_raise(ret); */
+ rb_exc_raise(rb_exc_new3(rb_obj_class(ret),
+ rb_funcall(ret, ID_to_s, 0, 0)));
}
+ DUMP1("exit ip_invoke");
return ret;
}
@@ -7692,6 +8725,10 @@ lib_split_tklist_core(ip_obj, list_str)
volatile VALUE ary, elem;
int idx;
int taint_flag = OBJ_TAINTED(list_str);
+#ifdef RUBY_VM
+ int list_enc_idx;
+ volatile VALUE list_ivar_enc;
+#endif
int result;
VALUE old_gc;
@@ -7706,6 +8743,10 @@ lib_split_tklist_core(ip_obj, list_str)
}
StringValue(list_str);
+#ifdef RUBY_VM
+ list_enc_idx = rb_enc_get_index(list_str);
+ list_ivar_enc = rb_ivar_get(list_str, ID_at_enc);
+#endif
{
#if TCL_MAJOR_VERSION >= 8
@@ -7744,10 +8785,22 @@ lib_split_tklist_core(ip_obj, list_str)
for(idx = 0; idx < objc; idx++) {
elem = get_str_from_obj(objv[idx]);
+#ifdef RUBY_VM
+ if (rb_enc_get_index(elem) == ENCODING_INDEX_BINARY) {
+ rb_enc_associate_index(elem, ENCODING_INDEX_BINARY);
+ rb_ivar_set(elem, ID_at_enc, ENCODING_NAME_BINARY);
+ } else {
+ rb_enc_associate_index(elem, list_enc_idx);
+ rb_ivar_set(elem, ID_at_enc, list_ivar_enc);
+ }
+#endif
if (taint_flag) OBJ_TAINT(elem);
+ /* RARRAY(ary)->ptr[idx] = elem; */
rb_ary_push(ary, elem);
}
+ /* RARRAY(ary)->len = objc; */
+
if (old_gc == Qfalse) rb_gc_enable();
rb_thread_critical = thr_crit_bup;
@@ -7784,8 +8837,11 @@ lib_split_tklist_core(ip_obj, list_str)
elem = rb_str_new2(argv[idx]);
}
/* rb_ivar_set(elem, ID_at_enc, rb_str_new2("binary")); */
- rb_ary_push(ary, elem);
+ /* RARRAY(ary)->ptr[idx] = elem; */
+ rb_ary_push(ary, elem)
}
+ /* RARRAY(ary)->len = argc; */
+
if (old_gc == Qfalse) rb_gc_enable();
#endif
}
@@ -7833,7 +8889,11 @@ lib_merge_tklist(argc, argv, obj)
old_gc = rb_gc_disable();
/* based on Tcl/Tk's Tcl_Merge() */
- flagPtr = ALLOC_N(int, argc);
+ /* flagPtr = ALLOC_N(int, argc); */
+ flagPtr = (int *)ckalloc(sizeof(int) * argc);
+#if 0 /* use Tcl_Preserve/Release */
+ Tcl_Preserve((ClientData)flagPtr); /* XXXXXXXXXX */
+#endif
/* pass 1 */
len = 1;
@@ -7841,7 +8901,7 @@ lib_merge_tklist(argc, argv, obj)
if (OBJ_TAINTED(argv[num])) taint_flag = 1;
dst = StringValuePtr(argv[num]);
#if TCL_MAJOR_VERSION >= 8
- len += Tcl_ScanCountedElement(dst, RSTRING_LEN(argv[num]),
+ len += Tcl_ScanCountedElement(dst, RSTRING_LEN(argv[num]),
&flagPtr[num]) + 1;
#else /* TCL_MAJOR_VERSION < 8 */
len += Tcl_ScanElement(dst, &flagPtr[num]) + 1;
@@ -7849,7 +8909,11 @@ lib_merge_tklist(argc, argv, obj)
}
/* pass 2 */
+ /* result = (char *)Tcl_Alloc(len); */
result = (char *)ckalloc(len);
+#if 0 /* use Tcl_Preserve/Release */
+ Tcl_Preserve((ClientData)result);
+#endif
dst = result;
for(num = 0; num < argc; num++) {
#if TCL_MAJOR_VERSION >= 8
@@ -7869,12 +8933,28 @@ lib_merge_tklist(argc, argv, obj)
dst[-1] = 0;
}
- free(flagPtr);
+#if 0 /* use Tcl_EventuallyFree */
+ Tcl_EventuallyFree((ClientData)flagPtr, TCL_DYNAMIC); /* XXXXXXXX */
+#else
+#if 0 /* use Tcl_Preserve/Release */
+ Tcl_Release((ClientData)flagPtr);
+#endif
+ /* free(flagPtr); */
+ ckfree((char*)flagPtr);
+#endif
/* create object */
str = rb_str_new(result, dst - result - 1);
if (taint_flag) OBJ_TAINT(str);
+#if 0 /* use Tcl_EventuallyFree */
+ Tcl_EventuallyFree((ClientData)result, TCL_DYNAMIC); /* XXXXXXXX */
+#else
+#if 0 /* use Tcl_Preserve/Release */
+ Tcl_Release((ClientData)result); /* XXXXXXXXXXX */
+#endif
+ /* Tcl_Free(result); */
ckfree(result);
+#endif
if (old_gc == Qfalse) rb_gc_enable();
rb_thread_critical = thr_crit_bup;
@@ -7919,17 +8999,15 @@ lib_conv_listelement(self, src)
return dst;
}
-
static VALUE
lib_getversion(self)
VALUE self;
{
- int major, minor, patchlevel, type;
volatile VALUE type_name;
- Tcl_GetVersion(&major, &minor, &patchlevel, &type);
+ set_tcltk_version();
- switch(type) {
+ switch(tcltk_version.type) {
case TCL_ALPHA_RELEASE:
type_name = rb_str_new2("alpha");
break;
@@ -7943,9 +9021,10 @@ lib_getversion(self)
type_name = rb_str_new2("unknown");
}
- return rb_ary_new3(5, INT2NUM(major), INT2NUM(minor),
- INT2NUM(type), type_name,
- INT2NUM(patchlevel));
+ return rb_ary_new3(5, INT2NUM(tcltk_version.major),
+ INT2NUM(tcltk_version.minor),
+ INT2NUM(tcltk_version.type), type_name,
+ INT2NUM(tcltk_version.patchlevel));
}
@@ -7970,6 +9049,7 @@ tcltklib_compile_info()
+ strlen("unknown tcl_threads");
info = ALLOC_N(char, size);
+ /* info = ckalloc(sizeof(char) * size); */ /* SEGV */
sprintf(info, form,
TCLTKLIB_RELEASE_DATE,
@@ -8005,10 +9085,527 @@ tcltklib_compile_info()
ret = rb_obj_freeze(rb_str_new2(info));
free(info);
+ /* ckfree(info); */
return ret;
}
+
+/*###############################################*/
+
+static VALUE
+create_dummy_encoding_for_tk_core(interp, name, error_mode)
+ VALUE interp;
+ VALUE name;
+ VALUE error_mode;
+{
+ struct tcltkip *ptr = get_ip(interp);
+
+ rb_secure(4);
+
+ StringValue(name);
+
+#if TCL_MAJOR_VERSION > 8 || (TCL_MAJOR_VERSION == 8 && TCL_MINOR_VERSION >= 1)
+ if (Tcl_GetEncoding(ptr->ip, RSTRING_PTR(name)) == (Tcl_Encoding) NULL) {
+ if (RTEST(error_mode)) {
+ rb_raise(rb_eArgError, "invalid Tk encoding name '%s'",
+ RSTRING_PTR(name));
+ } else {
+ return Qnil;
+ }
+ }
+#endif
+
+#ifdef RUBY_VM
+ if (RTEST(rb_define_dummy_encoding(RSTRING_PTR(name)))) {
+ int idx = rb_enc_find_index(StringValueCStr(name));
+ return rb_enc_from_encoding(rb_enc_from_index(idx));
+ } else {
+ if (RTEST(error_mode)) {
+ rb_raise(rb_eRuntimeError, "fail to create dummy encoding for '%s'",
+ RSTRING_PTR(name));
+ } else {
+ return Qnil;
+ }
+ }
+#else
+ return name;
+#endif
+}
+static VALUE
+create_dummy_encoding_for_tk(interp, name)
+ VALUE interp;
+ VALUE name;
+{
+ return create_dummy_encoding_for_tk_core(interp, name, Qtrue);
+}
+
+
+#ifdef RUBY_VM
+static int
+update_encoding_table(table, interp, error_mode)
+ VALUE table;
+ VALUE interp;
+ VALUE error_mode;
+{
+ struct tcltkip *ptr;
+ int retry = 0;
+ int i, idx, objc;
+ Tcl_Obj **objv;
+ Tcl_Obj *enc_list;
+ volatile VALUE encname = Qnil;
+ volatile VALUE encobj = Qnil;
+
+ /* interpreter check */
+ if (NIL_P(interp)) return 0;
+ ptr = get_ip(interp);
+ if (ptr == (struct tcltkip *) NULL) return 0;
+ if (deleted_ip(ptr)) return 0;
+
+ /* get Tcl's encoding list */
+ Tcl_GetEncodingNames(ptr->ip);
+ enc_list = Tcl_GetObjResult(ptr->ip);
+ Tcl_IncrRefCount(enc_list);
+
+ if (Tcl_ListObjGetElements(ptr->ip, enc_list,
+ &objc, &objv) != TCL_OK) {
+ Tcl_DecrRefCount(enc_list);
+ /* rb_raise(rb_eRuntimeError, "failt to get Tcl's encoding names");*/
+ return 0;
+ }
+
+ /* check each encoding name */
+ for(i = 0; i < objc; i++) {
+ encname = rb_str_new2(Tcl_GetString(objv[i]));
+ if (NIL_P(rb_hash_lookup(table, encname))) {
+ /* new Tk encoding -> add to table */
+ idx = rb_enc_find_index(StringValueCStr(encname));
+ if (idx < 0) {
+ encobj = create_dummy_encoding_for_tk_core(interp,encname,error_mode);
+ } else {
+ encobj = rb_enc_from_encoding(rb_enc_from_index(idx));
+ }
+ encname = rb_obj_freeze(encname);
+ rb_hash_aset(table, encname, encobj);
+ if (!NIL_P(encobj) && NIL_P(rb_hash_lookup(table, encobj))) {
+ rb_hash_aset(table, encobj, encname);
+ }
+ retry = 1;
+ }
+ }
+
+ Tcl_DecrRefCount(enc_list);
+
+ return retry;
+}
+
+static VALUE
+encoding_table_get_name_core(table, enc_arg, error_mode)
+ VALUE table;
+ VALUE enc_arg;
+ VALUE error_mode;
+{
+ volatile VALUE enc = enc_arg;
+ volatile VALUE name = Qnil;
+ volatile VALUE tmp = Qnil;
+ volatile VALUE interp = rb_ivar_get(table, ID_at_interp);
+ struct tcltkip *ptr = (struct tcltkip *) NULL;
+ int idx;
+
+ /* deleted interp ? */
+ if (!NIL_P(interp)) {
+ ptr = get_ip(interp);
+ if (deleted_ip(ptr)) {
+ ptr = (struct tcltkip *) NULL;
+ }
+ }
+
+ /* encoding argument check */
+ /* 1st: default encoding setting of interp */
+ if (ptr && NIL_P(enc)) {
+ if (rb_respond_to(interp, ID_encoding_name)) {
+ enc = rb_funcall(interp, ID_encoding_name, 0, 0);
+ }
+ }
+ /* 2nd: encoding system of Tcl/Tk */
+ if (NIL_P(enc)) {
+ enc = rb_str_new2(Tcl_GetEncodingName((Tcl_Encoding)NULL));
+ }
+ /* 3rd: Encoding.default_external */
+ if (NIL_P(enc)) {
+ enc = rb_enc_default_external();
+ }
+
+ if (RTEST(rb_obj_is_kind_of(enc, cRubyEncoding))) {
+ /* Ruby's Encoding object */
+ name = rb_hash_lookup(table, enc);
+ if (!NIL_P(name)) {
+ /* find */
+ return name;
+ }
+
+ /* is it new ? */
+ /* update check of Tk encoding names */
+ if (update_encoding_table(table, interp, error_mode)) {
+ /* add new relations to the table */
+ /* RETRY: registered Ruby encoding? */
+ name = rb_hash_lookup(table, enc);
+ if (!NIL_P(name)) {
+ /* find */
+ return name;
+ }
+ }
+ /* fail to find */
+
+ } else {
+ /* String or Symbol? */
+ name = rb_funcall(enc, ID_to_s, 0, 0);
+
+ if (!NIL_P(rb_hash_lookup(table, name))) {
+ /* find */
+ return name;
+ }
+
+ /* is it new ? */
+ idx = rb_enc_find_index(StringValueCStr(name));
+ if (idx >= 0) {
+ enc = rb_enc_from_encoding(rb_enc_from_index(idx));
+
+ /* registered Ruby encoding? */
+ tmp = rb_hash_lookup(table, enc);
+ if (!NIL_P(tmp)) {
+ /* find */
+ return tmp;
+ }
+
+ /* update check of Tk encoding names */
+ if (update_encoding_table(table, interp, error_mode)) {
+ /* add new relations to the table */
+ /* RETRY: registered Ruby encoding? */
+ tmp = rb_hash_lookup(table, enc);
+ if (!NIL_P(tmp)) {
+ /* find */
+ return tmp;
+ }
+ }
+ }
+ /* fail to find */
+ }
+
+ if (RTEST(error_mode)) {
+ enc = rb_funcall(enc_arg, ID_to_s, 0, 0);
+ rb_raise(rb_eArgError, "unsupported Tk encoding '%s'", RSTRING_PTR(enc));
+ }
+ return Qnil;
+}
+static VALUE
+encoding_table_get_obj_core(table, enc, error_mode)
+ VALUE table;
+ VALUE enc;
+ VALUE error_mode;
+{
+ volatile VALUE obj = Qnil;
+
+ obj = rb_hash_lookup(table,
+ encoding_table_get_name_core(table, enc, error_mode));
+ if (RTEST(rb_obj_is_kind_of(obj, cRubyEncoding))) {
+ return obj;
+ } else {
+ return Qnil;
+ }
+}
+
+#else /* ! RUBY_VM */
+#if TCL_MAJOR_VERSION > 8 || (TCL_MAJOR_VERSION == 8 && TCL_MINOR_VERSION >= 1)
+static int
+update_encoding_table(table, interp, error_mode)
+ VALUE table;
+ VALUE interp;
+ VALUE error_mode;
+{
+ struct tcltkip *ptr;
+ int retry = 0;
+ int i, idx, objc;
+ Tcl_Obj **objv;
+ Tcl_Obj *enc_list;
+ volatile VALUE encname = Qnil;
+ volatile VALUE encobj = Qnil;
+
+ /* interpreter check */
+ if (NIL_P(interp)) return 0;
+ ptr = get_ip(interp);
+ if (ptr == (struct tcltkip *) NULL) return 0;
+ if (deleted_ip(ptr)) return 0;
+
+ /* get Tcl's encoding list */
+ Tcl_GetEncodingNames(ptr->ip);
+ enc_list = Tcl_GetObjResult(ptr->ip);
+ Tcl_IncrRefCount(enc_list);
+
+ if (Tcl_ListObjGetElements(ptr->ip, enc_list, &objc, &objv) != TCL_OK) {
+ Tcl_DecrRefCount(enc_list);
+ /* rb_raise(rb_eRuntimeError, "failt to get Tcl's encoding names"); */
+ return 0;
+ }
+
+ /* get encoding name and set it to table */
+ for(i = 0; i < objc; i++) {
+ encname = rb_str_new2(Tcl_GetString(objv[i]));
+ if (NIL_P(rb_hash_lookup(table, encname))) {
+ /* new Tk encoding -> add to table */
+ encname = rb_obj_freeze(encname);
+ rb_hash_aset(table, encname, encname);
+ retry = 1;
+ }
+ }
+
+ Tcl_DecrRefCount(enc_list);
+
+ return retry;
+}
+
+static VALUE
+encoding_table_get_name_core(table, enc, error_mode)
+ VALUE table;
+ VALUE enc;
+ VALUE error_mode;
+{
+ volatile VALUE name = Qnil;
+ int retry = 0;
+
+ enc = rb_funcall(enc, ID_to_s, 0, 0);
+ name = rb_hash_lookup(table, enc);
+
+ if (!NIL_P(name)) {
+ /* find */
+ return name;
+ }
+
+ /* update check */
+ if (update_encoding_table(table, rb_ivar_get(table, ID_at_interp),
+ error_mode)) {
+ /* add new relations to the table */
+ /* RETRY: registered Ruby encoding? */
+ name = rb_hash_lookup(table, enc);
+ if (!NIL_P(name)) {
+ /* find */
+ return name;
+ }
+ }
+
+ if (RTEST(error_mode)) {
+ rb_raise(rb_eArgError, "unsupported Tk encoding '%s'", RSTRING_PTR(enc));
+ }
+ return Qnil;
+}
+static VALUE
+encoding_table_get_obj_core(table, enc, error_mode)
+ VALUE table;
+ VALUE enc;
+ VALUE error_mode;
+{
+ return encoding_table_get_name_core(table, enc, error_mode);
+}
+
+#else /* Tcl/Tk 7.x or 8.0 */
+static VALUE
+encoding_table_get_name_core(table, enc, error_mode)
+ VALUE table;
+ VALUE enc;
+ VALUE error_mode;
+{
+ return Qnil;
+}
+static VALUE
+encoding_table_get_obj_core(table, enc, error_mode)
+ VALUE table;
+ VALUE enc;
+ VALUE error_mode;
+{
+ return Qnil;
+}
+#endif /* end of dependency for the version of Tcl/Tk */
+#endif
+
+static VALUE
+encoding_table_get_name(table, enc)
+ VALUE table;
+ VALUE enc;
+{
+ return encoding_table_get_name_core(table, enc, Qtrue);
+}
+static VALUE
+encoding_table_get_obj(table, enc)
+ VALUE table;
+ VALUE enc;
+{
+ return encoding_table_get_obj_core(table, enc, Qtrue);
+}
+
+#ifdef RUBY_VM
+static VALUE
+create_encoding_table(interp)
+ VALUE interp;
+{
+ struct tcltkip *ptr = get_ip(interp);
+ volatile VALUE table = rb_hash_new();
+ volatile VALUE encname = Qnil;
+ volatile VALUE encobj = Qnil;
+ int i, idx, objc;
+ Tcl_Obj **objv;
+ Tcl_Obj *enc_list;
+
+ rb_secure(4);
+
+ /* set 'binary' encoding */
+ encobj = rb_enc_from_encoding(rb_enc_from_index(ENCODING_INDEX_BINARY));
+ rb_hash_aset(table, ENCODING_NAME_BINARY, encobj);
+ rb_hash_aset(table, encobj, ENCODING_NAME_BINARY);
+
+
+ /* Tcl stub check */
+ tcl_stubs_check();
+
+ /* get Tcl's encoding list */
+ Tcl_GetEncodingNames(ptr->ip);
+ enc_list = Tcl_GetObjResult(ptr->ip);
+ Tcl_IncrRefCount(enc_list);
+
+ if (Tcl_ListObjGetElements(ptr->ip, enc_list, &objc, &objv) != TCL_OK) {
+ Tcl_DecrRefCount(enc_list);
+ rb_raise(rb_eRuntimeError, "failt to get Tcl's encoding names");
+ }
+
+ /* get encoding name and set it to table */
+ for(i = 0; i < objc; i++) {
+ int name2obj, obj2name;
+
+ name2obj = 1; obj2name = 1;
+ encname = rb_obj_freeze(rb_str_new2(Tcl_GetString(objv[i])));
+ idx = rb_enc_find_index(StringValueCStr(encname));
+ if (idx < 0) {
+ /* fail to find ruby encoding -> check known encoding */
+ if (strcmp(RSTRING_PTR(encname), "identity") == 0) {
+ name2obj = 1; obj2name = 0;
+ idx = ENCODING_INDEX_BINARY;
+
+ } else if (strcmp(RSTRING_PTR(encname), "shiftjis") == 0) {
+ name2obj = 1; obj2name = 0;
+ idx = rb_enc_find_index("Shift_JIS");
+
+ } else if (strcmp(RSTRING_PTR(encname), "unicode") == 0) {
+ name2obj = 1; obj2name = 0;
+ idx = ENCODING_INDEX_UTF8;
+
+ } else if (strcmp(RSTRING_PTR(encname), "symbol") == 0) {
+ name2obj = 1; obj2name = 0;
+ idx = rb_enc_find_index("ASCII-8BIT");
+
+ } else {
+ /* regist dummy encoding */
+ name2obj = 1; obj2name = 1;
+ }
+ }
+
+ if (idx < 0) {
+ /* unknown encoding -> create dummy */
+ encobj = create_dummy_encoding_for_tk(interp, encname);
+ } else {
+ encobj = rb_enc_from_encoding(rb_enc_from_index(idx));
+ }
+
+ if (name2obj) {
+ DUMP2("create_encoding_table: name2obj: %s", RSTRING_PTR(encname));
+ rb_hash_aset(table, encname, encobj);
+ }
+ if (obj2name) {
+ DUMP2("create_encoding_table: obj2name: %s", RSTRING_PTR(encname));
+ rb_hash_aset(table, encobj, encname);
+ }
+ }
+
+ Tcl_DecrRefCount(enc_list);
+
+ rb_ivar_set(table, ID_at_interp, interp);
+ rb_ivar_set(interp, ID_encoding_table, table);
+
+ return table;
+}
+
+#else /* ! RUBY_VM */
+#if TCL_MAJOR_VERSION > 8 || (TCL_MAJOR_VERSION == 8 && TCL_MINOR_VERSION >= 1)
+static VALUE
+create_encoding_table(interp)
+ VALUE interp;
+{
+ struct tcltkip *ptr = get_ip(interp);
+ volatile VALUE table = rb_hash_new();
+ volatile VALUE encname = Qnil;
+ int i, objc;
+ Tcl_Obj **objv;
+ Tcl_Obj *enc_list;
+
+ rb_secure(4);
+
+ /* set 'binary' encoding */
+ rb_hash_aset(table, ENCODING_NAME_BINARY, ENCODING_NAME_BINARY);
+
+ /* get Tcl's encoding list */
+ Tcl_GetEncodingNames(ptr->ip);
+ enc_list = Tcl_GetObjResult(ptr->ip);
+ Tcl_IncrRefCount(enc_list);
+
+ if (Tcl_ListObjGetElements(ptr->ip, enc_list, &objc, &objv) != TCL_OK) {
+ Tcl_DecrRefCount(enc_list);
+ rb_raise(rb_eRuntimeError, "failt to get Tcl's encoding names");
+ }
+
+ /* get encoding name and set it to table */
+ for(i = 0; i < objc; i++) {
+ encname = rb_obj_freeze(rb_str_new2(Tcl_GetString(objv[i])));
+ rb_hash_aset(table, encname, encname);
+ }
+
+ Tcl_DecrRefCount(enc_list);
+
+ rb_ivar_set(table, ID_at_interp, interp);
+ rb_ivar_set(interp, ID_encoding_table, table);
+
+ return table;
+}
+
+#else /* Tcl/Tk 7.x or 8.0 */
+static VALUE
+create_encoding_table(interp)
+ VALUE interp;
+{
+ volatile VALUE table = rb_hash_new();
+ rb_secure(4);
+ rb_ivar_set(interp, ID_encoding_table, table);
+ return table;
+}
+#endif
+#endif
+
+static VALUE
+ip_get_encoding_table(interp)
+ VALUE interp;
+{
+ volatile VALUE table = Qnil;
+
+ table = rb_ivar_get(interp, ID_encoding_table);
+
+ if (NIL_P(table)) {
+ /* initialize encoding_table */
+ table = create_encoding_table(interp);
+ rb_define_singleton_method(table, "get_name", encoding_table_get_name, 1);
+ rb_define_singleton_method(table, "get_obj", encoding_table_get_obj, 1);
+ }
+
+ return table;
+}
+
+
/*###############################################*/
/*
@@ -8047,26 +9644,29 @@ struct dummy_TkMenuRef {
char *dummy3;
};
-#if 0
+#if 0 /* was available on Tk8.0 -- Tk8.4 */
EXTERN struct dummy_TkMenuRef *TkFindMenuReferences(Tcl_Interp*, char*);
-#else
-#define MENU_HASH_KEY "tkMenus" /* based on Tk8.0 - Tk8.5b1 */
+#else /* based on Tk8.0 -- Tk8.5.0 */
+#define MENU_HASH_KEY "tkMenus"
#endif
#endif
static VALUE
-ip_make_menu_embeddable(interp, menu_path)
+ip_make_menu_embeddable_core(interp, argc, argv)
VALUE interp;
- VALUE menu_path;
+ int argc;
+ VALUE *argv;
{
#if TCL_MAJOR_VERSION >= 8
+ volatile VALUE menu_path;
struct tcltkip *ptr = get_ip(interp);
struct dummy_TkMenuRef *menuRefPtr = NULL;
XEvent event;
Tcl_HashTable *menuTablePtr;
Tcl_HashEntry *hashEntryPtr;
+ menu_path = argv[0];
StringValue(menu_path);
#if 0 /* was available on Tk8.0 -- Tk8.4 */
@@ -8131,6 +9731,18 @@ ip_make_menu_embeddable(interp, menu_path)
return interp;
}
+static VALUE
+ip_make_menu_embeddable(interp, menu_path)
+ VALUE interp;
+ VALUE menu_path;
+{
+ VALUE argv[1];
+
+ argv[0] = menu_path;
+ return tk_funcall(ip_make_menu_embeddable_core, 1, argv, interp);
+}
+
+
/*###############################################*/
/*---- initialization ----*/
@@ -8152,6 +9764,22 @@ Init_tcltklib()
/* --------------------------------------------------------------- */
+#ifdef RUBY_VM
+ rb_global_variable(&cRubyEncoding);
+ cRubyEncoding = rb_const_get(rb_cObject, rb_intern("Encoding"));
+
+ ENCODING_INDEX_UTF8 = rb_enc_to_index(rb_utf8_encoding());
+ ENCODING_INDEX_BINARY = rb_enc_find_index("binary");
+#endif
+
+ rb_global_variable(&ENCODING_NAME_UTF8);
+ rb_global_variable(&ENCODING_NAME_BINARY);
+
+ ENCODING_NAME_UTF8 = rb_obj_freeze(rb_str_new2("utf-8"));
+ ENCODING_NAME_BINARY = rb_obj_freeze(rb_str_new2("binary"));
+
+ /* --------------------------------------------------------------- */
+
rb_global_variable(&eTkCallbackReturn);
rb_global_variable(&eTkCallbackBreak);
rb_global_variable(&eTkCallbackContinue);
@@ -8229,6 +9857,8 @@ Init_tcltklib()
ID_at_enc = rb_intern("@encoding");
ID_at_interp = rb_intern("@interp");
+ ID_encoding_name = rb_intern("encoding_name");
+ ID_encoding_table = rb_intern("encoding_table");
ID_stop_p = rb_intern("stop?");
ID_alive_p = rb_intern("alive?");
@@ -8262,8 +9892,10 @@ Init_tcltklib()
lib_evloop_abort_on_exc, 0);
rb_define_module_function(lib, "mainloop_abort_on_exception=",
lib_evloop_abort_on_exc_set, 1);
- rb_define_module_function(lib, "set_eventloop_window_mode",set_eventloop_window_mode,1);
- rb_define_module_function(lib, "get_eventloop_window_mode",get_eventloop_window_mode,0);
+ rb_define_module_function(lib, "set_eventloop_window_mode",
+ set_eventloop_window_mode, 1);
+ rb_define_module_function(lib, "get_eventloop_window_mode",
+ get_eventloop_window_mode, 0);
rb_define_module_function(lib, "set_eventloop_tick",set_eventloop_tick,1);
rb_define_module_function(lib, "get_eventloop_tick",get_eventloop_tick,0);
rb_define_module_function(lib, "set_no_event_wait", set_no_event_wait, 1);
@@ -8325,6 +9957,12 @@ Init_tcltklib()
/* --------------------------------------------------------------- */
+ rb_define_method(ip, "create_dummy_encoding_for_tk",
+ create_dummy_encoding_for_tk, 1);
+ rb_define_method(ip, "encoding_table", ip_get_encoding_table, 0);
+
+ /* --------------------------------------------------------------- */
+
rb_define_method(ip, "_get_variable", ip_get_variable, 2);
rb_define_method(ip, "_get_variable2", ip_get_variable2, 3);
rb_define_method(ip, "_set_variable", ip_set_variable, 3);
@@ -8384,7 +10022,11 @@ Init_tcltklib()
/* if ruby->nativethread-supprt and tcltklib->doen't,
the following will cause link-error. */
+#ifdef RUBY_VM
ruby_native_thread_p();
+#else
+ is_ruby_native_thread();
+#endif
/* --------------------------------------------------------------- */
@@ -8405,6 +10047,11 @@ Init_tcltklib()
}
/* --------------------------------------------------------------- */
+
+ Tcl_ObjType_ByteArray = Tcl_GetObjType(Tcl_ObjTypeName_ByteArray);
+ Tcl_ObjType_String = Tcl_GetObjType(Tcl_ObjTypeName_String);
+
+ /* --------------------------------------------------------------- */
}
/* eof */
diff --git a/ext/tk/tkutil/tkutil.c b/ext/tk/tkutil/tkutil.c
index cccb6e1553..1781dd5e4a 100644
--- a/ext/tk/tkutil/tkutil.c
+++ b/ext/tk/tkutil/tkutil.c
@@ -7,11 +7,20 @@
************************************************/
-#define TKUTIL_RELEASE_DATE "2006-04-06"
+#define TKUTIL_RELEASE_DATE "2008-03-29"
-#include "ruby/ruby.h"
+#include "ruby.h"
+
+#ifdef RUBY_VM /* Ruby 1.9 */
+/* #include "ruby/ruby.h" */
#include "ruby/signal.h"
#include "ruby/st.h"
+#else
+/* #include "ruby.h" */
+#include "rubysig.h"
+#include "version.h"
+#include "st.h"
+#endif
static VALUE cMethod;
@@ -25,6 +34,8 @@ static VALUE TK_None;
static VALUE cCB_SUBST;
static VALUE cSUBST_INFO;
+static VALUE ENCODING_NAME_UTF8; /* for saving GC cost */
+
static ID ID_split_tklist;
static ID ID_toUTF8;
static ID ID_fromUTF8;
@@ -382,7 +393,7 @@ ary2list(ary, enc_flag, self)
val = rb_funcall(cTclTkLib, ID_fromUTF8, 2, val, dst_enc);
rb_ivar_set(val, ID_at_enc, dst_enc);
} else {
- rb_ivar_set(val, ID_at_enc, rb_str_new2("utf-8"));
+ rb_ivar_set(val, ID_at_enc, ENCODING_NAME_UTF8);
}
return val;
} else {
@@ -475,7 +486,7 @@ ary2list2(ary, enc_flag, self)
val = rb_funcall(cTclTkLib, ID_fromUTF8, 2, val, dst_enc);
rb_ivar_set(val, ID_at_enc, dst_enc);
} else {
- rb_ivar_set(val, ID_at_enc, rb_str_new2("utf-8"));
+ rb_ivar_set(val, ID_at_enc, ENCODING_NAME_UTF8);
}
return val;
} else {
@@ -780,7 +791,11 @@ get_eval_string_core(obj, enc_flag, self)
return fromDefaultEnc_toUTF8(rb_str_new2(rb_id2name(SYM2ID(obj))), self);
}
} else {
+#ifdef RUBY_VM
+ return rb_sym_to_s(obj);
+#else
return rb_str_new2(rb_id2name(SYM2ID(obj)));
+#endif
}
case T_HASH:
@@ -1485,6 +1500,7 @@ tkobj_path(self)
return rb_ivar_get(self, ID_at_path);
}
+
/*************************************/
/* release date */
const char tkutil_release_date[] = TKUTIL_RELEASE_DATE;
@@ -1609,4 +1625,8 @@ Init_tkutil()
rb_define_method(mTK, "num_or_str", tcl2rb_num_or_str, 1);
/* --------------------- */
+ rb_global_variable(&ENCODING_NAME_UTF8);
+ ENCODING_NAME_UTF8 = rb_obj_freeze(rb_str_new2("utf-8"));
+
+ /* --------------------- */
}