diff options
-rw-r--r-- | ChangeLog | 8 | ||||
-rw-r--r-- | ext/tk/extconf.rb | 91 | ||||
-rw-r--r-- | ext/tk/lib/tk.rb | 48 | ||||
-rw-r--r-- | ext/tk/lib/tk/autoload.rb | 2 | ||||
-rw-r--r-- | ext/tk/lib/tk/variable.rb | 2 | ||||
-rw-r--r-- | ext/tk/tcltklib.c | 70 |
6 files changed, 155 insertions, 66 deletions
@@ -1,3 +1,11 @@ +Mon Oct 20 08:20:01 2008 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp> + + * ext/tk/lib/tk.rb: support Encoding.default_internal. + + * ext/tk/tcltklib.c: ditto. + + * ext/tk/extconf.rb: improve the strategy for searching Tcl/Tk headers. + Mon Oct 20 00:57:04 2008 Tanaka Akira <akr@fsij.org> * lib/test/unit.rb (Test::Unit.setup_argv): call given block for diff --git a/ext/tk/extconf.rb b/ext/tk/extconf.rb index a0e964a5f9..419c79ceda 100644 --- a/ext/tk/extconf.rb +++ b/ext/tk/extconf.rb @@ -64,6 +64,18 @@ tcltk_version = with_config("tcltkversion") use_X = with_config("X11", (! is_win32)) +def parse_tclConfig(file) + # check tclConfig.sh/tkConfig.sh + tbl = {} + IO.foreach(file){|line| + line.strip! + next if line !~ /^([^\#=][^=]*)=(['"]|)(.*)\2$/ + key, val = $1, $3 + tbl[key] = val.gsub(/\$\{([^}]+)\}/){|s| tbl[$1]} rescue nil + } + tbl +end + def check_tcltk_version(version) return [nil, nil] unless version @@ -118,7 +130,7 @@ def find_tcl(tcllib, stubs, version, *opt_paths) if version && ! version.empty? versions = [version] else - versions = %w[8.6 8.5 8.4 8.3 8.2 8.1 8.0 7.6] + versions = %w[8.7 8.6 8.5 8.4 8.3 8.2 8.1 8.0 7.6] end if tcllib @@ -161,7 +173,7 @@ def find_tk(tklib, stubs, version, *opt_paths) if version && ! version.empty? versions = [version] else - versions = %w[8.6 8.5 8.4 8.3 8.2 8.1 8.0 4.2] + versions = %w[8.7 8.6 8.5 8.4 8.3 8.2 8.1 8.0 4.2] end if tklib @@ -185,6 +197,35 @@ def find_tk(tklib, stubs, version, *opt_paths) st end +def find_tcltk_header(tclver, tkver) + base_dir = ['/usr/local/include', '/usr/pkg/include', '/usr/include'] + base_dir << '/Tcl/include' # default for ActiveTcl + + unless have_tcl_h = have_header('tcl.h') + if tclver && ! tclver.empty? + versions = [tclver] + else + versions = %w[8.7 8.6 8.5 8.4 8.3 8.2 8.1 8.0 7.6] + end + paths = base_dir.dup + versions.each{|ver| paths.concat(base_dir.map{|dir| dir + '/tcl' + ver})} + have_tcl_h = find_header('tcl.h', *paths) + end + + unless have_tk_h = have_header("tk.h") + if tkver && ! tkver.empty? + versions = [tkver] + else + versions = %w[8.7 8.6 8.5 8.4 8.3 8.2 8.1 8.0 4.2] + end + paths = base_dir.dup + versions.each{|ver| paths.concat(base_dir.map{|dir| dir + '/tk' + ver})} + have_tk_h = find_header('tk.h', *paths) + end + + have_tcl_h && have_tk_h +end + def find_X11(*opt_paths) default_paths = [ "/usr/X11/lib", "/usr/lib/X11", "/usr/X11R6/lib", "/usr/openwin/lib" ] @@ -218,37 +259,19 @@ def pthread_check() else # tcl-thread is unknown and tclConfig.sh is given begin - open(tclConfig, "r") do |cfg| - while line = cfg.gets() - if line =~ /^\s*TCL_THREADS=(0|1)/ - tcl_enable_thread = ($1 == "1") - break - end - - if line =~ /^\s*TCL_MAJOR_VERSION=("|')(\d+)\1/ - tcl_major_ver = $2 - if tcl_major_ver =~ /^[1-7]$/ - tcl_enable_thread = false - break - end - if tcl_major_ver == "8" && tcl_minor_ver == "0" - tcl_enable_thread = false - break - end - end - - if line =~ /^\s*TCL_MINOR_VERSION=("|')(\d+)\1/ - tcl_minor_ver = $2 - if tcl_major_ver == "8" && tcl_minor_ver == "0" - tcl_enable_thread = false - break - end - end + tbl = parse_tclConfig(tclConfig) + if tbl['TCL_THREADS'] + tcl_enable_thread = (tbl['TCL_THREADS'] == "1") + else + tcl_major_ver = tbl['TCL_MAJOR_VERSION'].to_i + tcl_minor_ver = tbl['TCL_MINOR_VERSION'].to_i + if tcl_major_ver < 8 || (tcl_major_ver == 8 && tcl_minor_ver == 0) + tcl_enable_thread = false end end if tcl_enable_thread == nil - # not find definition + # cannot find definition if tcl_major_ver puts("Warning: '#{tclConfig}' doesn't include TCL_THREADS definition.") else @@ -376,11 +399,11 @@ end tclver, tkver = check_tcltk_version(tcltk_version) -if have_header("tcl.h") && have_header("tk.h") && - ( tcltk_framework || - ( ( !use_X || find_X11(x11_ldir2, x11_ldir) ) && - find_tcl(tcllib, stubs, tclver, *tcl_ldir_list) && - find_tk(tklib, stubs, tkver, *tk_ldir_list) ) ) +if ( tcltk_framework || + ( find_tcltk_header(tclver, tkver) && + ( !use_X || find_X11(x11_ldir2, x11_ldir) ) && + find_tcl(tcllib, stubs, tclver, *tcl_ldir_list) && + find_tk(tklib, stubs, tkver, *tk_ldir_list) ) ) $CPPFLAGS += ' -DUSE_TCL_STUBS -DUSE_TK_STUBS' if stubs $CPPFLAGS += ' -D_WIN32' if /cygwin/ =~ RUBY_PLATFORM diff --git a/ext/tk/lib/tk.rb b/ext/tk/lib/tk.rb index c3401dfadb..67069abc32 100644 --- a/ext/tk/lib/tk.rb +++ b/ext/tk/lib/tk.rb @@ -1112,7 +1112,15 @@ module TkCore WITH_RUBY_VM = Object.const_defined?(:VM) && ::VM.class == Class WITH_ENCODING = defined?(::Encoding.default_external) && true #WITH_ENCODING = Object.const_defined?(:Encoding) && ::Encoding.class == Class - + #if TclTkLib::WINDOWING_SYSTEM == 'aqua' + # if (TclTkLib.get_version <=> [8, 4, TclTkLib::RELEASE_TYPE::FINAL, 9]) > 0 + # # *** KNOWN BUG *** + # # Main event loop thread of TkAqua (> Tk8.4.9) must be the main + # # application thread. So, ruby1.9 users must call Tk.mainloop on + # # the main application thread. + # RUN_EVENTLOOP_ON_MAIN_THREAD = true + # end + #end unless self.const_defined? :RUN_EVENTLOOP_ON_MAIN_THREAD ### Ruby 1.9 !!!!!!!!!!!!!!!!!!!!!!!!!! RUN_EVENTLOOP_ON_MAIN_THREAD = false @@ -1671,8 +1679,18 @@ module TkCore end def mainloop(check_root = true) - if !TkCore::WITH_RUBY_VM || TkCore::RUN_EVENTLOOP_ON_MAIN_THREAD + if !TkCore::WITH_RUBY_VM TclTkLib.mainloop(check_root) + + elsif TkCore::RUN_EVENTLOOP_ON_MAIN_THREAD + #if TclTkLib::WINDOWING_SYSTEM == 'aqua' && + # Thread.current != Thread.main && + # (TclTkLib.get_version <=> [8,4,TclTkLib::RELEASE_TYPE::FINAL,9]) > 0 + # raise RuntimeError, + # "eventloop on TkAqua ( > Tk8.4.9 ) works on the main thread only" + #end + TclTkLib.mainloop(check_root) + else ### Ruby 1.9 !!!!! unless TkCore::INTERP.default_master? # [MultiTkIp] slave interp ? @@ -2389,6 +2407,7 @@ if (/^(8\.[1-9]|9\.|[1-9][0-9])/ =~ Tk::TCL_VERSION && !Tk::JAPANIZED_TK) BINARY_NAME = 'binary'.freeze UTF8_NAME = 'utf-8'.freeze DEFAULT_EXTERNAL_NAME = RubyEncoding.default_external.name.freeze + DEFAULT_INTERNAL_NAME = RubyEncoding.default_internal.name.freeze rescue nil BINARY = RubyEncoding.find(BINARY_NAME) UNKNOWN = RubyEncoding.find('ASCII-8BIT') @@ -2528,7 +2547,7 @@ if (/^(8\.[1-9]|9\.|[1-9][0-9])/ =~ Tk::TCL_VERSION && !Tk::JAPANIZED_TK) def tk_encoding_names #TkComm.simplelist(TkCore::INTERP._invoke_without_enc(Tk::Encoding::ENCNAMES_CMD[0], Tk::Encoding::ENCNAMES_CMD[1])) TkComm.simplelist(TkCore::INTERP._invoke_without_enc('encoding', 'names')) - end + end def encoding_names self.tk_encoding_names.find_all{|name| Tk::Encoding::ENCODING_TABLE.get_name(name) rescue false @@ -2721,7 +2740,12 @@ if (/^(8\.[1-9]|9\.|[1-9][0-9])/ =~ Tk::TCL_VERSION && !Tk::JAPANIZED_TK) enc_name ||= Tk::Encoding::ENCODING_TABLE.get_name(str.encoding) rescue nil - unless enc_name + if enc_name + # str has its encoding information + encstr = __toUTF8(str, enc_name) + encstr.force_encoding(Tk::Encoding::UTF8_NAME) + return encstr + else # str.encoding isn't supported by Tk -> try to convert on Ruby begin return str.encode(Tk::Encoding::UTF8_NAME) # new string @@ -2976,6 +3000,7 @@ if (/^(8\.[1-9]|9\.|[1-9][0-9])/ =~ Tk::TCL_VERSION && !Tk::JAPANIZED_TK) else ### Ruby 1.9 !!!!!!!!!!!! loc_enc_obj = ::Encoding.find(::Encoding.locale_charmap) ext_enc_obj = ::Encoding.default_external + int_enc_obj = ::Encoding.default_internal || ext_enc_obj tksys_enc_name = Tk::Encoding::ENCODING_TABLE.get_name(Tk.encoding_system) # p [Tk.encoding, Tk.encoding_system, loc_enc_obj, ext_enc_obj] @@ -3052,7 +3077,8 @@ if (/^(8\.[1-9]|9\.|[1-9][0-9])/ =~ Tk::TCL_VERSION && !Tk::JAPANIZED_TK) end unless enc_name - if ext_enc_obj == Tk::Encoding::UNKNOWN + #if ext_enc_obj == Tk::Encoding::UNKNOWN + if int_enc_obj == Tk::Encoding::UNKNOWN if loc_enc_obj == Tk::Encoding::UNKNOWN # use Tk.encoding_system enc_name = tksys_enc_name @@ -3060,7 +3086,7 @@ if (/^(8\.[1-9]|9\.|[1-9][0-9])/ =~ Tk::TCL_VERSION && !Tk::JAPANIZED_TK) # 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 + if loc_enc_name # use locale_charmap enc_name = loc_enc_name else @@ -3074,10 +3100,12 @@ if (/^(8\.[1-9]|9\.|[1-9][0-9])/ =~ Tk::TCL_VERSION && !Tk::JAPANIZED_TK) 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 + #ext_enc_name = Tk::Encoding::ENCODING_TABLE.get_name(ext_enc_obj) + #if ext_enc_name && ext_enc_name != tksys_enc_name + int_enc_name = Tk::Encoding::ENCODING_TABLE.get_name(int_enc_obj) + if int_enc_name # use default_external - enc_name = ext_enc_name + enc_name = int_enc_name else # use Tk.encoding_system enc_name = tksys_enc_name @@ -5501,7 +5529,7 @@ TkWidget = TkWindow #Tk.freeze module Tk - RELEASE_DATE = '2008-06-17'.freeze + RELEASE_DATE = '2008-10-20'.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 0773f7708d..79b6e01eb8 100644 --- a/ext/tk/lib/tk/autoload.rb +++ b/ext/tk/lib/tk/autoload.rb @@ -394,7 +394,7 @@ Tk.default_widget_set = :Tk ############################################ # depend on the version of Tcl/Tk -# major, minor, type, type_name, patchlevel = TclTkLib.get_version +# major, minor, type, patchlevel = TclTkLib.get_version ############################################ # Ttk (Tile) support diff --git a/ext/tk/lib/tk/variable.rb b/ext/tk/lib/tk/variable.rb index f738a96ee7..b73a4677da 100644 --- a/ext/tk/lib/tk/variable.rb +++ b/ext/tk/lib/tk/variable.rb @@ -26,7 +26,7 @@ class TkVariable TkVar_ID_TBL.mutex.synchronize{ TkVar_ID_TBL.clear } } - major, minor, type, type_name, patchlevel = TclTkLib.get_version + major, minor, type, patchlevel = TclTkLib.get_version USE_OLD_TRACE_OPTION_STYLE = (major < 8) || (major == 8 && minor < 4) #TkCore::INTERP.add_tk_procs('rb_var', 'args', diff --git a/ext/tk/tcltklib.c b/ext/tk/tcltklib.c index a8829d3b69..34b66f76e6 100644 --- a/ext/tk/tcltklib.c +++ b/ext/tk/tcltklib.c @@ -4,7 +4,7 @@ * Oct. 24, 1997 Y. Matsumoto */ -#define TCLTKLIB_RELEASE_DATE "2008-06-17" +#define TCLTKLIB_RELEASE_DATE "2008-10-20" #include "ruby.h" @@ -44,9 +44,9 @@ #include "stubs.h" #ifndef TCL_ALPHA_RELEASE -#define TCL_ALPHA_RELEASE 0 -#define TCL_BETA_RELEASE 1 -#define TCL_FINAL_RELEASE 2 +#define TCL_ALPHA_RELEASE 0 /* "alpha" */ +#define TCL_BETA_RELEASE 1 /* "beta" */ +#define TCL_FINAL_RELEASE 2 /* "final" */ #endif static VALUE rb_thread_critical; /* dummy */ @@ -55,8 +55,8 @@ int rb_thread_check_trap_pending(); static struct { int major; int minor; + int type; /* ALPHA==0, BETA==1, FINAL==2 */ int patchlevel; - int type; } tcltk_version = {0, 0, 0, 0}; static void @@ -9070,28 +9070,30 @@ static VALUE lib_getversion(self) VALUE self; { - volatile VALUE type_name; + set_tcltk_version(); + + return rb_ary_new3(4, INT2NUM(tcltk_version.major), + INT2NUM(tcltk_version.minor), + INT2NUM(tcltk_version.type), + INT2NUM(tcltk_version.patchlevel)); +} +static VALUE +lib_get_reltype_name(self) + VALUE self; +{ set_tcltk_version(); switch(tcltk_version.type) { case TCL_ALPHA_RELEASE: - type_name = rb_str_new2("alpha"); - break; + return rb_str_new2("alpha"); case TCL_BETA_RELEASE: - type_name = rb_str_new2("beta"); - break; + return rb_str_new2("beta"); case TCL_FINAL_RELEASE: - type_name = rb_str_new2("final"); - break; + return rb_str_new2("final"); default: - type_name = rb_str_new2("unknown"); + rb_raise(rb_eRuntimeError, "tcltklib has invalid release type number"); } - - return rb_ary_new3(5, INT2NUM(tcltk_version.major), - INT2NUM(tcltk_version.minor), - INT2NUM(tcltk_version.type), type_name, - INT2NUM(tcltk_version.patchlevel)); } @@ -9294,14 +9296,22 @@ encoding_table_get_name_core(table, enc_arg, error_mode) enc = rb_funcall(interp, ID_encoding_name, 0, 0); } } - /* 2nd: encoding system of Tcl/Tk */ + /* 2nd: Encoding.default_internal */ + if (NIL_P(enc)) { + enc = rb_enc_default_internal(); + } + /* 3rd: encoding system of Tcl/Tk */ if (NIL_P(enc)) { enc = rb_str_new2(Tcl_GetEncodingName((Tcl_Encoding)NULL)); } - /* 3rd: Encoding.default_external */ + /* 4th: Encoding.default_external */ if (NIL_P(enc)) { enc = rb_enc_default_external(); } + /* 5th: Encoding.locale_charmap */ + if (NIL_P(enc)) { + enc = rb_locale_charmap(rb_cEncoding); + } if (RTEST(rb_obj_is_kind_of(enc, cRubyEncoding))) { /* Ruby's Encoding object */ @@ -9870,6 +9880,24 @@ Init_tcltklib() /* --------------------------------------------------------------- */ +#ifdef __WIN32__ +#define TK_WINDOWING_SYSTEM "win32" +#else +#ifdef MAC_TCL +#define TK_WINDOWING_SYSTEM "classic" +#else +#ifdef MAC_OSX_TK +#define TK_WINDOWING_SYSTEM "aqua" +#else +#define TK_WINDOWING_SYSTEM "x11" +#endif +#endif +#endif + rb_define_const(lib, "WINDOWING_SYSTEM", + rb_obj_freeze(rb_str_new2(TK_WINDOWING_SYSTEM))); + + /* --------------------------------------------------------------- */ + rb_define_const(ev_flag, "NONE", INT2FIX(0)); rb_define_const(ev_flag, "WINDOW", INT2FIX(TCL_WINDOW_EVENTS)); rb_define_const(ev_flag, "FILE", INT2FIX(TCL_FILE_EVENTS)); @@ -9899,6 +9927,8 @@ Init_tcltklib() /* --------------------------------------------------------------- */ rb_define_module_function(lib, "get_version", lib_getversion, -1); + rb_define_module_function(lib, "get_release_type_name", + lib_get_reltype_name, -1); rb_define_const(release_type, "ALPHA", INT2FIX(TCL_ALPHA_RELEASE)); rb_define_const(release_type, "BETA", INT2FIX(TCL_BETA_RELEASE)); |