1# 2# tkextlib/iwidgets/scrolledtext.rb 3# by Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) 4# 5 6require 'tk' 7require 'tk/text' 8require 'tkextlib/iwidgets.rb' 9 10module Tk 11 module Iwidgets 12 class Scrolledtext < Tk::Iwidgets::Scrolledwidget 13 end 14 end 15end 16 17class Tk::Iwidgets::Scrolledtext 18 TkCommandNames = ['::iwidgets::scrolledtext'.freeze].freeze 19 WidgetClassName = 'Scrolledtext'.freeze 20 WidgetClassNames[WidgetClassName] ||= self 21 22 def __strval_optkeys 23 super() << 'textbackground' 24 end 25 private :__strval_optkeys 26 27 def __font_optkeys 28 super() << 'textfont' 29 end 30 private :__font_optkeys 31 32 ################################ 33 34 def initialize(*args) 35 super(*args) 36 @text = component_widget('text') 37 end 38 39 def method_missing(id, *args) 40 if @text.respond_to?(id) 41 @text.__send__(id, *args) 42 else 43 super(id, *args) 44 end 45 end 46 47 ################################ 48 49 def child_site 50 window(tk_call(@path, 'childsite')) 51 end 52 53 def clear 54 tk_call(@path, 'clear') 55 self 56 end 57 58 def import(file, idx=nil) 59 if idx 60 tk_call(@path, 'import', file, index(idx)) 61 else 62 tk_call(@path, 'import', file) 63 end 64 self 65 end 66 67 def export(file) 68 tk_call(@path, 'export', file) 69 self 70 end 71 72 ##################################### 73 74 include TkTextTagConfig 75 76 def tagid(tag) 77 if tag.kind_of?(Tk::Itk::Component) 78 tag.name 79 else 80 super(tag) 81 end 82 end 83 private :tagid 84 85 def bbox(index) 86 list(tk_send('bbox', index)) 87 end 88 def compare(idx1, op, idx2) 89 bool(tk_send_without_enc('compare', _get_eval_enc_str(idx1), 90 op, _get_eval_enc_str(idx2))) 91 end 92 93 def debug 94 bool(tk_send_without_enc('debug')) 95 end 96 def debug=(boolean) 97 tk_send_without_enc('debug', boolean) 98 #self 99 boolean 100 end 101 102 def delete(first, last=None) 103 tk_send_without_enc('delete', first, last) 104 self 105 end 106 107 def dlineinfo(index) 108 list(tk_send_without_enc('dlineinfo', _get_eval_enc_str(index))) 109 end 110 111 def get(*index) 112 _fromUTF8(tk_send_without_enc('get', *index)) 113 end 114 def get_displaychars(*index) 115 # Tk8.5 feature 116 get('-displaychars', *index) 117 end 118 119 def image_cget_tkstring(index, slot) 120 _fromUTF8(tk_send_without_enc('image', 'cget', 121 _get_eval_enc_str(index), "-#{slot.to_s}")) 122 end 123 def image_cget_strict(index, slot) 124 case slot.to_s 125 when 'text', 'label', 'show', 'data', 'file' 126 _fromUTF8(tk_send_without_enc('image', 'cget', 127 _get_eval_enc_str(index), "-#{slot}")) 128 else 129 tk_tcl2ruby(_fromUTF8(tk_send_without_enc('image', 'cget', 130 _get_eval_enc_str(index), 131 "-#{slot}"))) 132 end 133 end 134 def image_cget(index, slot) 135 unless TkItemConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__ 136 image_cget_strict(index, slot) 137 else 138 begin 139 image_cget_strict(index, slot) 140 rescue => e 141 begin 142 if current_image_configinfo.has_key?(slot.to_s) 143 # error on known option 144 fail e 145 else 146 # unknown option 147 nil 148 end 149 rescue 150 fail e # tag error 151 end 152 end 153 end 154 end 155 156 def image_configure(index, slot, value=None) 157 if slot.kind_of? Hash 158 _fromUTF8(tk_send_without_enc('image', 'configure', 159 _get_eval_enc_str(index), 160 *hash_kv(slot, true))) 161 else 162 _fromUTF8(tk_send_without_enc('image', 'configure', 163 _get_eval_enc_str(index), 164 "-#{slot}", 165 _get_eval_enc_str(value))) 166 end 167 self 168 end 169 170 def image_configinfo(index, slot = nil) 171 if TkComm::GET_CONFIGINFO_AS_ARRAY 172 if slot 173 case slot.to_s 174 when 'text', 'label', 'show', 'data', 'file' 175 #conf = tk_split_simplelist(_fromUTF8(tk_send_without_enc('image', 'configure', _get_eval_enc_str(index), "-#{slot}"))) 176 conf = tk_split_simplelist(tk_send_without_enc('image', 'configure', _get_eval_enc_str(index), "-#{slot}"), false, true) 177 else 178 #conf = tk_split_list(_fromUTF8(tk_send_without_enc('image', 'configure', _get_eval_enc_str(index), "-#{slot}"))) 179 conf = tk_split_list(tk_send_without_enc('image', 'configure', _get_eval_enc_str(index), "-#{slot}"), 0, false, true) 180 end 181 conf[0] = conf[0][1..-1] 182 conf 183 else 184 #tk_split_simplelist(_fromUTF8(tk_send_without_enc('image', 'configure', _get_eval_enc_str(index)))).collect{|conflist| 185 # conf = tk_split_simplelist(conflist) 186 tk_split_simplelist(tk_send_without_enc('image', 'configure', _get_eval_enc_str(index)), false, false).collect{|conflist| 187 conf = tk_split_simplelist(conflist, false, true) 188 conf[0] = conf[0][1..-1] 189 case conf[0] 190 when 'text', 'label', 'show', 'data', 'file' 191 else 192 if conf[3] 193 if conf[3].index('{') 194 conf[3] = tk_split_list(conf[3]) 195 else 196 conf[3] = tk_tcl2ruby(conf[3]) 197 end 198 end 199 if conf[4] 200 if conf[4].index('{') 201 conf[4] = tk_split_list(conf[4]) 202 else 203 conf[4] = tk_tcl2ruby(conf[4]) 204 end 205 end 206 end 207 conf[1] = conf[1][1..-1] if conf.size == 2 # alias info 208 conf 209 } 210 end 211 else # ! TkComm::GET_CONFIGINFO_AS_ARRAY 212 if slot 213 case slot.to_s 214 when 'text', 'label', 'show', 'data', 'file' 215 #conf = tk_split_simplelist(_fromUTF8(tk_send_without_enc('image', 'configure', _get_eval_enc_str(index), "-#{slot}"))) 216 conf = tk_split_simplelist(tk_send_without_enc('image', 'configure', _get_eval_enc_str(index), "-#{slot}"), false, true) 217 else 218 #conf = tk_split_list(_fromUTF8(tk_send_without_enc('image', 'configure', _get_eval_enc_str(index), "-#{slot}"))) 219 conf = tk_split_list(tk_send_without_enc('image', 'configure', _get_eval_enc_str(index), "-#{slot}"), 0, false, true) 220 end 221 key = conf.shift[1..-1] 222 { key => conf } 223 else 224 ret = {} 225 #tk_split_simplelist(_fromUTF8(tk_send_without_enc('image', 'configure', _get_eval_enc_str(index)))).each{|conflist| 226 # conf = tk_split_simplelist(conflist) 227 tk_split_simplelist(tk_send_without_enc('image', 'configure', _get_eval_enc_str(index)), false, false).each{|conflist| 228 conf = tk_split_simplelist(conflist, false, true) 229 key = conf.shift[1..-1] 230 case key 231 when 'text', 'label', 'show', 'data', 'file' 232 else 233 if conf[2] 234 if conf[2].index('{') 235 conf[2] = tk_split_list(conf[2]) 236 else 237 conf[2] = tk_tcl2ruby(conf[2]) 238 end 239 end 240 if conf[3] 241 if conf[3].index('{') 242 conf[3] = tk_split_list(conf[3]) 243 else 244 conf[3] = tk_tcl2ruby(conf[3]) 245 end 246 end 247 end 248 if conf.size == 1 249 ret[key] = conf[0][1..-1] # alias info 250 else 251 ret[key] = conf 252 end 253 } 254 ret 255 end 256 end 257 end 258 259 def current_image_configinfo(index, slot = nil) 260 if TkComm::GET_CONFIGINFO_AS_ARRAY 261 if slot 262 conf = image_configinfo(index, slot) 263 {conf[0] => conf[4]} 264 else 265 ret = {} 266 image_configinfo(index).each{|conf| 267 ret[conf[0]] = conf[4] if conf.size > 2 268 } 269 ret 270 end 271 else # ! TkComm::GET_CONFIGINFO_AS_ARRAY 272 ret = {} 273 image_configinfo(index, slot).each{|k, conf| 274 ret[k] = conf[-1] if conf.kind_of?(Array) 275 } 276 ret 277 end 278 end 279 280 def image_names 281 #tk_split_simplelist(_fromUTF8(tk_send_without_enc('image', 'names'))).collect{|elt| 282 tk_split_simplelist(tk_send_without_enc('image', 'names'), false, true).collect{|elt| 283 tagid2obj(elt) 284 } 285 end 286 287 def index(idx) 288 tk_send_without_enc('index', _get_eval_enc_str(idx)) 289 end 290 291 def insert(index, *args) 292 tk_send('insert', index, *args) 293 self 294 end 295 296 def mark_names 297 #tk_split_simplelist(_fromUTF8(tk_send_without_enc('mark', 'names'))).collect{|elt| 298 tk_split_simplelist(tk_send_without_enc('mark', 'names'), false, true).collect{|elt| 299 tagid2obj(elt) 300 } 301 end 302 303 def mark_gravity(mark, direction=nil) 304 if direction 305 tk_send_without_enc('mark', 'gravity', 306 _get_eval_enc_str(mark), direction) 307 self 308 else 309 tk_send_without_enc('mark', 'gravity', _get_eval_enc_str(mark)) 310 end 311 end 312 313 def mark_set(mark, index) 314 tk_send_without_enc('mark', 'set', _get_eval_enc_str(mark), 315 _get_eval_enc_str(index)) 316 self 317 end 318 alias set_mark mark_set 319 320 def mark_unset(*marks) 321 tk_send_without_enc('mark', 'unset', 322 *(marks.collect{|mark| _get_eval_enc_str(mark)})) 323 self 324 end 325 alias unset_mark mark_unset 326 327 def mark_next(index) 328 tagid2obj(_fromUTF8(tk_send_without_enc('mark', 'next', 329 _get_eval_enc_str(index)))) 330 end 331 alias next_mark mark_next 332 333 def mark_previous(index) 334 tagid2obj(_fromUTF8(tk_send_without_enc('mark', 'previous', 335 _get_eval_enc_str(index)))) 336 end 337 alias previous_mark mark_previous 338 339 def scan_mark(x, y) 340 tk_send_without_enc('scan', 'mark', x, y) 341 self 342 end 343 def scan_dragto(x, y) 344 tk_send_without_enc('scan', 'dragto', x, y) 345 self 346 end 347 348 349 def _ktext_length(txt) 350 if TkCore::WITH_ENCODING ### Ruby 1.9 !!!!!!!!!!!!! 351 return txt.length 352 end 353 ########################### 354 355 if $KCODE !~ /n/i 356 return txt.gsub(/[^\Wa-zA-Z_\d]/, ' ').length 357 end 358 359 # $KCODE == 'NONE' 360 if JAPANIZED_TK 361 tk_call_without_enc('kstring', 'length', 362 _get_eval_enc_str(txt)).to_i 363 else 364 begin 365 tk_call_without_enc('encoding', 'convertto', 'ascii', 366 _get_eval_enc_str(txt)).length 367 rescue StandardError, NameError 368 # sorry, I have no plan 369 txt.length 370 end 371 end 372 end 373 private :_ktext_length 374 375 def tksearch(*args) 376 # call 'search' subcommand of text widget 377 # args ::= [<array_of_opts>] <pattern> <start_index> [<stop_index>] 378 # If <pattern> is regexp, then it must be a regular expression of Tcl 379 if args[0].kind_of?(Array) 380 opts = args.shift.collect{|opt| '-' + opt.to_s } 381 else 382 opts = [] 383 end 384 385 opts << '--' 386 387 ret = tk_send('search', *(opts + args)) 388 if ret == "" 389 nil 390 else 391 ret 392 end 393 end 394 395 def tksearch_with_count(*args) 396 # call 'search' subcommand of text widget 397 # args ::= [<array_of_opts>] <var> <pattern> <start_index> [<stop_index>] 398 # If <pattern> is regexp, then it must be a regular expression of Tcl 399 if args[0].kind_of?(Array) 400 opts = args.shift.collect{|opt| '-' + opt.to_s } 401 else 402 opts = [] 403 end 404 405 opts << '-count' << args.shift << '--' 406 407 ret = tk_send('search', *(opts + args)) 408 if ret == "" 409 nil 410 else 411 ret 412 end 413 end 414 415 def search_with_length(pat,start,stop=None) 416 pat = pat.chr if pat.kind_of? Integer 417 if stop != None 418 return ["", 0] if compare(start,'>=',stop) 419 txt = get(start,stop) 420 if (pos = txt.index(pat)) 421 match = $& 422 #pos = txt[0..(pos-1)].split('').length if pos > 0 423 pos = _ktext_length(txt[0..(pos-1)]) if pos > 0 424 if pat.kind_of? String 425 #return [index(start + " + #{pos} chars"), pat.split('').length] 426 return [index(start + " + #{pos} chars"), 427 _ktext_length(pat), pat.dup] 428 else 429 #return [index(start + " + #{pos} chars"), $&.split('').length] 430 return [index(start + " + #{pos} chars"), 431 _ktext_length(match), match] 432 end 433 else 434 return ["", 0] 435 end 436 else 437 txt = get(start,'end - 1 char') 438 if (pos = txt.index(pat)) 439 match = $& 440 #pos = txt[0..(pos-1)].split('').length if pos > 0 441 pos = _ktext_length(txt[0..(pos-1)]) if pos > 0 442 if pat.kind_of? String 443 #return [index(start + " + #{pos} chars"), pat.split('').length] 444 return [index(start + " + #{pos} chars"), 445 _ktext_length(pat), pat.dup] 446 else 447 #return [index(start + " + #{pos} chars"), $&.split('').length] 448 return [index(start + " + #{pos} chars"), 449 _ktext_length(match), match] 450 end 451 else 452 txt = get('1.0','end - 1 char') 453 if (pos = txt.index(pat)) 454 match = $& 455 #pos = txt[0..(pos-1)].split('').length if pos > 0 456 pos = _ktext_length(txt[0..(pos-1)]) if pos > 0 457 if pat.kind_of? String 458 #return [index("1.0 + #{pos} chars"), pat.split('').length] 459 return [index("1.0 + #{pos} chars"), 460 _ktext_length(pat), pat.dup] 461 else 462 #return [index("1.0 + #{pos} chars"), $&.split('').length] 463 return [index("1.0 + #{pos} chars"), _ktext_length(match), match] 464 end 465 else 466 return ["", 0] 467 end 468 end 469 end 470 end 471 472 def search(pat,start,stop=None) 473 search_with_length(pat,start,stop)[0] 474 end 475 476 def rsearch_with_length(pat,start,stop=None) 477 pat = pat.chr if pat.kind_of? Integer 478 if stop != None 479 return ["", 0] if compare(start,'<=',stop) 480 txt = get(stop,start) 481 if (pos = txt.rindex(pat)) 482 match = $& 483 #pos = txt[0..(pos-1)].split('').length if pos > 0 484 pos = _ktext_length(txt[0..(pos-1)]) if pos > 0 485 if pat.kind_of? String 486 #return [index(stop + " + #{pos} chars"), pat.split('').length] 487 return [index(stop + " + #{pos} chars"), _ktext_length(pat), pat.dup] 488 else 489 #return [index(stop + " + #{pos} chars"), $&.split('').length] 490 return [index(stop + " + #{pos} chars"), _ktext_length(match), match] 491 end 492 else 493 return ["", 0] 494 end 495 else 496 txt = get('1.0',start) 497 if (pos = txt.rindex(pat)) 498 match = $& 499 #pos = txt[0..(pos-1)].split('').length if pos > 0 500 pos = _ktext_length(txt[0..(pos-1)]) if pos > 0 501 if pat.kind_of? String 502 #return [index("1.0 + #{pos} chars"), pat.split('').length] 503 return [index("1.0 + #{pos} chars"), _ktext_length(pat), pat.dup] 504 else 505 #return [index("1.0 + #{pos} chars"), $&.split('').length] 506 return [index("1.0 + #{pos} chars"), _ktext_length(match), match] 507 end 508 else 509 txt = get('1.0','end - 1 char') 510 if (pos = txt.rindex(pat)) 511 match = $& 512 #pos = txt[0..(pos-1)].split('').length if pos > 0 513 pos = _ktext_length(txt[0..(pos-1)]) if pos > 0 514 if pat.kind_of? String 515 #return [index("1.0 + #{pos} chars"), pat.split('').length] 516 return [index("1.0 + #{pos} chars"), _ktext_length(pat), pat.dup] 517 else 518 #return [index("1.0 + #{pos} chars"), $&.split('').length] 519 return [index("1.0 + #{pos} chars"), _ktext_length(match), match] 520 end 521 else 522 return ["", 0] 523 end 524 end 525 end 526 end 527 528 def rsearch(pat,start,stop=None) 529 rsearch_with_length(pat,start,stop)[0] 530 end 531 532 def see(index) 533 tk_send_without_enc('see', index) 534 self 535 end 536 537 ############################### 538 539 def xview(*index) 540 if index.size == 0 541 list(tk_send_without_enc('xview')) 542 else 543 tk_send_without_enc('xview', *index) 544 self 545 end 546 end 547 def xview_moveto(*index) 548 xview('moveto', *index) 549 end 550 def xview_scroll(*index) 551 xview('scroll', *index) 552 end 553 554 def yview(*index) 555 if index.size == 0 556 list(tk_send_without_enc('yview')) 557 else 558 tk_send_without_enc('yview', *index) 559 self 560 end 561 end 562 def yview_moveto(*index) 563 yview('moveto', *index) 564 end 565 def yview_scroll(*index) 566 yview('scroll', *index) 567 end 568end 569