1#
2# tk/textmark.rb - methods for treating text marks
3#
4require 'tk'
5require 'tk/text'
6
7class TkTextMark<TkObject
8  include Tk::Text::IndexModMethods
9
10  TMarkID_TBL = TkCore::INTERP.create_table
11
12  (Tk_TextMark_ID = ['mark'.freeze, TkUtil.untrust('00000')]).instance_eval{
13    @mutex = Mutex.new
14    def mutex; @mutex; end
15    freeze
16  }
17
18  TkCore::INTERP.init_ip_env{
19    TMarkID_TBL.mutex.synchronize{ TMarkID_TBL.clear }
20  }
21
22  def TkTextMark.id2obj(text, id)
23    tpath = text.path
24    TMarkID_TBL.mutex.synchronize{
25      if TMarkID_TBL[tpath]
26        TMarkID_TBL[tpath][id]? TMarkID_TBL[tpath][id]: id
27      else
28        id
29      end
30    }
31  end
32
33  def initialize(parent, index)
34    #unless parent.kind_of?(Tk::Text)
35    #  fail ArgumentError, "expect Tk::Text for 1st argument"
36    #end
37    @parent = @t = parent
38    @tpath = parent.path
39    Tk_TextMark_ID.mutex.synchronize{
40      # @path = @id = Tk_TextMark_ID.join('')
41      @path = @id = Tk_TextMark_ID.join(TkCore::INTERP._ip_id_).freeze
42      Tk_TextMark_ID[1].succ!
43    }
44    TMarkID_TBL.mutex.synchronize{
45      TMarkID_TBL[@id] = self
46      TMarkID_TBL[@tpath] = {} unless TMarkID_TBL[@tpath]
47      TMarkID_TBL[@tpath][@id] = self
48    }
49    tk_call_without_enc(@t.path, 'mark', 'set', @id,
50                        _get_eval_enc_str(index))
51    @t._addtag id, self
52  end
53
54  def id
55    Tk::Text::IndexString.new(@id)
56  end
57
58  def exist?
59    #if ( tk_split_simplelist(_fromUTF8(tk_call_without_enc(@t.path, 'mark', 'names'))).find{|id| id == @id } )
60    if ( tk_split_simplelist(tk_call_without_enc(@t.path, 'mark', 'names'), false, true).find{|id| id == @id } )
61      true
62    else
63      false
64    end
65  end
66
67=begin
68  # move to Tk::Text::IndexModMethods module
69  def +(mod)
70    return chars(mod) if mod.kind_of?(Numeric)
71
72    mod = mod.to_s
73    if mod =~ /^\s*[+-]?\d/
74      Tk::Text::IndexString.new(@id + ' + ' + mod)
75    else
76      Tk::Text::IndexString.new(@id + ' ' + mod)
77    end
78  end
79
80  def -(mod)
81    return chars(-mod) if mod.kind_of?(Numeric)
82
83    mod = mod.to_s
84    if mod =~ /^\s*[+-]?\d/
85      Tk::Text::IndexString.new(@id + ' - ' + mod)
86    elsif mod =~ /^\s*[-]\s+(\d.*)$/
87      Tk::Text::IndexString.new(@id + ' - -' + $1)
88    else
89      Tk::Text::IndexString.new(@id + ' ' + mod)
90    end
91  end
92=end
93
94  def pos
95    @t.index(@id)
96  end
97
98  def pos=(where)
99    set(where)
100  end
101
102  def set(where)
103    tk_call_without_enc(@t.path, 'mark', 'set', @id,
104                        _get_eval_enc_str(where))
105    self
106  end
107
108  def unset
109    tk_call_without_enc(@t.path, 'mark', 'unset', @id)
110    self
111  end
112  alias destroy unset
113
114  def gravity
115    tk_call_without_enc(@t.path, 'mark', 'gravity', @id)
116  end
117
118  def gravity=(direction)
119    tk_call_without_enc(@t.path, 'mark', 'gravity', @id, direction)
120    #self
121    direction
122  end
123
124  def next(index = nil)
125    if index
126      @t.tagid2obj(_fromUTF8(tk_call_without_enc(@t.path, 'mark', 'next', _get_eval_enc_str(index))))
127    else
128      @t.tagid2obj(_fromUTF8(tk_call_without_enc(@t.path, 'mark', 'next', @id)))
129    end
130  end
131
132  def previous(index = nil)
133    if index
134      @t.tagid2obj(_fromUTF8(tk_call_without_enc(@t.path, 'mark', 'previous', _get_eval_enc_str(index))))
135    else
136      @t.tagid2obj(_fromUTF8(tk_call_without_enc(@t.path, 'mark', 'previous', @id)))
137    end
138  end
139end
140TktMark = TkTextMark
141
142class TkTextNamedMark<TkTextMark
143  def self.new(parent, name, index=nil)
144    TMarkID_TBL.mutex.synchronize{
145      if TMarkID_TBL[parent.path] && TMarkID_TBL[parent.path][name]
146        obj = TMarkID_TBL[parent.path][name]
147      else
148        # super(parent, name, *args)
149        (obj = self.allocate).instance_eval{
150          @parent = @t = parent
151          @tpath = parent.path
152          @path = @id = name
153          TMarkID_TBL[@id] = self
154          TMarkID_TBL[@tpath] = {} unless TMarkID_TBL[@tpath]
155          TMarkID_TBL[@tpath][@id] = self unless TMarkID_TBL[@tpath][@id]
156          @t._addtag @id, self
157        }
158        obj
159      end
160
161      if obj && index
162        tk_call_without_enc(parent.path, 'mark', 'set', name,
163                            _get_eval_enc_str(index))
164      end
165      obj
166    }
167  end
168
169  def initialize(parent, name, index=nil)
170    # dummy:: not called by 'new' method
171
172    #unless parent.kind_of?(Tk::Text)
173    #  fail ArgumentError, "expect Tk::Text for 1st argument"
174    #end
175    @parent = @t = parent
176    @tpath = parent.path
177    @path = @id = name
178    tk_call_without_enc(@t.path, 'mark', 'set', @id,
179                        _get_eval_enc_str(index)) if index
180    @t._addtag @id, self
181  end
182end
183TktNamedMark = TkTextNamedMark
184
185class TkTextMarkInsert<TkTextNamedMark
186  def self.new(parent,*args)
187    super(parent, 'insert', *args)
188  end
189end
190TktMarkInsert = TkTextMarkInsert
191
192class TkTextMarkCurrent<TkTextNamedMark
193  def self.new(parent,*args)
194    super(parent, 'current', *args)
195  end
196end
197TktMarkCurrent = TkTextMarkCurrent
198
199class TkTextMarkAnchor<TkTextNamedMark
200  def self.new(parent,*args)
201    super(parent, 'anchor', *args)
202  end
203end
204TktMarkAnchor = TkTextMarkAnchor
205