File: tk/text.rb

Overview
Module Structure
Class Hierarchy
Code

Overview

Module Structure

  module: <Toplevel Module>
  module: Tk
  class: Text#68
includes
  Scrollable ( Tk )
  TkTextTagConfig   
inherits from
  TkTextWin   
has properties
constant: ItemConfCMD #69
constant: TkCommandNames #252
constant: WidgetClassName #253
class method: new / 2 #256
method: init_instance_variable #267
method: __destroy_hook__ #272
method: create_self / 1 #281
method: __strval_optkeys #295
class method: at (1/2) / 2 #300
method: at (2/E) / 2 #304
method: index / 1 #308
method: get_displaychars / 1 #313
method: value #318
method: value= / 1 #322
method: clear #328
alias: erase clear #332
method: _addcmd / 1 #334
method: _addtag / 2 #338
method: tagid / 1 #342
method: tagid2obj / 1 #354
method: tag_names / 1 #362
method: mark_names #369
method: mark_gravity / 2 #376
method: mark_set / 2 #386
alias: set_mark mark_set #391
method: mark_unset / 1 #393
alias: unset_mark mark_unset #398
method: mark_next / 1 #400
alias: next_mark mark_next #404
method: mark_previous / 1 #406
alias: previous_mark mark_previous #410
method: image_cget_strict / 2 #412
method: image_cget / 2 #424
method: image_configure / 3 #446
method: image_configinfo / 2 #460
method: current_image_configinfo / 2 #549
method: image_names #570
method: set_insert / 1 #577
method: set_current / 1 #582
method: insert / 3 #587
method: destroy #606
method: backspace #614
method: bbox / 1 #618
method: compare / 3 #622
method: count / 3 #627
method: count_info / 3 #643
method: peer_names #659
method: replace / 3 #664
method: debug #669
method: debug= / 1 #672
method: dlineinfo / 1 #678
method: modified? #682
method: modified / 1 #685
method: modified= / 1 #689
method: edit_redo #694
method: edit_reset #698
method: edit_separator #702
method: edit_undo #706
method: xview_pickplace / 1 #711
method: yview_pickplace / 1 #716
method: text_copy #721
method: text_cut #727
method: text_paste #733
method: tag_add / 3 #739
alias: addtag tag_add #745
alias: add_tag tag_add #746
method: tag_delete / 1 #748
alias: deltag tag_delete #764
alias: delete_tag tag_delete #765
method: tag_bind / 3 #771
method: tag_bind_append / 3 #786
method: tag_bind_remove / 2 #797
method: tag_bindinfo / 2 #802
method: tag_raise / 2 #982
method: tag_lower / 2 #988
method: tag_remove / 2 #994
method: tag_ranges / 1 #1000
method: tag_nextrange / 3 #1013
method: tag_prevrange / 3 #1022
method: window_names #1215
method: _ktext_length / 1 #1222
method: tksearch / 1 #1248
method: tksearch_with_count / 1 #1281
method: search_with_length / 3 #1316
method: search / 3 #1373
method: rsearch_with_length / 3 #1377
method: rsearch / 3 #1429
method: dump / 3 #1433
method: _retrieve_braced_text / 2 #1516
method: _retrieve_backslashed_text / 2 #1535
method: dump_all / 2 #1552
method: dump_mark / 2 #1555
method: dump_tag / 2 #1558
method: dump_text / 2 #1561
method: dump_window / 2 #1564
method: dump_image / 2 #1567
  module: IndexModMethods#76
has properties
method: + / 1 #77
method: - / 1 #88
method: chars / 1 #101
alias: char chars #109
method: display_chars / 1 #111
alias: display_char display_chars #120
method: any_chars / 1 #122
alias: any_char any_chars #131
method: indices / 1 #133
method: display_indices / 1 #143
method: any_indices / 1 #153
method: lines / 1 #163
alias: line lines #171
method: display_lines / 1 #173
alias: display_line display_lines #182
method: any_lines / 1 #184
alias: any_line any_lines #193
method: linestart #195
method: lineend #198
method: display_linestart #202
method: display_lineend #206
method: wordstart #211
method: wordend #214
method: display_wordstart #218
method: display_wordend #222
  class: IndexString#228
includes
  IndexModMethods ( Tk::Text )
inherits from
  String ( Builtin-Module )
has properties
class method: at / 2 #231
class method: new / 1 #235
method: id #245
  class: Peer#1578
inherits from
  Text ( Tk )
has properties
method: initialize / 3 #1580
method: create_self / 1 #1588
  module: TkTextTagConfig#10
includes
  TkItemConfigMethod   
  TkTreatItemFont   
has properties
method: __item_cget_cmd / 1 #14
method: __item_config_cmd / 1 #19
method: __item_pathname / 1 #24
method: tag_cget / 2 #32
method: tag_cget_strict / 2 #35
method: tag_configure / 3 #38
method: tag_configinfo / 2 #41
method: current_tag_configinfo / 2 #44
method: window_cget / 2 #48
method: window_cget_strict / 2 #51
method: window_configure / 3 #54
method: window_configinfo / 2 #57
method: current_window_configinfo / 2 #60

Class Hierarchy

Object ( Builtin-Module )
String ( Builtin-Module )
  IndexString ( Tk::Text ) #228
TkKernel
TkObject
TkWindow
TkTextWin
Text ( Tk ) — #68
  Peer ( Tk::Text ) #1578

Code

   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