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