1 #
2 # tk/text.rb - Tk text classes
3 # by Yukihiro Matsumoto <matz@caelum.co.jp>
4 require 'tk'
5 require 'tk/itemfont'
6 require 'tk/itemconfig'
7 require 'tk/scrollable'
8 require 'tk/txtwin_abst'
9
10 module TkTextTagConfig
11 include TkTreatItemFont
12 include TkItemConfigMethod
13
14 def __item_cget_cmd(id) # id := [ type, tagOrId ]
15 [self.path, id[0], 'cget', id[1]]
16 end
17 private :__item_cget_cmd
18
19 def __item_config_cmd(id) # id := [ type, tagOrId ]
20 [self.path, id[0], 'configure', id[1]]
21 end
22 private :__item_config_cmd
23
24 def __item_pathname(id)
25 if id.kind_of?(Array)
26 id = tagid(id[1])
27 end
28 [self.path, id].join(';')
29 end
30 private :__item_pathname
31
32 def tag_cget(tagOrId, option)
33 itemcget(['tag', tagOrId], option)
34 end
35 def tag_cget_strict(tagOrId, option)
36 itemcget_strict(['tag', tagOrId], option)
37 end
38 def tag_configure(tagOrId, slot, value=None)
39 itemconfigure(['tag', tagOrId], slot, value)
40 end
41 def tag_configinfo(tagOrId, slot=nil)
42 itemconfiginfo(['tag', tagOrId], slot)
43 end
44 def current_tag_configinfo(tagOrId, slot=nil)
45 current_itemconfiginfo(['tag', tagOrId], slot)
46 end
47
48 def window_cget(tagOrId, option)
49 itemcget(['window', tagOrId], option)
50 end
51 def window_cget_strict(tagOrId, option)
52 itemcget_strict(['window', tagOrId], option)
53 end
54 def window_configure(tagOrId, slot, value=None)
55 itemconfigure(['window', tagOrId], slot, value)
56 end
57 def window_configinfo(tagOrId, slot=nil)
58 itemconfiginfo(['window', tagOrId], slot)
59 end
60 def current_window_configinfo(tagOrId, slot=nil)
61 current_itemconfiginfo(['window', tagOrId], slot)
62 end
63
64 private :itemcget, :itemcget_strict
65 private :itemconfigure, :itemconfiginfo, :current_itemconfiginfo
66 end
67
68 class Tk::Text<TkTextWin
69 ItemConfCMD = ['tag'.freeze, 'configure'.freeze].freeze
70 #include TkTreatTextTagFont
71 include TkTextTagConfig
72 include Scrollable
73
74 #######################################
75
76 module IndexModMethods
77 def +(mod)
78 return chars(mod) if mod.kind_of?(Numeric)
79
80 mod = mod.to_s
81 if mod =~ /^\s*[+-]?\d/
82 Tk::Text::IndexString.new(String.new(id) << ' + ' << mod)
83 else
84 Tk::Text::IndexString.new(String.new(id) << ' ' << mod)
85 end
86 end
87
88 def -(mod)
89 return chars(-mod) if mod.kind_of?(Numeric)
90
91 mod = mod.to_s
92 if mod =~ /^\s*[+-]?\d/
93 Tk::Text::IndexString.new(String.new(id) << ' - ' << mod)
94 elsif mod =~ /^\s*[-]\s+(\d.*)$/
95 Tk::Text::IndexString.new(String.new(id) << ' - -' << $1)
96 else
97 Tk::Text::IndexString.new(String.new(id) << ' ' << mod)
98 end
99 end
100
101 def chars(mod)
102 fail ArgumentError, 'expect Integer' unless mod.kind_of?(Integer)
103 if mod < 0
104 Tk::Text::IndexString.new(String.new(id) << ' ' << mod.to_s << ' chars')
105 else
106 Tk::Text::IndexString.new(String.new(id) << ' + ' << mod.to_s << ' chars')
107 end
108 end
109 alias char chars
110
111 def display_chars(mod)
112 # Tk8.5 feature
113 fail ArgumentError, 'expect Integer' unless mod.kind_of?(Integer)
114 if mod < 0
115 Tk::Text::IndexString.new(String.new(id) << ' ' << mod.to_s << ' display chars')
116 else
117 Tk::Text::IndexString.new(String.new(id) << ' + ' << mod.to_s << ' display chars')
118 end
119 end
120 alias display_char display_chars
121
122 def any_chars(mod)
123 # Tk8.5 feature
124 fail ArgumentError, 'expect Integer' unless mod.kind_of?(Integer)
125 if mod < 0
126 Tk::Text::IndexString.new(String.new(id) << ' ' << mod.to_s << ' any chars')
127 else
128 Tk::Text::IndexString.new(String.new(id) << ' + ' << mod.to_s << ' any chars')
129 end
130 end
131 alias any_char any_chars
132
133 def indices(mod)
134 # Tk8.5 feature
135 fail ArgumentError, 'expect Integer' unless mod.kind_of?(Integer)
136 if mod < 0
137 Tk::Text::IndexString.new(String.new(id) << ' ' << mod.to_s << ' indices')
138 else
139 Tk::Text::IndexString.new(String.new(id) << ' + ' << mod.to_s << ' indices')
140 end
141 end
142
143 def display_indices(mod)
144 # Tk8.5 feature
145 fail ArgumentError, 'expect Integer' unless mod.kind_of?(Integer)
146 if mod < 0
147 Tk::Text::IndexString.new(String.new(id) << ' ' << mod.to_s << ' display indices')
148 else
149 Tk::Text::IndexString.new(String.new(id) << ' + ' << mod.to_s << ' display indices')
150 end
151 end
152
153 def any_indices(mod)
154 # Tk8.5 feature
155 fail ArgumentError, 'expect Integer' unless mod.kind_of?(Integer)
156 if mod < 0
157 Tk::Text::IndexString.new(String.new(id) << ' ' << mod.to_s << ' any indices')
158 else
159 Tk::Text::IndexString.new(String.new(id) << ' + ' << mod.to_s << ' any indices')
160 end
161 end
162
163 def lines(mod)
164 fail ArgumentError, 'expect Integer' unless mod.kind_of?(Integer)
165 if mod < 0
166 Tk::Text::IndexString.new(String.new(id) << ' ' << mod.to_s << ' lines')
167 else
168 Tk::Text::IndexString.new(String.new(id) << ' + ' << mod.to_s << ' lines')
169 end
170 end
171 alias line lines
172
173 def display_lines(mod)
174 # Tk8.5 feature
175 fail ArgumentError, 'expect Integer' unless mod.kind_of?(Integer)
176 if mod < 0
177 Tk::Text::IndexString.new(String.new(id) << ' ' << mod.to_s << ' display_lines')
178 else
179 Tk::Text::IndexString.new(String.new(id) << ' + ' << mod.to_s << ' display lines')
180 end
181 end
182 alias display_line display_lines
183
184 def any_lines(mod)
185 # Tk8.5 feature
186 fail ArgumentError, 'expect Integer' unless mod.kind_of?(Integer)
187 if mod < 0
188 Tk::Text::IndexString.new(String.new(id) << ' ' << mod.to_s << ' any_lines')
189 else
190 Tk::Text::IndexString.new(String.new(id) << ' + ' << mod.to_s << ' any lines')
191 end
192 end
193 alias any_line any_lines
194
195 def linestart
196 Tk::Text::IndexString.new(String.new(id) << ' linestart')
197 end
198 def lineend
199 Tk::Text::IndexString.new(String.new(id) << ' lineend')
200 end
201
202 def display_linestart
203 # Tk8.5 feature
204 Tk::Text::IndexString.new(String.new(id) << ' display linestart')
205 end
206 def display_lineend
207 # Tk8.5 feature
208 Tk::Text::IndexString.new(String.new(id) << ' display lineend')
209 end
210
211 def wordstart
212 Tk::Text::IndexString.new(String.new(id) << ' wordstart')
213 end
214 def wordend
215 Tk::Text::IndexString.new(String.new(id) << ' wordend')
216 end
217
218 def display_wordstart
219 # Tk8.5 feature
220 Tk::Text::IndexString.new(String.new(id) << ' display wordstart')
221 end
222 def display_wordend
223 # Tk8.5 feature
224 Tk::Text::IndexString.new(String.new(id) << ' display wordend')
225 end
226 end
227
228 class IndexString < String
229 include IndexModMethods
230
231 def self.at(x,y)
232 self.new("@#{x},#{y}")
233 end
234
235 def self.new(str)
236 if str.kind_of?(String)
237 super(str)
238 elsif str.kind_of?(Symbol)
239 super(str.to_s)
240 else
241 str
242 end
243 end
244
245 def id
246 self
247 end
248 end
249
250 #######################################
251
252 TkCommandNames = ['text'.freeze].freeze
253 WidgetClassName = 'Text'.freeze
254 WidgetClassNames[WidgetClassName] = self
255
256 def self.new(*args, &block)
257 obj = super(*args){}
258 obj.init_instance_variable
259 if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!!
260 obj.instance_exec(obj, &block) if defined? yield
261 else
262 obj.instance_eval(&block) if defined? yield
263 end
264 obj
265 end
266
267 def init_instance_variable
268 @cmdtbl = []
269 @tags = {}
270 end
271
272 def __destroy_hook__
273 TkTextTag::TTagID_TBL.mutex.synchronize{
274 TkTextTag::TTagID_TBL.delete(@path)
275 }
276 TkTextTag::TMarkID_TBL.mutex.synchronize{
277 TkTextMark::TMarkID_TBL.delete(@path)
278 }
279 end
280
281 def create_self(keys)
282 #if keys and keys != None
283 # #tk_call_without_enc('text', @path, *hash_kv(keys, true))
284 # tk_call_without_enc(self.class::TkCommandNames[0], @path,
285 # *hash_kv(keys, true))
286 #else
287 # #tk_call_without_enc('text', @path)
288 # tk_call_without_enc(self.class::TkCommandNames[0], @path)
289 #end
290 super(keys)
291 init_instance_variable
292 end
293 private :create_self
294
295 def __strval_optkeys
296 super() << 'inactiveseletcionbackground'
297 end
298 private :__strval_optkeys
299
300 def self.at(x, y)
301 Tk::Text::IndexString.at(x, y)
302 end
303
304 def at(x, y)
305 Tk::Text::IndexString.at(x, y)
306 end
307
308 def index(idx)
309 Tk::Text::IndexString.new(tk_send_without_enc('index',
310 _get_eval_enc_str(idx)))
311 end
312
313 def get_displaychars(*index)
314 # Tk8.5 feature
315 get('-displaychars', *index)
316 end
317
318 def value
319 _fromUTF8(tk_send_without_enc('get', "1.0", "end - 1 char"))
320 end
321
322 def value= (val)
323 tk_send_without_enc('delete', "1.0", 'end')
324 tk_send_without_enc('insert', "1.0", _get_eval_enc_str(val))
325 val
326 end
327
328 def clear
329 tk_send_without_enc('delete', "1.0", 'end')
330 self
331 end
332 alias erase clear
333
334 def _addcmd(cmd)
335 @cmdtbl.push cmd
336 end
337
338 def _addtag(name, obj)
339 @tags[name] = obj
340 end
341
342 def tagid(tag)
343 if tag.kind_of?(TkTextTag) \
344 || tag.kind_of?(TkTextMark) \
345 || tag.kind_of?(TkTextImage) \
346 || tag.kind_of?(TkTextWindow)
347 tag.id
348 else
349 tag # maybe an Array of configure paramters
350 end
351 end
352 private :tagid
353
354 def tagid2obj(tagid)
355 if @tags[tagid]
356 @tags[tagid]
357 else
358 tagid
359 end
360 end
361
362 def tag_names(index=None)
363 #tk_split_simplelist(_fromUTF8(tk_send_without_enc('tag', 'names', _get_eval_enc_str(index)))).collect{|elt|
364 tk_split_simplelist(tk_send_without_enc('tag', 'names', _get_eval_enc_str(index)), false, true).collect{|elt|
365 tagid2obj(elt)
366 }
367 end
368
369 def mark_names
370 #tk_split_simplelist(_fromUTF8(tk_send_without_enc('mark', 'names'))).collect{|elt|
371 tk_split_simplelist(tk_send_without_enc('mark', 'names'), false, true).collect{|elt|
372 tagid2obj(elt)
373 }
374 end
375
376 def mark_gravity(mark, direction=nil)
377 if direction
378 tk_send_without_enc('mark', 'gravity',
379 _get_eval_enc_str(mark), direction)
380 self
381 else
382 tk_send_without_enc('mark', 'gravity', _get_eval_enc_str(mark))
383 end
384 end
385
386 def mark_set(mark, index)
387 tk_send_without_enc('mark', 'set', _get_eval_enc_str(mark),
388 _get_eval_enc_str(index))
389 self
390 end
391 alias set_mark mark_set
392
393 def mark_unset(*marks)
394 tk_send_without_enc('mark', 'unset',
395 *(marks.collect{|mark| _get_eval_enc_str(mark)}))
396 self
397 end
398 alias unset_mark mark_unset
399
400 def mark_next(index)
401 tagid2obj(_fromUTF8(tk_send_without_enc('mark', 'next',
402 _get_eval_enc_str(index))))
403 end
404 alias next_mark mark_next
405
406 def mark_previous(index)
407 tagid2obj(_fromUTF8(tk_send_without_enc('mark', 'previous',
408 _get_eval_enc_str(index))))
409 end
410 alias previous_mark mark_previous
411
412 def image_cget_strict(index, slot)
413 case slot.to_s
414 when 'text', 'label', 'show', 'data', 'file'
415 _fromUTF8(tk_send_without_enc('image', 'cget',
416 _get_eval_enc_str(index), "-#{slot}"))
417 else
418 tk_tcl2ruby(_fromUTF8(tk_send_without_enc('image', 'cget',
419 _get_eval_enc_str(index),
420 "-#{slot}")))
421 end
422 end
423
424 def image_cget(index, slot)
425 unless TkItemConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__
426 image_cget_strict(index, slot)
427 else
428 begin
429 image_cget_strict(index, slot)
430 rescue => e
431 begin
432 if current_image_configinfo(index).has_key?(slot.to_s)
433 # not tag error & option is known -> error on known option
434 fail e
435 else
436 # not tag error & option is unknown
437 nil
438 end
439 rescue
440 fail e # tag error
441 end
442 end
443 end
444 end
445
446 def image_configure(index, slot, value=None)
447 if slot.kind_of?(Hash)
448 _fromUTF8(tk_send_without_enc('image', 'configure',
449 _get_eval_enc_str(index),
450 *hash_kv(slot, true)))
451 else
452 _fromUTF8(tk_send_without_enc('image', 'configure',
453 _get_eval_enc_str(index),
454 "-#{slot}",
455 _get_eval_enc_str(value)))
456 end
457 self
458 end
459
460 def image_configinfo(index, slot = nil)
461 if TkComm::GET_CONFIGINFO_AS_ARRAY
462 if slot
463 case slot.to_s
464 when 'text', 'label', 'show', 'data', 'file'
465 #conf = tk_split_simplelist(_fromUTF8(tk_send_without_enc('image', 'configure', _get_eval_enc_str(index), "-#{slot}")))
466 conf = tk_split_simplelist(tk_send_without_enc('image', 'configure', _get_eval_enc_str(index), "-#{slot}"), false, true)
467 else
468 #conf = tk_split_list(_fromUTF8(tk_send_without_enc('image', 'configure', _get_eval_enc_str(index), "-#{slot}")))
469 conf = tk_split_list(tk_send_without_enc('image', 'configure', _get_eval_enc_str(index), "-#{slot}"), 0, false, true)
470 end
471 conf[0] = conf[0][1..-1]
472 conf
473 else
474 # tk_split_simplelist(_fromUTF8(tk_send_without_enc('image', 'configure', _get_eval_enc_str(index)))).collect{|conflist|
475 # conf = tk_split_simplelist(conflist)
476 tk_split_simplelist(tk_send_without_enc('image', 'configure', _get_eval_enc_str(index)), false, false).collect{|conflist|
477 conf = tk_split_simplelist(conflist, false, true)
478 conf[0] = conf[0][1..-1]
479 case conf[0]
480 when 'text', 'label', 'show', 'data', 'file'
481 else
482 if conf[3]
483 if conf[3].index('{')
484 conf[3] = tk_split_list(conf[3])
485 else
486 conf[3] = tk_tcl2ruby(conf[3])
487 end
488 end
489 if conf[4]
490 if conf[4].index('{')
491 conf[4] = tk_split_list(conf[4])
492 else
493 conf[4] = tk_tcl2ruby(conf[4])
494 end
495 end
496 end
497 conf[1] = conf[1][1..-1] if conf.size == 2 # alias info
498 conf
499 }
500 end
501 else # ! TkComm::GET_CONFIGINFO_AS_ARRAY
502 if slot
503 case slot.to_s
504 when 'text', 'label', 'show', 'data', 'file'
505 #conf = tk_split_simplelist(_fromUTF8(tk_send_without_enc('image', 'configure', _get_eval_enc_str(index), "-#{slot}")))
506 conf = tk_split_simplelist(tk_send_without_enc('image', 'configure', _get_eval_enc_str(index), "-#{slot}"), false, true)
507 else
508 #conf = tk_split_list(_fromUTF8(tk_send_without_enc('image', 'configure', _get_eval_enc_str(index), "-#{slot}")))
509 conf = tk_split_list(tk_send_without_enc('image', 'configure', _get_eval_enc_str(index), "-#{slot}"), 0, false, true)
510 end
511 key = conf.shift[1..-1]
512 { key => conf }
513 else
514 ret = {}
515 #tk_split_simplelist(_fromUTF8(tk_send_without_enc('image', 'configure', _get_eval_enc_str(index)))).each{|conflist|
516 # conf = tk_split_simplelist(conflist)
517 tk_split_simplelist(tk_send_without_enc('image', 'configure', _get_eval_enc_str(index)), false, false).each{|conflist|
518 conf = tk_split_simplelist(conflist, false, true)
519 key = conf.shift[1..-1]
520 case key
521 when 'text', 'label', 'show', 'data', 'file'
522 else
523 if conf[2]
524 if conf[2].index('{')
525 conf[2] = tk_split_list(conf[2])
526 else
527 conf[2] = tk_tcl2ruby(conf[2])
528 end
529 end
530 if conf[3]
531 if conf[3].index('{')
532 conf[3] = tk_split_list(conf[3])
533 else
534 conf[3] = tk_tcl2ruby(conf[3])
535 end
536 end
537 end
538 if conf.size == 1
539 ret[key] = conf[0][1..-1] # alias info
540 else
541 ret[key] = conf
542 end
543 }
544 ret
545 end
546 end
547 end
548
549 def current_image_configinfo(index, slot = nil)
550 if TkComm::GET_CONFIGINFO_AS_ARRAY
551 if slot
552 conf = image_configinfo(index, slot)
553 {conf[0] => conf[4]}
554 else
555 ret = {}
556 image_configinfo(index).each{|conf|
557 ret[conf[0]] = conf[4] if conf.size > 2
558 }
559 ret
560 end
561 else # ! TkComm::GET_CONFIGINFO_AS_ARRAY
562 ret = {}
563 image_configinfo(index, slot).each{|k, conf|
564 ret[k] = conf[-1] if conf.kind_of?(Array)
565 }
566 ret
567 end
568 end
569
570 def image_names
571 #tk_split_simplelist(_fromUTF8(tk_send_without_enc('image', 'names'))).collect{|elt|
572 tk_split_simplelist(tk_send_without_enc('image', 'names'), false, true).collect{|elt|
573 tagid2obj(elt)
574 }
575 end
576
577 def set_insert(index)
578 tk_send_without_enc('mark','set','insert', _get_eval_enc_str(index))
579 self
580 end
581
582 def set_current(index)
583 tk_send_without_enc('mark','set','current', _get_eval_enc_str(index))
584 self
585 end
586
587 def insert(index, chars, *tags)
588 if tags[0].kind_of?(Array)
589 # multiple chars-taglist argument :: str, [tag,...], str, [tag,...], ...
590 args = [chars]
591 while tags.size > 0
592 args << tags.shift.collect{|x|_get_eval_string(x)}.join(' ') # taglist
593 args << tags.shift if tags.size > 0 # chars
594 end
595 super(index, *args)
596 else
597 # single chars-taglist argument :: str, tag, tag, ...
598 if tags.size == 0
599 super(index, chars)
600 else
601 super(index, chars, tags.collect{|x|_get_eval_string(x)}.join(' '))
602 end
603 end
604 end
605
606 def destroy
607 @tags = {} unless @tags
608 @tags.each_value do |t|
609 t.destroy
610 end
611 super()
612 end
613
614 def backspace
615 self.delete 'insert'
616 end
617
618 def bbox(index)
619 list(tk_send_without_enc('bbox', _get_eval_enc_str(index)))
620 end
621
622 def compare(idx1, op, idx2)
623 bool(tk_send_without_enc('compare', _get_eval_enc_str(idx1),
624 op, _get_eval_enc_str(idx2)))
625 end
626
627 def count(idx1, idx2, *opts)
628 # opts are Tk8.5 feature
629 cnt = 0
630 args = opts.collect{|opt|
631 str = opt.to_s
632 cnt += 1 if str != 'update'
633 '-' + str
634 }
635 args << _get_eval_enc_str(idx1) << _get_eval_enc_str(idx2)
636 if cnt <= 1
637 number(tk_send_without_enc('count', *opts))
638 else
639 list(tk_send_without_enc('count', *opts))
640 end
641 end
642
643 def count_info(idx1, idx2, update=true)
644 # Tk8.5 feature
645 opts = [
646 :chars, :displaychars, :displayindices, :displaylines,
647 :indices, :lines, :xpixels, :ypixels
648 ]
649 if update
650 lst = count(idx1, idx2, :update, *opts)
651 else
652 lst = count(idx1, idx2, *opts)
653 end
654 info = {}
655 opts.each_with_index{|key, idx| info[key] = lst[idx]}
656 info
657 end
658
659 def peer_names()
660 # Tk8.5 feature
661 list(tk_send_without_enc('peer', 'names'))
662 end
663
664 def replace(idx1, idx2, *opts)
665 tk_send('replace', idx1, idx2, *opts)
666 self
667 end
668
669 def debug
670 bool(tk_send_without_enc('debug'))
671 end
672 def debug=(boolean)
673 tk_send_without_enc('debug', boolean)
674 #self
675 boolean
676 end
677
678 def dlineinfo(index)
679 list(tk_send_without_enc('dlineinfo', _get_eval_enc_str(index)))
680 end
681
682 def modified?
683 bool(tk_send_without_enc('edit', 'modified'))
684 end
685 def modified(mode)
686 tk_send_without_enc('edit', 'modified', mode)
687 self
688 end
689 def modified=(mode)
690 modified(mode)
691 mode
692 end
693
694 def edit_redo
695 tk_send_without_enc('edit', 'redo')
696 self
697 end
698 def edit_reset
699 tk_send_without_enc('edit', 'reset')
700 self
701 end
702 def edit_separator
703 tk_send_without_enc('edit', 'separator')
704 self
705 end
706 def edit_undo
707 tk_send_without_enc('edit', 'undo')
708 self
709 end
710
711 def xview_pickplace(index)
712 tk_send_without_enc('xview', '-pickplace', _get_eval_enc_str(index))
713 self
714 end
715
716 def yview_pickplace(index)
717 tk_send_without_enc('yview', '-pickplace', _get_eval_enc_str(index))
718 self
719 end
720
721 def text_copy
722 # Tk8.4 feature
723 tk_call_without_enc('tk_textCopy', @path)
724 self
725 end
726
727 def text_cut
728 # Tk8.4 feature
729 tk_call_without_enc('tk_textCut', @path)
730 self
731 end
732
733 def text_paste
734 # Tk8.4 feature
735 tk_call_without_enc('tk_textPaste', @path)
736 self
737 end
738
739 def tag_add(tag, index1, index2=None)
740 tk_send_without_enc('tag', 'add', _get_eval_enc_str(tag),
741 _get_eval_enc_str(index1),
742 _get_eval_enc_str(index2))
743 self
744 end
745 alias addtag tag_add
746 alias add_tag tag_add
747
748 def tag_delete(*tags)
749 tk_send_without_enc('tag', 'delete',
750 *(tags.collect{|tag| _get_eval_enc_str(tag)}))
751 TkTextTag::TTagID_TBL.mutex.synchronize{
752 if TkTextTag::TTagID_TBL[@path]
753 tags.each{|tag|
754 if tag.kind_of?(TkTextTag)
755 TkTextTag::TTagID_TBL[@path].delete(tag.id)
756 else
757 TkTextTag::TTagID_TBL[@path].delete(tag)
758 end
759 }
760 end
761 }
762 self
763 end
764 alias deltag tag_delete
765 alias delete_tag tag_delete
766
767 #def tag_bind(tag, seq, cmd=Proc.new, *args)
768 # _bind([@path, 'tag', 'bind', tag], seq, cmd, *args)
769 # self
770 #end
771 def tag_bind(tag, seq, *args)
772 # if args[0].kind_of?(Proc) || args[0].kind_of?(Method)
773 if TkComm._callback_entry?(args[0]) || !block_given?
774 cmd = args.shift
775 else
776 cmd = Proc.new
777 end
778 _bind([@path, 'tag', 'bind', tag], seq, cmd, *args)
779 self
780 end
781
782 #def tag_bind_append(tag, seq, cmd=Proc.new, *args)
783 # _bind_append([@path, 'tag', 'bind', tag], seq, cmd, *args)
784 # self
785 #end
786 def tag_bind_append(tag, seq, *args)
787 # if args[0].kind_of?(Proc) || args[0].kind_of?(Method)
788 if TkComm._callback_entry?(args[0]) || !block_given?
789 cmd = args.shift
790 else
791 cmd = Proc.new
792 end
793 _bind_append([@path, 'tag', 'bind', tag], seq, cmd, *args)
794 self
795 end
796
797 def tag_bind_remove(tag, seq)
798 _bind_remove([@path, 'tag', 'bind', tag], seq)
799 self
800 end
801
802 def tag_bindinfo(tag, context=nil)
803 _bindinfo([@path, 'tag', 'bind', tag], context)
804 end
805
806 =begin
807 def tag_cget(tag, key)
808 case key.to_s
809 when 'text', 'label', 'show', 'data', 'file'
810 tk_call_without_enc(@path, 'tag', 'cget',
811 _get_eval_enc_str(tag), "-#{key}")
812 when 'font', 'kanjifont'
813 #fnt = tk_tcl2ruby(tk_send('tag', 'cget', tag, "-#{key}"))
814 fnt = tk_tcl2ruby(_fromUTF8(tk_send_without_enc('tag','cget',_get_eval_enc_str(tag),'-font')))
815 unless fnt.kind_of?(TkFont)
816 fnt = tagfontobj(tag, fnt)
817 end
818 if key.to_s == 'kanjifont' && JAPANIZED_TK && TK_VERSION =~ /^4\.*/
819 # obsolete; just for compatibility
820 fnt.kanji_font
821 else
822 fnt
823 end
824 else
825 tk_tcl2ruby(_fromUTF8(tk_call_without_enc(@path,'tag','cget',_get_eval_enc_str(tag),"-#{key}")))
826 end
827 end
828
829 def tag_configure(tag, key, val=None)
830 if key.kind_of?(Hash)
831 key = _symbolkey2str(key)
832 if ( key['font'] || key['kanjifont'] \
833 || key['latinfont'] || key['asciifont'] )
834 tagfont_configure(tag, key)
835 else
836 tk_send_without_enc('tag', 'configure', _get_eval_enc_str(tag),
837 *hash_kv(key, true))
838 end
839
840 else
841 if key == 'font' || key == :font ||
842 key == 'kanjifont' || key == :kanjifont ||
843 key == 'latinfont' || key == :latinfont ||
844 key == 'asciifont' || key == :asciifont
845 if val == None
846 tagfontobj(tag)
847 else
848 tagfont_configure(tag, {key=>val})
849 end
850 else
851 tk_send_without_enc('tag', 'configure', _get_eval_enc_str(tag),
852 "-#{key}", _get_eval_enc_str(val))
853 end
854 end
855 self
856 end
857
858 def tag_configinfo(tag, key=nil)
859 if TkComm::GET_CONFIGINFO_AS_ARRAY
860 if key
861 case key.to_s
862 when 'text', 'label', 'show', 'data', 'file'
863 conf = tk_split_simplelist(_fromUTF8(tk_send_without_enc('tag','configure',_get_eval_enc_str(tag),"-#{key}")))
864 when 'font', 'kanjifont'
865 conf = tk_split_simplelist(_fromUTF8(tk_send_without_enc('tag','configure',_get_eval_enc_str(tag),"-#{key}")))
866 conf[4] = tagfont_configinfo(tag, conf[4])
867 else
868 conf = tk_split_list(_fromUTF8(tk_send_without_enc('tag','configure',_get_eval_enc_str(tag),"-#{key}")))
869 end
870 conf[0] = conf[0][1..-1]
871 conf
872 else
873 ret = tk_split_simplelist(_fromUTF8(tk_send('tag','configure',_get_eval_enc_str(tag)))).collect{|conflist|
874 conf = tk_split_simplelist(conflist)
875 conf[0] = conf[0][1..-1]
876 case conf[0]
877 when 'text', 'label', 'show', 'data', 'file'
878 else
879 if conf[3]
880 if conf[3].index('{')
881 conf[3] = tk_split_list(conf[3])
882 else
883 conf[3] = tk_tcl2ruby(conf[3])
884 end
885 end
886 if conf[4]
887 if conf[4].index('{')
888 conf[4] = tk_split_list(conf[4])
889 else
890 conf[4] = tk_tcl2ruby(conf[4])
891 end
892 end
893 end
894 conf[1] = conf[1][1..-1] if conf.size == 2 # alias info
895 conf
896 }
897 fontconf = ret.assoc('font')
898 if fontconf
899 ret.delete_if{|item| item[0] == 'font' || item[0] == 'kanjifont'}
900 fontconf[4] = tagfont_configinfo(tag, fontconf[4])
901 ret.push(fontconf)
902 else
903 ret
904 end
905 end
906 else # ! TkComm::GET_CONFIGINFO_AS_ARRAY
907 if key
908 case key.to_s
909 when 'text', 'label', 'show', 'data', 'file'
910 conf = tk_split_simplelist(_fromUTF8(tk_send_without_enc('tag','configure',_get_eval_enc_str(tag),"-#{key}")))
911 when 'font', 'kanjifont'
912 conf = tk_split_simplelist(_fromUTF8(tk_send_without_enc('tag','configure',_get_eval_enc_str(tag),"-#{key}")))
913 conf[4] = tagfont_configinfo(tag, conf[4])
914 else
915 conf = tk_split_list(_fromUTF8(tk_send_without_enc('tag','configure',_get_eval_enc_str(tag),"-#{key}")))
916 end
917 key = conf.shift[1..-1]
918 { key => conf }
919 else
920 ret = {}
921 tk_split_simplelist(_fromUTF8(tk_send('tag','configure',_get_eval_enc_str(tag)))).each{|conflist|
922 conf = tk_split_simplelist(conflist)
923 key = conf.shift[1..-1]
924 case key
925 when 'text', 'label', 'show', 'data', 'file'
926 else
927 if conf[2]
928 if conf[2].index('{')
929 conf[2] = tk_split_list(conf[2])
930 else
931 conf[2] = tk_tcl2ruby(conf[2])
932 end
933 end
934 if conf[3]
935 if conf[3].index('{')
936 conf[3] = tk_split_list(conf[3])
937 else
938 conf[3] = tk_tcl2ruby(conf[3])
939 end
940 end
941 end
942 if conf.size == 1
943 ret[key] = conf[0][1..-1] # alias info
944 else
945 ret[key] = conf
946 end
947 }
948 fontconf = ret['font']
949 if fontconf
950 ret.delete('font')
951 ret.delete('kanjifont')
952 fontconf[3] = tagfont_configinfo(tag, fontconf[3])
953 ret['font'] = fontconf
954 end
955 ret
956 end
957 end
958 end
959
960 def current_tag_configinfo(tag, key=nil)
961 if TkComm::GET_CONFIGINFO_AS_ARRAY
962 if key
963 conf = tag_configinfo(tag, key)
964 {conf[0] => conf[4]}
965 else
966 ret = {}
967 tag_configinfo(tag).each{|conf|
968 ret[conf[0]] = conf[4] if conf.size > 2
969 }
970 ret
971 end
972 else # ! TkComm::GET_CONFIGINFO_AS_ARRAY
973 ret = {}
974 tag_configinfo(tag, key).each{|k, conf|
975 ret[k] = conf[-1] if conf.kind_of?(Array)
976 }
977 ret
978 end
979 end
980 =end
981
982 def tag_raise(tag, above=None)
983 tk_send_without_enc('tag', 'raise', _get_eval_enc_str(tag),
984 _get_eval_enc_str(above))
985 self
986 end
987
988 def tag_lower(tag, below=None)
989 tk_send_without_enc('tag', 'lower', _get_eval_enc_str(tag),
990 _get_eval_enc_str(below))
991 self
992 end
993
994 def tag_remove(tag, *indices)
995 tk_send_without_enc('tag', 'remove', _get_eval_enc_str(tag),
996 *(indices.collect{|idx| _get_eval_enc_str(idx)}))
997 self
998 end
999
1000 def tag_ranges(tag)
1001 #l = tk_split_simplelist(tk_send_without_enc('tag', 'ranges',
1002 # _get_eval_enc_str(tag)))
1003 l = tk_split_simplelist(tk_send_without_enc('tag', 'ranges',
1004 _get_eval_enc_str(tag)),
1005 false, true)
1006 r = []
1007 while key=l.shift
1008 r.push [Tk::Text::IndexString.new(key), Tk::Text::IndexString.new(l.shift)]
1009 end
1010 r
1011 end
1012
1013 def tag_nextrange(tag, first, last=None)
1014 simplelist(tk_send_without_enc('tag', 'nextrange',
1015 _get_eval_enc_str(tag),
1016 _get_eval_enc_str(first),
1017 _get_eval_enc_str(last))).collect{|idx|
1018 Tk::Text::IndexString.new(idx)
1019 }
1020 end
1021
1022 def tag_prevrange(tag, first, last=None)
1023 simplelist(tk_send_without_enc('tag', 'prevrange',
1024 _get_eval_enc_str(tag),
1025 _get_eval_enc_str(first),
1026 _get_eval_enc_str(last))).collect{|idx|
1027 Tk::Text::IndexString.new(idx)
1028 }
1029 end
1030
1031 =begin
1032 def window_cget(index, slot)
1033 case slot.to_s
1034 when 'text', 'label', 'show', 'data', 'file'
1035 _fromUTF8(tk_send_without_enc('window', 'cget',
1036 _get_eval_enc_str(index), "-#{slot}"))
1037 when 'font', 'kanjifont'
1038 #fnt = tk_tcl2ruby(tk_send('window', 'cget', index, "-#{slot}"))
1039 fnt = tk_tcl2ruby(_fromUTF8(tk_send_without_enc('window', 'cget', _get_eval_enc_str(index), '-font')))
1040 unless fnt.kind_of?(TkFont)
1041 fnt = tagfontobj(index, fnt)
1042 end
1043 if slot.to_s == 'kanjifont' && JAPANIZED_TK && TK_VERSION =~ /^4\.*/
1044 # obsolete; just for compatibility
1045 fnt.kanji_font
1046 else
1047 fnt
1048 end
1049 else
1050 tk_tcl2ruby(_fromUTF8(tk_send_without_enc('window', 'cget', _get_eval_enc_str(index), "-#{slot}")))
1051 end
1052 end
1053
1054 def window_configure(index, slot, value=None)
1055 if index.kind_of?(TkTextWindow)
1056 index.configure(slot, value)
1057 else
1058 if slot.kind_of?(Hash)
1059 slot = _symbolkey2str(slot)
1060 win = slot['window']
1061 # slot['window'] = win.epath if win.kind_of?(TkWindow)
1062 slot['window'] = _epath(win) if win
1063 if slot['create']
1064 p_create = slot['create']
1065 if p_create.kind_of?(Proc)
1066 #=begin
1067 slot['create'] = install_cmd(proc{
1068 id = p_create.call
1069 if id.kind_of?(TkWindow)
1070 id.epath
1071 else
1072 id
1073 end
1074 })
1075 #=end
1076 slot['create'] = install_cmd(proc{_epath(p_create.call)})
1077 end
1078 end
1079 tk_send_without_enc('window', 'configure',
1080 _get_eval_enc_str(index),
1081 *hash_kv(slot, true))
1082 else
1083 if slot == 'window' || slot == :window
1084 # id = value
1085 # value = id.epath if id.kind_of?(TkWindow)
1086 value = _epath(value)
1087 end
1088 if slot == 'create' || slot == :create
1089 p_create = value
1090 if p_create.kind_of?(Proc)
1091 #=begin
1092 value = install_cmd(proc{
1093 id = p_create.call
1094 if id.kind_of?(TkWindow)
1095 id.epath
1096 else
1097 id
1098 end
1099 })
1100 #=end
1101 value = install_cmd(proc{_epath(p_create.call)})
1102 end
1103 end
1104 tk_send_without_enc('window', 'configure',
1105 _get_eval_enc_str(index),
1106 "-#{slot}", _get_eval_enc_str(value))
1107 end
1108 end
1109 self
1110 end
1111
1112 def window_configinfo(win, slot = nil)
1113 if TkComm::GET_CONFIGINFO_AS_ARRAY
1114 if slot
1115 case slot.to_s
1116 when 'text', 'label', 'show', 'data', 'file'
1117 conf = tk_split_simplelist(_fromUTF8(tk_send('window', 'configure', _get_eval_enc_str(win), "-#{slot}")))
1118 else
1119 conf = tk_split_list(_fromUTF8(tk_send('window', 'configure', _get_eval_enc_str(win), "-#{slot}")))
1120 end
1121 conf[0] = conf[0][1..-1]
1122 conf
1123 else
1124 tk_split_simplelist(_fromUTF8(tk_send('window', 'configure', _get_eval_enc_str(win)))).collect{|conflist|
1125 conf = tk_split_simplelist(conflist)
1126 conf[0] = conf[0][1..-1]
1127 case conf[0]
1128 when 'text', 'label', 'show', 'data', 'file'
1129 else
1130 if conf[3]
1131 if conf[3].index('{')
1132 conf[3] = tk_split_list(conf[3])
1133 else
1134 conf[3] = tk_tcl2ruby(conf[3])
1135 end
1136 end
1137 if conf[4]
1138 if conf[4].index('{')
1139 conf[4] = tk_split_list(conf[4])
1140 else
1141 conf[4] = tk_tcl2ruby(conf[4])
1142 end
1143 end
1144 end
1145 conf[1] = conf[1][1..-1] if conf.size == 2 # alias info
1146 conf
1147 }
1148 end
1149 else # ! TkComm::GET_CONFIGINFO_AS_ARRAY
1150 if slot
1151 case slot.to_s
1152 when 'text', 'label', 'show', 'data', 'file'
1153 conf = tk_split_simplelist(_fromUTF8(tk_send('window', 'configure', _get_eval_enc_str(win), "-#{slot}")))
1154 else
1155 conf = tk_split_list(_fromUTF8(tk_send('window', 'configure', _get_eval_enc_str(win), "-#{slot}")))
1156 end
1157 key = conf.shift[1..-1]
1158 { key => conf }
1159 else
1160 ret = {}
1161 tk_split_simplelist(_fromUTF8(tk_send('window', 'configure', _get_eval_enc_str(win)))).each{|conflist|
1162 conf = tk_split_simplelist(conflist)
1163 key = conf.shift[1..-1]
1164 case key
1165 when 'text', 'label', 'show', 'data', 'file'
1166 else
1167 if conf[2]
1168 if conf[2].index('{')
1169 conf[2] = tk_split_list(conf[2])
1170 else
1171 conf[2] = tk_tcl2ruby(conf[2])
1172 end
1173 end
1174 if conf[3]
1175 if conf[3].index('{')
1176 conf[3] = tk_split_list(conf[3])
1177 else
1178 conf[3] = tk_tcl2ruby(conf[3])
1179 end
1180 end
1181 end
1182 if conf.size == 1
1183 ret[key] = conf[0][1..-1] # alias info
1184 else
1185 ret[key] = conf
1186 end
1187 }
1188 ret
1189 end
1190 end
1191 end
1192
1193 def current_window_configinfo(win, slot = nil)
1194 if TkComm::GET_CONFIGINFO_AS_ARRAY
1195 if slot
1196 conf = window_configinfo(win, slot)
1197 {conf[0] => conf[4]}
1198 else
1199 ret = {}
1200 window_configinfo(win).each{|conf|
1201 ret[conf[0]] = conf[4] if conf.size > 2
1202 }
1203 ret
1204 end
1205 else # ! TkComm::GET_CONFIGINFO_AS_ARRAY
1206 ret = {}
1207 window_configinfo(win, slot).each{|k, conf|
1208 ret[k] = conf[-1] if conf.kind_of?(Array)
1209 }
1210 ret
1211 end
1212 end
1213 =end
1214
1215 def window_names
1216 # tk_split_simplelist(_fromUTF8(tk_send_without_enc('window', 'names'))).collect{|elt|
1217 tk_split_simplelist(tk_send_without_enc('window', 'names'), false, true).collect{|elt|
1218 tagid2obj(elt)
1219 }
1220 end
1221
1222 def _ktext_length(txt)
1223 if TkCore::WITH_ENCODING ### Ruby 1.9 !!!!!!!!!!!!!
1224 return txt.length
1225 end
1226 ###########################
1227
1228 if $KCODE !~ /n/i
1229 return txt.gsub(/[^\Wa-zA-Z_\d]/, ' ').length
1230 end
1231
1232 # $KCODE == 'NONE'
1233 if JAPANIZED_TK
1234 tk_call_without_enc('kstring', 'length',
1235 _get_eval_enc_str(txt)).to_i
1236 else
1237 begin
1238 tk_call_without_enc('encoding', 'convertto', 'ascii',
1239 _get_eval_enc_str(txt)).length
1240 rescue StandardError, NameError
1241 # sorry, I have no plan
1242 txt.length
1243 end
1244 end
1245 end
1246 private :_ktext_length
1247
1248 def tksearch(*args)
1249 # call 'search' subcommand of text widget
1250 # args ::= [<array_of_opts>] <pattern> <start_index> [<stop_index>]
1251 # If <pattern> is regexp, then it must be a regular expression of Tcl
1252 nocase = false
1253 if args[0].kind_of?(Array)
1254 opts = args.shift.collect{|opt|
1255 s_opt = opt.to_s
1256 nocase = true if s_opt == 'nocase'
1257 '-' + s_opt
1258 }
1259 else
1260 opts = []
1261 end
1262
1263 if args[0].kind_of?(Regexp)
1264 regexp = args.shift
1265 if !nocase && (regexp.options & Regexp::IGNORECASE) != 0
1266 opts << '-nocase'
1267 end
1268 args.unshift(regexp.source)
1269 end
1270
1271 opts << '--'
1272
1273 ret = tk_send('search', *(opts + args))
1274 if ret == ""
1275 nil
1276 else
1277 Tk::Text::IndexString.new(ret)
1278 end
1279 end
1280
1281 def tksearch_with_count(*args)
1282 # call 'search' subcommand of text widget
1283 # args ::= [<array_of_opts>] <var> <pattern> <start_index> [<stop_index>]
1284 # If <pattern> is regexp, then it must be a regular expression of Tcl
1285 nocase = false
1286 if args[0].kind_of?(Array)
1287 opts = args.shift.collect{|opt|
1288 s_opt = opt.to_s
1289 nocase = true if s_opt == 'nocase'
1290 '-' + s_opt
1291 }
1292 else
1293 opts = []
1294 end
1295
1296 opts << '-count' << args.shift
1297
1298 if args[0].kind_of?(Regexp)
1299 regexp = args.shift
1300 if !nocase && (regexp.options & Regexp::IGNORECASE) != 0
1301 opts << '-nocase'
1302 end
1303 args.unshift(regexp.source)
1304 end
1305
1306 opts << '--'
1307
1308 ret = tk_send('search', *(opts + args))
1309 if ret == ""
1310 nil
1311 else
1312 Tk::Text::IndexString.new(ret)
1313 end
1314 end
1315
1316 def search_with_length(pat,start,stop=None)
1317 pat = pat.chr if pat.kind_of?(Integer)
1318 if stop != None
1319 return ["", 0] if compare(start,'>=',stop)
1320 txt = get(start,stop)
1321 if (pos = txt.index(pat))
1322 match = $&
1323 #pos = txt[0..(pos-1)].split('').length if pos > 0
1324 pos = _ktext_length(txt[0..(pos-1)]) if pos > 0
1325 if pat.kind_of?(String)
1326 #return [index(start + " + #{pos} chars"), pat.split('').length]
1327 return [index(start + " + #{pos} chars"),
1328 _ktext_length(pat), pat.dup]
1329 else
1330 #return [index(start + " + #{pos} chars"), $&.split('').length]
1331 return [index(start + " + #{pos} chars"),
1332 _ktext_length(match), match]
1333 end
1334 else
1335 return ["", 0]
1336 end
1337 else
1338 txt = get(start,'end - 1 char')
1339 if (pos = txt.index(pat))
1340 match = $&
1341 #pos = txt[0..(pos-1)].split('').length if pos > 0
1342 pos = _ktext_length(txt[0..(pos-1)]) if pos > 0
1343 if pat.kind_of?(String)
1344 #return [index(start + " + #{pos} chars"), pat.split('').length]
1345 return [index(start + " + #{pos} chars"),
1346 _ktext_length(pat), pat.dup]
1347 else
1348 #return [index(start + " + #{pos} chars"), $&.split('').length]
1349 return [index(start + " + #{pos} chars"),
1350 _ktext_length(match), match]
1351 end
1352 else
1353 txt = get('1.0','end - 1 char')
1354 if (pos = txt.index(pat))
1355 match = $&
1356 #pos = txt[0..(pos-1)].split('').length if pos > 0
1357 pos = _ktext_length(txt[0..(pos-1)]) if pos > 0
1358 if pat.kind_of?(String)
1359 #return [index("1.0 + #{pos} chars"), pat.split('').length]
1360 return [index("1.0 + #{pos} chars"),
1361 _ktext_length(pat), pat.dup]
1362 else
1363 #return [index("1.0 + #{pos} chars"), $&.split('').length]
1364 return [index("1.0 + #{pos} chars"), _ktext_length(match), match]
1365 end
1366 else
1367 return ["", 0]
1368 end
1369 end
1370 end
1371 end
1372
1373 def search(pat,start,stop=None)
1374 search_with_length(pat,start,stop)[0]
1375 end
1376
1377 def rsearch_with_length(pat,start,stop=None)
1378 pat = pat.chr if pat.kind_of?(Integer)
1379 if stop != None
1380 return ["", 0] if compare(start,'<=',stop)
1381 txt = get(stop,start)
1382 if (pos = txt.rindex(pat))
1383 match = $&
1384 #pos = txt[0..(pos-1)].split('').length if pos > 0
1385 pos = _ktext_length(txt[0..(pos-1)]) if pos > 0
1386 if pat.kind_of?(String)
1387 #return [index(stop + " + #{pos} chars"), pat.split('').length]
1388 return [index(stop + " + #{pos} chars"), _ktext_length(pat), pat.dup]
1389 else
1390 #return [index(stop + " + #{pos} chars"), $&.split('').length]
1391 return [index(stop + " + #{pos} chars"), _ktext_length(match), match]
1392 end
1393 else
1394 return ["", 0]
1395 end
1396 else
1397 txt = get('1.0',start)
1398 if (pos = txt.rindex(pat))
1399 match = $&
1400 #pos = txt[0..(pos-1)].split('').length if pos > 0
1401 pos = _ktext_length(txt[0..(pos-1)]) if pos > 0
1402 if pat.kind_of?(String)
1403 #return [index("1.0 + #{pos} chars"), pat.split('').length]
1404 return [index("1.0 + #{pos} chars"), _ktext_length(pat), pat.dup]
1405 else
1406 #return [index("1.0 + #{pos} chars"), $&.split('').length]
1407 return [index("1.0 + #{pos} chars"), _ktext_length(match), match]
1408 end
1409 else
1410 txt = get('1.0','end - 1 char')
1411 if (pos = txt.rindex(pat))
1412 match = $&
1413 #pos = txt[0..(pos-1)].split('').length if pos > 0
1414 pos = _ktext_length(txt[0..(pos-1)]) if pos > 0
1415 if pat.kind_of?(String)
1416 #return [index("1.0 + #{pos} chars"), pat.split('').length]
1417 return [index("1.0 + #{pos} chars"), _ktext_length(pat), pat.dup]
1418 else
1419 #return [index("1.0 + #{pos} chars"), $&.split('').length]
1420 return [index("1.0 + #{pos} chars"), _ktext_length(match), match]
1421 end
1422 else
1423 return ["", 0]
1424 end
1425 end
1426 end
1427 end
1428
1429 def rsearch(pat,start,stop=None)
1430 rsearch_with_length(pat,start,stop)[0]
1431 end
1432
1433 def dump(type_info, *index, &block)
1434 if type_info.kind_of?(Symbol)
1435 type_info = [ type_info.to_s ]
1436 elsif type_info.kind_of?(String)
1437 type_info = [ type_info ]
1438 end
1439 args = type_info.collect{|inf| '-' + inf}
1440 args << '-command' << block if block
1441 str = tk_send('dump', *(args + index))
1442 result = []
1443 sel = nil
1444 i = 0
1445 while i < str.size
1446 # retrieve key
1447 idx = str.index(/ /, i)
1448 result.push str[i..(idx-1)]
1449 i = idx + 1
1450
1451 # retrieve value
1452 case result[-1]
1453 when 'text'
1454 if str[i] == ?{
1455 # text formed as {...}
1456 val, i = _retrieve_braced_text(str, i)
1457 result.push val
1458 else
1459 # text which may contain backslahes
1460 val, i = _retrieve_backslashed_text(str, i)
1461 result.push val
1462 end
1463 else
1464 idx = str.index(/ /, i)
1465 val = str[i..(idx-1)]
1466 case result[-1]
1467 when 'mark'
1468 case val
1469 when 'insert'
1470 result.push TkTextMarkInsert.new(self)
1471 when 'current'
1472 result.push TkTextMarkCurrent.new(self)
1473 when 'anchor'
1474 result.push TkTextMarkAnchor.new(self)
1475 else
1476 result.push tk_tcl2ruby(val)
1477 end
1478 when 'tagon'
1479 if val == 'sel'
1480 if sel
1481 result.push sel
1482 else
1483 result.push TkTextTagSel.new(self)
1484 end
1485 else
1486 result.push tk_tcl2ruby(val)
1487 end
1488 when 'tagoff'
1489 result.push tk_tcl2ruby(val)
1490 when 'window'
1491 result.push tk_tcl2ruby(val)
1492 when 'image'
1493 result.push tk_tcl2ruby(val)
1494 end
1495 i = idx + 1
1496 end
1497
1498 # retrieve index
1499 idx = str.index(/ /, i)
1500 if idx
1501 result.push(Tk::Text::IndexString.new(str[i..(idx-1)]))
1502 i = idx + 1
1503 else
1504 result.push(Tk::Text::IndexString.new(str[i..-1]))
1505 break
1506 end
1507 end
1508
1509 kvis = []
1510 until result.empty?
1511 kvis.push [result.shift, result.shift, result.shift]
1512 end
1513 kvis # result is [[key1, value1, index1], [key2, value2, index2], ...]
1514 end
1515
1516 def _retrieve_braced_text(str, i)
1517 cnt = 0
1518 idx = i
1519 while idx < str.size
1520 case str[idx]
1521 when ?{
1522 cnt += 1
1523 when ?}
1524 cnt -= 1
1525 if cnt == 0
1526 break
1527 end
1528 end
1529 idx += 1
1530 end
1531 return str[i+1..idx-1], idx + 2
1532 end
1533 private :_retrieve_braced_text
1534
1535 def _retrieve_backslashed_text(str, i)
1536 j = i
1537 idx = nil
1538 loop {
1539 idx = str.index(/ /, j)
1540 if str[idx-1] == ?\\
1541 j += 1
1542 else
1543 break
1544 end
1545 }
1546 val = str[i..(idx-1)]
1547 val.gsub!(/\\( |\{|\})/, '\1')
1548 return val, idx + 1
1549 end
1550 private :_retrieve_backslashed_text
1551
1552 def dump_all(*index, &block)
1553 dump(['all'], *index, &block)
1554 end
1555 def dump_mark(*index, &block)
1556 dump(['mark'], *index, &block)
1557 end
1558 def dump_tag(*index, &block)
1559 dump(['tag'], *index, &block)
1560 end
1561 def dump_text(*index, &block)
1562 dump(['text'], *index, &block)
1563 end
1564 def dump_window(*index, &block)
1565 dump(['window'], *index, &block)
1566 end
1567 def dump_image(*index, &block)
1568 dump(['image'], *index, &block)
1569 end
1570 end
1571
1572 #TkText = Tk::Text unless Object.const_defined? :TkText
1573 Tk.__set_toplevel_aliases__(:Tk, Tk::Text, :TkText)
1574
1575
1576 #######################################
1577
1578 class Tk::Text::Peer < Tk::Text
1579 # Tk8.5 feature
1580 def initialize(text, parent=nil, keys={})
1581 unless text.kind_of?(Tk::Text)
1582 fail ArgumentError, "Tk::Text is expected for 1st argument"
1583 end
1584 @src_text = text
1585 super(parent, keys)
1586 end
1587
1588 def create_self(keys)
1589 if keys and keys != None
1590 tk_call_without_enc(@src_text.path, 'peer', 'create', @path)
1591 else
1592 tk_call_without_enc(@src_text.path, 'peer', 'create', @path)
1593 end
1594 end
1595 private :create_self
1596 end