PageRenderTime 54ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 0ms

/sources/ruby-1.8.5/ext/tk/lib/tk.rb

http://rubyworks.googlecode.com/
Ruby | 2512 lines | 1680 code | 213 blank | 619 comment | 214 complexity | 671b949f0233287f272821fff9f2607f MD5 | raw file
Possible License(s): GPL-2.0, BSD-3-Clause, LGPL-2.1, AGPL-3.0, 0BSD, Unlicense

Large files files are truncated, but you can click here to view the full file

  1. #
  2. # tk.rb - Tk interface module using tcltklib
  3. # $Date: 2006/07/14 04:10:49 $
  4. # by Yukihiro Matsumoto <matz@netlab.jp>
  5. # use Shigehiro's tcltklib
  6. require 'tcltklib'
  7. require 'tkutil'
  8. # autoload
  9. require 'tk/autoload'
  10. class TclTkIp
  11. # backup original (without encoding) _eval and _invoke
  12. alias _eval_without_enc _eval
  13. alias _invoke_without_enc _invoke
  14. def _ip_id_
  15. # for RemoteTkIp
  16. ''
  17. end
  18. end
  19. # define TkComm module (step 1: basic functions)
  20. module TkComm
  21. include TkUtil
  22. extend TkUtil
  23. WidgetClassNames = {}.taint
  24. TkExtlibAutoloadModule = [].taint
  25. # None = Object.new ### --> definition is moved to TkUtil module
  26. # def None.to_s
  27. # 'None'
  28. # end
  29. # None.freeze
  30. #Tk_CMDTBL = {}
  31. #Tk_WINDOWS = {}
  32. Tk_IDs = ["00000".taint, "00000".taint].freeze # [0]-cmdid, [1]-winid
  33. # for backward compatibility
  34. Tk_CMDTBL = Object.new
  35. def Tk_CMDTBL.method_missing(id, *args)
  36. TkCore::INTERP.tk_cmd_tbl.__send__(id, *args)
  37. end
  38. Tk_CMDTBL.freeze
  39. Tk_WINDOWS = Object.new
  40. def Tk_WINDOWS.method_missing(id, *args)
  41. TkCore::INTERP.tk_windows.__send__(id, *args)
  42. end
  43. Tk_WINDOWS.freeze
  44. self.instance_eval{
  45. @cmdtbl = [].taint
  46. }
  47. unless const_defined?(:GET_CONFIGINFO_AS_ARRAY)
  48. # GET_CONFIGINFO_AS_ARRAY = false => returns a Hash { opt =>val, ... }
  49. # true => returns an Array [[opt,val], ... ]
  50. # val is a list which includes resource info.
  51. GET_CONFIGINFO_AS_ARRAY = true
  52. end
  53. unless const_defined?(:GET_CONFIGINFOwoRES_AS_ARRAY)
  54. # for configinfo without resource info; list of [opt, value] pair
  55. # false => returns a Hash { opt=>val, ... }
  56. # true => returns an Array [[opt,val], ... ]
  57. GET_CONFIGINFOwoRES_AS_ARRAY = true
  58. end
  59. # *** ATTENTION ***
  60. # 'current_configinfo' method always returns a Hash under all cases of above.
  61. def error_at
  62. frames = caller()
  63. frames.delete_if do |c|
  64. c =~ %r!/tk(|core|thcore|canvas|text|entry|scrollbox)\.rb:\d+!
  65. end
  66. frames
  67. end
  68. private :error_at
  69. def _genobj_for_tkwidget(path)
  70. return TkRoot.new if path == '.'
  71. begin
  72. #tk_class = TkCore::INTERP._invoke('winfo', 'class', path)
  73. tk_class = Tk.ip_invoke_without_enc('winfo', 'class', path)
  74. rescue
  75. return path
  76. end
  77. if ruby_class = WidgetClassNames[tk_class]
  78. ruby_class_name = ruby_class.name
  79. # gen_class_name = ruby_class_name + 'GeneratedOnTk'
  80. gen_class_name = ruby_class_name
  81. classname_def = ''
  82. else # ruby_class == nil
  83. mods = TkExtlibAutoloadModule.find_all{|m| m.const_defined?(tk_class)}
  84. mods.each{|mod|
  85. begin
  86. mod.const_get(tk_class) # auto_load
  87. break if (ruby_class = WidgetClassNames[tk_class])
  88. rescue LoadError
  89. # ignore load error
  90. end
  91. }
  92. unless ruby_class
  93. std_class = 'Tk' << tk_class
  94. if Object.const_defined?(std_class)
  95. Object.const_get(std_class) # auto_load
  96. ruby_class = WidgetClassNames[tk_class]
  97. end
  98. end
  99. if ruby_class
  100. # found
  101. ruby_class_name = ruby_class.name
  102. gen_class_name = ruby_class_name
  103. classname_def = ''
  104. else
  105. # unknown
  106. ruby_class_name = 'TkWindow'
  107. gen_class_name = 'TkWidget_' + tk_class
  108. classname_def = "WidgetClassName = '#{tk_class}'.freeze"
  109. end
  110. end
  111. ###################################
  112. =begin
  113. if ruby_class = WidgetClassNames[tk_class]
  114. ruby_class_name = ruby_class.name
  115. # gen_class_name = ruby_class_name + 'GeneratedOnTk'
  116. gen_class_name = ruby_class_name
  117. classname_def = ''
  118. else
  119. mod = TkExtlibAutoloadModule.find{|m| m.const_defined?(tk_class)}
  120. if mod
  121. ruby_class_name = mod.name + '::' + tk_class
  122. gen_class_name = ruby_class_name
  123. classname_def = ''
  124. elsif Object.const_defined?('Tk' + tk_class)
  125. ruby_class_name = 'Tk' + tk_class
  126. # gen_class_name = ruby_class_name + 'GeneratedOnTk'
  127. gen_class_name = ruby_class_name
  128. classname_def = ''
  129. else
  130. ruby_class_name = 'TkWindow'
  131. # gen_class_name = ruby_class_name + tk_class + 'GeneratedOnTk'
  132. gen_class_name = 'TkWidget_' + tk_class
  133. classname_def = "WidgetClassName = '#{tk_class}'.freeze"
  134. end
  135. end
  136. =end
  137. =begin
  138. unless Object.const_defined? gen_class_name
  139. Object.class_eval "class #{gen_class_name}<#{ruby_class_name}
  140. #{classname_def}
  141. end"
  142. end
  143. Object.class_eval "#{gen_class_name}.new('widgetname'=>'#{path}',
  144. 'without_creating'=>true)"
  145. =end
  146. base = Object
  147. gen_class_name.split('::').each{|klass|
  148. next if klass == ''
  149. if base.const_defined?(klass)
  150. base = base.class_eval klass
  151. else
  152. base = base.class_eval "class #{klass}<#{ruby_class_name}
  153. #{classname_def}
  154. end
  155. #{klass}"
  156. end
  157. }
  158. base.class_eval "#{gen_class_name}.new('widgetname'=>'#{path}',
  159. 'without_creating'=>true)"
  160. end
  161. private :_genobj_for_tkwidget
  162. module_function :_genobj_for_tkwidget
  163. def _at(x,y=nil)
  164. if y
  165. "@#{Integer(x)},#{Integer(y)}"
  166. else
  167. "@#{Integer(x)}"
  168. end
  169. end
  170. module_function :_at
  171. def tk_tcl2ruby(val, enc_mode = false, listobj = true)
  172. =begin
  173. if val =~ /^rb_out\S* (c(_\d+_)?\d+)/
  174. #return Tk_CMDTBL[$1]
  175. return TkCore::INTERP.tk_cmd_tbl[$1]
  176. #cmd_obj = TkCore::INTERP.tk_cmd_tbl[$1]
  177. #if cmd_obj.kind_of?(Proc) || cmd_obj.kind_of?(Method)
  178. # cmd_obj
  179. #else
  180. # cmd_obj.cmd
  181. #end
  182. end
  183. =end
  184. if val =~ /rb_out\S*(?:\s+(::\S*|[{](::.*)[}]|["](::.*)["]))? (c(_\d+_)?(\d+))/
  185. return TkCore::INTERP.tk_cmd_tbl[$4]
  186. end
  187. #if val.include? ?\s
  188. # return val.split.collect{|v| tk_tcl2ruby(v)}
  189. #end
  190. case val
  191. when /\A@font\S+\z/
  192. TkFont.get_obj(val)
  193. when /\A-?\d+\z/
  194. val.to_i
  195. when /\A\.\S*\z/
  196. #Tk_WINDOWS[val] ? Tk_WINDOWS[val] : _genobj_for_tkwidget(val)
  197. TkCore::INTERP.tk_windows[val]?
  198. TkCore::INTERP.tk_windows[val] : _genobj_for_tkwidget(val)
  199. when /\Ai(_\d+_)?\d+\z/
  200. TkImage::Tk_IMGTBL[val]? TkImage::Tk_IMGTBL[val] : val
  201. when /\A-?\d+\.?\d*(e[-+]?\d+)?\z/
  202. val.to_f
  203. when /\\ /
  204. val.gsub(/\\ /, ' ')
  205. when /[^\\] /
  206. if listobj
  207. #tk_split_escstr(val).collect{|elt|
  208. # tk_tcl2ruby(elt, enc_mode, listobj)
  209. #}
  210. val = _toUTF8(val) unless enc_mode
  211. tk_split_escstr(val, false, false).collect{|elt|
  212. tk_tcl2ruby(elt, true, listobj)
  213. }
  214. elsif enc_mode
  215. _fromUTF8(val)
  216. else
  217. val
  218. end
  219. else
  220. if enc_mode
  221. _fromUTF8(val)
  222. else
  223. val
  224. end
  225. end
  226. end
  227. private :tk_tcl2ruby
  228. module_function :tk_tcl2ruby
  229. #private_class_method :tk_tcl2ruby
  230. unless const_defined?(:USE_TCLs_LIST_FUNCTIONS)
  231. USE_TCLs_LIST_FUNCTIONS = true
  232. end
  233. if USE_TCLs_LIST_FUNCTIONS
  234. ###########################################################################
  235. # use Tcl function version of split_list
  236. ###########################################################################
  237. def tk_split_escstr(str, src_enc=true, dst_enc=true)
  238. str = _toUTF8(str) if src_enc
  239. if dst_enc
  240. TkCore::INTERP._split_tklist(str).map!{|s| _fromUTF8(s)}
  241. else
  242. TkCore::INTERP._split_tklist(str)
  243. end
  244. end
  245. def tk_split_sublist(str, depth=-1, src_enc=true, dst_enc=true)
  246. # return [] if str == ""
  247. # list = TkCore::INTERP._split_tklist(str)
  248. str = _toUTF8(str) if src_enc
  249. if depth == 0
  250. return "" if str == ""
  251. list = [str]
  252. else
  253. return [] if str == ""
  254. list = TkCore::INTERP._split_tklist(str)
  255. end
  256. if list.size == 1
  257. # tk_tcl2ruby(list[0], nil, false)
  258. tk_tcl2ruby(list[0], dst_enc, false)
  259. else
  260. list.collect{|token| tk_split_sublist(token, depth - 1, false, dst_enc)}
  261. end
  262. end
  263. def tk_split_list(str, depth=0, src_enc=true, dst_enc=true)
  264. return [] if str == ""
  265. str = _toUTF8(str) if src_enc
  266. TkCore::INTERP._split_tklist(str).map!{|token|
  267. tk_split_sublist(token, depth - 1, false, dst_enc)
  268. }
  269. end
  270. def tk_split_simplelist(str, src_enc=true, dst_enc=true)
  271. #lst = TkCore::INTERP._split_tklist(str)
  272. #if (lst.size == 1 && lst =~ /^\{.*\}$/)
  273. # TkCore::INTERP._split_tklist(str[1..-2])
  274. #else
  275. # lst
  276. #end
  277. str = _toUTF8(str) if src_enc
  278. if dst_enc
  279. TkCore::INTERP._split_tklist(str).map!{|s| _fromUTF8(s)}
  280. else
  281. TkCore::INTERP._split_tklist(str)
  282. end
  283. end
  284. def array2tk_list(ary, enc=nil)
  285. return "" if ary.size == 0
  286. sys_enc = TkCore::INTERP.encoding
  287. sys_enc = TclTkLib.encoding_system unless sys_enc
  288. dst_enc = (enc == nil)? sys_enc: enc
  289. dst = ary.collect{|e|
  290. if e.kind_of? Array
  291. s = array2tk_list(e, enc)
  292. elsif e.kind_of? Hash
  293. tmp_ary = []
  294. #e.each{|k,v| tmp_ary << k << v }
  295. e.each{|k,v| tmp_ary << "-#{_get_eval_string(k)}" << v }
  296. s = array2tk_list(tmp_ary, enc)
  297. else
  298. s = _get_eval_string(e, enc)
  299. end
  300. if dst_enc != true && dst_enc != false
  301. if (s_enc = s.instance_variable_get(:@encoding))
  302. s_enc = s_enc.to_s
  303. else
  304. s_enc = sys_enc
  305. end
  306. dst_enc = true if s_enc != dst_enc
  307. end
  308. s
  309. }
  310. if sys_enc && dst_enc
  311. dst.map!{|s| _toUTF8(s)}
  312. ret = TkCore::INTERP._merge_tklist(*dst)
  313. if dst_enc.kind_of?(String)
  314. ret = _fromUTF8(ret, dst_enc)
  315. ret.instance_variable_set(:@encoding, dst_enc)
  316. else
  317. ret.instance_variable_set(:@encoding, 'utf-8')
  318. end
  319. ret
  320. else
  321. TkCore::INTERP._merge_tklist(*dst)
  322. end
  323. end
  324. else
  325. ###########################################################################
  326. # use Ruby script version of split_list (traditional methods)
  327. ###########################################################################
  328. def tk_split_escstr(str, src_enc=true, dst_enc=true)
  329. return [] if str == ""
  330. list = []
  331. token = nil
  332. escape = false
  333. brace = 0
  334. str.split('').each {|c|
  335. brace += 1 if c == '{' && !escape
  336. brace -= 1 if c == '}' && !escape
  337. if brace == 0 && c == ' ' && !escape
  338. list << token.gsub(/^\{(.*)\}$/, '\1') if token
  339. token = nil
  340. else
  341. token = (token || "") << c
  342. end
  343. escape = (c == '\\' && !escape)
  344. }
  345. list << token.gsub(/^\{(.*)\}$/, '\1') if token
  346. list
  347. end
  348. def tk_split_sublist(str, depth=-1, src_enc=true, dst_enc=true)
  349. #return [] if str == ""
  350. #return [tk_split_sublist(str[1..-2])] if str =~ /^\{.*\}$/
  351. #list = tk_split_escstr(str)
  352. if depth == 0
  353. return "" if str == ""
  354. str = str[1..-2] if str =~ /^\{.*\}$/
  355. list = [str]
  356. else
  357. return [] if str == []
  358. return [tk_split_sublist(str[1..-2], depth - 1)] if str =~ /^\{.*\}$/
  359. list = tk_split_escstr(str)
  360. end
  361. if list.size == 1
  362. tk_tcl2ruby(list[0], nil, false)
  363. else
  364. list.collect{|token| tk_split_sublist(token, depth - 1)}
  365. end
  366. end
  367. def tk_split_list(str, depth=0, src_enc=true, dst_enc=true)
  368. return [] if str == ""
  369. tk_split_escstr(str).collect{|token|
  370. tk_split_sublist(token, depth - 1)
  371. }
  372. end
  373. =begin
  374. def tk_split_list(str)
  375. return [] if str == ""
  376. idx = str.index('{')
  377. while idx and idx > 0 and str[idx-1] == ?\\
  378. idx = str.index('{', idx+1)
  379. end
  380. unless idx
  381. list = tk_tcl2ruby(str)
  382. unless Array === list
  383. list = [list]
  384. end
  385. return list
  386. end
  387. list = tk_tcl2ruby(str[0,idx])
  388. list = [] if list == ""
  389. str = str[idx+1..-1]
  390. i = -1
  391. escape = false
  392. brace = 1
  393. str.each_byte {|c|
  394. i += 1
  395. brace += 1 if c == ?{ && !escape
  396. brace -= 1 if c == ?} && !escape
  397. escape = (c == ?\\)
  398. break if brace == 0
  399. }
  400. if str.size == i + 1
  401. return tk_split_list(str[0, i])
  402. end
  403. if str[0, i] == ' '
  404. list.push ' '
  405. else
  406. list.push tk_split_list(str[0, i])
  407. end
  408. list += tk_split_list(str[i+1..-1])
  409. list
  410. end
  411. =end
  412. def tk_split_simplelist(str, src_enc=true, dst_enc=true)
  413. return [] if str == ""
  414. list = []
  415. token = nil
  416. escape = false
  417. brace = 0
  418. str.split('').each {|c|
  419. if c == '\\' && !escape
  420. escape = true
  421. token = (token || "") << c if brace > 0
  422. next
  423. end
  424. brace += 1 if c == '{' && !escape
  425. brace -= 1 if c == '}' && !escape
  426. if brace == 0 && c == ' ' && !escape
  427. list << token.gsub(/^\{(.*)\}$/, '\1') if token
  428. token = nil
  429. else
  430. token = (token || "") << c
  431. end
  432. escape = false
  433. }
  434. list << token.gsub(/^\{(.*)\}$/, '\1') if token
  435. list
  436. end
  437. def array2tk_list(ary, enc=nil)
  438. ary.collect{|e|
  439. if e.kind_of? Array
  440. "{#{array2tk_list(e, enc)}}"
  441. elsif e.kind_of? Hash
  442. # "{#{e.to_a.collect{|ee| array2tk_list(ee)}.join(' ')}}"
  443. e.each{|k,v| tmp_ary << "-#{_get_eval_string(k)}" << v }
  444. array2tk_list(tmp_ary, enc)
  445. else
  446. s = _get_eval_string(e, enc)
  447. (s.index(/\s/) || s.size == 0)? "{#{s}}": s
  448. end
  449. }.join(" ")
  450. end
  451. end
  452. private :tk_split_escstr, :tk_split_sublist
  453. private :tk_split_list, :tk_split_simplelist
  454. private :array2tk_list
  455. module_function :tk_split_escstr, :tk_split_sublist
  456. module_function :tk_split_list, :tk_split_simplelist
  457. module_function :array2tk_list
  458. private_class_method :tk_split_escstr, :tk_split_sublist
  459. private_class_method :tk_split_list, :tk_split_simplelist
  460. # private_class_method :array2tk_list
  461. =begin
  462. ### --> definition is moved to TkUtil module
  463. def _symbolkey2str(keys)
  464. h = {}
  465. keys.each{|key,value| h[key.to_s] = value}
  466. h
  467. end
  468. private :_symbolkey2str
  469. module_function :_symbolkey2str
  470. =end
  471. =begin
  472. ### --> definition is moved to TkUtil module
  473. # def hash_kv(keys, enc_mode = nil, conf = [], flat = false)
  474. def hash_kv(keys, enc_mode = nil, conf = nil)
  475. # Hash {key=>val, key=>val, ... } or Array [ [key, val], [key, val], ... ]
  476. # ==> Array ['-key', val, '-key', val, ... ]
  477. dst = []
  478. if keys and keys != None
  479. keys.each{|k, v|
  480. #dst.push("-#{k}")
  481. dst.push('-' + k.to_s)
  482. if v != None
  483. # v = _get_eval_string(v, enc_mode) if (enc_mode || flat)
  484. v = _get_eval_string(v, enc_mode) if enc_mode
  485. dst.push(v)
  486. end
  487. }
  488. end
  489. if conf
  490. conf + dst
  491. else
  492. dst
  493. end
  494. end
  495. private :hash_kv
  496. module_function :hash_kv
  497. =end
  498. =begin
  499. ### --> definition is moved to TkUtil module
  500. def bool(val)
  501. case val
  502. when "1", 1, 'yes', 'true'
  503. true
  504. else
  505. false
  506. end
  507. end
  508. def number(val)
  509. case val
  510. when /^-?\d+$/
  511. val.to_i
  512. when /^-?\d+\.?\d*(e[-+]?\d+)?$/
  513. val.to_f
  514. else
  515. fail(ArgumentError, "invalid value for Number:'#{val}'")
  516. end
  517. end
  518. def string(val)
  519. if val == "{}"
  520. ''
  521. elsif val[0] == ?{ && val[-1] == ?}
  522. val[1..-2]
  523. else
  524. val
  525. end
  526. end
  527. def num_or_str(val)
  528. begin
  529. number(val)
  530. rescue ArgumentError
  531. string(val)
  532. end
  533. end
  534. =end
  535. def list(val, depth=0, enc=true)
  536. tk_split_list(val, depth, enc, enc)
  537. end
  538. def simplelist(val, src_enc=true, dst_enc=true)
  539. tk_split_simplelist(val, src_enc, dst_enc)
  540. end
  541. def window(val)
  542. if val =~ /^\./
  543. #Tk_WINDOWS[val]? Tk_WINDOWS[val] : _genobj_for_tkwidget(val)
  544. TkCore::INTERP.tk_windows[val]?
  545. TkCore::INTERP.tk_windows[val] : _genobj_for_tkwidget(val)
  546. else
  547. nil
  548. end
  549. end
  550. def image_obj(val)
  551. if val =~ /^i(_\d+_)?\d+$/
  552. TkImage::Tk_IMGTBL[val]? TkImage::Tk_IMGTBL[val] : val
  553. else
  554. val
  555. end
  556. end
  557. def procedure(val)
  558. =begin
  559. if val =~ /^rb_out\S* (c(_\d+_)?\d+)/
  560. #Tk_CMDTBL[$1]
  561. #TkCore::INTERP.tk_cmd_tbl[$1]
  562. TkCore::INTERP.tk_cmd_tbl[$1].cmd
  563. =end
  564. if val =~ /rb_out\S*(?:\s+(::\S*|[{](::.*)[}]|["](::.*)["]))? (c(_\d+_)?(\d+))/
  565. return TkCore::INTERP.tk_cmd_tbl[$4].cmd
  566. else
  567. #nil
  568. val
  569. end
  570. end
  571. private :bool, :number, :string, :num_or_str
  572. private :list, :simplelist, :window, :procedure
  573. module_function :bool, :number, :num_or_str, :string
  574. module_function :list, :simplelist, :window, :image_obj, :procedure
  575. def subst(str, *opts)
  576. # opts := :nobackslashes | :nocommands | novariables
  577. tk_call('subst',
  578. *(opts.collect{|opt|
  579. opt = opt.to_s
  580. (opt[0] == ?-)? opt: '-' << opt
  581. } << str))
  582. end
  583. def _toUTF8(str, encoding = nil)
  584. TkCore::INTERP._toUTF8(str, encoding)
  585. end
  586. def _fromUTF8(str, encoding = nil)
  587. TkCore::INTERP._fromUTF8(str, encoding)
  588. end
  589. private :_toUTF8, :_fromUTF8
  590. module_function :_toUTF8, :_fromUTF8
  591. def _callback_entry_class?(cls)
  592. cls <= Proc || cls <= Method || cls <= TkCallbackEntry
  593. end
  594. private :_callback_entry_class?
  595. module_function :_callback_entry_class?
  596. def _callback_entry?(obj)
  597. obj.kind_of?(Proc) || obj.kind_of?(Method) || obj.kind_of?(TkCallbackEntry)
  598. end
  599. private :_callback_entry?
  600. module_function :_callback_entry?
  601. =begin
  602. ### --> definition is moved to TkUtil module
  603. def _get_eval_string(str, enc_mode = nil)
  604. return nil if str == None
  605. if str.kind_of?(TkObject)
  606. str = str.path
  607. elsif str.kind_of?(String)
  608. str = _toUTF8(str) if enc_mode
  609. elsif str.kind_of?(Symbol)
  610. str = str.id2name
  611. str = _toUTF8(str) if enc_mode
  612. elsif str.kind_of?(Hash)
  613. str = hash_kv(str, enc_mode).join(" ")
  614. elsif str.kind_of?(Array)
  615. str = array2tk_list(str)
  616. str = _toUTF8(str) if enc_mode
  617. elsif str.kind_of?(Proc)
  618. str = install_cmd(str)
  619. elsif str == nil
  620. str = ""
  621. elsif str == false
  622. str = "0"
  623. elsif str == true
  624. str = "1"
  625. elsif (str.respond_to?(:to_eval))
  626. str = str.to_eval()
  627. str = _toUTF8(str) if enc_mode
  628. else
  629. str = str.to_s() || ''
  630. unless str.kind_of? String
  631. fail RuntimeError, "fail to convert the object to a string"
  632. end
  633. str = _toUTF8(str) if enc_mode
  634. end
  635. return str
  636. end
  637. =end
  638. =begin
  639. def _get_eval_string(obj, enc_mode = nil)
  640. case obj
  641. when Numeric
  642. obj.to_s
  643. when String
  644. (enc_mode)? _toUTF8(obj): obj
  645. when Symbol
  646. (enc_mode)? _toUTF8(obj.id2name): obj.id2name
  647. when TkObject
  648. obj.path
  649. when Hash
  650. hash_kv(obj, enc_mode).join(' ')
  651. when Array
  652. (enc_mode)? _toUTF8(array2tk_list(obj)): array2tk_list(obj)
  653. when Proc, Method, TkCallbackEntry
  654. install_cmd(obj)
  655. when false
  656. '0'
  657. when true
  658. '1'
  659. when nil
  660. ''
  661. when None
  662. nil
  663. else
  664. if (obj.respond_to?(:to_eval))
  665. (enc_mode)? _toUTF8(obj.to_eval): obj.to_eval
  666. else
  667. begin
  668. obj = obj.to_s || ''
  669. rescue
  670. fail RuntimeError, "fail to convert object '#{obj}' to string"
  671. end
  672. (enc_mode)? _toUTF8(obj): obj
  673. end
  674. end
  675. end
  676. private :_get_eval_string
  677. module_function :_get_eval_string
  678. =end
  679. =begin
  680. ### --> definition is moved to TkUtil module
  681. def _get_eval_enc_str(obj)
  682. return obj if obj == None
  683. _get_eval_string(obj, true)
  684. end
  685. private :_get_eval_enc_str
  686. module_function :_get_eval_enc_str
  687. =end
  688. =begin
  689. ### --> obsolete
  690. def ruby2tcl(v, enc_mode = nil)
  691. if v.kind_of?(Hash)
  692. v = hash_kv(v)
  693. v.flatten!
  694. v.collect{|e|ruby2tcl(e, enc_mode)}
  695. else
  696. _get_eval_string(v, enc_mode)
  697. end
  698. end
  699. private :ruby2tcl
  700. =end
  701. =begin
  702. ### --> definition is moved to TkUtil module
  703. def _conv_args(args, enc_mode, *src_args)
  704. conv_args = []
  705. src_args.each{|arg|
  706. conv_args << _get_eval_string(arg, enc_mode) unless arg == None
  707. # if arg.kind_of?(Hash)
  708. # arg.each{|k, v|
  709. # args << '-' + k.to_s
  710. # args << _get_eval_string(v, enc_mode)
  711. # }
  712. # elsif arg != None
  713. # args << _get_eval_string(arg, enc_mode)
  714. # end
  715. }
  716. args + conv_args
  717. end
  718. private :_conv_args
  719. =end
  720. def _curr_cmd_id
  721. #id = format("c%.4d", Tk_IDs[0])
  722. id = "c" + TkCore::INTERP._ip_id_ + TkComm::Tk_IDs[0]
  723. end
  724. def _next_cmd_id
  725. id = _curr_cmd_id
  726. #Tk_IDs[0] += 1
  727. TkComm::Tk_IDs[0].succ!
  728. id
  729. end
  730. private :_curr_cmd_id, :_next_cmd_id
  731. module_function :_curr_cmd_id, :_next_cmd_id
  732. def install_cmd(cmd)
  733. return '' if cmd == ''
  734. begin
  735. ns = TkCore::INTERP._invoke_without_enc('namespace', 'current')
  736. ns = nil if ns == '::' # for backward compatibility
  737. rescue
  738. # probably, Tcl7.6
  739. ns = nil
  740. end
  741. id = _next_cmd_id
  742. #Tk_CMDTBL[id] = cmd
  743. if cmd.kind_of?(TkCallbackEntry)
  744. TkCore::INTERP.tk_cmd_tbl[id] = cmd
  745. else
  746. TkCore::INTERP.tk_cmd_tbl[id] = TkCore::INTERP.get_cb_entry(cmd)
  747. end
  748. @cmdtbl = [] unless defined? @cmdtbl
  749. @cmdtbl.taint unless @cmdtbl.tainted?
  750. @cmdtbl.push id
  751. #return Kernel.format("rb_out %s", id);
  752. if ns
  753. 'rb_out' << TkCore::INTERP._ip_id_ << ' ' << ns << ' ' << id
  754. else
  755. 'rb_out' << TkCore::INTERP._ip_id_ << ' ' << id
  756. end
  757. end
  758. def uninstall_cmd(id)
  759. #id = $1 if /rb_out\S* (c(_\d+_)?\d+)/ =~ id
  760. id = $4 if id =~ /rb_out\S*(?:\s+(::\S*|[{](::.*)[}]|["](::.*)["]))? (c(_\d+_)?(\d+))/
  761. #Tk_CMDTBL.delete(id)
  762. TkCore::INTERP.tk_cmd_tbl.delete(id)
  763. end
  764. # private :install_cmd, :uninstall_cmd
  765. module_function :install_cmd, :uninstall_cmd
  766. =begin
  767. def install_win(ppath,name=nil)
  768. if !name or name == ''
  769. #name = format("w%.4d", Tk_IDs[1])
  770. #Tk_IDs[1] += 1
  771. name = "w" + Tk_IDs[1]
  772. Tk_IDs[1].succ!
  773. end
  774. if name[0] == ?.
  775. @path = name.dup
  776. elsif !ppath or ppath == "."
  777. @path = Kernel.format(".%s", name);
  778. else
  779. @path = Kernel.format("%s.%s", ppath, name)
  780. end
  781. #Tk_WINDOWS[@path] = self
  782. TkCore::INTERP.tk_windows[@path] = self
  783. end
  784. =end
  785. def install_win(ppath,name=nil)
  786. if name
  787. if name == ''
  788. raise ArgumentError, "invalid wiget-name '#{name}'"
  789. end
  790. if name[0] == ?.
  791. @path = '' + name
  792. @path.freeze
  793. return TkCore::INTERP.tk_windows[@path] = self
  794. end
  795. else
  796. name = "w" + TkCore::INTERP._ip_id_ + Tk_IDs[1]
  797. Tk_IDs[1].succ!
  798. end
  799. if !ppath or ppath == '.'
  800. @path = '.' + name
  801. else
  802. @path = ppath + '.' + name
  803. end
  804. @path.freeze
  805. TkCore::INTERP.tk_windows[@path] = self
  806. end
  807. def uninstall_win()
  808. #Tk_WINDOWS.delete(@path)
  809. TkCore::INTERP.tk_windows.delete(@path)
  810. end
  811. private :install_win, :uninstall_win
  812. def _epath(win)
  813. if win.kind_of?(TkObject)
  814. win.epath
  815. elsif win.respond_to?(:epath)
  816. win.epath
  817. else
  818. win
  819. end
  820. end
  821. private :_epath
  822. end
  823. # define TkComm module (step 2: event binding)
  824. module TkComm
  825. include TkEvent
  826. extend TkEvent
  827. def tk_event_sequence(context)
  828. if context.kind_of? TkVirtualEvent
  829. context = context.path
  830. end
  831. if context.kind_of? Array
  832. context = context.collect{|ev|
  833. if ev.kind_of? TkVirtualEvent
  834. ev.path
  835. else
  836. ev
  837. end
  838. }.join("><")
  839. end
  840. if /,/ =~ context
  841. context = context.split(/\s*,\s*/).join("><")
  842. else
  843. context
  844. end
  845. end
  846. def _bind_core(mode, what, context, cmd, *args)
  847. id = install_bind(cmd, *args) if cmd
  848. begin
  849. tk_call_without_enc(*(what + ["<#{tk_event_sequence(context)}>",
  850. mode + id]))
  851. rescue
  852. uninstall_cmd(id) if cmd
  853. fail
  854. end
  855. end
  856. def _bind(what, context, cmd, *args)
  857. _bind_core('', what, context, cmd, *args)
  858. end
  859. def _bind_append(what, context, cmd, *args)
  860. _bind_core('+', what, context, cmd, *args)
  861. end
  862. def _bind_remove(what, context)
  863. tk_call_without_enc(*(what + ["<#{tk_event_sequence(context)}>", '']))
  864. end
  865. def _bindinfo(what, context=nil)
  866. if context
  867. tk_call_without_enc(*what+["<#{tk_event_sequence(context)}>"]) .collect {|cmdline|
  868. =begin
  869. if cmdline =~ /^rb_out\S* (c(?:_\d+_)?\d+)\s+(.*)$/
  870. #[Tk_CMDTBL[$1], $2]
  871. [TkCore::INTERP.tk_cmd_tbl[$1], $2]
  872. =end
  873. if cmdline =~ /rb_out\S*(?:\s+(::\S*|[{](::.*)[}]|["](::.*)["]))? (c(_\d+_)?(\d+))/
  874. [TkCore::INTERP.tk_cmd_tbl[$4], $5]
  875. else
  876. cmdline
  877. end
  878. }
  879. else
  880. tk_split_simplelist(tk_call_without_enc(*what)).collect!{|seq|
  881. l = seq.scan(/<*[^<>]+>*/).collect!{|subseq|
  882. case (subseq)
  883. when /^<<[^<>]+>>$/
  884. TkVirtualEvent.getobj(subseq[1..-2])
  885. when /^<[^<>]+>$/
  886. subseq[1..-2]
  887. else
  888. subseq.split('')
  889. end
  890. }.flatten
  891. (l.size == 1) ? l[0] : l
  892. }
  893. end
  894. end
  895. def _bind_core_for_event_class(klass, mode, what, context, cmd, *args)
  896. id = install_bind_for_event_class(klass, cmd, *args) if cmd
  897. begin
  898. tk_call_without_enc(*(what + ["<#{tk_event_sequence(context)}>",
  899. mode + id]))
  900. rescue
  901. uninstall_cmd(id) if cmd
  902. fail
  903. end
  904. end
  905. def _bind_for_event_class(klass, what, context, cmd, *args)
  906. _bind_core_for_event_class(klass, '', what, context, cmd, *args)
  907. end
  908. def _bind_append_for_event_class(klass, what, context, cmd, *args)
  909. _bind_core_for_event_class(klass, '+', what, context, cmd, *args)
  910. end
  911. def _bind_remove_for_event_class(klass, what, context)
  912. _bind_remove(what, context)
  913. end
  914. def _bindinfo_for_event_class(klass, what, context=nil)
  915. _bindinfo(what, context)
  916. end
  917. private :tk_event_sequence
  918. private :_bind_core, :_bind, :_bind_append, :_bind_remove, :_bindinfo
  919. private :_bind_core_for_event_class, :_bind_for_event_class,
  920. :_bind_append_for_event_class, :_bind_remove_for_event_class,
  921. :_bindinfo_for_event_class
  922. #def bind(tagOrClass, context, cmd=Proc.new, *args)
  923. # _bind(["bind", tagOrClass], context, cmd, *args)
  924. # tagOrClass
  925. #end
  926. def bind(tagOrClass, context, *args)
  927. # if args[0].kind_of?(Proc) || args[0].kind_of?(Method)
  928. if TkComm._callback_entry?(args[0]) || !block_given?
  929. cmd = args.shift
  930. else
  931. cmd = Proc.new
  932. end
  933. _bind(["bind", tagOrClass], context, cmd, *args)
  934. tagOrClass
  935. end
  936. #def bind_append(tagOrClass, context, cmd=Proc.new, *args)
  937. # _bind_append(["bind", tagOrClass], context, cmd, *args)
  938. # tagOrClass
  939. #end
  940. def bind_append(tagOrClass, context, *args)
  941. # if args[0].kind_of?(Proc) || args[0].kind_of?(Method)
  942. if TkComm._callback_entry?(args[0]) || !block_given?
  943. cmd = args.shift
  944. else
  945. cmd = Proc.new
  946. end
  947. _bind_append(["bind", tagOrClass], context, cmd, *args)
  948. tagOrClass
  949. end
  950. def bind_remove(tagOrClass, context)
  951. _bind_remove(['bind', tagOrClass], context)
  952. tagOrClass
  953. end
  954. def bindinfo(tagOrClass, context=nil)
  955. _bindinfo(['bind', tagOrClass], context)
  956. end
  957. #def bind_all(context, cmd=Proc.new, *args)
  958. # _bind(['bind', 'all'], context, cmd, *args)
  959. # TkBindTag::ALL
  960. #end
  961. def bind_all(context, *args)
  962. # if args[0].kind_of?(Proc) || args[0].kind_of?(Method)
  963. if TkComm._callback_entry?(args[0]) || !block_given?
  964. cmd = args.shift
  965. else
  966. cmd = Proc.new
  967. end
  968. _bind(['bind', 'all'], context, cmd, *args)
  969. TkBindTag::ALL
  970. end
  971. #def bind_append_all(context, cmd=Proc.new, *args)
  972. # _bind_append(['bind', 'all'], context, cmd, *args)
  973. # TkBindTag::ALL
  974. #end
  975. def bind_append_all(context, *args)
  976. # if args[0].kind_of?(Proc) || args[0].kind_of?(Method)
  977. if TkComm._callback_entry?(args[0]) || !block_given?
  978. cmd = args.shift
  979. else
  980. cmd = Proc.new
  981. end
  982. _bind_append(['bind', 'all'], context, cmd, *args)
  983. TkBindTag::ALL
  984. end
  985. def bind_remove_all(context)
  986. _bind_remove(['bind', 'all'], context)
  987. TkBindTag::ALL
  988. end
  989. def bindinfo_all(context=nil)
  990. _bindinfo(['bind', 'all'], context)
  991. end
  992. end
  993. module TkCore
  994. include TkComm
  995. extend TkComm
  996. unless self.const_defined? :INTERP
  997. if self.const_defined? :IP_NAME
  998. name = IP_NAME.to_s
  999. else
  1000. #name = nil
  1001. name = $0
  1002. end
  1003. if self.const_defined? :IP_OPTS
  1004. if IP_OPTS.kind_of?(Hash)
  1005. opts = hash_kv(IP_OPTS).join(' ')
  1006. else
  1007. opts = IP_OPTS.to_s
  1008. end
  1009. else
  1010. opts = ''
  1011. end
  1012. INTERP = TclTkIp.new(name, opts)
  1013. def INTERP.__getip
  1014. self
  1015. end
  1016. INTERP.instance_eval{
  1017. @tk_cmd_tbl = {}.taint
  1018. def @tk_cmd_tbl.[]=(idx,val)
  1019. if self.has_key?(idx) && Thread.current.group != ThreadGroup::Default
  1020. fail SecurityError,"cannot change the entried command"
  1021. end
  1022. super(idx,val)
  1023. end
  1024. @tk_windows = {}.taint
  1025. @tk_table_list = [].taint
  1026. @init_ip_env = [].taint # table of Procs
  1027. @add_tk_procs = [].taint # table of [name, args, body]
  1028. @cb_entry_class = Class.new(TkCallbackEntry){
  1029. class << self
  1030. def inspect
  1031. sprintf("#<Class(TkCallbackEntry):%0x>", self.__id__)
  1032. end
  1033. alias to_s inspect
  1034. end
  1035. def initialize(ip, cmd)
  1036. @ip = ip
  1037. @cmd = cmd
  1038. end
  1039. attr_reader :ip, :cmd
  1040. def call(*args)
  1041. @ip.cb_eval(@cmd, *args)
  1042. end
  1043. def inspect
  1044. sprintf("#<cb_entry:%0x>", self.__id__)
  1045. end
  1046. alias to_s inspect
  1047. }.freeze
  1048. }
  1049. def INTERP.cb_entry_class
  1050. @cb_entry_class
  1051. end
  1052. def INTERP.tk_cmd_tbl
  1053. @tk_cmd_tbl
  1054. end
  1055. def INTERP.tk_windows
  1056. @tk_windows
  1057. end
  1058. class Tk_OBJECT_TABLE
  1059. def initialize(id)
  1060. @id = id
  1061. end
  1062. def method_missing(m, *args, &b)
  1063. TkCore::INTERP.tk_object_table(@id).__send__(m, *args, &b)
  1064. end
  1065. end
  1066. def INTERP.tk_object_table(id)
  1067. @tk_table_list[id]
  1068. end
  1069. def INTERP.create_table
  1070. id = @tk_table_list.size
  1071. (tbl = {}).tainted? || tbl.taint
  1072. @tk_table_list << tbl
  1073. # obj = Object.new
  1074. # obj.instance_eval <<-EOD
  1075. # def self.method_missing(m, *args)
  1076. # TkCore::INTERP.tk_object_table(#{id}).send(m, *args)
  1077. # end
  1078. # EOD
  1079. # return obj
  1080. Tk_OBJECT_TABLE.new(id)
  1081. end
  1082. def INTERP.get_cb_entry(cmd)
  1083. @cb_entry_class.new(__getip, cmd).freeze
  1084. end
  1085. def INTERP.cb_eval(cmd, *args)
  1086. TkUtil._get_eval_string(TkUtil.eval_cmd(cmd, *args))
  1087. end
  1088. def INTERP.init_ip_env(script = Proc.new)
  1089. @init_ip_env << script
  1090. script.call(self)
  1091. end
  1092. def INTERP.add_tk_procs(name, args = nil, body = nil)
  1093. if name.kind_of?(Array)
  1094. name.each{|param| self.add_tk_procs(*param)}
  1095. else
  1096. name = name.to_s
  1097. @add_tk_procs << [name, args, body]
  1098. self._invoke('proc', name, args, body) if args && body
  1099. end
  1100. end
  1101. def INTERP.remove_tk_procs(*names)
  1102. names.each{|name|
  1103. name = name.to_s
  1104. @add_tk_procs.delete_if{|elem|
  1105. elem.kind_of?(Array) && elem[0].to_s == name
  1106. }
  1107. self._invoke('rename', name, '')
  1108. }
  1109. end
  1110. def INTERP.init_ip_internal
  1111. ip = self
  1112. @init_ip_env.each{|script| script.call(ip)}
  1113. @add_tk_procs.each{|name,args,body| ip._invoke('proc',name,args,body)}
  1114. end
  1115. end
  1116. WIDGET_DESTROY_HOOK = '<WIDGET_DESTROY_HOOK>'
  1117. INTERP._invoke_without_enc('event', 'add',
  1118. "<#{WIDGET_DESTROY_HOOK}>", '<Destroy>')
  1119. INTERP._invoke_without_enc('bind', 'all', "<#{WIDGET_DESTROY_HOOK}>",
  1120. install_cmd(proc{|path|
  1121. unless TkCore::INTERP.deleted?
  1122. begin
  1123. if (widget=TkCore::INTERP.tk_windows[path])
  1124. if widget.respond_to?(:__destroy_hook__)
  1125. widget.__destroy_hook__
  1126. end
  1127. end
  1128. rescue Exception=>e
  1129. p e if $DEBUG
  1130. end
  1131. end
  1132. }) << ' %W')
  1133. INTERP.add_tk_procs(TclTkLib::FINALIZE_PROC_NAME, '',
  1134. "bind all <#{WIDGET_DESTROY_HOOK}> {}")
  1135. INTERP.add_tk_procs('rb_out', 'ns args', <<-'EOL')
  1136. if [regexp {^::} $ns] {
  1137. set cmd {namespace eval $ns {ruby_cmd TkCore callback} $args}
  1138. } else {
  1139. set cmd {eval {ruby_cmd TkCore callback} $ns $args}
  1140. }
  1141. if {[set st [catch $cmd ret]] != 0} {
  1142. #return -code $st $ret
  1143. set idx [string first "\n\n" $ret]
  1144. if {$idx > 0} {
  1145. return -code $st \
  1146. -errorinfo [string range $ret [expr $idx + 2] \
  1147. [string length $ret]] \
  1148. [string range $ret 0 [expr $idx - 1]]
  1149. } else {
  1150. return -code $st $ret
  1151. }
  1152. } else {
  1153. return $ret
  1154. }
  1155. EOL
  1156. =begin
  1157. INTERP.add_tk_procs('rb_out', 'args', <<-'EOL')
  1158. if {[set st [catch {eval {ruby_cmd TkCore callback} $args} ret]] != 0} {
  1159. #return -code $st $ret
  1160. set idx [string first "\n\n" $ret]
  1161. if {$idx > 0} {
  1162. return -code $st \
  1163. -errorinfo [string range $ret [expr $idx + 2] \
  1164. [string length $ret]] \
  1165. [string range $ret 0 [expr $idx - 1]]
  1166. } else {
  1167. return -code $st $ret
  1168. }
  1169. } else {
  1170. return $ret
  1171. }
  1172. EOL
  1173. =end
  1174. =begin
  1175. INTERP.add_tk_procs('rb_out', 'args', <<-'EOL')
  1176. #regsub -all {\\} $args {\\\\} args
  1177. #regsub -all {!} $args {\\!} args
  1178. #regsub -all "{" $args "\\{" args
  1179. regsub -all {(\\|!|\{|\})} $args {\\\1} args
  1180. if {[set st [catch {ruby [format "TkCore.callback %%Q!%s!" $args]} ret]] != 0} {
  1181. #return -code $st $ret
  1182. set idx [string first "\n\n" $ret]
  1183. if {$idx > 0} {
  1184. return -code $st \
  1185. -errorinfo [string range $ret [expr $idx + 2] \
  1186. [string length $ret]] \
  1187. [string range $ret 0 [expr $idx - 1]]
  1188. } else {
  1189. return -code $st $ret
  1190. }
  1191. } else {
  1192. return $ret
  1193. }
  1194. EOL
  1195. =end
  1196. at_exit{ INTERP.remove_tk_procs(TclTkLib::FINALIZE_PROC_NAME) }
  1197. EventFlag = TclTkLib::EventFlag
  1198. def callback_break
  1199. fail TkCallbackBreak, "Tk callback returns 'break' status"
  1200. end
  1201. def callback_continue
  1202. fail TkCallbackContinue, "Tk callback returns 'continue' status"
  1203. end
  1204. def callback_return
  1205. fail TkCallbackReturn, "Tk callback returns 'return' status"
  1206. end
  1207. def TkCore.callback(*arg)
  1208. begin
  1209. if TkCore::INTERP.tk_cmd_tbl.kind_of?(Hash)
  1210. #TkCore::INTERP.tk_cmd_tbl[arg.shift].call(*arg)
  1211. normal_ret = false
  1212. ret = catch(:IRB_EXIT) do # IRB hack
  1213. retval = TkCore::INTERP.tk_cmd_tbl[arg.shift].call(*arg)
  1214. normal_ret = true
  1215. retval
  1216. end
  1217. unless normal_ret
  1218. # catch IRB_EXIT
  1219. exit(ret)
  1220. end
  1221. ret
  1222. end
  1223. rescue SystemExit=>e
  1224. exit(e.status)
  1225. rescue Interrupt=>e
  1226. fail(e)
  1227. rescue Exception => e
  1228. begin
  1229. msg = _toUTF8(e.class.inspect) + ': ' +
  1230. _toUTF8(e.message) + "\n" +
  1231. "\n---< backtrace of Ruby side >-----\n" +
  1232. _toUTF8(e.backtrace.join("\n")) +
  1233. "\n---< backtrace of Tk side >-------"
  1234. msg.instance_variable_set(:@encoding, 'utf-8')
  1235. rescue Exception
  1236. msg = e.class.inspect + ': ' + e.message + "\n" +
  1237. "\n---< backtrace of Ruby side >-----\n" +
  1238. e.backtrace.join("\n") +
  1239. "\n---< backtrace of Tk side >-------"
  1240. end
  1241. # TkCore::INTERP._set_global_var('errorInfo', msg)
  1242. # fail(e)
  1243. fail(e, msg)
  1244. end
  1245. end
  1246. =begin
  1247. def TkCore.callback(arg_str)
  1248. # arg = tk_split_list(arg_str)
  1249. arg = tk_split_simplelist(arg_str)
  1250. #_get_eval_string(TkUtil.eval_cmd(Tk_CMDTBL[arg.shift], *arg))
  1251. #_get_eval_string(TkUtil.eval_cmd(TkCore::INTERP.tk_cmd_tbl[arg.shift],
  1252. # *arg))
  1253. # TkCore::INTERP.tk_cmd_tbl[arg.shift].call(*arg)
  1254. begin
  1255. TkCore::INTERP.tk_cmd_tbl[arg.shift].call(*arg)
  1256. rescue Exception => e
  1257. raise(e, e.class.inspect + ': ' + e.message + "\n" +
  1258. "\n---< backtrace of Ruby side >-----\n" +
  1259. e.backtrace.join("\n") +
  1260. "\n---< backtrace of Tk side >-------")
  1261. end
  1262. #=begin
  1263. # cb_obj = TkCore::INTERP.tk_cmd_tbl[arg.shift]
  1264. # unless $DEBUG
  1265. # cb_obj.call(*arg)
  1266. # else
  1267. # begin
  1268. # raise 'check backtrace'
  1269. # rescue
  1270. # # ignore backtrace before 'callback'
  1271. # pos = -($!.backtrace.size)
  1272. # end
  1273. # begin
  1274. # cb_obj.call(*arg)
  1275. # rescue
  1276. # trace = $!.backtrace
  1277. # raise $!, "\n#{trace[0]}: #{$!.message} (#{$!.class})\n" +
  1278. # "\tfrom #{trace[1..pos].join("\n\tfrom ")}"
  1279. # end
  1280. # end
  1281. #=end
  1282. end
  1283. =end
  1284. def load_cmd_on_ip(tk_cmd)
  1285. bool(tk_call('auto_load', tk_cmd))
  1286. end
  1287. def after(ms, cmd=Proc.new)
  1288. crit_bup = Thread.critical
  1289. Thread.critical = true
  1290. myid = _curr_cmd_id
  1291. cmdid = install_cmd(proc{ret = cmd.call;uninstall_cmd(myid); ret})
  1292. Thread.critical = crit_bup
  1293. tk_call_without_enc("after",ms,cmdid) # return id
  1294. # return
  1295. # if false #defined? Thread
  1296. # Thread.start do
  1297. # ms = Float(ms)/1000
  1298. # ms = 10 if ms == 0
  1299. # sleep ms/1000
  1300. # cmd.call
  1301. # end
  1302. # else
  1303. # cmdid = install_cmd(cmd)
  1304. # tk_call("after",ms,cmdid)
  1305. # end
  1306. end
  1307. def after_idle(cmd=Proc.new)
  1308. crit_bup = Thread.critical
  1309. Thread.critical = true
  1310. myid = _curr_cmd_id
  1311. cmdid = install_cmd(proc{ret = cmd.call;uninstall_cmd(myid); ret})
  1312. Thread.critical = crit_bup
  1313. tk_call_without_enc('after','idle',cmdid)
  1314. end
  1315. def after_cancel(afterId)
  1316. tk_call_without_enc('after','cancel',afterId)
  1317. end
  1318. def windowingsystem
  1319. tk_call_without_enc('tk', 'windowingsystem')
  1320. end
  1321. def scaling(scale=nil)
  1322. if scale
  1323. tk_call_without_enc('tk', 'scaling', scale)
  1324. else
  1325. Float(number(tk_call_without_enc('tk', 'scaling')))
  1326. end
  1327. end
  1328. def scaling_displayof(win, scale=nil)
  1329. if scale
  1330. tk_call_without_enc('tk', 'scaling', '-displayof', win, scale)
  1331. else
  1332. Float(number(tk_call_without_enc('tk', '-displayof', win, 'scaling')))
  1333. end
  1334. end
  1335. def inactive
  1336. Integer(tk_call_without_enc('tk', 'inactive'))
  1337. end
  1338. def inactive_displayof(win)
  1339. Integer(tk_call_without_enc('tk', 'inactive', '-displayof', win))
  1340. end
  1341. def reset_inactive
  1342. tk_call_without_enc('tk', 'inactive', 'reset')
  1343. end
  1344. def reset_inactive_displayof(win)
  1345. tk_call_without_enc('tk', 'inactive', '-displayof', win, 'reset')
  1346. end
  1347. def appname(name=None)
  1348. tk_call('tk', 'appname', name)
  1349. end
  1350. def appsend_deny
  1351. tk_call('rename', 'send', '')
  1352. end
  1353. def appsend(interp, async, *args)
  1354. if $SAFE >= 4
  1355. fail SecurityError, "cannot send Tk commands at level 4"
  1356. elsif $SAFE >= 1 && args.find{|obj| obj.tainted?}
  1357. fail SecurityError, "cannot send tainted Tk commands at level #{$SAFE}"
  1358. end
  1359. if async != true && async != false && async != nil
  1360. args.unshift(async)
  1361. async = false
  1362. end
  1363. if async
  1364. tk_call('send', '-async', '--', interp, *args)
  1365. else
  1366. tk_call('send', '--', interp, *args)
  1367. end
  1368. end
  1369. def rb_appsend(interp, async, *args)
  1370. if $SAFE >= 4
  1371. fail SecurityError, "cannot send Ruby commands at level 4"
  1372. elsif $SAFE >= 1 && args.find{|obj| obj.tainted?}
  1373. fail SecurityError, "cannot send tainted Ruby commands at level #{$SAFE}"
  1374. end
  1375. if async != true && async != false && async != nil
  1376. args.unshift(async)
  1377. async = false
  1378. end
  1379. #args = args.collect!{|c| _get_eval_string(c).gsub(/[\[\]$"]/, '\\\\\&')}
  1380. args = args.collect!{|c| _get_eval_string(c).gsub(/[\[\]$"\\]/, '\\\\\&')}
  1381. # args.push(').to_s"')
  1382. # appsend(interp, async, 'ruby "(', *args)
  1383. args.push('}.call)"')
  1384. appsend(interp, async, 'ruby "TkComm._get_eval_string(proc{', *args)
  1385. end
  1386. def appsend_displayof(interp, win, async, *args)
  1387. if $SAFE >= 4
  1388. fail SecurityError, "cannot send Tk commands at level 4"
  1389. elsif $SAFE >= 1 && args.find{|obj| obj.tainted?}
  1390. fail SecurityError, "cannot send tainted Tk commands at level #{$SAFE}"
  1391. end
  1392. win = '.' if win == nil
  1393. if async != true && async != false && async != nil
  1394. args.unshift(async)
  1395. async = false
  1396. end
  1397. if async
  1398. tk_call('send', '-async', '-displayof', win, '--', interp, *args)
  1399. else
  1400. tk_call('send', '-displayor', win, '--', interp, *args)
  1401. end
  1402. end
  1403. def rb_appsend_displayof(interp, win, async, *args)
  1404. if $SAFE >= 4
  1405. fail SecurityError, "cannot send Ruby commands at level 4"
  1406. elsif $SAFE >= 1 && args.find{|obj| obj.tainted?}
  1407. fail SecurityError, "cannot send tainted Ruby commands at level #{$SAFE}"
  1408. end
  1409. win = '.' if win == nil
  1410. if async != true && async != false && async != nil
  1411. args.unshift(async)
  1412. async = false
  1413. end
  1414. #args = args.collect!{|c| _get_eval_string(c).gsub(/[\[\]$"]/, '\\\\\&')}
  1415. args = args.collect!{|c| _get_eval_string(c).gsub(/[\[\]$"\\]/, '\\\\\&')}
  1416. # args.push(').to_s"')
  1417. # appsend_displayof(interp, win, async, 'ruby "(', *args)
  1418. args.push('}.call)"')
  1419. appsend(interp, win, async, 'ruby "TkComm._get_eval_string(proc{', *args)
  1420. end
  1421. def info(*args)
  1422. tk_call('info', *args)
  1423. end
  1424. def mainloop(check_root = true)
  1425. TclTkLib.mainloop(check_root)
  1426. end
  1427. def mainloop_thread?
  1428. # true : current thread is mainloop
  1429. # nil : there is no mainloop
  1430. # false : mainloop is running on the other thread
  1431. # ( At then, it is dangerous to call Tk interpreter directly. )
  1432. TclTkLib.mainloop_thread?
  1433. end
  1434. def mainloop_exist?
  1435. TclTkLib.mainloop_thread? != nil
  1436. end
  1437. def is_mainloop?
  1438. TclTkLib.mainloop_thread? == true
  1439. end
  1440. def mainloop_watchdog(check_root = true)
  1441. # watchdog restarts mainloop when mainloop is dead
  1442. TclTkLib.mainloop_watchdog(check_root)
  1443. end
  1444. def do_one_event(flag = TclTkLib::EventFlag::ALL)
  1445. TclTkLib.do_one_event(flag)
  1446. end
  1447. def set_eventloop_tick(timer_tick)
  1448. TclTkLib.set_eventloop_tick(timer_tick)
  1449. end
  1450. def get_eventloop_tick()
  1451. TclTkLib.get_eventloop_tick
  1452. end
  1453. def set_no_event_wait(wait)
  1454. TclTkLib.set_no_even_wait(wait)
  1455. end
  1456. def get_no_event_wait()
  1457. TclTkLib.get_no_eventloop_wait
  1458. end
  1459. def set_eventloop_weight(loop_max, no_event_tick)
  1460. TclTkLib.set_eventloop_weight(loop_max, no_event_tick)
  1461. end
  1462. def get_eventloop_weight()
  1463. TclTkLib.get_eventloop_weight
  1464. end
  1465. def restart(app_name = nil, keys = {})
  1466. TkCore::INTERP.init_ip_internal
  1467. tk_call('set', 'argv0', app_name) if app_name
  1468. if keys.kind_of?(Hash)
  1469. # tk_call('set', 'argc', keys.size * 2)
  1470. tk_call('set', 'argv', hash_kv(keys).join(' '))
  1471. end
  1472. INTERP.restart
  1473. nil
  1474. end
  1475. def event_generate(win, context, keys=nil)
  1476. #win = win.path if win.kind_of?(TkObject)
  1477. if context.kind_of?(TkEvent::Event)
  1478. context.generate(win, ((keys)? keys: {}))
  1479. elsif keys
  1480. tk_call_without_enc('event', 'generate', win,
  1481. "<#{tk_event_sequence(context)}>",
  1482. *hash_kv(keys, true))
  1483. else
  1484. tk_call_without_enc('event', 'generate', win,
  1485. "<#{tk_event_sequence(context)}>")
  1486. end
  1487. nil
  1488. end
  1489. def messageBox(keys)
  1490. tk_call('tk_messageBox', *hash_kv(keys))
  1491. end
  1492. def getOpenFile(keys = nil)
  1493. tk_call('tk_getOpenFile', *hash_kv(keys))
  1494. end
  1495. def getMultipleOpenFile(keys = nil)
  1496. simplelist(tk_call('tk_getOpenFile', '-multiple', '1', *hash_kv(keys)))
  1497. end
  1498. def getSaveFile(keys = nil)
  1499. tk_call('tk_getSaveFile', *hash_kv(keys))
  1500. end
  1501. def getMultipleSaveFile(keys = nil)
  1502. simplelist(tk_call('tk_getSaveFile', '-multiple', '1', *hash_kv(keys)))
  1503. end
  1504. def chooseColor(keys = nil)
  1505. tk_call('tk_chooseColor', *hash_kv(keys))
  1506. end
  1507. def chooseDirectory(keys = nil)
  1508. tk_call('tk_chooseDirectory', *hash_kv(keys))
  1509. end
  1510. def _ip_eval_core(enc_mode, cmd_string)
  1511. case enc_mode
  1512. when nil
  1513. res = INTERP._eval(cmd_string)
  1514. when false
  1515. res = INTERP._eval_without_enc(cmd_string)
  1516. when true
  1517. res = INTERP._eval_with_enc(cmd_string)
  1518. end
  1519. if INTERP._return_value() != 0
  1520. fail RuntimeError, res, error_at
  1521. end
  1522. return res
  1523. end
  1524. private :_ip_eval_core
  1525. def ip_eval(cmd_string)
  1526. _ip_eval_core(nil, cmd_string)
  1527. end
  1528. def ip_eval_without_enc(cmd_string)
  1529. _ip_eval_core(false, cmd_string)
  1530. end
  1531. def ip_eval_with_enc(cmd_string)
  1532. _ip_eval_core(true, cmd_string)
  1533. end
  1534. def _ip_invoke_core(enc_mode, *args)
  1535. case enc_mode
  1536. when false
  1537. res = INTERP._invoke_without_enc(*args)
  1538. when nil
  1539. res = INTERP._invoke(*args)
  1540. when true
  1541. res = INTERP._invoke_with_enc(*args)
  1542. end
  1543. if INTERP._return_value() != 0
  1544. fail RuntimeError, res, error_at
  1545. end
  1546. return res
  1547. end
  1548. private :_ip_invoke_core
  1549. def ip_invoke(*args)
  1550. _ip_invoke_core(nil, *args)
  1551. end
  1552. def ip_invoke_without_enc(*args)
  1553. _ip_invoke_core(false, *args)
  1554. end
  1555. def ip_invoke_with_enc(*args)
  1556. _ip_invoke_core(true, *args)
  1557. end
  1558. def _tk_call_core(enc_mode, *args)
  1559. ### puts args.inspect if $DEBUG
  1560. #args.collect! {|x|ruby2tcl(x, enc_mode)}
  1561. #args.compact!
  1562. #args.flatten!
  1563. args = _conv_args([], enc_mode, *args)
  1564. puts 'invoke args => ' + args.inspect if $DEBUG
  1565. ### print "=> ", args.join(" ").inspect, "\n" if $DEBUG
  1566. begin
  1567. # res = INTERP._invoke(*args).taint
  1568. # res = INTERP._invoke(enc_mode, *args)
  1569. res = _ip_invoke_core(enc_mode, *args)
  1570. # >>>>> _invoke returns a TAINTED string <<<<<
  1571. rescue NameError => err
  1572. # err = $!
  1573. begin
  1574. args.unshift "unknown"
  1575. #res = INTERP._invoke(*args).taint
  1576. #res = INTERP._invoke(enc_mode, *args)
  1577. res = _ip_invoke_core(enc_mode, *args)
  1578. # >>>>> _invoke returns a TAINTED string <<<<<
  1579. rescue StandardError => err2
  1580. fail err2 unless /^invalid command/ =~ err2.message
  1581. fail err
  1582. end
  1583. end
  1584. if INTERP._return_value() != 0
  1585. fail RuntimeError, res, error_at
  1586. end
  1587. ### print "==> ", res.inspect, "\n" if $DEBUG
  1588. return res
  1589. end
  1590. private :_tk_call_core
  1591. def tk_call(*args)
  1592. _tk_call_core(nil, *args)
  1593. end
  1594. def tk_call_without_enc(*args)
  1595. _tk_call_core(false, *args)
  1596. end
  1597. def tk_call_with_enc(*args)
  1598. _tk_call_core(true, *args)
  1599. end
  1600. def _tk_call_to_list_core(depth, arg_enc, val_enc, *args)
  1601. args = _conv_args([], arg_enc, *args)
  1602. val = _tk_call_core(false, *args)
  1603. if !depth.kind_of?(Integer) || depth == 0
  1604. tk_split_simplelist(val, false, val_enc)
  1605. else
  1606. tk_split_list(val, depth, false, val_enc)
  1607. end
  1608. end
  1609. #private :_tk_call_to_list_core
  1610. def tk_call_to_list(*args)
  1611. _tk_call_to_list_core(-1, nil, true, *args)
  1612. end
  1613. def tk_call_to_list_without_enc(*args)
  1614. _tk_call_to_list_core(-1, false, false, *args)
  1615. end
  1616. def tk_call_to_list_with_enc(*args)
  1617. _tk_call_to_list_core(-1, true, true, *args)
  1618. end
  1619. def tk_call_to_simplelist(*args)
  1620. _tk_call_to_list_core(0, nil, true, *args)
  1621. end
  1622. def tk_call_to_simplelist_without_enc(*args)
  1623. _tk_call_to_list_core(0, false, false, *args)
  1624. end
  1625. def tk_call_to_simplelist_with_enc(*args)
  1626. _tk_call_to_list_core(0, true, true, *args)
  1627. end
  1628. end
  1629. module Tk
  1630. include TkCore
  1631. extend Tk
  1632. TCL_VERSION = INTERP._invoke_without_enc("info", "tclversion").freeze
  1633. TCL_PATCHLEVEL = INTERP._invoke_without_enc("info", "patchlevel").freeze
  1634. major, minor = TCL_VERSION.split('.')
  1635. TCL_MAJOR_VERSION = major.to_i
  1636. TCL_MINOR_VERSION = minor.to_i
  1637. TK_VERSION = INTERP._invoke_without_enc("set", "tk_version").freeze
  1638. TK_PATCHLEVEL = INTERP._invoke_without_enc("set", "tk_patchLevel").freeze
  1639. major, minor = TK_VERSION.split('.')
  1640. TK_MAJOR_VERSION = major.to_i
  1641. TK_MINOR_VERSION = minor.to_i
  1642. JAPANIZED_TK = (INTERP._invoke_without_enc("info", "commands",
  1643. "kanji") != "").freeze
  1644. def Tk.const_missing(sym)
  1645. case(sym)
  1646. when :TCL_LIBRARY
  1647. INTERP._invoke_without_enc('global', 'tcl_library')
  1648. INTERP._invoke("set", "tcl_library").freeze
  1649. when :TK_LIBRARY
  1650. INTERP._invoke_without_enc('global', 'tk_library')
  1651. INTERP._invoke("set", "tk_library").freeze
  1652. when :LIBRARY
  1653. INTERP._invoke("info", "library").freeze
  1654. #when :PKG_PATH, :PACKAGE_PATH, :TCL_PACKAGE_PATH
  1655. # INTERP._invoke_without_enc('global', 'tcl_pkgPath')
  1656. # tk_split_simplelist(INTERP._invoke('set', 'tcl_pkgPath'))
  1657. #when :LIB_PATH, :LIBRARY_PATH, :TCL_LIBRARY_PATH
  1658. # INTERP._invoke_without_enc('global', 'tcl_libPath')
  1659. # tk_split_simplelist(INTERP._invoke('set', 'tcl_libPath'))
  1660. when :PLATFORM, :TCL_PLATFORM
  1661. if $SAFE >= 4
  1662. fail SecurityError, "can't get #{sym} when $SAFE >= 4"
  1663. end
  1664. INTERP._invoke_without_enc('global', 'tcl_platform')
  1665. Hash[*tk_split_simplelist(INTERP._invoke_without_enc('array', 'get',
  1666. 'tcl_platform'))]
  1667. when :ENV
  1668. INTERP._invoke_without_enc('global', 'env')
  1669. Hash[*tk_split_simplelist(INTERP._invoke('array', 'get', 'env'))]
  1670. #when :AUTO_PATH #<===
  1671. # tk_split_simplelist(INTERP._invoke('set', 'auto_path'))
  1672. #when :AUTO_OLDPATH
  1673. # tk_split_simplelist(

Large files files are truncated, but you can click here to view the full file