1# 2# tk/texttag.rb - methods for treating text tags 3# 4require 'tk' 5require 'tk/text' 6require 'tk/tagfont' 7 8class TkTextTag<TkObject 9 include TkTreatTagFont 10 include Tk::Text::IndexModMethods 11 12 TTagID_TBL = TkCore::INTERP.create_table 13 14 (Tk_TextTag_ID = ['tag'.freeze, TkUtil.untrust('00000')]).instance_eval{ 15 @mutex = Mutex.new 16 def mutex; @mutex; end 17 freeze 18 } 19 20 TkCore::INTERP.init_ip_env{ 21 TTagID_TBL.mutex.synchronize{ TTagID_TBL.clear } 22 } 23 24 def TkTextTag.id2obj(text, id) 25 tpath = text.path 26 TTagID_TBL.mutex.synchronize{ 27 if TTagID_TBL[tpath] 28 TTagID_TBL[tpath][id]? TTagID_TBL[tpath][id]: id 29 else 30 id 31 end 32 } 33 end 34 35 def initialize(parent, *args) 36 #unless parent.kind_of?(TkText) 37 # fail ArgumentError, "expect TkText for 1st argument" 38 #end 39 @parent = @t = parent 40 @tpath = parent.path 41 Tk_TextTag_ID.mutex.synchronize{ 42 # @path = @id = Tk_TextTag_ID.join('') 43 @path = @id = Tk_TextTag_ID.join(TkCore::INTERP._ip_id_).freeze 44 Tk_TextTag_ID[1].succ! 45 } 46 TTagID_TBL.mutex.synchronize{ 47 TTagID_TBL[@id] = self 48 TTagID_TBL[@tpath] = {} unless TTagID_TBL[@tpath] 49 TTagID_TBL[@tpath][@id] = self 50 } 51 #tk_call @t.path, "tag", "configure", @id, *hash_kv(keys) 52 if args != [] 53 keys = args.pop 54 if keys.kind_of?(Hash) 55 add(*args) if args != [] 56 configure(keys) 57 else 58 args.push keys 59 add(*args) 60 end 61 end 62 @t._addtag id, self 63 end 64 65 def id 66 Tk::Text::IndexString.new(@id) 67 end 68 69 def exist? 70 #if ( tk_split_simplelist(_fromUTF8(tk_call_without_enc(@t.path, 'tag', 'names'))).find{|id| id == @id } ) 71 if ( tk_split_simplelist(tk_call_without_enc(@t.path, 'tag', 'names'), false, true).find{|id| id == @id } ) 72 true 73 else 74 false 75 end 76 end 77 78 def first 79 Tk::Text::IndexString.new(@id + '.first') 80 end 81 82 def last 83 Tk::Text::IndexString.new(@id + '.last') 84 end 85 86 def add(*indices) 87 tk_call_without_enc(@t.path, 'tag', 'add', @id, 88 *(indices.collect{|idx| _get_eval_enc_str(idx)})) 89 self 90 end 91 92 def remove(*indices) 93 tk_call_without_enc(@t.path, 'tag', 'remove', @id, 94 *(indices.collect{|idx| _get_eval_enc_str(idx)})) 95 self 96 end 97 98 def ranges 99 l = tk_split_simplelist(tk_call_without_enc(@t.path, 'tag', 'ranges', @id)) 100 r = [] 101 while key=l.shift 102 r.push [Tk::Text::IndexString.new(key), Tk::Text::IndexString.new(l.shift)] 103 end 104 r 105 end 106 107 def nextrange(first, last=None) 108 simplelist(tk_call_without_enc(@t.path, 'tag', 'nextrange', @id, 109 _get_eval_enc_str(first), 110 _get_eval_enc_str(last))).collect{|idx| 111 Tk::Text::IndexString.new(idx) 112 } 113 end 114 115 def prevrange(first, last=None) 116 simplelist(tk_call_without_enc(@t.path, 'tag', 'prevrange', @id, 117 _get_eval_enc_str(first), 118 _get_eval_enc_str(last))).collect{|idx| 119 Tk::Text::IndexString.new(idx) 120 } 121 end 122 123 def [](key) 124 cget key 125 end 126 127 def []=(key,val) 128 configure key, val 129 val 130 end 131 132 def cget_tkstring(key) 133 @t.tag_cget_tkstring @id, key 134 end 135 def cget(key) 136 @t.tag_cget @id, key 137 end 138 def cget_strict(key) 139 @t.tag_cget_strict @id, key 140 end 141=begin 142 def cget(key) 143 case key.to_s 144 when 'text', 'label', 'show', 'data', 'file' 145 _fromUTF8(tk_call_without_enc(@t.path, 'tag', 'cget', @id, "-#{key}")) 146 when 'font', 'kanjifont' 147 #fnt = tk_tcl2ruby(tk_call(@t.path, 'tag', 'cget', @id, "-#{key}")) 148 fnt = tk_tcl2ruby(_fromUTF8(tk_call_without_enc(@t.path, 'tag', 'cget', 149 @id, '-font'))) 150 unless fnt.kind_of?(TkFont) 151 fnt = tagfontobj(@id, fnt) 152 end 153 if key.to_s == 'kanjifont' && JAPANIZED_TK && TK_VERSION =~ /^4\.*/ 154 # obsolete; just for compatibility 155 fnt.kanji_font 156 else 157 fnt 158 end 159 else 160 tk_tcl2ruby(_fromUTF8(tk_call_without_enc(@t.path, 'tag', 'cget', 161 @id, "-#{key}"))) 162 end 163 end 164=end 165 166 def configure(key, val=None) 167 @t.tag_configure @id, key, val 168 end 169# def configure(key, val=None) 170# if key.kind_of?(Hash) 171# tk_call @t.path, 'tag', 'configure', @id, *hash_kv(key) 172# else 173# tk_call @t.path, 'tag', 'configure', @id, "-#{key}", val 174# end 175# end 176# def configure(key, value) 177# if value == FALSE 178# value = "0" 179# elsif value.kind_of?(Proc) 180# value = install_cmd(value) 181# end 182# tk_call @t.path, 'tag', 'configure', @id, "-#{key}", value 183# end 184 185 def configinfo(key=nil) 186 @t.tag_configinfo @id, key 187 end 188 189 def current_configinfo(key=nil) 190 @t.current_tag_configinfo @id, key 191 end 192 193 #def bind(seq, cmd=Proc.new, *args) 194 # _bind([@t.path, 'tag', 'bind', @id], seq, cmd, *args) 195 # self 196 #end 197 def bind(seq, *args) 198 # if args[0].kind_of?(Proc) || args[0].kind_of?(Method) 199 if TkComm._callback_entry?(args[0]) || !block_given? 200 cmd = args.shift 201 else 202 cmd = Proc.new 203 end 204 _bind([@t.path, 'tag', 'bind', @id], seq, cmd, *args) 205 self 206 end 207 208 #def bind_append(seq, cmd=Proc.new, *args) 209 # _bind_append([@t.path, 'tag', 'bind', @id], seq, cmd, *args) 210 # self 211 #end 212 def bind_append(seq, *args) 213 # if args[0].kind_of?(Proc) || args[0].kind_of?(Method) 214 if TkComm._callback_entry?(args[0]) || !block_given? 215 cmd = args.shift 216 else 217 cmd = Proc.new 218 end 219 _bind_append([@t.path, 'tag', 'bind', @id], seq, cmd, *args) 220 self 221 end 222 223 def bind_remove(seq) 224 _bind_remove([@t.path, 'tag', 'bind', @id], seq) 225 self 226 end 227 228 def bindinfo(context=nil) 229 _bindinfo([@t.path, 'tag', 'bind', @id], context) 230 end 231 232 def raise(above=None) 233 tk_call_without_enc(@t.path, 'tag', 'raise', @id, 234 _get_eval_enc_str(above)) 235 self 236 end 237 238 def lower(below=None) 239 tk_call_without_enc(@t.path, 'tag', 'lower', @id, 240 _get_eval_enc_str(below)) 241 self 242 end 243 244 def destroy 245 tk_call_without_enc(@t.path, 'tag', 'delete', @id) 246 TTagID_TBL.mutex.synchronize{ 247 TTagID_TBL[@tpath].delete(@id) if TTagID_TBL[@tpath] 248 } 249 self 250 end 251end 252TktTag = TkTextTag 253 254class TkTextNamedTag<TkTextTag 255 def self.new(parent, name, *args) 256 tagobj = nil 257 TTagID_TBL.mutex.synchronize{ 258 if TTagID_TBL[parent.path] && TTagID_TBL[parent.path][name] 259 tagobj = TTagID_TBL[parent.path][name] 260 else 261 # super(parent, name, *args) 262 (tagobj = self.allocate).instance_eval{ 263 @parent = @t = parent 264 @tpath = parent.path 265 @path = @id = name 266 TTagID_TBL[@id] = self 267 TTagID_TBL[@tpath] = {} unless TTagID_TBL[@tpath] 268 TTagID_TBL[@tpath][@id] = self unless TTagID_TBL[@tpath][@id] 269 @t._addtag @id, self 270 } 271 end 272 } 273 274 if args != [] 275 keys = args.pop 276 if keys.kind_of?(Hash) 277 tagobj.add(*args) if args != [] 278 tagobj.configure(keys) 279 else 280 args.push keys 281 tagobj.add(*args) 282 end 283 end 284 285 tagobj 286 end 287 288 def initialize(parent, name, *args) 289 # dummy:: not called by 'new' method 290 291 #unless parent.kind_of?(Tk::Text) 292 # fail ArgumentError, "expect Tk::Text for 1st argument" 293 #end 294 @parent = @t = parent 295 @tpath = parent.path 296 @path = @id = name 297 298 #if mode 299 # tk_call @t.path, "addtag", @id, *args 300 #end 301 if args != [] 302 keys = args.pop 303 if keys.kind_of?(Hash) 304 add(*args) if args != [] 305 configure(keys) 306 else 307 args.push keys 308 add(*args) 309 end 310 end 311 @t._addtag @id, self 312 end 313end 314TktNamedTag = TkTextNamedTag 315 316class TkTextTagSel<TkTextNamedTag 317 def self.new(parent, *args) 318 super(parent, 'sel', *args) 319 end 320end 321TktTagSel = TkTextTagSel 322