1 #
2 # tk.rb - Tk interface module using tcltklib
3 # by Yukihiro Matsumoto <matz@netlab.jp>
4
5 # use Shigehiro's tcltklib
6 require 'tcltklib'
7 require 'tkutil'
8
9 # autoload
10 require 'tk/autoload'
11
12 # for Mutex
13 require 'thread'
14
15 class TclTkIp
16 # backup original (without encoding) _eval and _invoke
17 alias _eval_without_enc _eval
18 alias _invoke_without_enc _invoke
19
20 def _ip_id_
21 # for RemoteTkIp
22 ''
23 end
24 end
25
26 # define TkComm module (step 1: basic functions)
27 module TkComm
28 include TkUtil
29 extend TkUtil
30
31 WidgetClassNames = {}.taint
32 TkExtlibAutoloadModule = [].taint
33
34 # None = Object.new ### --> definition is moved to TkUtil module
35 # def None.to_s
36 # 'None'
37 # end
38 # None.freeze
39
40 #Tk_CMDTBL = {}
41 #Tk_WINDOWS = {}
42 Tk_IDs = ["00000".taint, "00000".taint] # [0]-cmdid, [1]-winid
43 Tk_IDs.instance_eval{
44 @mutex = Mutex.new
45 def mutex; @mutex; end
46 freeze
47 }
48
49 # for backward compatibility
50 Tk_CMDTBL = Object.new
51 def Tk_CMDTBL.method_missing(id, *args)
52 TkCore::INTERP.tk_cmd_tbl.__send__(id, *args)
53 end
54 Tk_CMDTBL.freeze
55 Tk_WINDOWS = Object.new
56 def Tk_WINDOWS.method_missing(id, *args)
57 TkCore::INTERP.tk_windows.__send__(id, *args)
58 end
59 Tk_WINDOWS.freeze
60
61 self.instance_eval{
62 @cmdtbl = [].taint
63 }
64
65 unless const_defined?(:GET_CONFIGINFO_AS_ARRAY)
66 # GET_CONFIGINFO_AS_ARRAY = false => returns a Hash { opt =>val, ... }
67 # true => returns an Array [[opt,val], ... ]
68 # val is a list which includes resource info.
69 GET_CONFIGINFO_AS_ARRAY = true
70 end
71 unless const_defined?(:GET_CONFIGINFOwoRES_AS_ARRAY)
72 # for configinfo without resource info; list of [opt, value] pair
73 # false => returns a Hash { opt=>val, ... }
74 # true => returns an Array [[opt,val], ... ]
75 GET_CONFIGINFOwoRES_AS_ARRAY = true
76 end
77 # *** ATTENTION ***
78 # 'current_configinfo' method always returns a Hash under all cases of above.
79
80 def error_at
81 frames = caller()
82 frames.delete_if do |c|
83 c =~ %r!/tk(|core|thcore|canvas|text|entry|scrollbox)\.rb:\d+!
84 end
85 frames
86 end
87 private :error_at
88
89 def _genobj_for_tkwidget(path)
90 return TkRoot.new if path == '.'
91
92 begin
93 #tk_class = TkCore::INTERP._invoke('winfo', 'class', path)
94 tk_class = Tk.ip_invoke_without_enc('winfo', 'class', path)
95 rescue
96 return path
97 end
98
99 if ruby_class = WidgetClassNames[tk_class]
100 ruby_class_name = ruby_class.name
101 # gen_class_name = ruby_class_name + 'GeneratedOnTk'
102 gen_class_name = ruby_class_name
103 classname_def = ''
104 else # ruby_class == nil
105 mods = TkExtlibAutoloadModule.find_all{|m| m.const_defined?(tk_class)}
106 mods.each{|mod|
107 begin
108 mod.const_get(tk_class) # auto_load
109 break if (ruby_class = WidgetClassNames[tk_class])
110 rescue LoadError
111 # ignore load error
112 end
113 }
114
115 unless ruby_class
116 std_class = 'Tk' << tk_class
117 if Object.const_defined?(std_class)
118 Object.const_get(std_class) # auto_load
119 ruby_class = WidgetClassNames[tk_class]
120 end
121 end
122
123 if ruby_class
124 # found
125 ruby_class_name = ruby_class.name
126 gen_class_name = ruby_class_name
127 classname_def = ''
128 else
129 # unknown
130 ruby_class_name = 'TkWindow'
131 gen_class_name = 'TkWidget_' + tk_class
132 classname_def = "WidgetClassName = '#{tk_class}'.freeze"
133 end
134 end
135
136 ###################################
137 =begin
138 if ruby_class = WidgetClassNames[tk_class]
139 ruby_class_name = ruby_class.name
140 # gen_class_name = ruby_class_name + 'GeneratedOnTk'
141 gen_class_name = ruby_class_name
142 classname_def = ''
143 else
144 mod = TkExtlibAutoloadModule.find{|m| m.const_defined?(tk_class)}
145 if mod
146 ruby_class_name = mod.name + '::' + tk_class
147 gen_class_name = ruby_class_name
148 classname_def = ''
149 elsif Object.const_defined?('Tk' + tk_class)
150 ruby_class_name = 'Tk' + tk_class
151 # gen_class_name = ruby_class_name + 'GeneratedOnTk'
152 gen_class_name = ruby_class_name
153 classname_def = ''
154 else
155 ruby_class_name = 'TkWindow'
156 # gen_class_name = ruby_class_name + tk_class + 'GeneratedOnTk'
157 gen_class_name = 'TkWidget_' + tk_class
158 classname_def = "WidgetClassName = '#{tk_class}'.freeze"
159 end
160 end
161 =end
162
163 =begin
164 unless Object.const_defined? gen_class_name
165 Object.class_eval "class #{gen_class_name}<#{ruby_class_name}
166 #{classname_def}
167 end"
168 end
169 Object.class_eval "#{gen_class_name}.new('widgetname'=>'#{path}',
170 'without_creating'=>true)"
171 =end
172 base = Object
173 gen_class_name.split('::').each{|klass|
174 next if klass == ''
175 if base.const_defined?(klass)
176 base = base.class_eval klass
177 else
178 base = base.class_eval "class #{klass}<#{ruby_class_name}
179 #{classname_def}
180 end
181 #{klass}"
182 end
183 }
184 base.class_eval "#{gen_class_name}.new('widgetname'=>'#{path}',
185 'without_creating'=>true)"
186 end
187 private :_genobj_for_tkwidget
188 module_function :_genobj_for_tkwidget
189
190 def _at(x,y=nil)
191 if y
192 "@#{Integer(x)},#{Integer(y)}"
193 else
194 "@#{Integer(x)}"
195 end
196 end
197 module_function :_at
198
199 def tk_tcl2ruby(val, enc_mode = false, listobj = true)
200 =begin
201 if val =~ /^rb_out\S* (c(_\d+_)?\d+)/
202 #return Tk_CMDTBL[$1]
203 return TkCore::INTERP.tk_cmd_tbl[$1]
204 #cmd_obj = TkCore::INTERP.tk_cmd_tbl[$1]
205 #if cmd_obj.kind_of?(Proc) || cmd_obj.kind_of?(Method)
206 # cmd_obj
207 #else
208 # cmd_obj.cmd
209 #end
210 end
211 =end
212 if val =~ /rb_out\S*(?:\s+(::\S*|[{](::.*)[}]|["](::.*)["]))? (c(_\d+_)?(\d+))/
213 return TkCore::INTERP.tk_cmd_tbl[$4]
214 end
215 #if val.include? ?\s
216 # return val.split.collect{|v| tk_tcl2ruby(v)}
217 #end
218 case val
219 when /\A@font\S+\z/
220 TkFont.get_obj(val)
221 when /\A-?\d+\z/
222 val.to_i
223 when /\A\.\S*\z/
224 #Tk_WINDOWS[val] ? Tk_WINDOWS[val] : _genobj_for_tkwidget(val)
225 TkCore::INTERP.tk_windows[val]?
226 TkCore::INTERP.tk_windows[val] : _genobj_for_tkwidget(val)
227 when /\Ai(_\d+_)?\d+\z/
228 TkImage::Tk_IMGTBL.mutex.synchronize{
229 TkImage::Tk_IMGTBL[val]? TkImage::Tk_IMGTBL[val] : val
230 }
231 when /\A-?\d+\.?\d*(e[-+]?\d+)?\z/
232 val.to_f
233 when /\\ /
234 val.gsub(/\\ /, ' ')
235 when /[^\\] /
236 if listobj
237 #tk_split_escstr(val).collect{|elt|
238 # tk_tcl2ruby(elt, enc_mode, listobj)
239 #}
240 val = _toUTF8(val) unless enc_mode
241 tk_split_escstr(val, false, false).collect{|elt|
242 tk_tcl2ruby(elt, true, listobj)
243 }
244 elsif enc_mode
245 _fromUTF8(val)
246 else
247 val
248 end
249 else
250 if enc_mode
251 _fromUTF8(val)
252 else
253 val
254 end
255 end
256 end
257
258 private :tk_tcl2ruby
259 module_function :tk_tcl2ruby
260 #private_class_method :tk_tcl2ruby
261
262 unless const_defined?(:USE_TCLs_LIST_FUNCTIONS)
263 USE_TCLs_LIST_FUNCTIONS = true
264 end
265
266 if USE_TCLs_LIST_FUNCTIONS
267 ###########################################################################
268 # use Tcl function version of split_list
269 ###########################################################################
270
271 def tk_split_escstr(str, src_enc=true, dst_enc=true)
272 str = _toUTF8(str) if src_enc
273 if dst_enc
274 TkCore::INTERP._split_tklist(str).map!{|s| _fromUTF8(s)}
275 else
276 TkCore::INTERP._split_tklist(str)
277 end
278 end
279
280 def tk_split_sublist(str, depth=-1, src_enc=true, dst_enc=true)
281 # return [] if str == ""
282 # list = TkCore::INTERP._split_tklist(str)
283 str = _toUTF8(str) if src_enc
284
285 if depth == 0
286 return "" if str == ""
287 list = [str]
288 else
289 return [] if str == ""
290 list = TkCore::INTERP._split_tklist(str)
291 end
292 if list.size == 1
293 # tk_tcl2ruby(list[0], nil, false)
294 tk_tcl2ruby(list[0], dst_enc, false)
295 else
296 list.collect{|token| tk_split_sublist(token, depth - 1, false, dst_enc)}
297 end
298 end
299
300 def tk_split_list(str, depth=0, src_enc=true, dst_enc=true)
301 return [] if str == ""
302 str = _toUTF8(str) if src_enc
303 TkCore::INTERP._split_tklist(str).map!{|token|
304 tk_split_sublist(token, depth - 1, false, dst_enc)
305 }
306 end
307
308 def tk_split_simplelist(str, src_enc=true, dst_enc=true)
309 #lst = TkCore::INTERP._split_tklist(str)
310 #if (lst.size == 1 && lst =~ /^\{.*\}$/)
311 # TkCore::INTERP._split_tklist(str[1..-2])
312 #else
313 # lst
314 #end
315
316 str = _toUTF8(str) if src_enc
317 if dst_enc
318 TkCore::INTERP._split_tklist(str).map!{|s| _fromUTF8(s)}
319 else
320 TkCore::INTERP._split_tklist(str)
321 end
322 end
323
324 def array2tk_list(ary, enc=nil)
325 return "" if ary.size == 0
326
327 sys_enc = TkCore::INTERP.encoding
328 sys_enc = TclTkLib.encoding_system unless sys_enc
329
330 dst_enc = (enc == nil)? sys_enc: enc
331
332 dst = ary.collect{|e|
333 if e.kind_of? Array
334 s = array2tk_list(e, enc)
335 elsif e.kind_of? Hash
336 tmp_ary = []
337 #e.each{|k,v| tmp_ary << k << v }
338 e.each{|k,v| tmp_ary << "-#{_get_eval_string(k)}" << v }
339 s = array2tk_list(tmp_ary, enc)
340 else
341 s = _get_eval_string(e, enc)
342 end
343
344 if dst_enc != true && dst_enc != false
345 if (s_enc = s.instance_variable_get(:@encoding))
346 s_enc = s_enc.to_s
347 elsif TkCore::WITH_ENCODING
348 s_enc = s.encoding.name
349 else
350 s_enc = sys_enc
351 end
352 dst_enc = true if s_enc != dst_enc
353 end
354
355 s
356 }
357
358 if sys_enc && dst_enc
359 dst.map!{|s| _toUTF8(s)}
360 ret = TkCore::INTERP._merge_tklist(*dst)
361 if TkCore::WITH_ENCODING
362 if dst_enc.kind_of?(String)
363 ret = _fromUTF8(ret, dst_enc)
364 ret.force_encoding(dst_enc)
365 else
366 ret.force_encoding('utf-8')
367 end
368 else # without encoding
369 if dst_enc.kind_of?(String)
370 ret = _fromUTF8(ret, dst_enc)
371 ret.instance_variable_set(:@encoding, dst_enc)
372 else
373 ret.instance_variable_set(:@encoding, 'utf-8')
374 end
375 end
376 ret
377 else
378 TkCore::INTERP._merge_tklist(*dst)
379 end
380 end
381
382 else
383 ###########################################################################
384 # use Ruby script version of split_list (traditional methods)
385 ###########################################################################
386
387 def tk_split_escstr(str, src_enc=true, dst_enc=true)
388 return [] if str == ""
389 list = []
390 token = nil
391 escape = false
392 brace = 0
393 str.split('').each {|c|
394 brace += 1 if c == '{' && !escape
395 brace -= 1 if c == '}' && !escape
396 if brace == 0 && c == ' ' && !escape
397 list << token.gsub(/^\{(.*)\}$/, '\1') if token
398 token = nil
399 else
400 token = (token || "") << c
401 end
402 escape = (c == '\\' && !escape)
403 }
404 list << token.gsub(/^\{(.*)\}$/, '\1') if token
405 list
406 end
407
408 def tk_split_sublist(str, depth=-1, src_enc=true, dst_enc=true)
409 #return [] if str == ""
410 #return [tk_split_sublist(str[1..-2])] if str =~ /^\{.*\}$/
411 #list = tk_split_escstr(str)
412 if depth == 0
413 return "" if str == ""
414 str = str[1..-2] if str =~ /^\{.*\}$/
415 list = [str]
416 else
417 return [] if str == []
418 return [tk_split_sublist(str[1..-2], depth - 1)] if str =~ /^\{.*\}$/
419 list = tk_split_escstr(str)
420 end
421 if list.size == 1
422 tk_tcl2ruby(list[0], nil, false)
423 else
424 list.collect{|token| tk_split_sublist(token, depth - 1)}
425 end
426 end
427
428 def tk_split_list(str, depth=0, src_enc=true, dst_enc=true)
429 return [] if str == ""
430 tk_split_escstr(str).collect{|token|
431 tk_split_sublist(token, depth - 1)
432 }
433 end
434
435 def tk_split_simplelist(str, src_enc=true, dst_enc=true)
436 return [] if str == ""
437 list = []
438 token = nil
439 escape = false
440 brace = 0
441 str.split('').each {|c|
442 if c == '\\' && !escape
443 escape = true
444 token = (token || "") << c if brace > 0
445 next
446 end
447 brace += 1 if c == '{' && !escape
448 brace -= 1 if c == '}' && !escape
449 if brace == 0 && c == ' ' && !escape
450 list << token.gsub(/^\{(.*)\}$/, '\1') if token
451 token = nil
452 else
453 token = (token || "") << c
454 end
455 escape = false
456 }
457 list << token.gsub(/^\{(.*)\}$/, '\1') if token
458 list
459 end
460
461 def array2tk_list(ary, enc=nil)
462 ary.collect{|e|
463 if e.kind_of? Array
464 "{#{array2tk_list(e, enc)}}"
465 elsif e.kind_of? Hash
466 # "{#{e.to_a.collect{|ee| array2tk_list(ee)}.join(' ')}}"
467 e.each{|k,v| tmp_ary << "-#{_get_eval_string(k)}" << v }
468 array2tk_list(tmp_ary, enc)
469 else
470 s = _get_eval_string(e, enc)
471 (s.index(/\s/) || s.size == 0)? "{#{s}}": s
472 end
473 }.join(" ")
474 end
475 end
476
477 private :tk_split_escstr, :tk_split_sublist
478 private :tk_split_list, :tk_split_simplelist
479 private :array2tk_list
480
481 module_function :tk_split_escstr, :tk_split_sublist
482 module_function :tk_split_list, :tk_split_simplelist
483 module_function :array2tk_list
484
485 private_class_method :tk_split_escstr, :tk_split_sublist
486 private_class_method :tk_split_list, :tk_split_simplelist
487 # private_class_method :array2tk_list
488
489 =begin
490 ### --> definition is moved to TkUtil module
491 def _symbolkey2str(keys)
492 h = {}
493 keys.each{|key,value| h[key.to_s] = value}
494 h
495 end
496 private :_symbolkey2str
497 module_function :_symbolkey2str
498 =end
499
500 =begin
501 ### --> definition is moved to TkUtil module
502 # def hash_kv(keys, enc_mode = nil, conf = [], flat = false)
503 def hash_kv(keys, enc_mode = nil, conf = nil)
504 # Hash {key=>val, key=>val, ... } or Array [ [key, val], [key, val], ... ]
505 # ==> Array ['-key', val, '-key', val, ... ]
506 dst = []
507 if keys and keys != None
508 keys.each{|k, v|
509 #dst.push("-#{k}")
510 dst.push('-' + k.to_s)
511 if v != None
512 # v = _get_eval_string(v, enc_mode) if (enc_mode || flat)
513 v = _get_eval_string(v, enc_mode) if enc_mode
514 dst.push(v)
515 end
516 }
517 end
518 if conf
519 conf + dst
520 else
521 dst
522 end
523 end
524 private :hash_kv
525 module_function :hash_kv
526 =end
527
528 =begin
529 ### --> definition is moved to TkUtil module
530 def bool(val)
531 case val
532 when "1", 1, 'yes', 'true'
533 true
534 else
535 false
536 end
537 end
538
539 def number(val)
540 case val
541 when /^-?\d+$/
542 val.to_i
543 when /^-?\d+\.?\d*(e[-+]?\d+)?$/
544 val.to_f
545 else
546 fail(ArgumentError, "invalid value for Number:'#{val}'")
547 end
548 end
549 def string(val)
550 if val == "{}"
551 ''
552 elsif val[0] == ?{ && val[-1] == ?}
553 val[1..-2]
554 else
555 val
556 end
557 end
558 def num_or_str(val)
559 begin
560 number(val)
561 rescue ArgumentError
562 string(val)
563 end
564 end
565 =end
566
567 def list(val, depth=0, enc=true)
568 tk_split_list(val, depth, enc, enc)
569 end
570 def simplelist(val, src_enc=true, dst_enc=true)
571 tk_split_simplelist(val, src_enc, dst_enc)
572 end
573 def window(val)
574 if val =~ /^\./
575 #Tk_WINDOWS[val]? Tk_WINDOWS[val] : _genobj_for_tkwidget(val)
576 TkCore::INTERP.tk_windows[val]?
577 TkCore::INTERP.tk_windows[val] : _genobj_for_tkwidget(val)
578 else
579 nil
580 end
581 end
582 def image_obj(val)
583 if val =~ /^i(_\d+_)?\d+$/
584 TkImage::Tk_IMGTBL.mutex.synchronize{
585 TkImage::Tk_IMGTBL[val]? TkImage::Tk_IMGTBL[val] : val
586 }
587 else
588 val
589 end
590 end
591 def procedure(val)
592 =begin
593 if val =~ /^rb_out\S* (c(_\d+_)?\d+)/
594 #Tk_CMDTBL[$1]
595 #TkCore::INTERP.tk_cmd_tbl[$1]
596 TkCore::INTERP.tk_cmd_tbl[$1].cmd
597 =end
598 if val =~ /rb_out\S*(?:\s+(::\S*|[{](::.*)[}]|["](::.*)["]))? (c(_\d+_)?(\d+))/
599 return TkCore::INTERP.tk_cmd_tbl[$4].cmd
600 else
601 #nil
602 val
603 end
604 end
605 private :bool, :number, :string, :num_or_str
606 private :list, :simplelist, :window, :procedure
607 module_function :bool, :number, :num_or_str, :string
608 module_function :list, :simplelist, :window, :image_obj, :procedure
609
610 def subst(str, *opts)
611 # opts := :nobackslashes | :nocommands | novariables
612 tk_call('subst',
613 *(opts.collect{|opt|
614 opt = opt.to_s
615 (opt[0] == ?-)? opt: '-' << opt
616 } << str))
617 end
618
619 def _toUTF8(str, encoding = nil)
620 TkCore::INTERP._toUTF8(str, encoding)
621 end
622 def _fromUTF8(str, encoding = nil)
623 TkCore::INTERP._fromUTF8(str, encoding)
624 end
625 private :_toUTF8, :_fromUTF8
626 module_function :_toUTF8, :_fromUTF8
627
628 def _callback_entry_class?(cls)
629 cls <= Proc || cls <= Method || cls <= TkCallbackEntry
630 end
631 private :_callback_entry_class?
632 module_function :_callback_entry_class?
633
634 def _callback_entry?(obj)
635 obj.kind_of?(Proc) || obj.kind_of?(Method) || obj.kind_of?(TkCallbackEntry)
636 end
637 private :_callback_entry?
638 module_function :_callback_entry?
639
640 =begin
641 ### --> definition is moved to TkUtil module
642 def _get_eval_string(str, enc_mode = nil)
643 return nil if str == None
644 if str.kind_of?(TkObject)
645 str = str.path
646 elsif str.kind_of?(String)
647 str = _toUTF8(str) if enc_mode
648 elsif str.kind_of?(Symbol)
649 str = str.id2name
650 str = _toUTF8(str) if enc_mode
651 elsif str.kind_of?(Hash)
652 str = hash_kv(str, enc_mode).join(" ")
653 elsif str.kind_of?(Array)
654 str = array2tk_list(str)
655 str = _toUTF8(str) if enc_mode
656 elsif str.kind_of?(Proc)
657 str = install_cmd(str)
658 elsif str == nil
659 str = ""
660 elsif str == false
661 str = "0"
662 elsif str == true
663 str = "1"
664 elsif (str.respond_to?(:to_eval))
665 str = str.to_eval()
666 str = _toUTF8(str) if enc_mode
667 else
668 str = str.to_s() || ''
669 unless str.kind_of? String
670 fail RuntimeError, "fail to convert the object to a string"
671 end
672 str = _toUTF8(str) if enc_mode
673 end
674 return str
675 end
676 =end
677 =begin
678 def _get_eval_string(obj, enc_mode = nil)
679 case obj
680 when Numeric
681 obj.to_s
682 when String
683 (enc_mode)? _toUTF8(obj): obj
684 when Symbol
685 (enc_mode)? _toUTF8(obj.id2name): obj.id2name
686 when TkObject
687 obj.path
688 when Hash
689 hash_kv(obj, enc_mode).join(' ')
690 when Array
691 (enc_mode)? _toUTF8(array2tk_list(obj)): array2tk_list(obj)
692 when Proc, Method, TkCallbackEntry
693 install_cmd(obj)
694 when false
695 '0'
696 when true
697 '1'
698 when nil
699 ''
700 when None
701 nil
702 else
703 if (obj.respond_to?(:to_eval))
704 (enc_mode)? _toUTF8(obj.to_eval): obj.to_eval
705 else
706 begin
707 obj = obj.to_s || ''
708 rescue
709 fail RuntimeError, "fail to convert object '#{obj}' to string"
710 end
711 (enc_mode)? _toUTF8(obj): obj
712 end
713 end
714 end
715 private :_get_eval_string
716 module_function :_get_eval_string
717 =end
718
719 =begin
720 ### --> definition is moved to TkUtil module
721 def _get_eval_enc_str(obj)
722 return obj if obj == None
723 _get_eval_string(obj, true)
724 end
725 private :_get_eval_enc_str
726 module_function :_get_eval_enc_str
727 =end
728
729 =begin
730 ### --> obsolete
731 def ruby2tcl(v, enc_mode = nil)
732 if v.kind_of?(Hash)
733 v = hash_kv(v)
734 v.flatten!
735 v.collect{|e|ruby2tcl(e, enc_mode)}
736 else
737 _get_eval_string(v, enc_mode)
738 end
739 end
740 private :ruby2tcl
741 =end
742
743 =begin
744 ### --> definition is moved to TkUtil module
745 def _conv_args(args, enc_mode, *src_args)
746 conv_args = []
747 src_args.each{|arg|
748 conv_args << _get_eval_string(arg, enc_mode) unless arg == None
749 # if arg.kind_of?(Hash)
750 # arg.each{|k, v|
751 # args << '-' + k.to_s
752 # args << _get_eval_string(v, enc_mode)
753 # }
754 # elsif arg != None
755 # args << _get_eval_string(arg, enc_mode)
756 # end
757 }
758 args + conv_args
759 end
760 private :_conv_args
761 =end
762
763 def _curr_cmd_id
764 #id = format("c%.4d", Tk_IDs[0])
765 id = "c" + TkCore::INTERP._ip_id_ + TkComm::Tk_IDs[0]
766 end
767 def _next_cmd_id
768 TkComm::Tk_IDs.mutex.synchronize{
769 id = _curr_cmd_id
770 #Tk_IDs[0] += 1
771 TkComm::Tk_IDs[0].succ!
772 id
773 }
774 end
775 private :_curr_cmd_id, :_next_cmd_id
776 module_function :_curr_cmd_id, :_next_cmd_id
777
778 def TkComm.install_cmd(cmd, local_cmdtbl=nil)
779 return '' if cmd == ''
780 begin
781 ns = TkCore::INTERP._invoke_without_enc('namespace', 'current')
782 ns = nil if ns == '::' # for backward compatibility
783 rescue
784 # probably, Tcl7.6
785 ns = nil
786 end
787 id = _next_cmd_id
788 #Tk_CMDTBL[id] = cmd
789 if cmd.kind_of?(TkCallbackEntry)
790 TkCore::INTERP.tk_cmd_tbl[id] = cmd
791 else
792 TkCore::INTERP.tk_cmd_tbl[id] = TkCore::INTERP.get_cb_entry(cmd)
793 end
794 @cmdtbl = [] unless defined? @cmdtbl
795 @cmdtbl.taint unless @cmdtbl.tainted?
796 @cmdtbl.push id
797
798 if local_cmdtbl && local_cmdtbl.kind_of?(Array)
799 begin
800 local_cmdtbl << id
801 rescue Exception
802 # ignore
803 end
804 end
805
806 #return Kernel.format("rb_out %s", id);
807 if ns
808 'rb_out' << TkCore::INTERP._ip_id_ << ' ' << ns << ' ' << id
809 else
810 'rb_out' << TkCore::INTERP._ip_id_ << ' ' << id
811 end
812 end
813 def TkComm.uninstall_cmd(id, local_cmdtbl=nil)
814 #id = $1 if /rb_out\S* (c(_\d+_)?\d+)/ =~ id
815 id = $4 if id =~ /rb_out\S*(?:\s+(::\S*|[{](::.*)[}]|["](::.*)["]))? (c(_\d+_)?(\d+))/
816
817 if local_cmdtbl && local_cmdtbl.kind_of?(Array)
818 begin
819 local_cmdtbl.delete(id)
820 rescue Exception
821 # ignore
822 end
823 end
824 @cmdtbl.delete(id)
825
826 #Tk_CMDTBL.delete(id)
827 TkCore::INTERP.tk_cmd_tbl.delete(id)
828 end
829 # private :install_cmd, :uninstall_cmd
830 # module_function :install_cmd, :uninstall_cmd
831 def install_cmd(cmd)
832 TkComm.install_cmd(cmd, @cmdtbl)
833 end
834 def uninstall_cmd(id)
835 TkComm.uninstall_cmd(id, @cmdtbl)
836 end
837
838 =begin
839 def install_win(ppath,name=nil)
840 if !name or name == ''
841 #name = format("w%.4d", Tk_IDs[1])
842 #Tk_IDs[1] += 1
843 name = "w" + Tk_IDs[1]
844 Tk_IDs[1].succ!
845 end
846 if name[0] == ?.
847 @path = name.dup
848 elsif !ppath or ppath == "."
849 @path = Kernel.format(".%s", name);
850 else
851 @path = Kernel.format("%s.%s", ppath, name)
852 end
853 #Tk_WINDOWS[@path] = self
854 TkCore::INTERP.tk_windows[@path] = self
855 end
856 =end
857 def install_win(ppath,name=nil)
858 if name
859 if name == ''
860 raise ArgumentError, "invalid wiget-name '#{name}'"
861 end
862 if name[0] == ?.
863 @path = '' + name
864 @path.freeze
865 return TkCore::INTERP.tk_windows[@path] = self
866 end
867 else
868 Tk_IDs.mutex.synchronize{
869 name = "w" + TkCore::INTERP._ip_id_ + Tk_IDs[1]
870 Tk_IDs[1].succ!
871 }
872 end
873 if !ppath or ppath == '.'
874 @path = '.' + name
875 else
876 @path = ppath + '.' + name
877 end
878 @path.freeze
879 TkCore::INTERP.tk_windows[@path] = self
880 end
881
882 def uninstall_win()
883 #Tk_WINDOWS.delete(@path)
884 TkCore::INTERP.tk_windows.delete(@path)
885 end
886 private :install_win, :uninstall_win
887
888 def _epath(win)
889 if win.kind_of?(TkObject)
890 win.epath
891 elsif win.respond_to?(:epath)
892 win.epath
893 else
894 win
895 end
896 end
897 private :_epath
898 end
899
900 # define TkComm module (step 2: event binding)
901 module TkComm
902 include TkEvent
903 extend TkEvent
904
905 def tk_event_sequence(context)
906 if context.kind_of? TkVirtualEvent
907 context = context.path
908 end
909 if context.kind_of? Array
910 context = context.collect{|ev|
911 if ev.kind_of? TkVirtualEvent
912 ev.path
913 else
914 ev
915 end
916 }.join("><")
917 end
918 if /,/ =~ context
919 context = context.split(/\s*,\s*/).join("><")
920 else
921 context
922 end
923 end
924
925 def _bind_core(mode, what, context, cmd, *args)
926 id = install_bind(cmd, *args) if cmd
927 begin
928 tk_call_without_enc(*(what + ["<#{tk_event_sequence(context)}>",
929 mode + id]))
930 rescue
931 uninstall_cmd(id) if cmd
932 fail
933 end
934 end
935
936 def _bind(what, context, cmd, *args)
937 _bind_core('', what, context, cmd, *args)
938 end
939
940 def _bind_append(what, context, cmd, *args)
941 _bind_core('+', what, context, cmd, *args)
942 end
943
944 def _bind_remove(what, context)
945 tk_call_without_enc(*(what + ["<#{tk_event_sequence(context)}>", '']))
946 end
947
948 def _bindinfo(what, context=nil)
949 if context
950 if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!!
951 enum_obj = tk_call_without_enc(*what+["<#{tk_event_sequence(context)}>"]).each_line
952 else
953 enum_obj = tk_call_without_enc(*what+["<#{tk_event_sequence(context)}>"])
954 end
955 enum_obj.collect {|cmdline|
956 =begin
957 if cmdline =~ /^rb_out\S* (c(?:_\d+_)?\d+)\s+(.*)$/
958 #[Tk_CMDTBL[$1], $2]
959 [TkCore::INTERP.tk_cmd_tbl[$1], $2]
960 =end
961 if cmdline =~ /rb_out\S*(?:\s+(::\S*|[{](::.*)[}]|["](::.*)["]))? (c(_\d+_)?(\d+))/
962 [TkCore::INTERP.tk_cmd_tbl[$4], $5]
963 else
964 cmdline
965 end
966 }
967 else
968 tk_split_simplelist(tk_call_without_enc(*what)).collect!{|seq|
969 l = seq.scan(/<*[^<>]+>*/).collect!{|subseq|
970 case (subseq)
971 when /^<<[^<>]+>>$/
972 TkVirtualEvent.getobj(subseq[1..-2])
973 when /^<[^<>]+>$/
974 subseq[1..-2]
975 else
976 subseq.split('')
977 end
978 }.flatten
979 (l.size == 1) ? l[0] : l
980 }
981 end
982 end
983
984 def _bind_core_for_event_class(klass, mode, what, context, cmd, *args)
985 id = install_bind_for_event_class(klass, cmd, *args) if cmd
986 begin
987 tk_call_without_enc(*(what + ["<#{tk_event_sequence(context)}>",
988 mode + id]))
989 rescue
990 uninstall_cmd(id) if cmd
991 fail
992 end
993 end
994
995 def _bind_for_event_class(klass, what, context, cmd, *args)
996 _bind_core_for_event_class(klass, '', what, context, cmd, *args)
997 end
998
999 def _bind_append_for_event_class(klass, what, context, cmd, *args)
1000 _bind_core_for_event_class(klass, '+', what, context, cmd, *args)
1001 end
1002
1003 def _bind_remove_for_event_class(klass, what, context)
1004 _bind_remove(what, context)
1005 end
1006
1007 def _bindinfo_for_event_class(klass, what, context=nil)
1008 _bindinfo(what, context)
1009 end
1010
1011 private :tk_event_sequence
1012 private :_bind_core, :_bind, :_bind_append, :_bind_remove, :_bindinfo
1013 private :_bind_core_for_event_class, :_bind_for_event_class,
1014 :_bind_append_for_event_class, :_bind_remove_for_event_class,
1015 :_bindinfo_for_event_class
1016
1017 #def bind(tagOrClass, context, cmd=Proc.new, *args)
1018 # _bind(["bind", tagOrClass], context, cmd, *args)
1019 # tagOrClass
1020 #end
1021 def bind(tagOrClass, context, *args)
1022 # if args[0].kind_of?(Proc) || args[0].kind_of?(Method)
1023 if TkComm._callback_entry?(args[0]) || !block_given?
1024 cmd = args.shift
1025 else
1026 cmd = Proc.new
1027 end
1028 _bind(["bind", tagOrClass], context, cmd, *args)
1029 tagOrClass
1030 end
1031
1032 #def bind_append(tagOrClass, context, cmd=Proc.new, *args)
1033 # _bind_append(["bind", tagOrClass], context, cmd, *args)
1034 # tagOrClass
1035 #end
1036 def bind_append(tagOrClass, context, *args)
1037 # if args[0].kind_of?(Proc) || args[0].kind_of?(Method)
1038 if TkComm._callback_entry?(args[0]) || !block_given?
1039 cmd = args.shift
1040 else
1041 cmd = Proc.new
1042 end
1043 _bind_append(["bind", tagOrClass], context, cmd, *args)
1044 tagOrClass
1045 end
1046
1047 def bind_remove(tagOrClass, context)
1048 _bind_remove(['bind', tagOrClass], context)
1049 tagOrClass
1050 end
1051
1052 def bindinfo(tagOrClass, context=nil)
1053 _bindinfo(['bind', tagOrClass], context)
1054 end
1055
1056 #def bind_all(context, cmd=Proc.new, *args)
1057 # _bind(['bind', 'all'], context, cmd, *args)
1058 # TkBindTag::ALL
1059 #end
1060 def bind_all(context, *args)
1061 # if args[0].kind_of?(Proc) || args[0].kind_of?(Method)
1062 if TkComm._callback_entry?(args[0]) || !block_given?
1063 cmd = args.shift
1064 else
1065 cmd = Proc.new
1066 end
1067 _bind(['bind', 'all'], context, cmd, *args)
1068 TkBindTag::ALL
1069 end
1070
1071 #def bind_append_all(context, cmd=Proc.new, *args)
1072 # _bind_append(['bind', 'all'], context, cmd, *args)
1073 # TkBindTag::ALL
1074 #end
1075 def bind_append_all(context, *args)
1076 # if args[0].kind_of?(Proc) || args[0].kind_of?(Method)
1077 if TkComm._callback_entry?(args[0]) || !block_given?
1078 cmd = args.shift
1079 else
1080 cmd = Proc.new
1081 end
1082 _bind_append(['bind', 'all'], context, cmd, *args)
1083 TkBindTag::ALL
1084 end
1085
1086 def bind_remove_all(context)
1087 _bind_remove(['bind', 'all'], context)
1088 TkBindTag::ALL
1089 end
1090
1091 def bindinfo_all(context=nil)
1092 _bindinfo(['bind', 'all'], context)
1093 end
1094 end
1095
1096
1097 module TkCore
1098 include TkComm
1099 extend TkComm
1100
1101 WITH_RUBY_VM = Object.const_defined?(:VM) && ::VM.class == Class
1102 WITH_ENCODING = Object.const_defined?(:Encoding) && ::Encoding.class == Class
1103
1104 unless self.const_defined? :RUN_EVENTLOOP_ON_MAIN_THREAD
1105 ### Ruby 1.9 !!!!!!!!!!!!!!!!!!!!!!!!!!
1106 RUN_EVENTLOOP_ON_MAIN_THREAD = false
1107 end
1108
1109 unless self.const_defined? :INTERP
1110 if self.const_defined? :IP_NAME
1111 name = IP_NAME.to_s
1112 else
1113 #name = nil
1114 name = $0
1115 end
1116 if self.const_defined? :IP_OPTS
1117 if IP_OPTS.kind_of?(Hash)
1118 opts = hash_kv(IP_OPTS).join(' ')
1119 else
1120 opts = IP_OPTS.to_s
1121 end
1122 else
1123 opts = ''
1124 end
1125
1126 if !WITH_RUBY_VM || RUN_EVENTLOOP_ON_MAIN_THREAD ### check Ruby 1.9 !!!!!!!
1127 INTERP = TclTkIp.new(name, opts)
1128 else
1129 INTERP_MUTEX = Mutex.new
1130 INTERP_ROOT_CHECK = ConditionVariable.new
1131 INTERP_THREAD = Thread.new{
1132 begin
1133 Thread.current[:interp] = interp = TclTkIp.new(name, opts)
1134 rescue => e
1135 Thread.current[:interp] = e
1136 raise e
1137 end
1138 Thread.current[:status] = nil
1139 #sleep
1140
1141 begin
1142 Thread.current[:status] = TclTkLib.mainloop(true)
1143 rescue Exception=>e
1144 Thread.current[:status] = e
1145 ensure
1146 INTERP_MUTEX.synchronize{ INTERP_ROOT_CHECK.broadcast }
1147 end
1148 Thread.current[:status] = TclTkLib.mainloop(false)
1149 }
1150
1151 until INTERP_THREAD[:interp]
1152 Thread.pass
1153 end
1154 # INTERP_THREAD.run
1155 raise INTERP_THREAD[:interp] if INTERP_THREAD[:interp].kind_of? Exception
1156
1157 INTERP = INTERP_THREAD[:interp]
1158 end
1159
1160 def INTERP.__getip
1161 self
1162 end
1163
1164 INTERP.instance_eval{
1165 # @tk_cmd_tbl = {}.taint
1166 @tk_cmd_tbl = Hash.new{|hash, key|
1167 fail IndexError, "unknown command ID '#{key}'"
1168 }.taint
1169 def @tk_cmd_tbl.[]=(idx,val)
1170 if self.has_key?(idx) && Thread.current.group != ThreadGroup::Default
1171 fail SecurityError,"cannot change the entried command"
1172 end
1173 super(idx,val)
1174 end
1175
1176 @tk_windows = {}.taint
1177
1178 @tk_table_list = [].taint
1179
1180 @init_ip_env = [].taint # table of Procs
1181 @add_tk_procs = [].taint # table of [name, args, body]
1182
1183 @cb_entry_class = Class.new(TkCallbackEntry){
1184 class << self
1185 def inspect
1186 sprintf("#<Class(TkCallbackEntry):%0x>", self.__id__)
1187 end
1188 alias to_s inspect
1189 end
1190
1191 def initialize(ip, cmd)
1192 @ip = ip
1193 @cmd = cmd
1194 end
1195 attr_reader :ip, :cmd
1196 def call(*args)
1197 @ip.cb_eval(@cmd, *args)
1198 end
1199 def inspect
1200 sprintf("#<cb_entry:%0x>", self.__id__)
1201 end
1202 alias to_s inspect
1203 }.freeze
1204 }
1205
1206 def INTERP.cb_entry_class
1207 @cb_entry_class
1208 end
1209 def INTERP.tk_cmd_tbl
1210 @tk_cmd_tbl
1211 end
1212 def INTERP.tk_windows
1213 @tk_windows
1214 end
1215
1216 class Tk_OBJECT_TABLE
1217 def initialize(id)
1218 @id = id
1219 @mutex = Mutex.new
1220 end
1221 def mutex
1222 @mutex
1223 end
1224 def method_missing(m, *args, &b)
1225 TkCore::INTERP.tk_object_table(@id).__send__(m, *args, &b)
1226 end
1227 end
1228
1229 def INTERP.tk_object_table(id)
1230 @tk_table_list[id]
1231 end
1232 def INTERP.create_table
1233 id = @tk_table_list.size
1234 (tbl = {}).tainted? || tbl.taint
1235 @tk_table_list << tbl
1236 # obj = Object.new
1237 # obj.instance_eval <<-EOD
1238 # def self.method_missing(m, *args)
1239 # TkCore::INTERP.tk_object_table(#{id}).send(m, *args)
1240 # end
1241 # EOD
1242 # return obj
1243 Tk_OBJECT_TABLE.new(id)
1244 end
1245
1246 def INTERP.get_cb_entry(cmd)
1247 @cb_entry_class.new(__getip, cmd).freeze
1248 end
1249 def INTERP.cb_eval(cmd, *args)
1250 TkUtil._get_eval_string(TkUtil.eval_cmd(cmd, *args))
1251 end
1252
1253 def INTERP.init_ip_env(script = Proc.new)
1254 @init_ip_env << script
1255 script.call(self)
1256 end
1257 def INTERP.add_tk_procs(name, args = nil, body = nil)
1258 if name.kind_of?(Array)
1259 name.each{|param| self.add_tk_procs(*param)}
1260 else
1261 name = name.to_s
1262 @add_tk_procs << [name, args, body]
1263 self._invoke('proc', name, args, body) if args && body
1264 end
1265 end
1266 def INTERP.remove_tk_procs(*names)
1267 names.each{|name|
1268 name = name.to_s
1269 @add_tk_procs.delete_if{|elem|
1270 elem.kind_of?(Array) && elem[0].to_s == name
1271 }
1272 self._invoke('rename', name, '')
1273 }
1274 end
1275 def INTERP.init_ip_internal
1276 ip = self
1277 @init_ip_env.each{|script| script.call(ip)}
1278 @add_tk_procs.each{|name,args,body| ip._invoke('proc',name,args,body)}
1279 end
1280 end
1281
1282 WIDGET_DESTROY_HOOK = '<WIDGET_DESTROY_HOOK>'
1283 INTERP._invoke_without_enc('event', 'add',
1284 "<#{WIDGET_DESTROY_HOOK}>", '<Destroy>')
1285 INTERP._invoke_without_enc('bind', 'all', "<#{WIDGET_DESTROY_HOOK}>",
1286 install_cmd(proc{|path|
1287 unless TkCore::INTERP.deleted?
1288 begin
1289 if (widget=TkCore::INTERP.tk_windows[path])
1290 if widget.respond_to?(:__destroy_hook__)
1291 widget.__destroy_hook__
1292 end
1293 end
1294 rescue Exception=>e
1295 p e if $DEBUG
1296 end
1297 end
1298 }) << ' %W')
1299
1300 INTERP.add_tk_procs(TclTkLib::FINALIZE_PROC_NAME, '',
1301 "catch { bind all <#{WIDGET_DESTROY_HOOK}> {} }")
1302
1303 INTERP.add_tk_procs('rb_out', 'ns args', <<-'EOL')
1304 if [regexp {^::} $ns] {
1305 set cmd {namespace eval $ns {ruby_cmd TkCore callback} $args}
1306 } else {
1307 set cmd {eval {ruby_cmd TkCore callback} $ns $args}
1308 }
1309 if {[set st [catch $cmd ret]] != 0} {
1310 #return -code $st $ret
1311 set idx [string first "\n\n" $ret]
1312 if {$idx > 0} {
1313 return -code $st \
1314 -errorinfo [string range $ret [expr $idx + 2] \
1315 [string length $ret]] \
1316 [string range $ret 0 [expr $idx - 1]]
1317 } else {
1318 return -code $st $ret
1319 }
1320 } else {
1321 return $ret
1322 }
1323 EOL
1324 =begin
1325 INTERP.add_tk_procs('rb_out', 'args', <<-'EOL')
1326 if {[set st [catch {eval {ruby_cmd TkCore callback} $args} ret]] != 0} {
1327 #return -code $st $ret
1328 set idx [string first "\n\n" $ret]
1329 if {$idx > 0} {
1330 return -code $st \
1331 -errorinfo [string range $ret [expr $idx + 2] \
1332 [string length $ret]] \
1333 [string range $ret 0 [expr $idx - 1]]
1334 } else {
1335 return -code $st $ret
1336 }
1337 } else {
1338 return $ret
1339 }
1340 EOL
1341 =end
1342 =begin
1343 INTERP.add_tk_procs('rb_out', 'args', <<-'EOL')
1344 #regsub -all {\\} $args {\\\\} args
1345 #regsub -all {!} $args {\\!} args
1346 #regsub -all "{" $args "\\{" args
1347 regsub -all {(\\|!|\{|\})} $args {\\\1} args
1348 if {[set st [catch {ruby [format "TkCore.callback %%Q!%s!" $args]} ret]] != 0} {
1349 #return -code $st $ret
1350 set idx [string first "\n\n" $ret]
1351 if {$idx > 0} {
1352 return -code $st \
1353 -errorinfo [string range $ret [expr $idx + 2] \
1354 [string length $ret]] \
1355 [string range $ret 0 [expr $idx - 1]]
1356 } else {
1357 return -code $st $ret
1358 }
1359 } else {
1360 return $ret
1361 }
1362 EOL
1363 =end
1364
1365 at_exit{ INTERP.remove_tk_procs(TclTkLib::FINALIZE_PROC_NAME) }
1366
1367 EventFlag = TclTkLib::EventFlag
1368
1369 def callback_break
1370 fail TkCallbackBreak, "Tk callback returns 'break' status"
1371 end
1372
1373 def callback_continue
1374 fail TkCallbackContinue, "Tk callback returns 'continue' status"
1375 end
1376
1377 def callback_return
1378 fail TkCallbackReturn, "Tk callback returns 'return' status"
1379 end
1380
1381 def TkCore.callback(*arg)
1382 begin
1383 if TkCore::INTERP.tk_cmd_tbl.kind_of?(Hash)
1384 #TkCore::INTERP.tk_cmd_tbl[arg.shift].call(*arg)
1385 normal_ret = false
1386 ret = catch(:IRB_EXIT) do # IRB hack
1387 retval = TkCore::INTERP.tk_cmd_tbl[arg.shift].call(*arg)
1388 normal_ret = true
1389 retval
1390 end
1391 unless normal_ret
1392 # catch IRB_EXIT
1393 exit(ret)
1394 end
1395 ret
1396 end
1397 rescue SystemExit=>e
1398 exit(e.status)
1399 rescue Interrupt=>e
1400 fail(e)
1401 rescue Exception => e
1402 begin
1403 msg = _toUTF8(e.class.inspect) + ': ' +
1404 _toUTF8(e.message) + "\n" +
1405 "\n---< backtrace of Ruby side >-----\n" +
1406 _toUTF8(e.backtrace.join("\n")) +
1407 "\n---< backtrace of Tk side >-------"
1408 if TkCore::WITH_ENCODING
1409 msg.force_encoding('utf-8')
1410 else
1411 msg.instance_variable_set(:@encoding, 'utf-8')
1412 end
1413 rescue Exception
1414 msg = e.class.inspect + ': ' + e.message + "\n" +
1415 "\n---< backtrace of Ruby side >-----\n" +
1416 e.backtrace.join("\n") +
1417 "\n---< backtrace of Tk side >-------"
1418 end
1419 # TkCore::INTERP._set_global_var('errorInfo', msg)
1420 # fail(e)
1421 fail(e, msg)
1422 end
1423 end
1424 =begin
1425 def TkCore.callback(arg_str)
1426 # arg = tk_split_list(arg_str)
1427 arg = tk_split_simplelist(arg_str)
1428 #_get_eval_string(TkUtil.eval_cmd(Tk_CMDTBL[arg.shift], *arg))
1429 #_get_eval_string(TkUtil.eval_cmd(TkCore::INTERP.tk_cmd_tbl[arg.shift],
1430 # *arg))
1431 # TkCore::INTERP.tk_cmd_tbl[arg.shift].call(*arg)
1432 begin
1433 TkCore::INTERP.tk_cmd_tbl[arg.shift].call(*arg)
1434 rescue Exception => e
1435 raise(e, e.class.inspect + ': ' + e.message + "\n" +
1436 "\n---< backtrace of Ruby side >-----\n" +
1437 e.backtrace.join("\n") +
1438 "\n---< backtrace of Tk side >-------")
1439 end
1440 #=begin
1441 # cb_obj = TkCore::INTERP.tk_cmd_tbl[arg.shift]
1442 # unless $DEBUG
1443 # cb_obj.call(*arg)
1444 # else
1445 # begin
1446 # raise 'check backtrace'
1447 # rescue
1448 # # ignore backtrace before 'callback'
1449 # pos = -($!.backtrace.size)
1450 # end
1451 # begin
1452 # cb_obj.call(*arg)
1453 # rescue
1454 # trace = $!.backtrace
1455 # raise $!, "\n#{trace[0]}: #{$!.message} (#{$!.class})\n" +
1456 # "\tfrom #{trace[1..pos].join("\n\tfrom ")}"
1457 # end
1458 # end
1459 #=end
1460 end
1461 =end
1462
1463 def load_cmd_on_ip(tk_cmd)
1464 bool(tk_call('auto_load', tk_cmd))
1465 end
1466
1467 def after(ms, cmd=Proc.new)
1468 cmdid = install_cmd(proc{ret = cmd.call;uninstall_cmd(cmdid); ret})
1469 after_id = tk_call_without_enc("after",ms,cmdid)
1470 after_id.instance_variable_set('@cmdid', cmdid)
1471 after_id
1472 end
1473 =begin
1474 def after(ms, cmd=Proc.new)
1475 crit_bup = Thread.critical
1476 Thread.critical = true
1477
1478 myid = _curr_cmd_id
1479 cmdid = install_cmd(proc{ret = cmd.call;uninstall_cmd(myid); ret})
1480
1481 Thread.critical = crit_bup
1482
1483 tk_call_without_enc("after",ms,cmdid) # return id
1484 # return
1485 # if false #defined? Thread
1486 # Thread.start do
1487 # ms = Float(ms)/1000
1488 # ms = 10 if ms == 0
1489 # sleep ms/1000
1490 # cmd.call
1491 # end
1492 # else
1493 # cmdid = install_cmd(cmd)
1494 # tk_call("after",ms,cmdid)
1495 # end
1496 end
1497 =end
1498
1499 def after_idle(cmd=Proc.new)
1500 cmdid = install_cmd(proc{ret = cmd.call;uninstall_cmd(cmdid); ret})
1501 after_id = tk_call_without_enc('after','idle',cmdid)
1502 after_id.instance_variable_set('@cmdid', cmdid)
1503 after_id
1504 end
1505 =begin
1506 def after_idle(cmd=Proc.new)
1507 crit_bup = Thread.critical
1508 Thread.critical = true
1509
1510 myid = _curr_cmd_id
1511 cmdid = install_cmd(proc{ret = cmd.call;uninstall_cmd(myid); ret})
1512
1513 Thread.critical = crit_bup
1514
1515 tk_call_without_enc('after','idle',cmdid)
1516 end
1517 =end
1518
1519 def after_cancel(afterId)
1520 tk_call_without_enc('after','cancel',afterId)
1521 if (cmdid = afterId.instance_variable_get('@cmdid'))
1522 afterId.instance_variable_set('@cmdid', nil)
1523 uninstall_cmd(cmdid)
1524 end
1525 afterId
1526 end
1527
1528 def windowingsystem
1529 tk_call_without_enc('tk', 'windowingsystem')
1530 end
1531
1532 def scaling(scale=nil)
1533 if scale
1534 tk_call_without_enc('tk', 'scaling', scale)
1535 else
1536 Float(number(tk_call_without_enc('tk', 'scaling')))
1537 end
1538 end
1539 def scaling_displayof(win, scale=nil)
1540 if scale
1541 tk_call_without_enc('tk', 'scaling', '-displayof', win, scale)
1542 else
1543 Float(number(tk_call_without_enc('tk', '-displayof', win, 'scaling')))
1544 end
1545 end
1546
1547 def inactive
1548 Integer(tk_call_without_enc('tk', 'inactive'))
1549 end
1550 def inactive_displayof(win)
1551 Integer(tk_call_without_enc('tk', 'inactive', '-displayof', win))
1552 end
1553 def reset_inactive
1554 tk_call_without_enc('tk', 'inactive', 'reset')
1555 end
1556 def reset_inactive_displayof(win)
1557 tk_call_without_enc('tk', 'inactive', '-displayof', win, 'reset')
1558 end
1559
1560 def appname(name=None)
1561 tk_call('tk', 'appname', name)
1562 end
1563
1564 def appsend_deny
1565 tk_call('rename', 'send', '')
1566 end
1567
1568 def appsend(interp, async, *args)
1569 if $SAFE >= 4
1570 fail SecurityError, "cannot send Tk commands at level 4"
1571 elsif $SAFE >= 1 && args.find{|obj| obj.tainted?}
1572 fail SecurityError, "cannot send tainted Tk commands at level #{$SAFE}"
1573 end
1574 if async != true && async != false && async != nil
1575 args.unshift(async)
1576 async = false
1577 end
1578 if async
1579 tk_call('send', '-async', '--', interp, *args)
1580 else
1581 tk_call('send', '--', interp, *args)
1582 end
1583 end
1584
1585 def rb_appsend(interp, async, *args)
1586 if $SAFE >= 4
1587 fail SecurityError, "cannot send Ruby commands at level 4"
1588 elsif $SAFE >= 1 && args.find{|obj| obj.tainted?}
1589 fail SecurityError, "cannot send tainted Ruby commands at level #{$SAFE}"
1590 end
1591 if async != true && async != false && async != nil
1592 args.unshift(async)
1593 async = false
1594 end
1595 #args = args.collect!{|c| _get_eval_string(c).gsub(/[\[\]$"]/, '\\\\\&')}
1596 args = args.collect!{|c| _get_eval_string(c).gsub(/[\[\]$"\\]/, '\\\\\&')}
1597 # args.push(').to_s"')
1598 # appsend(interp, async, 'ruby "(', *args)
1599 args.push('}.call)"')
1600 appsend(interp, async, 'ruby "TkComm._get_eval_string(proc{', *args)
1601 end
1602
1603 def appsend_displayof(interp, win, async, *args)
1604 if $SAFE >= 4
1605 fail SecurityError, "cannot send Tk commands at level 4"
1606 elsif $SAFE >= 1 && args.find{|obj| obj.tainted?}
1607 fail SecurityError, "cannot send tainted Tk commands at level #{$SAFE}"
1608 end
1609 win = '.' if win == nil
1610 if async != true && async != false && async != nil
1611 args.unshift(async)
1612 async = false
1613 end
1614 if async
1615 tk_call('send', '-async', '-displayof', win, '--', interp, *args)
1616 else
1617 tk_call('send', '-displayor', win, '--', interp, *args)
1618 end
1619 end
1620
1621 def rb_appsend_displayof(interp, win, async, *args)
1622 if $SAFE >= 4
1623 fail SecurityError, "cannot send Ruby commands at level 4"
1624 elsif $SAFE >= 1 && args.find{|obj| obj.tainted?}
1625 fail SecurityError, "cannot send tainted Ruby commands at level #{$SAFE}"
1626 end
1627 win = '.' if win == nil
1628 if async != true && async != false && async != nil
1629 args.unshift(async)
1630 async = false
1631 end
1632 #args = args.collect!{|c| _get_eval_string(c).gsub(/[\[\]$"]/, '\\\\\&')}
1633 args = args.collect!{|c| _get_eval_string(c).gsub(/[\[\]$"\\]/, '\\\\\&')}
1634 # args.push(').to_s"')
1635 # appsend_displayof(interp, win, async, 'ruby "(', *args)
1636 args.push('}.call)"')
1637 appsend(interp, win, async, 'ruby "TkComm._get_eval_string(proc{', *args)
1638 end
1639
1640 def info(*args)
1641 tk_call('info', *args)
1642 end
1643
1644 def mainloop(check_root = true)
1645 if !TkCore::WITH_RUBY_VM || TkCore::RUN_EVENTLOOP_ON_MAIN_THREAD
1646 TclTkLib.mainloop(check_root)
1647 else ### Ruby 1.9 !!!!!
1648 begin
1649 TclTkLib.set_eventloop_window_mode(true)
1650 if check_root
1651 INTERP_MUTEX.synchronize{
1652 INTERP_ROOT_CHECK.wait(INTERP_MUTEX)
1653 status = INTERP_THREAD[:status]
1654 if status
1655 INTERP_THREAD[:status] = nil
1656 raise status if status.kind_of?(Exception)
1657 end
1658 }
1659 else
1660 INTERP_THREAD.value
1661 end
1662 ensure
1663 TclTkLib.set_eventloop_window_mode(false)
1664 end
1665 end
1666 end
1667
1668 def mainloop_thread?
1669 # true : current thread is mainloop
1670 # nil : there is no mainloop
1671 # false : mainloop is running on the other thread
1672 # ( At then, it is dangerous to call Tk interpreter directly. )
1673 if !TkCore::WITH_RUBY_VM || TkCore::RUN_EVENTLOOP_ON_MAIN_THREAD
1674 ### Ruby 1.9 !!!!!!!!!!!
1675 TclTkLib.mainloop_thread?
1676 else
1677 Thread.current == INTERP_THREAD
1678 end
1679 end
1680
1681 def mainloop_exist?
1682 TclTkLib.mainloop_thread? != nil
1683 end
1684
1685 def is_mainloop?
1686 TclTkLib.mainloop_thread? == true
1687 end
1688
1689 def mainloop_watchdog(check_root = true)
1690 # watchdog restarts mainloop when mainloop is dead
1691 TclTkLib.mainloop_watchdog(check_root)
1692 end
1693
1694 def do_one_event(flag = TclTkLib::EventFlag::ALL)
1695 TclTkLib.do_one_event(flag)
1696 end
1697
1698 def set_eventloop_tick(timer_tick)
1699 TclTkLib.set_eventloop_tick(timer_tick)
1700 end
1701
1702 def get_eventloop_tick()
1703 TclTkLib.get_eventloop_tick
1704 end
1705
1706 def set_no_event_wait(wait)
1707 TclTkLib.set_no_even_wait(wait)
1708 end
1709
1710 def get_no_event_wait()
1711 TclTkLib.get_no_eventloop_wait
1712 end
1713
1714 def set_eventloop_weight(loop_max, no_event_tick)
1715 TclTkLib.set_eventloop_weight(loop_max, no_event_tick)
1716 end
1717
1718 def get_eventloop_weight()
1719 TclTkLib.get_eventloop_weight
1720 end
1721
1722 def restart(app_name = nil, keys = {})
1723 TkCore::INTERP.init_ip_internal
1724
1725 tk_call('set', 'argv0', app_name) if app_name
1726 if keys.kind_of?(Hash)
1727 # tk_call('set', 'argc', keys.size * 2)
1728 tk_call('set', 'argv', hash_kv(keys).join(' '))
1729 end
1730
1731 INTERP.restart
1732 nil
1733 end
1734
1735 def event_generate(win, context, keys=nil)
1736 #win = win.path if win.kind_of?(TkObject)
1737 if context.kind_of?(TkEvent::Event)
1738 context.generate(win, ((keys)? keys: {}))
1739 elsif keys
1740 tk_call_without_enc('event', 'generate', win,
1741 "<#{tk_event_sequence(context)}>",
1742 *hash_kv(keys, true))
1743 else
1744 tk_call_without_enc('event', 'generate', win,
1745 "<#{tk_event_sequence(context)}>")
1746 end
1747 nil
1748 end
1749
1750 def messageBox(keys)
1751 tk_call('tk_messageBox', *hash_kv(keys))
1752 end
1753
1754 def getOpenFile(keys = nil)
1755 tk_call('tk_getOpenFile', *hash_kv(keys))
1756 end
1757 def getMultipleOpenFile(keys = nil)
1758 simplelist(tk_call('tk_getOpenFile', '-multiple', '1', *hash_kv(keys)))
1759 end
1760
1761 def getSaveFile(keys = nil)
1762 tk_call('tk_getSaveFile', *hash_kv(keys))
1763 end
1764 def getMultipleSaveFile(keys = nil)
1765 simplelist(tk_call('tk_getSaveFile', '-multiple', '1', *hash_kv(keys)))
1766 end
1767
1768 def chooseColor(keys = nil)
1769 tk_call('tk_chooseColor', *hash_kv(keys))
1770 end
1771
1772 def chooseDirectory(keys = nil)
1773 tk_call('tk_chooseDirectory', *hash_kv(keys))
1774 end
1775
1776 def _ip_eval_core(enc_mode, cmd_string)
1777 case enc_mode
1778 when nil
1779 res = INTERP._eval(cmd_string)
1780 when false
1781 res = INTERP._eval_without_enc(cmd_string)
1782 when true
1783 res = INTERP._eval_with_enc(cmd_string)
1784 end
1785 if INTERP._return_value() != 0
1786 fail RuntimeError, res, error_at
1787 end
1788 return res
1789 end
1790 private :_ip_eval_core
1791
1792 def ip_eval(cmd_string)
1793 _ip_eval_core(nil, cmd_string)
1794 end
1795
1796 def ip_eval_without_enc(cmd_string)
1797 _ip_eval_core(false, cmd_string)
1798 end
1799
1800 def ip_eval_with_enc(cmd_string)
1801 _ip_eval_core(true, cmd_string)
1802 end
1803
1804 def _ip_invoke_core(enc_mode, *args)
1805 case enc_mode
1806 when false
1807 res = INTERP._invoke_without_enc(*args)
1808 when nil
1809 res = INTERP._invoke(*args)
1810 when true
1811 res = INTERP._invoke_with_enc(*args)
1812 end
1813 if INTERP._return_value() != 0
1814 fail RuntimeError, res, error_at
1815 end
1816 return res
1817 end
1818 private :_ip_invoke_core
1819
1820 def ip_invoke(*args)
1821 _ip_invoke_core(nil, *args)
1822 end
1823
1824 def ip_invoke_without_enc(*args)
1825 _ip_invoke_core(false, *args)
1826 end
1827
1828 def ip_invoke_with_enc(*args)
1829 _ip_invoke_core(true, *args)
1830 end
1831
1832 def _tk_call_core(enc_mode, *args)
1833 ### puts args.inspect if $DEBUG
1834 #args.collect! {|x|ruby2tcl(x, enc_mode)}
1835 #args.compact!
1836 #args.flatten!
1837 args = _conv_args([], enc_mode, *args)
1838 puts 'invoke args => ' + args.inspect if $DEBUG
1839 ### print "=> ", args.join(" ").inspect, "\n" if $DEBUG
1840 begin
1841 # res = INTERP._invoke(*args).taint
1842 # res = INTERP._invoke(enc_mode, *args)
1843 res = _ip_invoke_core(enc_mode, *args)
1844 # >>>>> _invoke returns a TAINTED string <<<<<
1845 rescue NameError => err
1846 # err = $!
1847 begin
1848 args.unshift "unknown"
1849 #res = INTERP._invoke(*args).taint
1850 #res = INTERP._invoke(enc_mode, *args)
1851 res = _ip_invoke_core(enc_mode, *args)
1852 # >>>>> _invoke returns a TAINTED string <<<<<
1853 rescue StandardError => err2
1854 fail err2 unless /^invalid command/ =~ err2.message
1855 fail err
1856 end
1857 end
1858 if INTERP._return_value() != 0
1859 fail RuntimeError, res, error_at
1860 end
1861 ### print "==> ", res.inspect, "\n" if $DEBUG
1862 return res
1863 end
1864 private :_tk_call_core
1865
1866 def tk_call(*args)
1867 _tk_call_core(nil, *args)
1868 end
1869
1870 def tk_call_without_enc(*args)
1871 _tk_call_core(false, *args)
1872 end
1873
1874 def tk_call_with_enc(*args)
1875 _tk_call_core(true, *args)
1876 end
1877
1878 def _tk_call_to_list_core(depth, arg_enc, val_enc, *args)
1879 args = _conv_args([], arg_enc, *args)
1880 val = _tk_call_core(false, *args)
1881 if !depth.kind_of?(Integer) || depth == 0
1882 tk_split_simplelist(val, false, val_enc)
1883 else
1884 tk_split_list(val, depth, false, val_enc)
1885 end
1886 end
1887 #private :_tk_call_to_list_core
1888
1889 def tk_call_to_list(*args)
1890 _tk_call_to_list_core(-1, nil, true, *args)
1891 end
1892
1893 def tk_call_to_list_without_enc(*args)
1894 _tk_call_to_list_core(-1, false, false, *args)
1895 end
1896
1897 def tk_call_to_list_with_enc(*args)
1898 _tk_call_to_list_core(-1, true, true, *args)
1899 end
1900
1901 def tk_call_to_simplelist(*args)
1902 _tk_call_to_list_core(0, nil, true, *args)
1903 end
1904
1905 def tk_call_to_simplelist_without_enc(*args)
1906 _tk_call_to_list_core(0, false, false, *args)
1907 end
1908
1909 def tk_call_to_simplelist_with_enc(*args)
1910 _tk_call_to_list_core(0, true, true, *args)
1911 end
1912 end
1913
1914
1915 module Tk
1916 include TkCore
1917 extend Tk
1918
1919 TCL_VERSION = INTERP._invoke_without_enc("info", "tclversion").freeze
1920 TCL_PATCHLEVEL = INTERP._invoke_without_enc("info", "patchlevel").freeze
1921
1922 major, minor = TCL_VERSION.split('.')
1923 TCL_MAJOR_VERSION = major.to_i
1924 TCL_MINOR_VERSION = minor.to_i
1925
1926 TK_VERSION = INTERP._invoke_without_enc("set", "tk_version").freeze
1927 TK_PATCHLEVEL = INTERP._invoke_without_enc("set", "tk_patchLevel").freeze
1928
1929 major, minor = TK_VERSION.split('.')
1930 TK_MAJOR_VERSION = major.to_i
1931 TK_MINOR_VERSION = minor.to_i
1932
1933 JAPANIZED_TK = (INTERP._invoke_without_enc("info", "commands",
1934 "kanji") != "").freeze
1935
1936 def Tk.const_missing(sym)
1937 case(sym)
1938 when :TCL_LIBRARY
1939 INTERP._invoke_without_enc('global', 'tcl_library')
1940 INTERP._invoke("set", "tcl_library").freeze
1941
1942 when :TK_LIBRARY
1943 INTERP._invoke_without_enc('global', 'tk_library')
1944 INTERP._invoke("set", "tk_library").freeze
1945
1946 when :LIBRARY
1947 INTERP._invoke("info", "library").freeze
1948
1949 #when :PKG_PATH, :PACKAGE_PATH, :TCL_PACKAGE_PATH
1950 # INTERP._invoke_without_enc('global', 'tcl_pkgPath')
1951 # tk_split_simplelist(INTERP._invoke('set', 'tcl_pkgPath'))
1952
1953 #when :LIB_PATH, :LIBRARY_PATH, :TCL_LIBRARY_PATH
1954 # INTERP._invoke_without_enc('global', 'tcl_libPath')
1955 # tk_split_simplelist(INTERP._invoke('set', 'tcl_libPath'))
1956
1957 when :PLATFORM, :TCL_PLATFORM
1958 if $SAFE >= 4
1959 fail SecurityError, "can't get #{sym} when $SAFE >= 4"
1960 end
1961 INTERP._invoke_without_enc('global', 'tcl_platform')
1962 Hash[*tk_split_simplelist(INTERP._invoke_without_enc('array', 'get',
1963 'tcl_platform'))]
1964
1965 when :ENV
1966 INTERP._invoke_without_enc('global', 'env')
1967 Hash[*tk_split_simplelist(INTERP._invoke('array', 'get', 'env'))]
1968
1969 #when :AUTO_PATH #<===
1970 # tk_split_simplelist(INTERP._invoke('set', 'auto_path'))
1971
1972 #when :AUTO_OLDPATH
1973 # tk_split_simplelist(INTERP._invoke('set', 'auto_oldpath'))
1974
1975 when :AUTO_INDEX
1976 INTERP._invoke_without_enc('global', 'auto_index')
1977 Hash[*tk_split_simplelist(INTERP._invoke('array', 'get', 'auto_index'))]
1978
1979 when :PRIV, :PRIVATE, :TK_PRIV
1980 priv = {}
1981 if INTERP._invoke_without_enc('info', 'vars', 'tk::Priv') != ""
1982 var_nam = 'tk::Priv'
1983 else
1984 var_nam = 'tkPriv'
1985 end
1986 INTERP._invoke_without_enc('global', var_nam)
1987 Hash[*tk_split_simplelist(INTERP._invoke('array', 'get',
1988 var_nam))].each{|k,v|
1989 k.freeze
1990 case v
1991 when /^-?\d+$/
1992 priv[k] = v.to_i
1993 when /^-?\d+\.?\d*(e[-+]?\d+)?$/
1994 priv[k] = v.to_f
1995 else
1996 priv[k] = v.freeze
1997 end
1998 }
1999 priv
2000
2001 else
2002 raise NameError, 'uninitialized constant Tk::' + sym.id2name
2003 end
2004 end
2005
2006 def Tk.errorInfo
2007 INTERP._invoke_without_enc('global', 'errorInfo')
2008 INTERP._invoke_without_enc('set', 'errorInfo')
2009 end
2010
2011 def Tk.errorCode
2012 INTERP._invoke_without_enc('global', 'errorCode')
2013 code = tk_split_simplelist(INTERP._invoke_without_enc('set', 'errorCode'))
2014 case code[0]
2015 when 'CHILDKILLED', 'CHILDSTATUS', 'CHILDSUSP'
2016 begin
2017 pid = Integer(code[1])
2018 code[1] = pid
2019 rescue
2020 end
2021 end
2022 code
2023 end
2024
2025 def Tk.has_mainwindow?
2026 INTERP.has_mainwindow?
2027 end
2028
2029 def root
2030 Tk::Root.new
2031 end
2032
2033 def Tk.load_tclscript(file, enc=nil)
2034 if enc
2035 # TCL_VERSION >= 8.5
2036 tk_call('source', '-encoding', enc, file)
2037 else
2038 tk_call('source', file)
2039 end
2040 end
2041
2042 def Tk.load_tcllibrary(file, pkg_name=None, interp=None)
2043 tk_call('load', file, pkg_name, interp)
2044 end
2045
2046 def Tk.unload_tcllibrary(*args)
2047 if args[-1].kind_of?(Hash)
2048 keys = _symbolkey2str(args.pop)
2049 nocomp = (keys['nocomplain'])? '-nocomplain': None
2050 keeplib = (keys['keeplibrary'])? '-keeplibrary': None
2051 tk_call('unload', nocomp, keeplib, '--', *args)
2052 else
2053 tk_call('unload', *args)
2054 end
2055 end
2056
2057 def Tk.pkgconfig_list(mod)
2058 # Tk8.5 feature
2059 if mod.kind_of?(Module)
2060 if mod.respond_to?(:package_name)
2061 pkgname = mod.package_name
2062 elsif mod.const_defined?(:PACKAGE_NAME)
2063 pkgname = mod::PACKAGE_NAME
2064 else
2065 fail NotImplementedError, 'may not be a module for a Tcl extension'
2066 end
2067 else
2068 pkgname = mod.to_s
2069 end
2070
2071 pkgname = '::' << pkgname unless pkgname =~ /^::/
2072
2073 tk_split_list(tk_call(pkgname + '::pkgconfig', 'list'))
2074 end
2075
2076 def Tk.pkgconfig_get(mod, key)
2077 # Tk8.5 feature
2078 if mod.kind_of?(Module)
2079 if mod.respond_to?(:package_name)
2080 pkgname = mod.package_name
2081 else
2082 fail NotImplementedError, 'may not be a module for a Tcl extension'
2083 end
2084 else
2085 pkgname = mod.to_s
2086 end
2087
2088 pkgname = '::' << pkgname unless pkgname =~ /^::/
2089
2090 tk_call(pkgname + '::pkgconfig', 'get', key)
2091 end
2092
2093 def Tk.tcl_pkgconfig_list
2094 # Tk8.5 feature
2095 Tk.pkgconfig_list('::tcl')
2096 end
2097
2098 def Tk.tcl_pkgconfig_get(key)
2099 # Tk8.5 feature
2100 Tk.pkgconfig_get('::tcl', key)
2101 end
2102
2103 def Tk.tk_pkgconfig_list
2104 # Tk8.5 feature
2105 Tk.pkgconfig_list('::tk')
2106 end
2107
2108 def Tk.tk_pkgconfig_get(key)
2109 # Tk8.5 feature
2110 Tk.pkgconfig_get('::tk', key)
2111 end
2112
2113 def Tk.bell(nice = false)
2114 if nice
2115 tk_call_without_enc('bell', '-nice')
2116 else
2117 tk_call_without_enc('bell')
2118 end
2119 nil
2120 end
2121
2122 def Tk.bell_on_display(win, nice = false)
2123 if nice
2124 tk_call_without_enc('bell', '-displayof', win, '-nice')
2125 else
2126 tk_call_without_enc('bell', '-displayof', win)
2127 end
2128 nil
2129 end
2130
2131 def Tk.destroy(*wins)
2132 #tk_call_without_enc('destroy', *wins)
2133 tk_call_without_enc('destroy', *(wins.collect{|win|
2134 if win.kind_of?(TkWindow)
2135 win.epath
2136 else
2137 win
2138 end
2139 }))
2140 end
2141
2142 def Tk.exit
2143 tk_call_without_enc('destroy', '.')
2144 end
2145
2146 ################################################
2147
2148 def Tk.sleep(ms = nil, id = nil)
2149 if id
2150 var = (id.kind_of?(TkVariable))? id: TkVarAccess.new(id.to_s)
2151 else
2152 var = TkVariable.new
2153 end
2154
2155 var.value = tk_call_without_enc('after', ms, proc{ var.value = 0 }) if ms
2156 var.thread_wait
2157 ms
2158 end
2159
2160 def Tk.wakeup(id)
2161 ((id.kind_of?(TkVariable))? id: TkVarAccess.new(id.to_s)).value = 0
2162 nil
2163 end
2164
2165 ################################################
2166
2167 def Tk.pack(*args)
2168 TkPack.configure(*args)
2169 end
2170 def Tk.pack_forget(*args)
2171 TkPack.forget(*args)
2172 end
2173 def Tk.unpack(*args)
2174 TkPack.forget(*args)
2175 end
2176
2177 def Tk.grid(*args)
2178 TkGrid.configure(*args)
2179 end
2180 def Tk.grid_forget(*args)
2181 TkGrid.forget(*args)
2182 end
2183 def Tk.ungrid(*args)
2184 TkGrid.forget(*args)
2185 end
2186
2187 def Tk.place(*args)
2188 TkPlace.configure(*args)
2189 end
2190 def Tk.place_forget(*args)
2191 TkPlace.forget(*args)
2192 end
2193 def Tk.unplace(*args)
2194 TkPlace.forget(*args)
2195 end
2196
2197 def Tk.update(idle=nil)
2198 if idle
2199 tk_call_without_enc('update', 'idletasks')
2200 else
2201 tk_call_without_enc('update')
2202 end
2203 end
2204 def Tk.update_idletasks
2205 update(true)
2206 end
2207 def update(idle=nil)
2208 # only for backward compatibility (This never be recommended to use)
2209 Tk.update(idle)
2210 self
2211 end
2212
2213 # NOTE::
2214 # If no eventloop-thread is running, "thread_update" method is same
2215 # to "update" method. Else, "thread_update" method waits to complete
2216 # idletask operation on the eventloop-thread.
2217 def Tk.thread_update(idle=nil)
2218 if idle
2219 tk_call_without_enc('thread_update', 'idletasks')
2220 else
2221 tk_call_without_enc('thread_update')
2222 end
2223 end
2224 def Tk.thread_update_idletasks
2225 thread_update(true)
2226 end
2227
2228 def Tk.lower_window(win, below=None)
2229 tk_call('lower', _epath(win), _epath(below))
2230 nil
2231 end
2232 def Tk.raise_window(win, above=None)
2233 tk_call('raise', _epath(win), _epath(above))
2234 nil
2235 end
2236
2237 def Tk.current_grabs(win = nil)
2238 if win
2239 window(tk_call_without_enc('grab', 'current', win))
2240 else
2241 tk_split_list(tk_call_without_enc('grab', 'current'))
2242 end
2243 end
2244
2245 def Tk.focus(display=nil)
2246 if display == nil
2247 window(tk_call_without_enc('focus'))
2248 else
2249 window(tk_call_without_enc('focus', '-displayof', display))
2250 end
2251 end
2252
2253 def Tk.focus_to(win, force=false)
2254 if force
2255 tk_call_without_enc('focus', '-force', win)
2256 else
2257 tk_call_without_enc('focus', win)
2258 end
2259 end
2260
2261 def Tk.focus_lastfor(win)
2262 window(tk_call_without_enc('focus', '-lastfor', win))
2263 end
2264
2265 def Tk.focus_next(win)
2266 TkManageFocus.next(win)
2267 end
2268
2269 def Tk.focus_prev(win)
2270 TkManageFocus.prev(win)
2271 end
2272
2273 def Tk.strictMotif(mode=None)
2274 bool(tk_call_without_enc('set', 'tk_strictMotif', mode))
2275 end
2276
2277 def Tk.show_kinsoku(mode='both')
2278 begin
2279 if /^8\.*/ === TK_VERSION && JAPANIZED_TK
2280 tk_split_simplelist(tk_call('kinsoku', 'show', mode))
2281 end
2282 rescue
2283 end
2284 end
2285 def Tk.add_kinsoku(chars, mode='both')
2286 begin
2287 if /^8\.*/ === TK_VERSION && JAPANIZED_TK
2288 tk_split_simplelist(tk_call('kinsoku', 'add', mode,
2289 *(chars.split(''))))
2290 else
2291 []
2292 end
2293 rescue
2294 []
2295 end
2296 end
2297 def Tk.delete_kinsoku(chars, mode='both')
2298 begin
2299 if /^8\.*/ === TK_VERSION && JAPANIZED_TK
2300 tk_split_simplelist(tk_call('kinsoku', 'delete', mode,
2301 *(chars.split(''))))
2302 end
2303 rescue
2304 end
2305 end
2306
2307 def Tk.toUTF8(str, encoding = nil)
2308 _toUTF8(str, encoding)
2309 end
2310
2311 def Tk.fromUTF8(str, encoding = nil)
2312 _fromUTF8(str, encoding)
2313 end
2314 end
2315
2316 ###########################################
2317 # string with Tcl's encoding
2318 ###########################################
2319 module Tk
2320 def Tk.subst_utf_backslash(str)
2321 Tk::EncodedString.subst_utf_backslash(str)
2322 end
2323 def Tk.subst_tk_backslash(str)
2324 Tk::EncodedString.subst_tk_backslash(str)
2325 end
2326 def Tk.utf_to_backslash_sequence(str)
2327 Tk::EncodedString.utf_to_backslash_sequence(str)
2328 end
2329 def Tk.utf_to_backslash(str)
2330 Tk::EncodedString.utf_to_backslash_sequence(str)
2331 end
2332 def Tk.to_backslash_sequence(str)
2333 Tk::EncodedString.to_backslash_sequence(str)
2334 end
2335 end
2336
2337
2338 ###########################################
2339 # convert kanji string to/from utf-8
2340 ###########################################
2341 if (/^(8\.[1-9]|9\.|[1-9][0-9])/ =~ Tk::TCL_VERSION && !Tk::JAPANIZED_TK)
2342 module Tk
2343 module Encoding
2344 extend Encoding
2345
2346 TkCommandNames = ['encoding'.freeze].freeze
2347
2348 #############################################
2349
2350 if TkCore::WITH_ENCODING ### Ruby 1.9
2351 RubyEncoding = ::Encoding
2352
2353 # for saving GC cost
2354 #ENCNAMES_CMD = ['encoding'.freeze, 'names'.freeze]
2355 BINARY_NAME = 'binary'.freeze
2356 UTF8_NAME = 'utf-8'.freeze
2357 DEFAULT_EXTERNAL_NAME = RubyEncoding.default_external.name.freeze
2358
2359 BINARY = RubyEncoding.find(BINARY_NAME)
2360 UNKNOWN = RubyEncoding.find('ASCII-8BIT')
2361
2362 ### start of creating ENCODING_TABLE
2363 ENCODING_TABLE = TkCore::INTERP.encoding_table
2364 =begin
2365 ENCODING_TABLE = {
2366 'binary' => BINARY,
2367 # 'UNKNOWN-8BIT' => UNKNOWN,
2368 }
2369
2370 list = TkCore::INTERP._invoke_without_enc(ENCNAMES_CMD[0],
2371 ENCNAMES_CMD[1])
2372 TkCore::INTERP._split_tklist(list).each{|name|
2373 begin
2374 enc = RubyEncoding.find(name)
2375 rescue ArgumentError
2376 case name
2377 when 'identity'
2378 enc = BINARY
2379 when 'shiftjis'
2380 enc = RubyEncoding.find('Shift_JIS')
2381 when 'unicode'
2382 enc = RubyEncoding.find('UTF-8')
2383 #if Tk.tk_call('set', 'tcl_platform(byteOrder)') =='littleEndian'
2384 # enc = RubyEncoding.find('UTF-16LE')
2385 #else
2386 # enc = RubyEncoding.find('UTF-16BE')
2387 #end
2388 when 'symbol'
2389 # single byte data
2390 enc = RubyEncoding.find('ASCII-8BIT') ### ???
2391 else
2392 # unsupported on Ruby, but supported on Tk
2393 enc = TkCore::INTERP.create_dummy_encoding_for_tk(name)
2394 end
2395 end
2396 ENCODING_TABLE[name.freeze] = enc
2397 }
2398 =end
2399 =begin
2400 def ENCODING_TABLE.get_name(enc)
2401 orig_enc = enc
2402
2403 # unles enc, use system default
2404 # 1st: Ruby/Tk default encoding
2405 # 2nd: Tcl/Tk default encoding
2406 # 3rd: Ruby's default_external
2407 enc ||= TkCore::INTERP.encoding
2408 enc ||= TclTkLib.encoding_system
2409 enc ||= DEFAULT_EXTERNAL_NAME
2410
2411 if enc.kind_of?(RubyEncoding)
2412 # Ruby's Encoding object
2413 if (name = self.key(enc))
2414 return name
2415 end
2416
2417 # Is it new ?
2418 list = TkCore::INTERP._invoke_without_enc(ENCNAMES_CMD[0],
2419 ENCNAMES_CMD[1])
2420 TkComm.simplelist(list).each{|name|
2421 if ((enc == RubyEncoding.find(name)) rescue false)
2422 # new relation!! update table
2423 self[name.freeze] = enc
2424 return name
2425 end
2426 }
2427 else
2428 # String or Symbol ?
2429 if self[name = enc.to_s]
2430 return name
2431 end
2432
2433 # Is it new ?
2434 if (enc_obj = (RubyEncoding.find(name) rescue false))
2435 list = TkCore::INTERP._invoke_without_enc(ENCNAMES_CMD[0],
2436 ENCNAMES_CMD[1])
2437 if TkComm.simplelist(list).index(name)
2438 # Tk's encoding name ?
2439 self[name.freeze] = enc_obj # new relation!! update table
2440 return name
2441 else
2442 # Ruby's encoding name ?
2443 if (name = self.key(enc_obj))
2444 return name
2445 end
2446 end
2447 end
2448 end
2449
2450 fail ArgumentError, "unsupported Tk encoding '#{orig_enc}'"
2451 end
2452
2453 def ENCODING_TABLE.get_obj(enc)
2454 # returns the encoding object.
2455 # If 'enc' is the encoding name on Tk only, it returns nil.
2456 ((obj = self[self.get_name(enc)]).kind_of?(RubyEncoding))? obj: nil
2457 end
2458 =end
2459 ### end of creating ENCODING_TABLE
2460
2461 end
2462
2463 #############################################
2464
2465 if TkCore::WITH_ENCODING
2466 ################################
2467 ### Ruby 1.9
2468 ################################
2469 def force_default_encoding(mode)
2470 TkCore::INTERP.force_default_encoding = mode
2471 end
2472
2473 def force_default_encoding?
2474 TkCore::INTERP.force_default_encoding?
2475 end
2476
2477 def default_encoding=(enc)
2478 TkCore::INTERP.default_encoding = Tk::Encoding::ENCODING_TABLE.get_name(enc)
2479 end
2480
2481 def encoding=(enc)
2482 TkCore::INTERP.encoding = Tk::Encoding::ENCODING_TABLE.get_name(enc)
2483 end
2484
2485 def encoding_name
2486 Tk::Encoding::ENCODING_TABLE.get_name(TkCore::INTERP.encoding)
2487 end
2488 def encoding_obj
2489 Tk::Encoding::ENCODING_TABLE.get_obj(TkCore::INTERP.encoding)
2490 end
2491 alias encoding encoding_name
2492 alias default_encoding encoding_name
2493
2494 def tk_encoding_names
2495 TkComm.simplelist(TkCore::INTERP._invoke_without_enc(Tk::Encoding::ENCNAMES_CMD[0], Tk::Encoding::ENCNAMES_CMD[1]))
2496 end
2497 def encoding_names
2498 self.tk_encoding_names.find_all{|name|
2499 Tk::Encoding::ENCODING_TABLE.get_name(name) rescue false
2500 }
2501 end
2502 def encoding_objs
2503 self.tk_encoding_names.map!{|name|
2504 Tk::Encoding::ENCODING_TABLE.get_obj(name) rescue nil
2505 }.compact
2506 end
2507
2508 def encoding_system=(enc)
2509 TclTkLib.encoding_system = Tk::Encoding::ENCODING_TABLE.get_name(enc)
2510 end
2511
2512 def encoding_system_name
2513 Tk::Encoding::ENCODING_TABLE.get_name(TclTkLib.encoding_system)
2514 end
2515 def encoding_system_obj
2516 Tk::Encoding::ENCODING_TABLE.get_obj(TclTkLib.encoding_system)
2517 end
2518 alias encoding_system encoding_system_name
2519
2520 ################################
2521 else
2522 ################################
2523 ### Ruby 1.8-
2524 ################################
2525 def force_default_encoding=(mode)
2526 true
2527 end
2528
2529 def force_default_encoding?
2530 true
2531 end
2532
2533 def default_encoding=(enc)
2534 TkCore::INTERP.default_encoding = enc
2535 end
2536
2537 def encoding=(enc)
2538 TkCore::INTERP.encoding = enc
2539 end
2540
2541 def encoding_obj
2542 TkCore::INTERP.encoding
2543 end
2544 def encoding_name
2545 TkCore::INTERP.encoding
2546 end
2547 alias encoding encoding_name
2548 alias default_encoding encoding_name
2549
2550 def tk_encoding_names
2551 TkComm.simplelist(Tk.tk_call('encoding', 'names'))
2552 end
2553 def encoding_objs
2554 self.tk_encoding_names
2555 end
2556 def encoding_names
2557 self.tk_encoding_names
2558 end
2559
2560 def encoding_system=(enc)
2561 TclTkLib.encoding_system = enc
2562 end
2563
2564 def encoding_system_name
2565 TclTkLib.encoding_system
2566 end
2567 def encoding_system_obj
2568 TclTkLib.encoding_system
2569 end
2570 alias encoding_system encoding_system_name
2571
2572 ################################
2573 end
2574
2575 def encoding_convertfrom(str, enc=nil)
2576 enc = encoding_system_name unless enc
2577 str = str.dup
2578 if TkCore::WITH_ENCODING
2579 if str.kind_of?(Tk::EncodedString)
2580 str.__instance_variable_set('@encoding', nil)
2581 else
2582 str.instance_variable_set('@encoding', nil)
2583 end
2584 str.force_encoding('binary')
2585 else
2586 str.instance_variable_set('@encoding', 'binary')
2587 end
2588 ret = TkCore::INTERP._invoke_without_enc('encoding', 'convertfrom',
2589 enc, str)
2590 if TkCore::WITH_ENCODING
2591 ret.force_encoding('utf-8')
2592 else
2593 Tk::UTF8_String.new(ret)
2594 end
2595 ret
2596 end
2597 alias encoding_convert_from encoding_convertfrom
2598
2599 def encoding_convertto(str, enc=nil)
2600 # str must be a UTF-8 string
2601 enc = encoding_system_name unless enc
2602 ret = TkCore::INTERP._invoke_without_enc('encoding', 'convertto',
2603 enc, str)
2604 #ret.instance_variable_set('@encoding', 'binary')
2605 if TkCore::WITH_ENCODING
2606 #ret.force_encoding(Tk::Encoding::ENCODING_TABLE.get_obj('binary'))
2607 ret.force_encoding(Tk::Encoding::ENCODING_TABLE.get_obj(enc))
2608 end
2609 ret
2610 end
2611 alias encoding_convert_to encoding_convertto
2612
2613 def encoding_dirs
2614 # Tcl8.5 feature
2615 TkComm.simplelist(Tk.tk_call_without_enc('encoding', 'dirs'))
2616 end
2617
2618 def encoding_dirs=(dir_list) # an array or a Tcl's list string
2619 # Tcl8.5 feature
2620 Tk.tk_call_without_enc('encoding', 'dirs', dir_list)
2621 end
2622 end
2623
2624 extend Encoding
2625 end
2626
2627 class TclTkIp
2628 def force_default_encoding=(mode)
2629 @force_default_encoding = (mode)? true: false
2630 end
2631
2632 def force_default_encoding?
2633 @force_default_encoding ||= false
2634 end
2635
2636 def default_encoding=(name)
2637 name = name.name if name.kind_of?(::Encoding) if Tk::WITH_ENCODING
2638 @encoding = name
2639 end
2640
2641 # from tkencoding.rb by ttate@jaist.ac.jp
2642 #attr_accessor :encoding
2643 def encoding=(name)
2644 self.force_default_encoding = true # for comaptibility
2645 self.default_encoding = name
2646 end
2647
2648 def encoding_name
2649 (@encoding)? @encoding.dup: nil
2650 end
2651 alias encoding encoding_name
2652 alias default_encoding encoding_name
2653
2654 def encoding_obj
2655 if Tk::WITH_ENCODING
2656 Tk::Encoding.tcl2rb_encoding(@encoding)
2657 else
2658 (@encoding)? @encoding.dup: nil
2659 end
2660 end
2661
2662 alias __toUTF8 _toUTF8
2663 alias __fromUTF8 _fromUTF8
2664
2665 if Object.const_defined?(:Encoding) && ::Encoding.class == Class
2666 # with Encoding (Ruby 1.9+)
2667 #
2668 # use functions on Tcl as default.
2669 # but when unsupported encoding on Tcl, use methods on Ruby.
2670 #
2671 def _toUTF8(str, enc = nil)
2672 if enc
2673 # use given encoding
2674 begin
2675 enc_name = Tk::Encoding::ENCODING_TABLE.get_name(enc)
2676 rescue
2677 # unknown encoding for Tk -> try to convert encoding on Ruby
2678 str = str.dup.force_encoding(enc)
2679 str.encode!(Tk::Encoding::UTF8_NAME) # modify self !!
2680 return str # if no error, probably succeed converting
2681 end
2682 end
2683
2684 enc_name ||= str.instance_variable_get(:@encoding)
2685
2686 enc_name ||=
2687 Tk::Encoding::ENCODING_TABLE.get_name(str.encoding) rescue nil
2688
2689 unless enc_name
2690 # str.encoding isn't supported by Tk -> try to convert on Ruby
2691 begin
2692 return str.encode(Tk::Encoding::UTF8_NAME) # new string
2693 rescue
2694 # error -> ignore, try to use default encoding of Ruby/Tk
2695 end
2696 end
2697
2698 #enc_name ||=
2699 # Tk::Encoding::ENCODING_TABLE.get_name(Tk.encoding) rescue nil
2700 enc_name ||= Tk::Encoding::ENCODING_TABLE.get_name(nil)
2701
2702 # is 'binary' encoding?
2703 if enc_name == Tk::Encoding::BINARY_NAME
2704 return str.dup.force_encoding(Tk::Encoding::BINARY_NAME)
2705 end
2706
2707 # force default encoding?
2708 if ! str.kind_of?(Tk::EncodedString) && self.force_default_encoding?
2709 enc_name = Tk::Encoding::ENCODING_TABLE.get_name(Tk.default_encoding)
2710 end
2711
2712 encstr = __toUTF8(str, enc_name)
2713 encstr.force_encoding(Tk::Encoding::UTF8_NAME)
2714 encstr
2715 end
2716 def _fromUTF8(str, enc = nil)
2717 # str must be UTF-8 or binary.
2718 enc_name = str.instance_variable_get(:@encoding)
2719 enc_name ||=
2720 Tk::Encoding::ENCODING_TABLE.get_name(str.encoding) rescue nil
2721
2722 # is 'binary' encoding?
2723 if enc_name == Tk::Encoding::BINARY_NAME
2724 return str.dup.force_encoding(Tk::Encoding::BINARY_NAME)
2725 end
2726
2727 # get target encoding name (if enc == nil, use default encoding)
2728 begin
2729 enc_name = Tk::Encoding::ENCODING_TABLE.get_name(enc)
2730 rescue
2731 # then, enc != nil
2732 # unknown encoding for Tk -> try to convert encoding on Ruby
2733 str = str.dup.force_encoding(Tk::Encoding::UTF8_NAME)
2734 str.encode!(enc) # modify self !!
2735 return str # if no error, probably succeed converting
2736 end
2737
2738 encstr = __fromUTF8(str, enc_name)
2739 encstr.force_encoding(Tk::Encoding::ENCODING_TABLE.get_obj(enc_name))
2740 encstr
2741 end
2742 ###
2743 else
2744 # without Encoding (Ruby 1.8)
2745 def _toUTF8(str, encoding = nil)
2746 __toUTF8(str, encoding)
2747 end
2748 def _fromUTF8(str, encoding = nil)
2749 __fromUTF8(str, encoding)
2750 end
2751 ###
2752 end
2753
2754 alias __eval _eval
2755 alias __invoke _invoke
2756
2757 def _eval(cmd)
2758 _fromUTF8(__eval(_toUTF8(cmd)))
2759 end
2760
2761 def _invoke(*cmds)
2762 _fromUTF8(__invoke(*(cmds.collect{|cmd| _toUTF8(cmd)})))
2763 end
2764
2765 alias _eval_with_enc _eval
2766 alias _invoke_with_enc _invoke
2767
2768 =begin
2769 #### --> definition is moved to TclTkIp module
2770
2771 def _toUTF8(str, encoding = nil)
2772 # decide encoding
2773 if encoding
2774 encoding = encoding.to_s
2775 elsif str.kind_of?(Tk::EncodedString) && str.encoding != nil
2776 encoding = str.encoding.to_s
2777 elsif str.instance_variable_get(:@encoding)
2778 encoding = str.instance_variable_get(:@encoding).to_s
2779 elsif defined?(@encoding) && @encoding != nil
2780 encoding = @encoding.to_s
2781 else
2782 encoding = __invoke('encoding', 'system')
2783 end
2784
2785 # convert
2786 case encoding
2787 when 'utf-8', 'binary'
2788 str
2789 else
2790 __toUTF8(str, encoding)
2791 end
2792 end
2793
2794 def _fromUTF8(str, encoding = nil)
2795 unless encoding
2796 if defined?(@encoding) && @encoding != nil
2797 encoding = @encoding.to_s
2798 else
2799 encoding = __invoke('encoding', 'system')
2800 end
2801 end
2802
2803 if str.kind_of?(Tk::EncodedString)
2804 if str.encoding == 'binary'
2805 str
2806 else
2807 __fromUTF8(str, encoding)
2808 end
2809 elsif str.instance_variable_get(:@encoding).to_s == 'binary'
2810 str
2811 else
2812 __fromUTF8(str, encoding)
2813 end
2814 end
2815 =end
2816
2817 =begin
2818 def _eval(cmd)
2819 if defined?(@encoding) && @encoding != 'utf-8'
2820 ret = if cmd.kind_of?(Tk::EncodedString)
2821 case cmd.encoding
2822 when 'utf-8', 'binary'
2823 __eval(cmd)
2824 else
2825 __eval(_toUTF8(cmd, cmd.encoding))
2826 end
2827 elsif cmd.instance_variable_get(:@encoding) == 'binary'
2828 __eval(cmd)
2829 else
2830 __eval(_toUTF8(cmd, @encoding))
2831 end
2832 if ret.kind_of?(String) && ret.instance_variable_get(:@encoding) == 'binary'
2833 ret
2834 else
2835 _fromUTF8(ret, @encoding)
2836 end
2837 else
2838 __eval(cmd)
2839 end
2840 end
2841
2842 def _invoke(*cmds)
2843 if defined?(@encoding) && @encoding != 'utf-8'
2844 cmds = cmds.collect{|cmd|
2845 if cmd.kind_of?(Tk::EncodedString)
2846 case cmd.encoding
2847 when 'utf-8', 'binary'
2848 cmd
2849 else
2850 _toUTF8(cmd, cmd.encoding)
2851 end
2852 elsif cmd.instance_variable_get(:@encoding) == 'binary'
2853 cmd
2854 else
2855 _toUTF8(cmd, @encoding)
2856 end
2857 }
2858 ret = __invoke(*cmds)
2859 if ret.kind_of?(String) && ret.instance_variable_get(:@encoding) == 'binary'
2860 ret
2861 else
2862 _fromUTF8(ret, @encoding)
2863 end
2864 else
2865 __invoke(*cmds)
2866 end
2867 end
2868 =end
2869 end
2870
2871 module TclTkLib
2872 class << self
2873 def force_default_encoding=(mode)
2874 TkCore::INTERP.force_default_encoding = mode
2875 end
2876
2877 def force_default_encoding?
2878 TkCore::INTERP.force_default_encoding?
2879 end
2880
2881 def default_encoding=(name)
2882 TkCore::INTERP.default_encoding = name
2883 end
2884
2885 alias _encoding encoding
2886 alias _encoding= encoding=
2887 def encoding=(name)
2888 name = name.name if name.kind_of?(::Encoding) if Tk::WITH_ENCODING
2889 TkCore::INTERP.encoding = name
2890 end
2891
2892 def encoding_name
2893 TkCore::INTERP.encoding
2894 end
2895 alias encoding encoding_name
2896 alias default_encoding encoding_name
2897
2898 def encoding_obj
2899 if Tk::WITH_ENCODING
2900 Tk::Encoding.tcl2rb_encoding(TkCore::INTERP.encoding)
2901 else
2902 TkCore::INTERP.encoding
2903 end
2904 end
2905 end
2906 end
2907
2908 # estimate encoding
2909 unless TkCore::WITH_ENCODING
2910 case $KCODE
2911 when /^e/i # EUC
2912 Tk.encoding = 'euc-jp'
2913 Tk.encoding_system = 'euc-jp'
2914 when /^s/i # SJIS
2915 begin
2916 if Tk.encoding_system == 'cp932'
2917 Tk.encoding = 'cp932'
2918 else
2919 Tk.encoding = 'shiftjis'
2920 Tk.encoding_system = 'shiftjis'
2921 end
2922 rescue StandardError, NameError
2923 Tk.encoding = 'shiftjis'
2924 Tk.encoding_system = 'shiftjis'
2925 end
2926 when /^u/i # UTF8
2927 Tk.encoding = 'utf-8'
2928 Tk.encoding_system = 'utf-8'
2929 else # NONE
2930 if defined? DEFAULT_TK_ENCODING
2931 Tk.encoding_system = DEFAULT_TK_ENCODING
2932 end
2933 begin
2934 Tk.encoding = Tk.encoding_system
2935 rescue StandardError, NameError
2936 Tk.encoding = 'utf-8'
2937 Tk.encoding_system = 'utf-8'
2938 end
2939 end
2940
2941 else ### Ruby 1.9 !!!!!!!!!!!!
2942 loc_enc_obj = ::Encoding.find(::Encoding.locale_charmap)
2943 ext_enc_obj = ::Encoding.default_external
2944 tksys_enc_name = Tk::Encoding::ENCODING_TABLE.get_name(Tk.encoding_system)
2945 # p [Tk.encoding, Tk.encoding_system, loc_enc_obj, ext_enc_obj]
2946
2947 =begin
2948 if ext_enc_obj == Tk::Encoding::UNKNOWN
2949 if defind? DEFAULT_TK_ENCODING
2950 if DEFAULT_TK_ENCODING.kind_of?(::Encoding)
2951 tk_enc_name = DEFAULT_TK_ENCODING.name
2952 tksys_enc_name = DEFAULT_TK_ENCODING.name
2953 else
2954 tk_enc_name = DEFAULT_TK_ENCODING
2955 tksys_enc_name = DEFAULT_TK_ENCODING
2956 end
2957 else
2958 tk_enc_name = loc_enc_obj.name
2959 tksys_enc_name = loc_enc_obj.name
2960 end
2961 else
2962 tk_enc_name = ext_enc_obj.name
2963 tksys_enc_name = ext_enc_obj.name
2964 end
2965
2966 # Tk.encoding = tk_enc_name
2967 Tk.default_encoding = tk_enc_name
2968 Tk.encoding_system = tksys_enc_name
2969 =end
2970
2971 if ext_enc_obj == Tk::Encoding::UNKNOWN
2972 if loc_enc_obj == Tk::Encoding::UNKNOWN
2973 # use Tk.encoding_system
2974 else
2975 # use locale_charmap
2976 begin
2977 loc_enc_name = Tk::Encoding::ENCODING_TABLE.get_name(loc_enc_obj)
2978 if loc_enc_name && loc_enc_name != tksys_enc_name
2979 # use locale_charmap
2980 Tk.encoding_system = loc_enc_name
2981 else
2982 # use Tk.encoding_system
2983 end
2984 rescue ArgumentError
2985 # unsupported encoding on Tk -> use Tk.encoding_system
2986 end
2987 end
2988 else
2989 begin
2990 ext_enc_name = Tk::Encoding::ENCODING_TABLE.get_name(ext_enc_obj)
2991 if ext_enc_name && ext_enc_name != tksys_enc_name
2992 # use default_external
2993 Tk.encoding_system = ext_enc_name
2994 else
2995 # use Tk.encoding_system
2996 end
2997 rescue ArgumentError
2998 # unsupported encoding on Tk -> use Tk.encoding_system
2999 end
3000 end
3001
3002 # setup Tk.encoding
3003 enc_name = nil
3004
3005 begin
3006 default_def = DEFAULT_TK_ENCODING
3007 if ::Encoding.find(default_def.to_s) != Tk::Encoding::UNKNOWN
3008 enc_name = Tk::Encoding::ENCODING_TABLE.get_name(default_def)
3009 end
3010 rescue NameError
3011 # ignore
3012 enc_name = nil
3013 rescue ArgumentError
3014 enc_name = nil
3015 fail ArgumentError,
3016 "DEFAULT_TK_ENCODING has an unknown encoding #{default_def}"
3017 end
3018
3019 unless enc_name
3020 if ext_enc_obj == Tk::Encoding::UNKNOWN
3021 if loc_enc_obj == Tk::Encoding::UNKNOWN
3022 # use Tk.encoding_system
3023 enc_name = tksys_enc_name
3024 else
3025 # use locale_charmap
3026 begin
3027 loc_enc_name = Tk::Encoding::ENCODING_TABLE.get_name(loc_enc_obj)
3028 if loc_enc_name && loc_enc_name != tksys_enc_name
3029 # use locale_charmap
3030 enc_name = loc_enc_name
3031 else
3032 # use Tk.encoding_system
3033 enc_name = tksys_enc_name
3034 end
3035 rescue ArgumentError
3036 # unsupported encoding on Tk -> use Tk.encoding_system
3037 enc_name = tksys_enc_name
3038 end
3039 end
3040 else
3041 begin
3042 ext_enc_name = Tk::Encoding::ENCODING_TABLE.get_name(ext_enc_obj)
3043 if ext_enc_name && ext_enc_name != tksys_enc_name
3044 # use default_external
3045 enc_name = ext_enc_name
3046 else
3047 # use Tk.encoding_system
3048 enc_name = tksys_enc_name
3049 end
3050 rescue ArgumentError
3051 # unsupported encoding on Tk -> use Tk.encoding_system
3052 enc_name = tksys_enc_name
3053 end
3054 end
3055 end
3056
3057 Tk.default_encoding = (enc_name)? enc_name: tksys_enc_name
3058 end
3059
3060 else
3061 # dummy methods
3062 module Tk
3063 module Encoding
3064 extend Encoding
3065
3066 def force_default_encoding=(mode)
3067 nil
3068 end
3069
3070 def force_default_encoding?
3071 nil
3072 end
3073
3074 def default_encoding=(enc)
3075 nil
3076 end
3077 def default_encoding
3078 nil
3079 end
3080
3081 def encoding=(name)
3082 nil
3083 end
3084 def encoding
3085 nil
3086 end
3087 def encoding_names
3088 nil
3089 end
3090 def encoding_system
3091 nil
3092 end
3093 def encoding_system=(enc)
3094 nil
3095 end
3096
3097 def encoding_convertfrom(str, enc=None)
3098 str
3099 end
3100 alias encoding_convert_from encoding_convertfrom
3101
3102 def encoding_convertto(str, enc=None)
3103 str
3104 end
3105 alias encoding_convert_to encoding_convertto
3106 def encoding_dirs
3107 nil
3108 end
3109 def encoding_dirs=(dir_array)
3110 nil
3111 end
3112 end
3113
3114 extend Encoding
3115 end
3116
3117 class TclTkIp
3118 attr_accessor :encoding
3119
3120 alias __eval _eval
3121 alias __invoke _invoke
3122
3123 alias _eval_with_enc _eval
3124 alias _invoke_with_enc _invoke
3125 end
3126 end
3127
3128
3129 module TkBindCore
3130 #def bind(context, cmd=Proc.new, *args)
3131 # Tk.bind(self, context, cmd, *args)
3132 #end
3133 def bind(context, *args)
3134 # if args[0].kind_of?(Proc) || args[0].kind_of?(Method)
3135 if TkComm._callback_entry?(args[0]) || !block_given?
3136 cmd = args.shift
3137 else
3138 cmd = Proc.new
3139 end
3140 Tk.bind(self, context, cmd, *args)
3141 end
3142
3143 #def bind_append(context, cmd=Proc.new, *args)
3144 # Tk.bind_append(self, context, cmd, *args)
3145 #end
3146 def bind_append(context, *args)
3147 # if args[0].kind_of?(Proc) || args[0].kind_of?(Method)
3148 if TkComm._callback_entry?(args[0]) || !block_given?
3149 cmd = args.shift
3150 else
3151 cmd = Proc.new
3152 end
3153 Tk.bind_append(self, context, cmd, *args)
3154 end
3155
3156 def bind_remove(context)
3157 Tk.bind_remove(self, context)
3158 end
3159
3160 def bindinfo(context=nil)
3161 Tk.bindinfo(self, context)
3162 end
3163 end
3164
3165
3166 module TkTreatFont
3167 def __font_optkeys
3168 ['font']
3169 end
3170 private :__font_optkeys
3171
3172 def __pathname
3173 self.path
3174 end
3175 private :__pathname
3176
3177 ################################
3178
3179 def font_configinfo(key = nil)
3180 optkeys = __font_optkeys
3181 if key && !optkeys.find{|opt| opt.to_s == key.to_s}
3182 fail ArgumentError, "unknown font option name `#{key}'"
3183 end
3184
3185 win, tag = __pathname.split(':')
3186
3187 if key
3188 pathname = [win, tag, key].join(';')
3189 TkFont.used_on(pathname) ||
3190 TkFont.init_widget_font(pathname, *__confinfo_cmd)
3191 elsif optkeys.size == 1
3192 pathname = [win, tag, optkeys[0]].join(';')
3193 TkFont.used_on(pathname) ||
3194 TkFont.init_widget_font(pathname, *__confinfo_cmd)
3195 else
3196 fonts = {}
3197 optkeys.each{|key|
3198 key = key.to_s
3199 pathname = [win, tag, key].join(';')
3200 fonts[key] =
3201 TkFont.used_on(pathname) ||
3202 TkFont.init_widget_font(pathname, *__confinfo_cmd)
3203 }
3204 fonts
3205 end
3206 end
3207 alias fontobj font_configinfo
3208
3209 def font_configure(slot)
3210 pathname = __pathname
3211
3212 slot = _symbolkey2str(slot)
3213
3214 __font_optkeys.each{|optkey|
3215 optkey = optkey.to_s
3216 l_optkey = 'latin' << optkey
3217 a_optkey = 'ascii' << optkey
3218 k_optkey = 'kanji' << optkey
3219
3220 if slot.key?(optkey)
3221 fnt = slot.delete(optkey)
3222 if fnt.kind_of?(TkFont)
3223 slot.delete(l_optkey)
3224 slot.delete(a_optkey)
3225 slot.delete(k_optkey)
3226
3227 fnt.call_font_configure([pathname, optkey], *(__config_cmd << {}))
3228 next
3229 else
3230 if fnt
3231 if (slot.key?(l_optkey) ||
3232 slot.key?(a_optkey) ||
3233 slot.key?(k_optkey))
3234 fnt = TkFont.new(fnt)
3235
3236 lfnt = slot.delete(l_optkey)
3237 lfnt = slot.delete(a_optkey) if slot.key?(a_optkey)
3238 kfnt = slot.delete(k_optkey)
3239
3240 fnt.latin_replace(lfnt) if lfnt
3241 fnt.kanji_replace(kfnt) if kfnt
3242
3243 fnt.call_font_configure([pathname, optkey],
3244 *(__config_cmd << {}))
3245 next
3246 else
3247 fnt = hash_kv(fnt) if fnt.kind_of?(Hash)
3248 unless TkConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__
3249 tk_call(*(__config_cmd << "-#{optkey}" << fnt))
3250 else
3251 begin
3252 tk_call(*(__config_cmd << "-#{optkey}" << fnt))
3253 rescue
3254 # ignore
3255 end
3256 end
3257 end
3258 end
3259 next
3260 end
3261 end
3262
3263 lfnt = slot.delete(l_optkey)
3264 lfnt = slot.delete(a_optkey) if slot.key?(a_optkey)
3265 kfnt = slot.delete(k_optkey)
3266
3267 if lfnt && kfnt
3268 TkFont.new(lfnt, kfnt).call_font_configure([pathname, optkey],
3269 *(__config_cmd << {}))
3270 elsif lfnt
3271 latinfont_configure([lfnt, optkey])
3272 elsif kfnt
3273 kanjifont_configure([kfnt, optkey])
3274 end
3275 }
3276
3277 # configure other (without font) options
3278 tk_call(*(__config_cmd.concat(hash_kv(slot)))) if slot != {}
3279 self
3280 end
3281
3282 def latinfont_configure(ltn, keys=nil)
3283 if ltn.kind_of?(Array)
3284 key = ltn[1]
3285 ltn = ltn[0]
3286 else
3287 key = nil
3288 end
3289
3290 optkeys = __font_optkeys
3291 if key && !optkeys.find{|opt| opt.to_s == key.to_s}
3292 fail ArgumentError, "unknown font option name `#{key}'"
3293 end
3294
3295 win, tag = __pathname.split(':')
3296
3297 optkeys = [key] if key
3298
3299 optkeys.each{|optkey|
3300 optkey = optkey.to_s
3301
3302 pathname = [win, tag, optkey].join(';')
3303
3304 if (fobj = TkFont.used_on(pathname))
3305 fobj = TkFont.new(fobj) # create a new TkFont object
3306 elsif Tk::JAPANIZED_TK
3307 fobj = fontobj # create a new TkFont object
3308 else
3309 ltn = hash_kv(ltn) if ltn.kind_of?(Hash)
3310 unless TkConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__
3311 tk_call(*(__config_cmd << "-#{optkey}" << ltn))
3312 else
3313 begin
3314 tk_call(*(__config_cmd << "-#{optkey}" << ltn))
3315 rescue => e
3316 # ignore
3317 end
3318 end
3319 next
3320 end
3321
3322 if fobj.kind_of?(TkFont)
3323 if ltn.kind_of?(TkFont)
3324 conf = {}
3325 ltn.latin_configinfo.each{|key,val| conf[key] = val}
3326 if keys
3327 fobj.latin_configure(conf.update(keys))
3328 else
3329 fobj.latin_configure(conf)
3330 end
3331 else
3332 fobj.latin_replace(ltn)
3333 end
3334 end
3335
3336 fobj.call_font_configure([pathname, optkey], *(__config_cmd << {}))
3337 }
3338 self
3339 end
3340 alias asciifont_configure latinfont_configure
3341
3342 def kanjifont_configure(knj, keys=nil)
3343 if knj.kind_of?(Array)
3344 key = knj[1]
3345 knj = knj[0]
3346 else
3347 key = nil
3348 end
3349
3350 optkeys = __font_optkeys
3351 if key && !optkeys.find{|opt| opt.to_s == key.to_s}
3352 fail ArgumentError, "unknown font option name `#{key}'"
3353 end
3354
3355 win, tag = __pathname.split(':')
3356
3357 optkeys = [key] if key
3358
3359 optkeys.each{|optkey|
3360 optkey = optkey.to_s
3361
3362 pathname = [win, tag, optkey].join(';')
3363
3364 if (fobj = TkFont.used_on(pathname))
3365 fobj = TkFont.new(fobj) # create a new TkFont object
3366 elsif Tk::JAPANIZED_TK
3367 fobj = fontobj # create a new TkFont object
3368 else
3369 knj = hash_kv(knj) if knj.kind_of?(Hash)
3370 unless TkConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__
3371 tk_call(*(__config_cmd << "-#{optkey}" << knj))
3372 else
3373 begin
3374 tk_call(*(__config_cmd << "-#{optkey}" << knj))
3375 rescue => e
3376 # ignore
3377 end
3378 end
3379 next
3380 end
3381
3382 if fobj.kind_of?(TkFont)
3383 if knj.kind_of?(TkFont)
3384 conf = {}
3385 knj.kanji_configinfo.each{|key,val| conf[key] = val}
3386 if keys
3387 fobj.kanji_configure(conf.update(keys))
3388 else
3389 fobj.kanji_configure(conf)
3390 end
3391 else
3392 fobj.kanji_replace(knj)
3393 end
3394 end
3395
3396 fobj.call_font_configure([pathname, optkey], *(__config_cmd << {}))
3397 }
3398 self
3399 end
3400
3401 def font_copy(win, wintag=nil, winkey=nil, targetkey=nil)
3402 if wintag
3403 if winkey
3404 fnt = win.tagfontobj(wintag, winkey).dup
3405 else
3406 fnt = win.tagfontobj(wintag).dup
3407 end
3408 else
3409 if winkey
3410 fnt = win.fontobj(winkey).dup
3411 else
3412 fnt = win.fontobj.dup
3413 end
3414 end
3415
3416 if targetkey
3417 fnt.call_font_configure([__pathname, targetkey], *(__config_cmd << {}))
3418 else
3419 fnt.call_font_configure(__pathname, *(__config_cmd << {}))
3420 end
3421 self
3422 end
3423
3424 def latinfont_copy(win, wintag=nil, winkey=nil, targetkey=nil)
3425 if targetkey
3426 fontobj(targetkey).dup.call_font_configure([__pathname, targetkey],
3427 *(__config_cmd << {}))
3428 else
3429 fontobj.dup.call_font_configure(__pathname, *(__config_cmd << {}))
3430 end
3431
3432 if wintag
3433 if winkey
3434 fontobj.latin_replace(win.tagfontobj(wintag, winkey).latin_font_id)
3435 else
3436 fontobj.latin_replace(win.tagfontobj(wintag).latin_font_id)
3437 end
3438 else
3439 if winkey
3440 fontobj.latin_replace(win.fontobj(winkey).latin_font_id)
3441 else
3442 fontobj.latin_replace(win.fontobj.latin_font_id)
3443 end
3444 end
3445 self
3446 end
3447 alias asciifont_copy latinfont_copy
3448
3449 def kanjifont_copy(win, wintag=nil, winkey=nil, targetkey=nil)
3450 if targetkey
3451 fontobj(targetkey).dup.call_font_configure([__pathname, targetkey],
3452 *(__config_cmd << {}))
3453 else
3454 fontobj.dup.call_font_configure(__pathname, *(__config_cmd << {}))
3455 end
3456
3457 if wintag
3458 if winkey
3459 fontobj.kanji_replace(win.tagfontobj(wintag, winkey).kanji_font_id)
3460 else
3461 fontobj.kanji_replace(win.tagfontobj(wintag).kanji_font_id)
3462 end
3463 else
3464 if winkey
3465 fontobj.kanji_replace(win.fontobj(winkey).kanji_font_id)
3466 else
3467 fontobj.kanji_replace(win.fontobj.kanji_font_id)
3468 end
3469 end
3470 self
3471 end
3472 end
3473
3474
3475 module TkConfigMethod
3476 include TkUtil
3477 include TkTreatFont
3478
3479 def TkConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__
3480 @mode || false
3481 end
3482 def TkConfigMethod.__set_IGNORE_UNKNOWN_CONFIGURE_OPTION__!(mode)
3483 fail SecurityError, "can't change the mode" if $SAFE>=4
3484 @mode = (mode)? true: false
3485 end
3486
3487 def __cget_cmd
3488 [self.path, 'cget']
3489 end
3490 private :__cget_cmd
3491
3492 def __config_cmd
3493 [self.path, 'configure']
3494 end
3495 private :__config_cmd
3496
3497 def __confinfo_cmd
3498 __config_cmd
3499 end
3500 private :__confinfo_cmd
3501
3502 def __configinfo_struct
3503 {:key=>0, :alias=>1, :db_name=>1, :db_class=>2,
3504 :default_value=>3, :current_value=>4}
3505 end
3506 private :__configinfo_struct
3507
3508 def __optkey_aliases
3509 {}
3510 end
3511 private :__optkey_aliases
3512
3513 def __numval_optkeys
3514 []
3515 end
3516 private :__numval_optkeys
3517
3518 def __numstrval_optkeys
3519 []
3520 end
3521 private :__numstrval_optkeys
3522
3523 def __boolval_optkeys
3524 ['exportselection', 'jump', 'setgrid', 'takefocus']
3525 end
3526 private :__boolval_optkeys
3527
3528 def __strval_optkeys
3529 [
3530 'text', 'label', 'show', 'data', 'file',
3531 'activebackground', 'activeforeground', 'background',
3532 'disabledforeground', 'disabledbackground', 'foreground',
3533 'highlightbackground', 'highlightcolor', 'insertbackground',
3534 'selectbackground', 'selectforeground', 'troughcolor'
3535 ]
3536 end
3537 private :__strval_optkeys
3538
3539 def __listval_optkeys
3540 []
3541 end
3542 private :__listval_optkeys
3543
3544 def __numlistval_optkeys
3545 []
3546 end
3547 private :__numlistval_optkeys
3548
3549 def __tkvariable_optkeys
3550 ['variable', 'textvariable']
3551 end
3552 private :__tkvariable_optkeys
3553
3554 def __val2ruby_optkeys # { key=>proc, ... }
3555 # The method is used to convert a opt-value to a ruby's object.
3556 # When get the value of the option "key", "proc.call(value)" is called.
3557 {}
3558 end
3559 private :__val2ruby_optkeys
3560
3561 def __ruby2val_optkeys # { key=>proc, ... }
3562 # The method is used to convert a ruby's object to a opt-value.
3563 # When set the value of the option "key", "proc.call(value)" is called.
3564 # That is, "-#{key} #{proc.call(value)}".
3565 {}
3566 end
3567 private :__ruby2val_optkeys
3568
3569 def __methodcall_optkeys # { key=>method, ... }
3570 # The method is used to both of get and set.
3571 # Usually, the 'key' will not be a widget option.
3572 {}
3573 end
3574 private :__methodcall_optkeys
3575
3576 def __keyonly_optkeys # { def_key=>undef_key or nil, ... }
3577 {}
3578 end
3579 private :__keyonly_optkeys
3580
3581 def __conv_keyonly_opts(keys)
3582 return keys unless keys.kind_of?(Hash)
3583 keyonly = __keyonly_optkeys
3584 keys2 = {}
3585 keys.each{|k, v|
3586 optkey = keyonly.find{|kk,vv| kk.to_s == k.to_s}
3587 if optkey
3588 defkey, undefkey = optkey
3589 if v
3590 keys2[defkey.to_s] = None
3591 elsif undefkey
3592 keys2[undefkey.to_s] = None
3593 else
3594 # remove key
3595 end
3596 else
3597 keys2[k.to_s] = v
3598 end
3599 }
3600 keys2
3601 end
3602 private :__conv_keyonly_opts
3603
3604 def config_hash_kv(keys, enc_mode = nil, conf = nil)
3605 hash_kv(__conv_keyonly_opts(keys), enc_mode, conf)
3606 end
3607
3608 ################################
3609
3610 def [](id)
3611 cget(id)
3612 end
3613
3614 def []=(id, val)
3615 configure(id, val)
3616 val
3617 end
3618
3619 def __cget_core(slot)
3620 orig_slot = slot
3621 slot = slot.to_s
3622
3623 if slot.length == 0
3624 fail ArgumentError, "Invalid option `#{orig_slot.inspect}'"
3625 end
3626
3627 alias_name, real_name = __optkey_aliases.find{|k, v| k.to_s == slot}
3628 if real_name
3629 slot = real_name.to_s
3630 end
3631
3632 if ( method = _symbolkey2str(__val2ruby_optkeys())[slot] )
3633 optval = tk_call_without_enc(*(__cget_cmd << "-#{slot}"))
3634 begin
3635 return method.call(optval)
3636 rescue => e
3637 warn("Warning:: #{e.message} (when #{method}.call(#{optval.inspect})") if $DEBUG
3638 return optval
3639 end
3640 end
3641
3642 if ( method = _symbolkey2str(__methodcall_optkeys)[slot] )
3643 return self.__send__(method)
3644 end
3645
3646 case slot
3647 when /^(#{__numval_optkeys.join('|')})$/
3648 begin
3649 number(tk_call_without_enc(*(__cget_cmd << "-#{slot}")))
3650 rescue
3651 nil
3652 end
3653
3654 when /^(#{__numstrval_optkeys.join('|')})$/
3655 num_or_str(tk_call_without_enc(*(__cget_cmd << "-#{slot}")))
3656
3657 when /^(#{__boolval_optkeys.join('|')})$/
3658 begin
3659 bool(tk_call_without_enc(*(__cget_cmd << "-#{slot}")))
3660 rescue
3661 nil
3662 end
3663
3664 when /^(#{__listval_optkeys.join('|')})$/
3665 simplelist(tk_call_without_enc(*(__cget_cmd << "-#{slot}")))
3666
3667 when /^(#{__numlistval_optkeys.join('|')})$/
3668 conf = tk_call_without_enc(*(__cget_cmd << "-#{slot}"))
3669 if conf =~ /^[0-9+-]/
3670 list(conf)
3671 else
3672 conf
3673 end
3674
3675 when /^(#{__strval_optkeys.join('|')})$/
3676 _fromUTF8(tk_call_without_enc(*(__cget_cmd << "-#{slot}")))
3677
3678 when /^(|latin|ascii|kanji)(#{__font_optkeys.join('|')})$/
3679 fontcode = $1
3680 fontkey = $2
3681 fnt = tk_tcl2ruby(tk_call_without_enc(*(__cget_cmd << "-#{fontkey}")), true)
3682 unless fnt.kind_of?(TkFont)
3683 fnt = fontobj(fontkey)
3684 end
3685 if fontcode == 'kanji' && JAPANIZED_TK && TK_VERSION =~ /^4\.*/
3686 # obsolete; just for compatibility
3687 fnt.kanji_font
3688 else
3689 fnt
3690 end
3691
3692 when /^(#{__tkvariable_optkeys.join('|')})$/
3693 v = tk_call_without_enc(*(__cget_cmd << "-#{slot}"))
3694 (v.empty?)? nil: TkVarAccess.new(v)
3695
3696 else
3697 tk_tcl2ruby(tk_call_without_enc(*(__cget_cmd << "-#{slot}")), true)
3698 end
3699 end
3700 private :__cget_core
3701
3702 def cget(slot)
3703 unless TkConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__
3704 __cget_core(slot)
3705 else
3706 begin
3707 __cget_core(slot)
3708 rescue => e
3709 if current_configinfo.has_key?(slot.to_s)
3710 # error on known option
3711 fail e
3712 else
3713 # unknown option
3714 nil
3715 end
3716 end
3717 end
3718 end
3719 def cget_strict(slot)
3720 # never use TkConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__
3721 __cget_core(slot)
3722 end
3723
3724 def __configure_core(slot, value=None)
3725 if slot.kind_of? Hash
3726 slot = _symbolkey2str(slot)
3727
3728 __optkey_aliases.each{|alias_name, real_name|
3729 alias_name = alias_name.to_s
3730 if slot.has_key?(alias_name)
3731 slot[real_name.to_s] = slot.delete(alias_name)
3732 end
3733 }
3734
3735 __methodcall_optkeys.each{|key, method|
3736 value = slot.delete(key.to_s)
3737 self.__send__(method, value) if value
3738 }
3739
3740 __ruby2val_optkeys.each{|key, method|
3741 key = key.to_s
3742 slot[key] = method.call(slot[key]) if slot.has_key?(key)
3743 }
3744
3745 __keyonly_optkeys.each{|defkey, undefkey|
3746 conf = slot.find{|kk, vv| kk == defkey.to_s}
3747 if conf
3748 k, v = conf
3749 if v
3750 slot[k] = None
3751 else
3752 slot[undefkey.to_s] = None if undefkey
3753 slot.delete(k)
3754 end
3755 end
3756 }
3757
3758 if (slot.find{|k, v| k =~ /^(|latin|ascii|kanji)(#{__font_optkeys.join('|')})$/})
3759 font_configure(slot)
3760 elsif slot.size > 0
3761 tk_call(*(__config_cmd.concat(hash_kv(slot))))
3762 end
3763
3764 else
3765 orig_slot = slot
3766 slot = slot.to_s
3767 if slot.length == 0
3768 fail ArgumentError, "Invalid option `#{orig_slot.inspect}'"
3769 end
3770
3771 alias_name, real_name = __optkey_aliases.find{|k, v| k.to_s == slot}
3772 if real_name
3773 slot = real_name.to_s
3774 end
3775
3776 if ( conf = __keyonly_optkeys.find{|k, v| k.to_s == slot} )
3777 defkey, undefkey = conf
3778 if value
3779 tk_call(*(__config_cmd << "-#{defkey}"))
3780 elsif undefkey
3781 tk_call(*(__config_cmd << "-#{undefkey}"))
3782 end
3783 elsif ( method = _symbolkey2str(__ruby2val_optkeys)[slot] )
3784 tk_call(*(__config_cmd << "-#{slot}" << method.call(value)))
3785 elsif ( method = _symbolkey2str(__methodcall_optkeys)[slot] )
3786 self.__send__(method, value)
3787 elsif (slot =~ /^(|latin|ascii|kanji)(#{__font_optkeys.join('|')})$/)
3788 if value == None
3789 fontobj($2)
3790 else
3791 font_configure({slot=>value})
3792 end
3793 else
3794 tk_call(*(__config_cmd << "-#{slot}" << value))
3795 end
3796 end
3797 self
3798 end
3799 private :__configure_core
3800
3801 def __check_available_configure_options(keys)
3802 availables = self.current_configinfo.keys
3803
3804 # add non-standard keys
3805 availables |= __font_optkeys.map{|k|
3806 [k.to_s, "latin#{k}", "ascii#{k}", "kanji#{k}"]
3807 }.flatten
3808 availables |= __methodcall_optkeys.keys.map{|k| k.to_s}
3809 availables |= __keyonly_optkeys.keys.map{|k| k.to_s}
3810
3811 keys = _symbolkey2str(keys)
3812 keys.delete_if{|k, v| !(availables.include?(k))}
3813 end
3814
3815 def configure(slot, value=None)
3816 unless TkConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__
3817 __configure_core(slot, value)
3818 else
3819 if slot.kind_of?(Hash)
3820 begin
3821 __configure_core(slot)
3822 rescue
3823 slot = __check_available_configure_options(slot)
3824 __configure_core(slot) unless slot.empty?
3825 end
3826 else
3827 begin
3828 __configure_core(slot, value)
3829 rescue => e
3830 if current_configinfo.has_key?(slot.to_s)
3831 # error on known option
3832 fail e
3833 else
3834 # unknown option
3835 nil
3836 end
3837 end
3838 end
3839 end
3840 self
3841 end
3842
3843 def configure_cmd(slot, value)
3844 configure(slot, install_cmd(value))
3845 end
3846
3847 def __configinfo_core(slot = nil)
3848 if TkComm::GET_CONFIGINFO_AS_ARRAY
3849 if (slot &&
3850 slot.to_s =~ /^(|latin|ascii|kanji)(#{__font_optkeys.join('|')})$/)
3851 fontkey = $2
3852 # conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__confinfo_cmd << "-#{fontkey}"))))
3853 conf = tk_split_simplelist(tk_call_without_enc(*(__confinfo_cmd << "-#{fontkey}")), false, true)
3854 conf[__configinfo_struct[:key]] =
3855 conf[__configinfo_struct[:key]][1..-1]
3856 if ( ! __configinfo_struct[:alias] \
3857 || conf.size > __configinfo_struct[:alias] + 1 )
3858 fnt = conf[__configinfo_struct[:default_value]]
3859 if TkFont.is_system_font?(fnt)
3860 conf[__configinfo_struct[:default_value]] = TkNamedFont.new(fnt)
3861 end
3862 conf[__configinfo_struct[:current_value]] = fontobj(fontkey)
3863 elsif ( __configinfo_struct[:alias] \
3864 && conf.size == __configinfo_struct[:alias] + 1 \
3865 && conf[__configinfo_struct[:alias]][0] == ?- )
3866 conf[__configinfo_struct[:alias]] =
3867 conf[__configinfo_struct[:alias]][1..-1]
3868 end
3869 conf
3870 else
3871 if slot
3872 slot = slot.to_s
3873
3874 alias_name, real_name = __optkey_aliases.find{|k, v| k.to_s == slot}
3875 if real_name
3876 slot = real_name.to_s
3877 end
3878
3879 case slot
3880 when /^(#{__val2ruby_optkeys().keys.join('|')})$/
3881 method = _symbolkey2str(__val2ruby_optkeys())[slot]
3882 conf = tk_split_simplelist(tk_call_without_enc(*(__confinfo_cmd() << "-#{slot}")), false, true)
3883 if ( __configinfo_struct[:default_value] \
3884 && conf[__configinfo_struct[:default_value]] )
3885 optval = conf[__configinfo_struct[:default_value]]
3886 begin
3887 val = method.call(optval)
3888 rescue => e
3889 warn("Warning:: #{e.message} (when #{method}.call(#{optval.inspect})") if $DEBUG
3890 val = optval
3891 end
3892 conf[__configinfo_struct[:default_value]] = val
3893 end
3894 if ( conf[__configinfo_struct[:current_value]] )
3895 optval = conf[__configinfo_struct[:current_value]]
3896 begin
3897 val = method.call(optval)
3898 rescue => e
3899 warn("Warning:: #{e.message} (when #{method}.call(#{optval.inspect})") if $DEBUG
3900 val = optval
3901 end
3902 conf[__configinfo_struct[:current_value]] = val
3903 end
3904
3905 when /^(#{__methodcall_optkeys.keys.join('|')})$/
3906 method = _symbolkey2str(__methodcall_optkeys)[slot]
3907 return [slot, '', '', '', self.__send__(method)]
3908
3909 when /^(#{__numval_optkeys.join('|')})$/
3910 # conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}"))))
3911 conf = tk_split_simplelist(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")), false, true)
3912
3913 if ( __configinfo_struct[:default_value] \
3914 && conf[__configinfo_struct[:default_value]])
3915 begin
3916 conf[__configinfo_struct[:default_value]] =
3917 number(conf[__configinfo_struct[:default_value]])
3918 rescue
3919 conf[__configinfo_struct[:default_value]] = nil
3920 end
3921 end
3922 if ( conf[__configinfo_struct[:current_value]] )
3923 begin
3924 conf[__configinfo_struct[:current_value]] =
3925 number(conf[__configinfo_struct[:current_value]])
3926 rescue
3927 conf[__configinfo_struct[:current_value]] = nil
3928 end
3929 end
3930
3931 when /^(#{__numstrval_optkeys.join('|')})$/
3932 # conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}"))))
3933 conf = tk_split_simplelist(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")), false, true)
3934
3935 if ( __configinfo_struct[:default_value] \
3936 && conf[__configinfo_struct[:default_value]])
3937 conf[__configinfo_struct[:default_value]] =
3938 num_or_str(conf[__configinfo_struct[:default_value]])
3939 end
3940 if ( conf[__configinfo_struct[:current_value]] )
3941 conf[__configinfo_struct[:current_value]] =
3942 num_or_str(conf[__configinfo_struct[:current_value]])
3943 end
3944
3945 when /^(#{__boolval_optkeys.join('|')})$/
3946 # conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}"))))
3947 conf = tk_split_simplelist(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")), false, true)
3948
3949 if ( __configinfo_struct[:default_value] \
3950 && conf[__configinfo_struct[:default_value]])
3951 begin
3952 conf[__configinfo_struct[:default_value]] =
3953 bool(conf[__configinfo_struct[:default_value]])
3954 rescue
3955 conf[__configinfo_struct[:default_value]] = nil
3956 end
3957 end
3958 if ( conf[__configinfo_struct[:current_value]] )
3959 begin
3960 conf[__configinfo_struct[:current_value]] =
3961 bool(conf[__configinfo_struct[:current_value]])
3962 rescue
3963 conf[__configinfo_struct[:current_value]] = nil
3964 end
3965 end
3966
3967 when /^(#{__listval_optkeys.join('|')})$/
3968 # conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}"))))
3969 conf = tk_split_simplelist(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")), false, true)
3970
3971 if ( __configinfo_struct[:default_value] \
3972 && conf[__configinfo_struct[:default_value]])
3973 conf[__configinfo_struct[:default_value]] =
3974 simplelist(conf[__configinfo_struct[:default_value]])
3975 end
3976 if ( conf[__configinfo_struct[:current_value]] )
3977 conf[__configinfo_struct[:current_value]] =
3978 simplelist(conf[__configinfo_struct[:current_value]])
3979 end
3980
3981 when /^(#{__numlistval_optkeys.join('|')})$/
3982 # conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}"))))
3983 conf = tk_split_simplelist(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")), false, true)
3984
3985 if ( __configinfo_struct[:default_value] \
3986 && conf[__configinfo_struct[:default_value]] \
3987 && conf[__configinfo_struct[:default_value]] =~ /^[0-9]/ )
3988 conf[__configinfo_struct[:default_value]] =
3989 list(conf[__configinfo_struct[:default_value]])
3990 end
3991 if ( conf[__configinfo_struct[:current_value]] \
3992 && conf[__configinfo_struct[:current_value]] =~ /^[0-9]/ )
3993 conf[__configinfo_struct[:current_value]] =
3994 list(conf[__configinfo_struct[:current_value]])
3995 end
3996
3997 when /^(#{__strval_optkeys.join('|')})$/
3998 # conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}"))))
3999 conf = tk_split_simplelist(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")), false, true)
4000
4001 when /^(#{__tkvariable_optkeys.join('|')})$/
4002 conf = tk_split_simplelist(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")), false, true)
4003
4004 if ( __configinfo_struct[:default_value] \
4005 && conf[__configinfo_struct[:default_value]])
4006 v = conf[__configinfo_struct[:default_value]]
4007 if v.empty?
4008 conf[__configinfo_struct[:default_value]] = nil
4009 else
4010 conf[__configinfo_struct[:default_value]] = TkVarAccess.new(v)
4011 end
4012 end
4013 if ( conf[__configinfo_struct[:current_value]] )
4014 v = conf[__configinfo_struct[:current_value]]
4015 if v.empty?
4016 conf[__configinfo_struct[:current_value]] = nil
4017 else
4018 conf[__configinfo_struct[:current_value]] = TkVarAccess.new(v)
4019 end
4020 end
4021
4022 else
4023 # conf = tk_split_list(_fromUTF8(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}"))))
4024 conf = tk_split_list(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")), 0, false, true)
4025 end
4026 conf[__configinfo_struct[:key]] =
4027 conf[__configinfo_struct[:key]][1..-1]
4028
4029 if ( __configinfo_struct[:alias] \
4030 && conf.size == __configinfo_struct[:alias] + 1 \
4031 && conf[__configinfo_struct[:alias]][0] == ?- )
4032 conf[__configinfo_struct[:alias]] =
4033 conf[__configinfo_struct[:alias]][1..-1]
4034 end
4035
4036 conf
4037
4038 else
4039 # ret = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*__confinfo_cmd))).collect{|conflist|
4040 # conf = tk_split_simplelist(conflist)
4041 ret = tk_split_simplelist(tk_call_without_enc(*__confinfo_cmd), false, false).collect{|conflist|
4042 conf = tk_split_simplelist(conflist, false, true)
4043 conf[__configinfo_struct[:key]] =
4044 conf[__configinfo_struct[:key]][1..-1]
4045
4046 optkey = conf[__configinfo_struct[:key]]
4047 case optkey
4048 when /^(#{__val2ruby_optkeys().keys.join('|')})$/
4049 method = _symbolkey2str(__val2ruby_optkeys())[optkey]
4050 if ( __configinfo_struct[:default_value] \
4051 && conf[__configinfo_struct[:default_value]] )
4052 optval = conf[__configinfo_struct[:default_value]]
4053 begin
4054 val = method.call(optval)
4055 rescue => e
4056 warn("Warning:: #{e.message} (when #{method}.call(#{optval.inspect})") if $DEBUG
4057 val = optval
4058 end
4059 conf[__configinfo_struct[:default_value]] = val
4060 end
4061 if ( conf[__configinfo_struct[:current_value]] )
4062 optval = conf[__configinfo_struct[:current_value]]
4063 begin
4064 val = method.call(optval)
4065 rescue => e
4066 warn("Warning:: #{e.message} (when #{method}.call(#{optval.inspect})") if $DEBUG
4067 val = optval
4068 end
4069 conf[__configinfo_struct[:current_value]] = val
4070 end
4071
4072 when /^(#{__strval_optkeys.join('|')})$/
4073 # do nothing
4074
4075 when /^(#{__numval_optkeys.join('|')})$/
4076 if ( __configinfo_struct[:default_value] \
4077 && conf[__configinfo_struct[:default_value]] )
4078 begin
4079 conf[__configinfo_struct[:default_value]] =
4080 number(conf[__configinfo_struct[:default_value]])
4081 rescue
4082 conf[__configinfo_struct[:default_value]] = nil
4083 end
4084 end
4085 if ( conf[__configinfo_struct[:current_value]] )
4086 begin
4087 conf[__configinfo_struct[:current_value]] =
4088 number(conf[__configinfo_struct[:current_value]])
4089 rescue
4090 conf[__configinfo_struct[:current_value]] = nil
4091 end
4092 end
4093
4094 when /^(#{__numstrval_optkeys.join('|')})$/
4095 if ( __configinfo_struct[:default_value] \
4096 && conf[__configinfo_struct[:default_value]] )
4097 conf[__configinfo_struct[:default_value]] =
4098 num_or_str(conf[__configinfo_struct[:default_value]])
4099 end
4100 if ( conf[__configinfo_struct[:current_value]] )
4101 conf[__configinfo_struct[:current_value]] =
4102 num_or_str(conf[__configinfo_struct[:current_value]])
4103 end
4104
4105 when /^(#{__boolval_optkeys.join('|')})$/
4106 if ( __configinfo_struct[:default_value] \
4107 && conf[__configinfo_struct[:default_value]] )
4108 begin
4109 conf[__configinfo_struct[:default_value]] =
4110 bool(conf[__configinfo_struct[:default_value]])
4111 rescue
4112 conf[__configinfo_struct[:default_value]] = nil
4113 end
4114 end
4115 if ( conf[__configinfo_struct[:current_value]] )
4116 begin
4117 conf[__configinfo_struct[:current_value]] =
4118 bool(conf[__configinfo_struct[:current_value]])
4119 rescue
4120 conf[__configinfo_struct[:current_value]] = nil
4121 end
4122 end
4123
4124 when /^(#{__listval_optkeys.join('|')})$/
4125 if ( __configinfo_struct[:default_value] \
4126 && conf[__configinfo_struct[:default_value]] )
4127 conf[__configinfo_struct[:default_value]] =
4128 simplelist(conf[__configinfo_struct[:default_value]])
4129 end
4130 if ( conf[__configinfo_struct[:current_value]] )
4131 conf[__configinfo_struct[:current_value]] =
4132 simplelist(conf[__configinfo_struct[:current_value]])
4133 end
4134
4135 when /^(#{__numlistval_optkeys.join('|')})$/
4136 if ( __configinfo_struct[:default_value] \
4137 && conf[__configinfo_struct[:default_value]] \
4138 && conf[__configinfo_struct[:default_value]] =~ /^[0-9]/ )
4139 conf[__configinfo_struct[:default_value]] =
4140 list(conf[__configinfo_struct[:default_value]])
4141 end
4142 if ( conf[__configinfo_struct[:current_value]] \
4143 && conf[__configinfo_struct[:current_value]] =~ /^[0-9]/ )
4144 conf[__configinfo_struct[:current_value]] =
4145 list(conf[__configinfo_struct[:current_value]])
4146 end
4147
4148 when /^(#{__tkvariable_optkeys.join('|')})$/
4149 if ( __configinfo_struct[:default_value] \
4150 && conf[__configinfo_struct[:default_value]] )
4151 v = conf[__configinfo_struct[:default_value]]
4152 if v.empty?
4153 conf[__configinfo_struct[:default_value]] = nil
4154 else
4155 conf[__configinfo_struct[:default_value]] = TkVarAccess.new(v)
4156 end
4157 end
4158 if ( conf[__configinfo_struct[:current_value]] )
4159 v = conf[__configinfo_struct[:current_value]]
4160 if v.empty?
4161 conf[__configinfo_struct[:current_value]] = nil
4162 else
4163 conf[__configinfo_struct[:current_value]] = TkVarAccess.new(v)
4164 end
4165 end
4166
4167 else
4168 if ( __configinfo_struct[:default_value] \
4169 && conf[__configinfo_struct[:default_value]] )
4170 if conf[__configinfo_struct[:default_value]].index('{')
4171 conf[__configinfo_struct[:default_value]] =
4172 tk_split_list(conf[__configinfo_struct[:default_value]])
4173 else
4174 conf[__configinfo_struct[:default_value]] =
4175 tk_tcl2ruby(conf[__configinfo_struct[:default_value]])
4176 end
4177 end
4178 if conf[__configinfo_struct[:current_value]]
4179 if conf[__configinfo_struct[:current_value]].index('{')
4180 conf[__configinfo_struct[:current_value]] =
4181 tk_split_list(conf[__configinfo_struct[:current_value]])
4182 else
4183 conf[__configinfo_struct[:current_value]] =
4184 tk_tcl2ruby(conf[__configinfo_struct[:current_value]])
4185 end
4186 end
4187 end
4188
4189 if ( __configinfo_struct[:alias] \
4190 && conf.size == __configinfo_struct[:alias] + 1 \
4191 && conf[__configinfo_struct[:alias]][0] == ?- )
4192 conf[__configinfo_struct[:alias]] =
4193 conf[__configinfo_struct[:alias]][1..-1]
4194 end
4195
4196 conf
4197 }
4198
4199 __font_optkeys.each{|optkey|
4200 optkey = optkey.to_s
4201 fontconf = ret.assoc(optkey)
4202 if fontconf && fontconf.size > 2
4203 ret.delete_if{|inf| inf[0] =~ /^(|latin|ascii|kanji)#{optkey}$/}
4204 fnt = fontconf[__configinfo_struct[:default_value]]
4205 if TkFont.is_system_font?(fnt)
4206 fontconf[__configinfo_struct[:default_value]] \
4207 = TkNamedFont.new(fnt)
4208 end
4209 fontconf[__configinfo_struct[:current_value]] = fontobj(optkey)
4210 ret.push(fontconf)
4211 end
4212 }
4213
4214 __methodcall_optkeys.each{|optkey, method|
4215 ret << [optkey.to_s, '', '', '', self.__send__(method)]
4216 }
4217
4218 ret
4219 end
4220 end
4221
4222 else # ! TkComm::GET_CONFIGINFO_AS_ARRAY
4223 if (slot &&
4224 slot.to_s =~ /^(|latin|ascii|kanji)(#{__font_optkeys.join('|')})$/)
4225 fontkey = $2
4226 # conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__confinfo_cmd << "-#{fontkey}"))))
4227 conf = tk_split_simplelist(tk_call_without_enc(*(__confinfo_cmd << "-#{fontkey}")), false, true)
4228 conf[__configinfo_struct[:key]] =
4229 conf[__configinfo_struct[:key]][1..-1]
4230
4231 if ( ! __configinfo_struct[:alias] \
4232 || conf.size > __configinfo_struct[:alias] + 1 )
4233 fnt = conf[__configinfo_struct[:default_value]]
4234 if TkFont.is_system_font?(fnt)
4235 conf[__configinfo_struct[:default_value]] = TkNamedFont.new(fnt)
4236 end
4237 conf[__configinfo_struct[:current_value]] = fontobj(fontkey)
4238 { conf.shift => conf }
4239 elsif ( __configinfo_struct[:alias] \
4240 && conf.size == __configinfo_struct[:alias] + 1 )
4241 if conf[__configinfo_struct[:alias]][0] == ?-
4242 conf[__configinfo_struct[:alias]] =
4243 conf[__configinfo_struct[:alias]][1..-1]
4244 end
4245 { conf[0] => conf[1] }
4246 else
4247 { conf.shift => conf }
4248 end
4249 else
4250 if slot
4251 slot = slot.to_s
4252
4253 alias_name, real_name = __optkey_aliases.find{|k, v| k.to_s == slot}
4254 if real_name
4255 slot = real_name.to_s
4256 end
4257
4258 case slot
4259 when /^(#{__val2ruby_optkeys().keys.join('|')})$/
4260 method = _symbolkey2str(__val2ruby_optkeys())[slot]
4261 conf = tk_split_simplelist(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")), false, true)
4262 if ( __configinfo_struct[:default_value] \
4263 && conf[__configinfo_struct[:default_value]] )
4264 optval = conf[__configinfo_struct[:default_value]]
4265 begin
4266 val = method.call(optval)
4267 rescue => e
4268 warn("Warning:: #{e.message} (when #{method}.call(#{optval.inspect})") if $DEBUG
4269 val = optval
4270 end
4271 conf[__configinfo_struct[:default_value]] = val
4272 end
4273 if ( conf[__configinfo_struct[:current_value]] )
4274 optval = conf[__configinfo_struct[:current_value]]
4275 begin
4276 val = method.call(optval)
4277 rescue => e
4278 warn("Warning:: #{e.message} (when #{method}.call(#{optval.inspect})") if $DEBUG
4279 val = optval
4280 end
4281 conf[__configinfo_struct[:current_value]] = val
4282 end
4283
4284 when /^(#{__methodcall_optkeys.keys.join('|')})$/
4285 method = _symbolkey2str(__methodcall_optkeys)[slot]
4286 return {slot => ['', '', '', self.__send__(method)]}
4287
4288 when /^(#{__numval_optkeys.join('|')})$/
4289 # conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}"))))
4290 conf = tk_split_simplelist(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")), false, true)
4291
4292 if ( __configinfo_struct[:default_value] \
4293 && conf[__configinfo_struct[:default_value]] )
4294 begin
4295 conf[__configinfo_struct[:default_value]] =
4296 number(conf[__configinfo_struct[:default_value]])
4297 rescue
4298 conf[__configinfo_struct[:default_value]] = nil
4299 end
4300 end
4301 if ( conf[__configinfo_struct[:current_value]] )
4302 begin
4303 conf[__configinfo_struct[:current_value]] =
4304 number(conf[__configinfo_struct[:current_value]])
4305 rescue
4306 conf[__configinfo_struct[:current_value]] = nil
4307 end
4308 end
4309
4310 when /^(#{__numstrval_optkeys.join('|')})$/
4311 # conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}"))))
4312 conf = tk_split_simplelist(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")), false, true)
4313
4314 if ( __configinfo_struct[:default_value] \
4315 && conf[__configinfo_struct[:default_value]] )
4316 conf[__configinfo_struct[:default_value]] =
4317 num_or_str(conf[__configinfo_struct[:default_value]])
4318 end
4319 if ( conf[__configinfo_struct[:current_value]] )
4320 conf[__configinfo_struct[:current_value]] =
4321 num_or_str(conf[__configinfo_struct[:current_value]])
4322 end
4323
4324 when /^(#{__boolval_optkeys.join('|')})$/
4325 # conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}"))))
4326 conf = tk_split_simplelist(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")), false, true)
4327
4328 if ( __configinfo_struct[:default_value] \
4329 && conf[__configinfo_struct[:default_value]] )
4330 begin
4331 conf[__configinfo_struct[:default_value]] =
4332 bool(conf[__configinfo_struct[:default_value]])
4333 rescue
4334 conf[__configinfo_struct[:default_value]] = nil
4335 end
4336 end
4337 if ( conf[__configinfo_struct[:current_value]] )
4338 begin
4339 conf[__configinfo_struct[:current_value]] =
4340 bool(conf[__configinfo_struct[:current_value]])
4341 rescue
4342 conf[__configinfo_struct[:current_value]] = nil
4343 end
4344 end
4345
4346 when /^(#{__listval_optkeys.join('|')})$/
4347 # conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}"))))
4348 conf = tk_split_simplelist(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")), false, true)
4349
4350 if ( __configinfo_struct[:default_value] \
4351 && conf[__configinfo_struct[:default_value]] )
4352 conf[__configinfo_struct[:default_value]] =
4353 simplelist(conf[__configinfo_struct[:default_value]])
4354 end
4355 if ( conf[__configinfo_struct[:current_value]] )
4356 conf[__configinfo_struct[:current_value]] =
4357 simplelist(conf[__configinfo_struct[:current_value]])
4358 end
4359
4360 when /^(#{__numlistval_optkeys.join('|')})$/
4361 # conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}"))))
4362 conf = tk_split_simplelist(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")), false, true)
4363
4364 if ( __configinfo_struct[:default_value] \
4365 && conf[__configinfo_struct[:default_value]] \
4366 && conf[__configinfo_struct[:default_value]] =~ /^[0-9]/ )
4367 conf[__configinfo_struct[:default_value]] =
4368 list(conf[__configinfo_struct[:default_value]])
4369 end
4370 if ( conf[__configinfo_struct[:current_value]] \
4371 && conf[__configinfo_struct[:current_value]] =~ /^[0-9]/ )
4372 conf[__configinfo_struct[:current_value]] =
4373 list(conf[__configinfo_struct[:current_value]])
4374 end
4375
4376 when /^(#{__tkvariable_optkeys.join('|')})$/
4377 conf = tk_split_simplelist(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")), false, true)
4378
4379 if ( __configinfo_struct[:default_value] \
4380 && conf[__configinfo_struct[:default_value]] )
4381 v = conf[__configinfo_struct[:default_value]]
4382 if v.empty?
4383 conf[__configinfo_struct[:default_value]] = nil
4384 else
4385 conf[__configinfo_struct[:default_value]] = TkVarAccess.new(v)
4386 end
4387 end
4388 if ( conf[__configinfo_struct[:current_value]] )
4389 v = conf[__configinfo_struct[:current_value]]
4390 if v.empty?
4391 conf[__configinfo_struct[:current_value]] = nil
4392 else
4393 conf[__configinfo_struct[:current_value]] = TkVarAccess.new(v)
4394 end
4395 end
4396
4397 when /^(#{__strval_optkeys.join('|')})$/
4398 # conf = tk_split_simplelist(_fromUTF8(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}"))))
4399 conf = tk_split_simplelist(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")), false, true)
4400 else
4401 # conf = tk_split_list(_fromUTF8(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}"))))
4402 conf = tk_split_list(tk_call_without_enc(*(__confinfo_cmd << "-#{slot}")), 0, false, true)
4403 end
4404 conf[__configinfo_struct[:key]] =
4405 conf[__configinfo_struct[:key]][1..-1]
4406
4407 if ( __configinfo_struct[:alias] \
4408 && conf.size == __configinfo_struct[:alias] + 1 )
4409 if conf[__configinfo_struct[:alias]][0] == ?-
4410 conf[__configinfo_struct[:alias]] =
4411 conf[__configinfo_struct[:alias]][1..-1]
4412 end
4413 { conf[0] => conf[1] }
4414 else
4415 { conf.shift => conf }
4416 end
4417
4418 else
4419 ret = {}
4420 # tk_split_simplelist(_fromUTF8(tk_call_without_enc(*__confinfo_cmd))).each{|conflist|
4421 # conf = tk_split_simplelist(conflist)
4422 tk_split_simplelist(tk_call_without_enc(*__confinfo_cmd), false, false).each{|conflist|
4423 conf = tk_split_simplelist(conflist, false, true)
4424 conf[__configinfo_struct[:key]] =
4425 conf[__configinfo_struct[:key]][1..-1]
4426
4427 optkey = conf[__configinfo_struct[:key]]
4428 case optkey
4429 when /^(#{__val2ruby_optkeys().keys.join('|')})$/
4430 method = _symbolkey2str(__val2ruby_optkeys())[optkey]
4431 if ( __configinfo_struct[:default_value] \
4432 && conf[__configinfo_struct[:default_value]] )
4433 optval = conf[__configinfo_struct[:default_value]]
4434 begin
4435 val = method.call(optval)
4436 rescue => e
4437 warn("Warning:: #{e.message} (when #{method}.call(#{optval.inspect})") if $DEBUG
4438 val = optval
4439 end
4440 conf[__configinfo_struct[:default_value]] = val
4441 end
4442 if ( conf[__configinfo_struct[:current_value]] )
4443 optval = conf[__configinfo_struct[:current_value]]
4444 begin
4445 val = method.call(optval)
4446 rescue => e
4447 warn("Warning:: #{e.message} (when #{method}.call(#{optval.inspect})") if $DEBUG
4448 val = optval
4449 end
4450 conf[__configinfo_struct[:current_value]] = val
4451 end
4452
4453 when /^(#{__strval_optkeys.join('|')})$/
4454 # do nothing
4455
4456 when /^(#{__numval_optkeys.join('|')})$/
4457 if ( __configinfo_struct[:default_value] \
4458 && conf[__configinfo_struct[:default_value]] )
4459 begin
4460 conf[__configinfo_struct[:default_value]] =
4461 number(conf[__configinfo_struct[:default_value]])
4462 rescue
4463 conf[__configinfo_struct[:default_value]] = nil
4464 end
4465 end
4466 if ( conf[__configinfo_struct[:current_value]] )
4467 begin
4468 conf[__configinfo_struct[:current_value]] =
4469 number(conf[__configinfo_struct[:current_value]])
4470 rescue
4471 conf[__configinfo_struct[:current_value]] = nil
4472 end
4473 end
4474
4475 when /^(#{__numstrval_optkeys.join('|')})$/
4476 if ( __configinfo_struct[:default_value] \
4477 && conf[__configinfo_struct[:default_value]] )
4478 conf[__configinfo_struct[:default_value]] =
4479 num_or_str(conf[__configinfo_struct[:default_value]])
4480 end
4481 if ( conf[__configinfo_struct[:current_value]] )
4482 conf[__configinfo_struct[:current_value]] =
4483 num_or_str(conf[__configinfo_struct[:current_value]])
4484 end
4485
4486 when /^(#{__boolval_optkeys.join('|')})$/
4487 if ( __configinfo_struct[:default_value] \
4488 && conf[__configinfo_struct[:default_value]] )
4489 begin
4490 conf[__configinfo_struct[:default_value]] =
4491 bool(conf[__configinfo_struct[:default_value]])
4492 rescue
4493 conf[__configinfo_struct[:default_value]] = nil
4494 end
4495 end
4496 if ( conf[__configinfo_struct[:current_value]] )
4497 begin
4498 conf[__configinfo_struct[:current_value]] =
4499 bool(conf[__configinfo_struct[:current_value]])
4500 rescue
4501 conf[__configinfo_struct[:current_value]] = nil
4502 end
4503 end
4504
4505 when /^(#{__listval_optkeys.join('|')})$/
4506 if ( __configinfo_struct[:default_value] \
4507 && conf[__configinfo_struct[:default_value]] )
4508 conf[__configinfo_struct[:default_value]] =
4509 simplelist(conf[__configinfo_struct[:default_value]])
4510 end
4511 if ( conf[__configinfo_struct[:current_value]] )
4512 conf[__configinfo_struct[:current_value]] =
4513 simplelist(conf[__configinfo_struct[:current_value]])
4514 end
4515
4516 when /^(#{__numlistval_optkeys.join('|')})$/
4517 if ( __configinfo_struct[:default_value] \
4518 && conf[__configinfo_struct[:default_value]] \
4519 && conf[__configinfo_struct[:default_value]] =~ /^[0-9]/ )
4520 conf[__configinfo_struct[:default_value]] =
4521 list(conf[__configinfo_struct[:default_value]])
4522 end
4523 if ( conf[__configinfo_struct[:current_value]] \
4524 && conf[__configinfo_struct[:current_value]] =~ /^[0-9]/ )
4525 conf[__configinfo_struct[:current_value]] =
4526 list(conf[__configinfo_struct[:current_value]])
4527 end
4528
4529 when /^(#{__tkvariable_optkeys.join('|')})$/
4530 if ( __configinfo_struct[:default_value] \
4531 && conf[__configinfo_struct[:default_value]] )
4532 v = conf[__configinfo_struct[:default_value]]
4533 if v.empty?
4534 conf[__configinfo_struct[:default_value]] = nil
4535 else
4536 conf[__configinfo_struct[:default_value]] = TkVarAccess.new
4537 end
4538 end
4539 if ( conf[__configinfo_struct[:current_value]] )
4540 v = conf[__configinfo_struct[:current_value]]
4541 if v.empty?
4542 conf[__configinfo_struct[:current_value]] = nil
4543 else
4544 conf[__configinfo_struct[:current_value]] = TkVarAccess.new
4545 end
4546 end
4547
4548 else
4549 if ( __configinfo_struct[:default_value] \
4550 && conf[__configinfo_struct[:default_value]] )
4551 if conf[__configinfo_struct[:default_value]].index('{')
4552 conf[__configinfo_struct[:default_value]] =
4553 tk_split_list(conf[__configinfo_struct[:default_value]])
4554 else
4555 conf[__configinfo_struct[:default_value]] =
4556 tk_tcl2ruby(conf[__configinfo_struct[:default_value]])
4557 end
4558 end
4559 if conf[__configinfo_struct[:current_value]]
4560 if conf[__configinfo_struct[:current_value]].index('{')
4561 conf[__configinfo_struct[:current_value]] =
4562 tk_split_list(conf[__configinfo_struct[:current_value]])
4563 else
4564 conf[__configinfo_struct[:current_value]] =
4565 tk_tcl2ruby(conf[__configinfo_struct[:current_value]])
4566 end
4567 end
4568 end
4569
4570 if ( __configinfo_struct[:alias] \
4571 && conf.size == __configinfo_struct[:alias] + 1 )
4572 if conf[__configinfo_struct[:alias]][0] == ?-
4573 conf[__configinfo_struct[:alias]] =
4574 conf[__configinfo_struct[:alias]][1..-1]
4575 end
4576 ret[conf[0]] = conf[1]
4577 else
4578 ret[conf.shift] = conf
4579 end
4580 }
4581
4582 __font_optkeys.each{|optkey|
4583 optkey = optkey.to_s
4584 fontconf = ret[optkey]
4585 if fontconf.kind_of?(Array)
4586 ret.delete(optkey)
4587 ret.delete('latin' << optkey)
4588 ret.delete('ascii' << optkey)
4589 ret.delete('kanji' << optkey)
4590 fnt = fontconf[__configinfo_struct[:default_value]]
4591 if TkFont.is_system_font?(fnt)
4592 fontconf[__configinfo_struct[:default_value]] \
4593 = TkNamedFont.new(fnt)
4594 end
4595 fontconf[__configinfo_struct[:current_value]] = fontobj(optkey)
4596 ret[optkey] = fontconf
4597 end
4598 }
4599
4600 __methodcall_optkeys.each{|optkey, method|
4601 ret[optkey.to_s] = ['', '', '', self.__send__(method)]
4602 }
4603
4604 ret
4605 end
4606 end
4607 end
4608 end
4609 private :__configinfo_core
4610
4611 def configinfo(slot = nil)
4612 if slot && TkConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__
4613 begin
4614 __configinfo_core(slot)
4615 rescue
4616 Array.new(__configinfo_struct.values.max).unshift(slot.to_s)
4617 end
4618 else
4619 __configinfo_core(slot)
4620 end
4621 end
4622
4623 def current_configinfo(slot = nil)
4624 if TkComm::GET_CONFIGINFO_AS_ARRAY
4625 if slot
4626 org_slot = slot
4627 begin
4628 conf = configinfo(slot)
4629 if ( ! __configinfo_struct[:alias] \
4630 || conf.size > __configinfo_struct[:alias] + 1 )
4631 return {conf[0] => conf[-1]}
4632 end
4633 slot = conf[__configinfo_struct[:alias]]
4634 end while(org_slot != slot)
4635 fail RuntimeError,
4636 "there is a configure alias loop about '#{org_slot}'"
4637 else
4638 ret = {}
4639 configinfo().each{|conf|
4640 if ( ! __configinfo_struct[:alias] \
4641 || conf.size > __configinfo_struct[:alias] + 1 )
4642 ret[conf[0]] = conf[-1]
4643 end
4644 }
4645 ret
4646 end
4647 else # ! TkComm::GET_CONFIGINFO_AS_ARRAY
4648 ret = {}
4649 configinfo(slot).each{|key, conf|
4650 ret[key] = conf[-1] if conf.kind_of?(Array)
4651 }
4652 ret
4653 end
4654 end
4655 end
4656
4657 class TkObject<TkKernel
4658 extend TkCore
4659 include Tk
4660 include TkConfigMethod
4661 include TkBindCore
4662
4663 ### --> definition is moved to TkUtil module
4664 # def path
4665 # @path
4666 # end
4667
4668 def epath
4669 @path
4670 end
4671
4672 def to_eval
4673 @path
4674 end
4675
4676 def tk_send(cmd, *rest)
4677 tk_call(path, cmd, *rest)
4678 end
4679 def tk_send_without_enc(cmd, *rest)
4680 tk_call_without_enc(path, cmd, *rest)
4681 end
4682 def tk_send_with_enc(cmd, *rest)
4683 tk_call_with_enc(path, cmd, *rest)
4684 end
4685 # private :tk_send, :tk_send_without_enc, :tk_send_with_enc
4686
4687 def tk_send_to_list(cmd, *rest)
4688 tk_call_to_list(path, cmd, *rest)
4689 end
4690 def tk_send_to_list_without_enc(cmd, *rest)
4691 tk_call_to_list_without_enc(path, cmd, *rest)
4692 end
4693 def tk_send_to_list_with_enc(cmd, *rest)
4694 tk_call_to_list_with_enc(path, cmd, *rest)
4695 end
4696 def tk_send_to_simplelist(cmd, *rest)
4697 tk_call_to_simplelist(path, cmd, *rest)
4698 end
4699 def tk_send_to_simplelist_without_enc(cmd, *rest)
4700 tk_call_to_simplelist_without_enc(path, cmd, *rest)
4701 end
4702 def tk_send_to_simplelist_with_enc(cmd, *rest)
4703 tk_call_to_simplelist_with_enc(path, cmd, *rest)
4704 end
4705
4706 def method_missing(id, *args)
4707 name = id.id2name
4708 case args.length
4709 when 1
4710 if name[-1] == ?=
4711 configure name[0..-2], args[0]
4712 args[0]
4713 else
4714 configure name, args[0]
4715 self
4716 end
4717 when 0
4718 begin
4719 cget(name)
4720 rescue
4721 if self.kind_of?(TkWindow)
4722 fail NameError,
4723 "unknown option '#{id}' for #{self.inspect} (deleted widget?)"
4724 else
4725 super(id, *args)
4726 end
4727 # fail NameError,
4728 # "undefined local variable or method `#{name}' for #{self.to_s}",
4729 # error_at
4730 end
4731 else
4732 super(id, *args)
4733 # fail NameError, "undefined method `#{name}' for #{self.to_s}", error_at
4734 end
4735 end
4736
4737 =begin
4738 def [](id)
4739 cget(id)
4740 end
4741
4742 def []=(id, val)
4743 configure(id, val)
4744 val
4745 end
4746 =end
4747
4748 def event_generate(context, keys=nil)
4749 if context.kind_of?(TkEvent::Event)
4750 context.generate(self, ((keys)? keys: {}))
4751 elsif keys
4752 #tk_call('event', 'generate', path,
4753 # "<#{tk_event_sequence(context)}>", *hash_kv(keys))
4754 tk_call_without_enc('event', 'generate', path,
4755 "<#{tk_event_sequence(context)}>",
4756 *hash_kv(keys, true))
4757 else
4758 #tk_call('event', 'generate', path, "<#{tk_event_sequence(context)}>")
4759 tk_call_without_enc('event', 'generate', path,
4760 "<#{tk_event_sequence(context)}>")
4761 end
4762 end
4763
4764 def tk_trace_variable(v)
4765 #unless v.kind_of?(TkVariable)
4766 # fail(ArgumentError, "type error (#{v.class}); must be TkVariable object")
4767 #end
4768 v
4769 end
4770 private :tk_trace_variable
4771
4772 def destroy
4773 #tk_call 'trace', 'vdelete', @tk_vn, 'w', @var_id if @var_id
4774 end
4775 end
4776
4777
4778 class TkWindow<TkObject
4779 include TkWinfo
4780 extend TkBindCore
4781 include Tk::Wm_for_General
4782
4783 @@WIDGET_INSPECT_FULL = false
4784 def TkWindow._widget_inspect_full_?
4785 @@WIDGET_INSPECT_FULL
4786 end
4787 def TkWindow._widget_inspect_full_=(mode)
4788 @@WIDGET_INSPECT_FULL = (mode && true) || false
4789 end
4790
4791 TkCommandNames = [].freeze
4792 ## ==> If TkCommandNames[0] is a string (not a null string),
4793 ## assume the string is a Tcl/Tk's create command of the widget class.
4794 WidgetClassName = ''.freeze
4795 # WidgetClassNames[WidgetClassName] = self
4796 ## ==> If self is a widget class, entry to the WidgetClassNames table.
4797 def self.to_eval
4798 self::WidgetClassName
4799 end
4800
4801 def initialize(parent=nil, keys=nil)
4802 if parent.kind_of? Hash
4803 keys = _symbolkey2str(parent)
4804 parent = keys.delete('parent')
4805 widgetname = keys.delete('widgetname')
4806 install_win(if parent then parent.path end, widgetname)
4807 without_creating = keys.delete('without_creating')
4808 # if without_creating && !widgetname
4809 # fail ArgumentError,
4810 # "if set 'without_creating' to true, need to define 'widgetname'"
4811 # end
4812 elsif keys
4813 keys = _symbolkey2str(keys)
4814 widgetname = keys.delete('widgetname')
4815 install_win(if parent then parent.path end, widgetname)
4816 without_creating = keys.delete('without_creating')
4817 # if without_creating && !widgetname
4818 # fail ArgumentError,
4819 # "if set 'without_creating' to true, need to define 'widgetname'"
4820 # end
4821 else
4822 install_win(if parent then parent.path end)
4823 end
4824 if self.method(:create_self).arity == 0
4825 p 'create_self has no arg' if $DEBUG
4826 create_self unless without_creating
4827 if keys
4828 # tk_call @path, 'configure', *hash_kv(keys)
4829 configure(keys)
4830 end
4831 else
4832 p 'create_self has args' if $DEBUG
4833 fontkeys = {}
4834 methodkeys = {}
4835 if keys
4836 #['font', 'kanjifont', 'latinfont', 'asciifont'].each{|key|
4837 # fontkeys[key] = keys.delete(key) if keys.key?(key)
4838 #}
4839 __font_optkeys.each{|key|
4840 fkey = key.to_s
4841 fontkeys[fkey] = keys.delete(fkey) if keys.key?(fkey)
4842
4843 fkey = "kanji#{key}"
4844 fontkeys[fkey] = keys.delete(fkey) if keys.key?(fkey)
4845
4846 fkey = "latin#{key}"
4847 fontkeys[fkey] = keys.delete(fkey) if keys.key?(fkey)
4848
4849 fkey = "ascii#{key}"
4850 fontkeys[fkey] = keys.delete(fkey) if keys.key?(fkey)
4851 }
4852
4853 __optkey_aliases.each{|alias_name, real_name|
4854 alias_name = alias_name.to_s
4855 if keys.has_key?(alias_name)
4856 keys[real_name.to_s] = keys.delete(alias_name)
4857 end
4858 }
4859
4860 __methodcall_optkeys.each{|key|
4861 key = key.to_s
4862 methodkeys[key] = keys.delete(key) if keys.key?(key)
4863 }
4864
4865 __ruby2val_optkeys.each{|key, method|
4866 key = key.to_s
4867 keys[key] = method.call(keys[key]) if keys.has_key?(key)
4868 }
4869 end
4870 if without_creating && keys
4871 #configure(keys)
4872 configure(__conv_keyonly_opts(keys))
4873 else
4874 #create_self(keys)
4875 create_self(__conv_keyonly_opts(keys))
4876 end
4877 font_configure(fontkeys) unless fontkeys.empty?
4878 configure(methodkeys) unless methodkeys.empty?
4879 end
4880 end
4881
4882 def create_self(keys)
4883 # may need to override
4884 begin
4885 cmd = self.class::TkCommandNames[0]
4886 fail unless (cmd.kind_of?(String) && cmd.length > 0)
4887 rescue
4888 fail RuntimeError, "class #{self.class} may be an abstract class"
4889 end
4890
4891 if keys and keys != None
4892 unless TkConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__
4893 tk_call_without_enc(cmd, @path, *hash_kv(keys, true))
4894 else
4895 begin
4896 tk_call_without_enc(cmd, @path, *hash_kv(keys, true))
4897 rescue => e
4898 tk_call_without_enc(cmd, @path)
4899 keys = __check_available_configure_options(keys)
4900 unless keys.empty?
4901 begin
4902 # try to configure
4903 configure(keys)
4904 rescue
4905 # fail => includes options adaptable when creattion only?
4906 begin
4907 tk_call_without_enc('destroy', @path)
4908 rescue
4909 # cannot rescue options error
4910 fail e
4911 else
4912 # re-create widget
4913 tk_call_without_enc(cmd, @path, *hash_kv(keys, true))
4914 end
4915 end
4916 end
4917 end
4918 end
4919 else
4920 tk_call_without_enc(cmd, @path)
4921 end
4922 end
4923 private :create_self
4924
4925 def inspect
4926 if @@WIDGET_INSPECT_FULL
4927 super
4928 else
4929 str = super
4930 str[0..(str.index(' '))] << '@path=' << @path.inspect << '>'
4931 end
4932 end
4933
4934 def exist?
4935 TkWinfo.exist?(self)
4936 end
4937
4938 def bind_class
4939 @db_class || self.class()
4940 end
4941
4942 def database_classname
4943 TkWinfo.classname(self)
4944 end
4945 def database_class
4946 name = database_classname()
4947 if WidgetClassNames[name]
4948 WidgetClassNames[name]
4949 else
4950 TkDatabaseClass.new(name)
4951 end
4952 end
4953 def self.database_classname
4954 self::WidgetClassName
4955 end
4956 def self.database_class
4957 WidgetClassNames[self::WidgetClassName]
4958 end
4959
4960 def pack(keys = nil)
4961 #tk_call_without_enc('pack', epath, *hash_kv(keys, true))
4962 if keys
4963 TkPack.configure(self, keys)
4964 else
4965 TkPack.configure(self)
4966 end
4967 self
4968 end
4969
4970 def pack_in(target, keys = nil)
4971 if keys
4972 keys = keys.dup
4973 keys['in'] = target
4974 else
4975 keys = {'in'=>target}
4976 end
4977 #tk_call 'pack', epath, *hash_kv(keys)
4978 TkPack.configure(self, keys)
4979 self
4980 end
4981
4982 def pack_forget
4983 #tk_call_without_enc('pack', 'forget', epath)
4984 TkPack.forget(self)
4985 self
4986 end
4987 alias unpack pack_forget
4988
4989 def pack_config(slot, value=None)
4990 #if slot.kind_of? Hash
4991 # tk_call 'pack', 'configure', epath, *hash_kv(slot)
4992 #else
4993 # tk_call 'pack', 'configure', epath, "-#{slot}", value
4994 #end
4995 if slot.kind_of? Hash
4996 TkPack.configure(self, slot)
4997 else
4998 TkPack.configure(self, slot=>value)
4999 end
5000 end
5001 alias pack_configure pack_config
5002
5003 def pack_info()
5004 #ilist = list(tk_call('pack', 'info', epath))
5005 #info = {}
5006 #while key = ilist.shift
5007 # info[key[1..-1]] = ilist.shift
5008 #end
5009 #return info
5010 TkPack.info(self)
5011 end
5012
5013 def pack_propagate(mode=None)
5014 #if mode == None
5015 # bool(tk_call('pack', 'propagate', epath))
5016 #else
5017 # tk_call('pack', 'propagate', epath, mode)
5018 # self
5019 #end
5020 if mode == None
5021 TkPack.propagate(self)
5022 else
5023 TkPack.propagate(self, mode)
5024 self
5025 end
5026 end
5027
5028 def pack_slaves()
5029 #list(tk_call('pack', 'slaves', epath))
5030 TkPack.slaves(self)
5031 end
5032
5033 def grid(keys = nil)
5034 #tk_call 'grid', epath, *hash_kv(keys)
5035 if keys
5036 TkGrid.configure(self, keys)
5037 else
5038 TkGrid.configure(self)
5039 end
5040 self
5041 end
5042
5043 def grid_in(target, keys = nil)
5044 if keys
5045 keys = keys.dup
5046 keys['in'] = target
5047 else
5048 keys = {'in'=>target}
5049 end
5050 #tk_call 'grid', epath, *hash_kv(keys)
5051 TkGrid.configure(self, keys)
5052 self
5053 end
5054
5055 def grid_anchor(anchor=None)
5056 if anchor == None
5057 TkGrid.anchor(self)
5058 else
5059 TkGrid.anchor(self, anchor)
5060 self
5061 end
5062 end
5063
5064 def grid_forget
5065 #tk_call('grid', 'forget', epath)
5066 TkGrid.forget(self)
5067 self
5068 end
5069 alias ungrid grid_forget
5070
5071 def grid_bbox(*args)
5072 #list(tk_call('grid', 'bbox', epath, *args))
5073 TkGrid.bbox(self, *args)
5074 end
5075
5076 def grid_config(slot, value=None)
5077 #if slot.kind_of? Hash
5078 # tk_call 'grid', 'configure', epath, *hash_kv(slot)
5079 #else
5080 # tk_call 'grid', 'configure', epath, "-#{slot}", value
5081 #end
5082 if slot.kind_of? Hash
5083 TkGrid.configure(self, slot)
5084 else
5085 TkGrid.configure(self, slot=>value)
5086 end
5087 end
5088 alias grid_configure grid_config
5089
5090 def grid_columnconfig(index, keys)
5091 #tk_call('grid', 'columnconfigure', epath, index, *hash_kv(keys))
5092 TkGrid.columnconfigure(self, index, keys)
5093 end
5094 alias grid_columnconfigure grid_columnconfig
5095 alias grid_column grid_columnconfig
5096
5097 def grid_rowconfig(index, keys)
5098 #tk_call('grid', 'rowconfigure', epath, index, *hash_kv(keys))
5099 TkGrid.rowconfigure(self, index, keys)
5100 end
5101 alias grid_rowconfigure grid_rowconfig
5102 alias grid_row grid_rowconfig
5103
5104 def grid_columnconfiginfo(index, slot=nil)
5105 #if slot
5106 # tk_call('grid', 'columnconfigure', epath, index, "-#{slot}").to_i
5107 #else
5108 # ilist = list(tk_call('grid', 'columnconfigure', epath, index))
5109 # info = {}
5110 # while key = ilist.shift
5111 # info[key[1..-1]] = ilist.shift
5112 # end
5113 # info
5114 #end
5115 TkGrid.columnconfiginfo(self, index, slot)
5116 end
5117
5118 def grid_rowconfiginfo(index, slot=nil)
5119 #if slot
5120 # tk_call('grid', 'rowconfigure', epath, index, "-#{slot}").to_i
5121 #else
5122 # ilist = list(tk_call('grid', 'rowconfigure', epath, index))
5123 # info = {}
5124 # while key = ilist.shift
5125 # info[key[1..-1]] = ilist.shift
5126 # end
5127 # info
5128 #end
5129 TkGrid.rowconfiginfo(self, index, slot)
5130 end
5131
5132 def grid_info()
5133 #list(tk_call('grid', 'info', epath))
5134 TkGrid.info(self)
5135 end
5136
5137 def grid_location(x, y)
5138 #list(tk_call('grid', 'location', epath, x, y))
5139 TkGrid.location(self, x, y)
5140 end
5141
5142 def grid_propagate(mode=None)
5143 #if mode == None
5144 # bool(tk_call('grid', 'propagate', epath))
5145 #else
5146 # tk_call('grid', 'propagate', epath, mode)
5147 # self
5148 #end
5149 if mode == None
5150 TkGrid.propagate(self)
5151 else
5152 TkGrid.propagate(self, mode)
5153 self
5154 end
5155 end
5156
5157 def grid_remove()
5158 #tk_call 'grid', 'remove', epath
5159 TkGrid.remove(self)
5160 self
5161 end
5162
5163 def grid_size()
5164 #list(tk_call('grid', 'size', epath))
5165 TkGrid.size(self)
5166 end
5167
5168 def grid_slaves(args)
5169 #list(tk_call('grid', 'slaves', epath, *hash_kv(args)))
5170 TkGrid.slaves(self, args)
5171 end
5172
5173 def place(keys)
5174 #tk_call 'place', epath, *hash_kv(keys)
5175 TkPlace.configure(self, keys)
5176 self
5177 end
5178
5179 def place_in(target, keys = nil)
5180 if keys
5181 keys = keys.dup
5182 keys['in'] = target
5183 else
5184 keys = {'in'=>target}
5185 end
5186 #tk_call 'place', epath, *hash_kv(keys)
5187 TkPlace.configure(self, keys)
5188 self
5189 end
5190
5191 def place_forget
5192 #tk_call 'place', 'forget', epath
5193 TkPlace.forget(self)
5194 self
5195 end
5196 alias unplace place_forget
5197
5198 def place_config(slot, value=None)
5199 #if slot.kind_of? Hash
5200 # tk_call 'place', 'configure', epath, *hash_kv(slot)
5201 #else
5202 # tk_call 'place', 'configure', epath, "-#{slot}", value
5203 #end
5204 TkPlace.configure(self, slot, value)
5205 end
5206 alias place_configure place_config
5207
5208 def place_configinfo(slot = nil)
5209 # for >= Tk8.4a2 ?
5210 #if slot
5211 # conf = tk_split_list(tk_call('place', 'configure', epath, "-#{slot}") )
5212 # conf[0] = conf[0][1..-1]
5213 # conf
5214 #else
5215 # tk_split_simplelist(tk_call('place',
5216 # 'configure', epath)).collect{|conflist|
5217 # conf = tk_split_simplelist(conflist)
5218 # conf[0] = conf[0][1..-1]
5219 # conf
5220 # }
5221 #end
5222 TkPlace.configinfo(self, slot)
5223 end
5224
5225 def place_info()
5226 #ilist = list(tk_call('place', 'info', epath))
5227 #info = {}
5228 #while key = ilist.shift
5229 # info[key[1..-1]] = ilist.shift
5230 #end
5231 #return info
5232 TkPlace.info(self)
5233 end
5234
5235 def place_slaves()
5236 #list(tk_call('place', 'slaves', epath))
5237 TkPlace.slaves(self)
5238 end
5239
5240 def set_focus(force=false)
5241 if force
5242 tk_call_without_enc('focus', '-force', path)
5243 else
5244 tk_call_without_enc('focus', path)
5245 end
5246 self
5247 end
5248 alias focus set_focus
5249
5250 def grab(opt = nil)
5251 unless opt
5252 tk_call_without_enc('grab', 'set', path)
5253 return self
5254 end
5255
5256 case opt
5257 when 'set', :set
5258 tk_call_without_enc('grab', 'set', path)
5259 return self
5260 when 'global', :global
5261 #return(tk_call('grab', 'set', '-global', path))
5262 tk_call_without_enc('grab', 'set', '-global', path)
5263 return self
5264 when 'release', :release
5265 #return tk_call('grab', 'release', path)
5266 tk_call_without_enc('grab', 'release', path)
5267 return self
5268 when 'current', :current
5269 return window(tk_call_without_enc('grab', 'current', path))
5270 when 'status', :status
5271 return tk_call_without_enc('grab', 'status', path)
5272 else
5273 return tk_call_without_enc('grab', opt, path)
5274 end
5275 end
5276
5277 def grab_current
5278 grab('current')
5279 end
5280 alias current_grab grab_current
5281 def grab_release
5282 grab('release')
5283 end
5284 alias release_grab grab_release
5285 def grab_set
5286 grab('set')
5287 end
5288 alias set_grab grab_set
5289 def grab_set_global
5290 grab('global')
5291 end
5292 alias set_global_grab grab_set_global
5293 def grab_status
5294 grab('status')
5295 end
5296
5297 def lower(below=None)
5298 # below = below.epath if below.kind_of?(TkObject)
5299 below = _epath(below)
5300 tk_call 'lower', epath, below
5301 self
5302 end
5303 alias lower_window lower
5304 def raise(above=None)
5305 #above = above.epath if above.kind_of?(TkObject)
5306 above = _epath(above)
5307 tk_call 'raise', epath, above
5308 self
5309 end
5310 alias raise_window raise
5311
5312 def command(cmd=nil, &b)
5313 if cmd
5314 configure_cmd('command', cmd)
5315 elsif b
5316 configure_cmd('command', Proc.new(&b))
5317 else
5318 cget('command')
5319 end
5320 end
5321
5322 def colormodel(model=None)
5323 tk_call('tk', 'colormodel', path, model)
5324 self
5325 end
5326
5327 def caret(keys=nil)
5328 TkXIM.caret(path, keys)
5329 end
5330
5331 def destroy
5332 super
5333 children = []
5334 rexp = /^#{self.path}\.[^.]+$/
5335 TkCore::INTERP.tk_windows.each{|path, obj|
5336 children << [path, obj] if path =~ rexp
5337 }
5338 if defined?(@cmdtbl)
5339 for id in @cmdtbl
5340 uninstall_cmd id
5341 end
5342 end
5343
5344 children.each{|path, obj|
5345 obj.instance_eval{
5346 if defined?(@cmdtbl)
5347 for id in @cmdtbl
5348 uninstall_cmd id
5349 end
5350 end
5351 }
5352 TkCore::INTERP.tk_windows.delete(path)
5353 }
5354
5355 begin
5356 tk_call_without_enc('destroy', epath)
5357 rescue
5358 end
5359 uninstall_win
5360 end
5361
5362 def wait_visibility(on_thread = true)
5363 if $SAFE >= 4
5364 fail SecurityError, "can't wait visibility at $SAFE >= 4"
5365 end
5366 on_thread &= (Thread.list.size != 1)
5367 if on_thread
5368 INTERP._thread_tkwait('visibility', path)
5369 else
5370 INTERP._invoke('tkwait', 'visibility', path)
5371 end
5372 end
5373 def eventloop_wait_visibility
5374 wait_visibility(false)
5375 end
5376 def thread_wait_visibility
5377 wait_visibility(true)
5378 end
5379 alias wait wait_visibility
5380 alias tkwait wait_visibility
5381 alias eventloop_wait eventloop_wait_visibility
5382 alias eventloop_tkwait eventloop_wait_visibility
5383 alias eventloop_tkwait_visibility eventloop_wait_visibility
5384 alias thread_wait thread_wait_visibility
5385 alias thread_tkwait thread_wait_visibility
5386 alias thread_tkwait_visibility thread_wait_visibility
5387
5388 def wait_destroy(on_thread = true)
5389 if $SAFE >= 4
5390 fail SecurityError, "can't wait destroy at $SAFE >= 4"
5391 end
5392 on_thread &= (Thread.list.size != 1)
5393 if on_thread
5394 INTERP._thread_tkwait('window', epath)
5395 else
5396 INTERP._invoke('tkwait', 'window', epath)
5397 end
5398 end
5399 alias wait_window wait_destroy
5400 def eventloop_wait_destroy
5401 wait_destroy(false)
5402 end
5403 alias eventloop_wait_window eventloop_wait_destroy
5404 def thread_wait_destroy
5405 wait_destroy(true)
5406 end
5407 alias thread_wait_window thread_wait_destroy
5408
5409 alias tkwait_destroy wait_destroy
5410 alias tkwait_window wait_destroy
5411
5412 alias eventloop_tkwait_destroy eventloop_wait_destroy
5413 alias eventloop_tkwait_window eventloop_wait_destroy
5414
5415 alias thread_tkwait_destroy thread_wait_destroy
5416 alias thread_tkwait_window thread_wait_destroy
5417
5418 def bindtags(taglist=nil)
5419 if taglist
5420 fail ArgumentError, "taglist must be Array" unless taglist.kind_of? Array
5421 tk_call('bindtags', path, taglist)
5422 taglist
5423 else
5424 list(tk_call('bindtags', path)).collect{|tag|
5425 if tag.kind_of?(String)
5426 if cls = WidgetClassNames[tag]
5427 cls
5428 elsif btag = TkBindTag.id2obj(tag)
5429 btag
5430 else
5431 tag
5432 end
5433 else
5434 tag
5435 end
5436 }
5437 end
5438 end
5439
5440 def bindtags=(taglist)
5441 bindtags(taglist)
5442 taglist
5443 end
5444
5445 def bindtags_shift
5446 taglist = bindtags
5447 tag = taglist.shift
5448 bindtags(taglist)
5449 tag
5450 end
5451
5452 def bindtags_unshift(tag)
5453 bindtags(bindtags().unshift(tag))
5454 end
5455 end
5456 TkWidget = TkWindow
5457
5458 # freeze core modules
5459 #TclTkLib.freeze
5460 #TclTkIp.freeze
5461 #TkUtil.freeze
5462 #TkKernel.freeze
5463 #TkComm.freeze
5464 #TkComm::Event.freeze
5465 #TkCore.freeze
5466 #Tk.freeze
5467
5468 module Tk
5469 RELEASE_DATE = '2008-05-23'.freeze
5470
5471 autoload :AUTO_PATH, 'tk/variable'
5472 autoload :TCL_PACKAGE_PATH, 'tk/variable'
5473 autoload :PACKAGE_PATH, 'tk/variable'
5474 autoload :TCL_LIBRARY_PATH, 'tk/variable'
5475 autoload :LIBRARY_PATH, 'tk/variable'
5476 autoload :TCL_PRECISION, 'tk/variable'
5477 end
5478
5479 # call setup script for Tk extension libraries (base configuration)
5480 begin
5481 require 'tkextlib/version.rb'
5482 require 'tkextlib/setup.rb'
5483 rescue LoadError
5484 # ignore
5485 end