mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
![nagai](/assets/img/avatar_default.png)
* Although requiring manual control of GC, memory eating problem of TkCanvas Items is fixed. Probably, a time when GC should run is only after removing many canvas items. GC's cost is large and the man who knows proper timing to start GC is the man who create the script. So, Ruby/Tk doesn't start GC automatically. tktext.rb : * add some methods and bug fix tk.rb : * add widget destroy hook binding to TkBindTag::ALL git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@4001 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
1241 lines
27 KiB
Ruby
1241 lines
27 KiB
Ruby
#
|
|
# tktext.rb - Tk text classes
|
|
# $Date$
|
|
# by Yukihiro Matsumoto <matz@caelum.co.jp>
|
|
|
|
require 'tk.rb'
|
|
require 'tkfont'
|
|
|
|
module TkTreatTextTagFont
|
|
include TkTreatItemFont
|
|
|
|
ItemCMD = ['tag', 'configure']
|
|
def __conf_cmd(idx)
|
|
ItemCMD[idx]
|
|
end
|
|
|
|
def __item_pathname(tagOrId)
|
|
if tagOrId.kind_of?(TkTextTag)
|
|
self.path + ';' + tagOrId.id
|
|
else
|
|
self.path + ';' + tagOrId
|
|
end
|
|
end
|
|
end
|
|
|
|
class TkText<TkTextWin
|
|
ItemConfCMD = ['tag', 'configure']
|
|
include TkTreatTextTagFont
|
|
include Scrollable
|
|
|
|
WidgetClassName = 'Text'.freeze
|
|
WidgetClassNames[WidgetClassName] = self
|
|
|
|
def self.new(*args, &block)
|
|
obj = super(*args){}
|
|
obj.init_instance_variable
|
|
obj.instance_eval(&block) if defined? yield
|
|
obj
|
|
end
|
|
|
|
def init_instance_variable
|
|
@cmdtbl = {}
|
|
@tags = {}
|
|
end
|
|
|
|
def __destroy_hook__
|
|
TTagID_TBL.delete(@path)
|
|
TMarkID_TBL.delete(@path)
|
|
end
|
|
|
|
def create_self(keys)
|
|
if keys and keys != None
|
|
tk_call 'text', @path, *hash_kv(keys)
|
|
else
|
|
tk_call 'text', @path
|
|
end
|
|
init_instance_variable
|
|
end
|
|
|
|
def index(index)
|
|
tk_send 'index', index
|
|
end
|
|
|
|
def value
|
|
tk_send 'get', "1.0", "end - 1 char"
|
|
end
|
|
|
|
def value= (val)
|
|
tk_send 'delete', "1.0", 'end'
|
|
tk_send 'insert', "1.0", val
|
|
end
|
|
|
|
def _addcmd(cmd)
|
|
@cmdtbl.push cmd
|
|
end
|
|
|
|
def _addtag(name, obj)
|
|
@tags[name] = obj
|
|
end
|
|
|
|
def tagid2obj(tagid)
|
|
if @tags[tagid]
|
|
@tags[tagid]
|
|
else
|
|
tagid
|
|
end
|
|
end
|
|
|
|
def tag_names(index=None)
|
|
tk_split_simplelist(tk_send('tag', 'names', index)).collect{|elt|
|
|
tagid2obj(elt)
|
|
}
|
|
end
|
|
|
|
def mark_names
|
|
tk_split_simplelist(tk_send('mark', 'names')).collect{|elt|
|
|
tagid2obj(elt)
|
|
}
|
|
end
|
|
|
|
def mark_gravity(mark, direction=nil)
|
|
if direction
|
|
tk_send 'mark', 'gravity', mark, direction
|
|
self
|
|
else
|
|
tk_send 'mark', 'gravity', mark
|
|
end
|
|
end
|
|
|
|
def mark_set(mark, index)
|
|
tk_send 'mark', 'set', mark, index
|
|
self
|
|
end
|
|
alias set_mark mark_set
|
|
|
|
def mark_unset(*marks)
|
|
tk_send 'mark', 'unset', *marks
|
|
self
|
|
end
|
|
alias unset_mark mark_unset
|
|
|
|
def mark_next(index)
|
|
tagid2obj(tk_send('mark', 'next', index))
|
|
end
|
|
alias next_mark mark_next
|
|
|
|
def mark_previous(index)
|
|
tagid2obj(tk_send('mark', 'previous', index))
|
|
end
|
|
alias previous_mark mark_previous
|
|
|
|
def image_cget(index, slot)
|
|
case slot.to_s
|
|
when 'text', 'label', 'show', 'data', 'file'
|
|
tk_send('image', 'cget', index, "-#{slot}")
|
|
else
|
|
tk_tcl2ruby(tk_send('image', 'cget', index, "-#{slot}"))
|
|
end
|
|
end
|
|
|
|
def image_configure(index, slot, value=None)
|
|
if slot.kind_of? Hash
|
|
tk_send('image', 'configure', index, *hash_kv(slot))
|
|
else
|
|
tk_send('image', 'configure', index, "-#{slot}", value)
|
|
end
|
|
self
|
|
end
|
|
|
|
def image_configinfo(index, slot = nil)
|
|
if slot
|
|
case slot.to_s
|
|
when 'text', 'label', 'show', 'data', 'file'
|
|
conf = tk_split_simplelist(tk_send('image', 'configure',
|
|
index, "-#{slot}"))
|
|
else
|
|
conf = tk_split_list(tk_send('image', 'configure',
|
|
index, "-#{slot}"))
|
|
end
|
|
conf[0] = conf[0][1..-1]
|
|
conf
|
|
else
|
|
tk_split_simplelist(tk_send('image', 'configure',
|
|
index)).collect{|conflist|
|
|
conf = tk_split_simplelist(conflist)
|
|
conf[0] = conf[0][1..-1]
|
|
case conf[0]
|
|
when 'text', 'label', 'show', 'data', 'file'
|
|
else
|
|
if conf[3]
|
|
if conf[3].index('{')
|
|
conf[3] = tk_split_list(conf[3])
|
|
else
|
|
conf[3] = tk_tcl2ruby(conf[3])
|
|
end
|
|
end
|
|
if conf[4]
|
|
if conf[4].index('{')
|
|
conf[4] = tk_split_list(conf[4])
|
|
else
|
|
conf[4] = tk_tcl2ruby(conf[4])
|
|
end
|
|
end
|
|
end
|
|
conf
|
|
}
|
|
end
|
|
end
|
|
|
|
def image_names
|
|
tk_split_simplelist(tk_send('image', 'names')).collect{|elt|
|
|
tagid2obj(elt)
|
|
}
|
|
end
|
|
|
|
def set_insert(index)
|
|
tk_send 'mark', 'set', 'insert', index
|
|
self
|
|
end
|
|
|
|
def set_current(index)
|
|
tk_send 'mark', 'set', 'current', index
|
|
self
|
|
end
|
|
|
|
def insert(index, chars, *tags)
|
|
if tags[0].kind_of? Array
|
|
# multiple chars-taglist argument
|
|
args = [chars]
|
|
while tags.size > 0
|
|
tags.shift.collect{|x|_get_eval_string(x)}.join(' ') # taglist
|
|
args << tags.shift if tags.size > 0 # chars
|
|
end
|
|
super index, *args
|
|
else
|
|
# single chars-taglist argument
|
|
super index, chars, tags.collect{|x|_get_eval_string(x)}.join(' ')
|
|
end
|
|
end
|
|
|
|
def destroy
|
|
@tags = {} unless @tags
|
|
@tags.each_value do |t|
|
|
t.destroy
|
|
end
|
|
super
|
|
end
|
|
|
|
def backspace
|
|
self.delete 'insert'
|
|
end
|
|
|
|
def compare(idx1, op, idx2)
|
|
bool(tk_send('compare', idx1, op, idx2))
|
|
end
|
|
|
|
def debug
|
|
bool(tk_send('debug'))
|
|
end
|
|
def debug=(boolean)
|
|
tk_send 'debug', boolean
|
|
self
|
|
end
|
|
def bbox(index)
|
|
list(tk_send('bbox', index))
|
|
end
|
|
|
|
def dlineinfo(index)
|
|
list(tk_send('dlineinfo', index))
|
|
end
|
|
|
|
def modified?
|
|
bool(tk_send('edit', 'modified'))
|
|
end
|
|
def modified(mode)
|
|
tk_send('edit', 'modified', mode)
|
|
self
|
|
end
|
|
def edit_redo
|
|
tk_send('edit', 'redo')
|
|
self
|
|
end
|
|
def edit_reset
|
|
tk_send('edit', 'reset')
|
|
self
|
|
end
|
|
def edit_separator
|
|
tk_send('edit', 'separator')
|
|
self
|
|
end
|
|
def edit_undo
|
|
tk_send('edit', 'undo')
|
|
self
|
|
end
|
|
|
|
def yview_pickplace(*what)
|
|
tk_send 'yview', '-pickplace', *what
|
|
self
|
|
end
|
|
|
|
def xview_pickplace(*what)
|
|
tk_send 'xview', '-pickplace', *what
|
|
self
|
|
end
|
|
|
|
def tag_add(tag, index1, index2=None)
|
|
tk_send 'tag', 'add', tag, index1, index2
|
|
self
|
|
end
|
|
alias addtag tag_add
|
|
alias add_tag tag_add
|
|
|
|
def tag_delete(*tags)
|
|
tk_send 'tag', 'delete', *tags
|
|
if TkTextTag::TTagID_TBL[@path]
|
|
tags.each{|tag|
|
|
if tag.kind_of? TkTextTag
|
|
TTagID_TBL[@path].delete(tag.id)
|
|
else
|
|
TTagID_TBL[@path].delete(tag)
|
|
end
|
|
}
|
|
end
|
|
self
|
|
end
|
|
alias deltag tag_delete
|
|
alias delete_tag tag_delete
|
|
|
|
def tag_bind(tag, seq, cmd=Proc.new, args=nil)
|
|
_bind([@path, 'tag', 'bind', tag], seq, cmd, args)
|
|
self
|
|
end
|
|
|
|
def tag_bind_append(tag, seq, cmd=Proc.new, args=nil)
|
|
_bind_append([@path, 'tag', 'bind', tag], seq, cmd, args)
|
|
self
|
|
end
|
|
|
|
def tag_bind_remove(tag, seq)
|
|
_bind_remove([@path, 'tag', 'bind', tag], seq)
|
|
self
|
|
end
|
|
|
|
def tag_bindinfo(tag, context=nil)
|
|
_bindinfo([@path, 'tag', 'bind', tag], context)
|
|
end
|
|
|
|
def tag_cget(tag, key)
|
|
case key.to_s
|
|
when 'text', 'label', 'show', 'data', 'file'
|
|
tk_call(@path, 'tag', 'cget', tag, "-#{key}")
|
|
else
|
|
tk_tcl2ruby(tk_call(@path, 'tag', 'cget', tag, "-#{key}"))
|
|
end
|
|
end
|
|
|
|
def tag_configure(tag, key, val=None)
|
|
if key.kind_of? Hash
|
|
key = _symbolkey2str(key)
|
|
if ( key['font'] || key['kanjifont'] \
|
|
|| key['latinfont'] || key['asciifont'] )
|
|
tagfont_configure(tag, key)
|
|
else
|
|
tk_send 'tag', 'configure', tag, *hash_kv(key)
|
|
end
|
|
|
|
else
|
|
if key == 'font' || key == :font ||
|
|
key == 'kanjifont' || key == :kanjifont ||
|
|
key == 'latinfont' || key == :latinfont ||
|
|
key == 'asciifont' || key == :asciifont
|
|
tagfont_configure(tag, {key=>val})
|
|
else
|
|
tk_send 'tag', 'configure', tag, "-#{key}", val
|
|
end
|
|
end
|
|
self
|
|
end
|
|
|
|
def tag_configinfo(tag, key=nil)
|
|
if key
|
|
case key.to_s
|
|
when 'text', 'label', 'show', 'data', 'file'
|
|
conf = tk_split_simplelist(tk_send('tag','configure',tag,"-#{key}"))
|
|
else
|
|
conf = tk_split_list(tk_send('tag','configure',tag,"-#{key}"))
|
|
end
|
|
conf[0] = conf[0][1..-1]
|
|
conf
|
|
else
|
|
tk_split_simplelist(tk_send('tag', 'configure', tag)).collect{|conflist|
|
|
conf = tk_split_simplelist(conflist)
|
|
conf[0] = conf[0][1..-1]
|
|
case conf[0]
|
|
when 'text', 'label', 'show', 'data', 'file'
|
|
else
|
|
if conf[3]
|
|
if conf[3].index('{')
|
|
conf[3] = tk_split_list(conf[3])
|
|
else
|
|
conf[3] = tk_tcl2ruby(conf[3])
|
|
end
|
|
end
|
|
if conf[4]
|
|
if conf[4].index('{')
|
|
conf[4] = tk_split_list(conf[4])
|
|
else
|
|
conf[4] = tk_tcl2ruby(conf[4])
|
|
end
|
|
end
|
|
end
|
|
conf
|
|
}
|
|
end
|
|
end
|
|
|
|
def tag_raise(tag, above=None)
|
|
tk_send 'tag', 'raise', tag, above
|
|
self
|
|
end
|
|
|
|
def tag_lower(tag, below=None)
|
|
tk_send 'tag', 'lower', tag, below
|
|
self
|
|
end
|
|
|
|
def tag_remove(tag, *index)
|
|
tk_send 'tag', 'remove', tag, *index
|
|
self
|
|
end
|
|
|
|
def tag_ranges(tag)
|
|
l = tk_split_simplelist(tk_send('tag', 'ranges', tag))
|
|
r = []
|
|
while key=l.shift
|
|
r.push [key, l.shift]
|
|
end
|
|
r
|
|
end
|
|
|
|
def tag_nextrange(tag, first, last=None)
|
|
tk_split_list(tk_send('tag', 'nextrange', tag, first, last))
|
|
end
|
|
|
|
def tag_prevrange(tag, first, last=None)
|
|
tk_split_list(tk_send('tag', 'prevrange', tag, first, last))
|
|
end
|
|
|
|
def window_cget(index, slot)
|
|
case slot.to_s
|
|
when 'text', 'label', 'show', 'data', 'file'
|
|
tk_send('window', 'cget', index, "-#{slot}")
|
|
else
|
|
tk_tcl2ruby(tk_send('window', 'cget', index, "-#{slot}"))
|
|
end
|
|
end
|
|
|
|
def window_configure(index, slot, value=None)
|
|
if index.kind_of? TkTextWindow
|
|
index.configure(slot, value)
|
|
else
|
|
if slot.kind_of? Hash
|
|
tk_send('window', 'configure', index, *hash_kv(slot))
|
|
else
|
|
tk_send('window', 'configure', index, "-#{slot}", value)
|
|
end
|
|
end
|
|
self
|
|
end
|
|
|
|
def window_configinfo(win, slot = nil)
|
|
if slot
|
|
case slot.to_s
|
|
when 'text', 'label', 'show', 'data', 'file'
|
|
conf = tk_split_simplelist(tk_send('window', 'configure',
|
|
win, "-#{slot}"))
|
|
else
|
|
conf = tk_split_list(tk_send('window', 'configure',
|
|
win, "-#{slot}"))
|
|
end
|
|
conf[0] = conf[0][1..-1]
|
|
conf
|
|
else
|
|
tk_split_simplelist(tk_send('window', 'configure',
|
|
win)).collect{|conflist|
|
|
conf = tk_split_simplelist(conflist)
|
|
conf[0] = conf[0][1..-1]
|
|
case conf[0]
|
|
when 'text', 'label', 'show', 'data', 'file'
|
|
else
|
|
if conf[3]
|
|
if conf[3].index('{')
|
|
conf[3] = tk_split_list(conf[3])
|
|
else
|
|
conf[3] = tk_tcl2ruby(conf[3])
|
|
end
|
|
end
|
|
if conf[4]
|
|
if conf[4].index('{')
|
|
conf[4] = tk_split_list(conf[4])
|
|
else
|
|
conf[4] = tk_tcl2ruby(conf[4])
|
|
end
|
|
end
|
|
end
|
|
conf
|
|
}
|
|
end
|
|
end
|
|
|
|
def window_names
|
|
tk_split_simplelist(tk_send('window', 'names')).collect{|elt|
|
|
tagid2obj(elt)
|
|
}
|
|
end
|
|
|
|
def _ktext_length(txt)
|
|
if $KCODE !~ /n/i
|
|
return txt.gsub(/[^\Wa-zA-Z_\d]/, ' ').length
|
|
end
|
|
|
|
# $KCODE == 'NONE'
|
|
if JAPANIZED_TK
|
|
tk_call('kstring', 'length', txt).to_i
|
|
else
|
|
begin
|
|
tk_call('encoding', 'convertto', 'ascii', txt).length
|
|
rescue StandardError, NameError
|
|
# sorry, I have no plan
|
|
txt.length
|
|
end
|
|
end
|
|
end
|
|
private :_ktext_length
|
|
|
|
def search_with_length(pat,start,stop=None)
|
|
pat = pat.chr if pat.kind_of? Integer
|
|
if stop != None
|
|
return ["", 0] if compare(start,'>=',stop)
|
|
txt = get(start,stop)
|
|
if (pos = txt.index(pat))
|
|
match = $&
|
|
#pos = txt[0..(pos-1)].split('').length if pos > 0
|
|
pos = _ktext_length(txt[0..(pos-1)]) if pos > 0
|
|
if pat.kind_of? String
|
|
#return [index(start + " + #{pos} chars"), pat.split('').length]
|
|
return [index(start + " + #{pos} chars"),
|
|
_ktext_length(pat), pat.dup]
|
|
else
|
|
#return [index(start + " + #{pos} chars"), $&.split('').length]
|
|
return [index(start + " + #{pos} chars"),
|
|
_ktext_length(match), match]
|
|
end
|
|
else
|
|
return ["", 0]
|
|
end
|
|
else
|
|
txt = get(start,'end - 1 char')
|
|
if (pos = txt.index(pat))
|
|
match = $&
|
|
#pos = txt[0..(pos-1)].split('').length if pos > 0
|
|
pos = _ktext_length(txt[0..(pos-1)]) if pos > 0
|
|
if pat.kind_of? String
|
|
#return [index(start + " + #{pos} chars"), pat.split('').length]
|
|
return [index(start + " + #{pos} chars"),
|
|
_ktext_length(pat), pat.dup]
|
|
else
|
|
#return [index(start + " + #{pos} chars"), $&.split('').length]
|
|
return [index(start + " + #{pos} chars"),
|
|
_ktext_length(match), match]
|
|
end
|
|
else
|
|
txt = get('1.0','end - 1 char')
|
|
if (pos = txt.index(pat))
|
|
match = $&
|
|
#pos = txt[0..(pos-1)].split('').length if pos > 0
|
|
pos = _ktext_length(txt[0..(pos-1)]) if pos > 0
|
|
if pat.kind_of? String
|
|
#return [index("1.0 + #{pos} chars"), pat.split('').length]
|
|
return [index("1.0 + #{pos} chars"),
|
|
_ktext_length(pat), pat.dup]
|
|
else
|
|
#return [index("1.0 + #{pos} chars"), $&.split('').length]
|
|
return [index("1.0 + #{pos} chars"), _ktext_length(match), match]
|
|
end
|
|
else
|
|
return ["", 0]
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
def search(pat,start,stop=None)
|
|
search_with_length(pat,start,stop)[0]
|
|
end
|
|
|
|
def rsearch_with_length(pat,start,stop=None)
|
|
pat = pat.chr if pat.kind_of? Integer
|
|
if stop != None
|
|
return ["", 0] if compare(start,'<=',stop)
|
|
txt = get(stop,start)
|
|
if (pos = txt.rindex(pat))
|
|
match = $&
|
|
#pos = txt[0..(pos-1)].split('').length if pos > 0
|
|
pos = _ktext_length(txt[0..(pos-1)]) if pos > 0
|
|
if pat.kind_of? String
|
|
#return [index(stop + " + #{pos} chars"), pat.split('').length]
|
|
return [index(stop + " + #{pos} chars"), _ktext_length(pat), pat.dup]
|
|
else
|
|
#return [index(stop + " + #{pos} chars"), $&.split('').length]
|
|
return [index(stop + " + #{pos} chars"), _ktext_length(match), match]
|
|
end
|
|
else
|
|
return ["", 0]
|
|
end
|
|
else
|
|
txt = get('1.0',start)
|
|
if (pos = txt.rindex(pat))
|
|
match = $&
|
|
#pos = txt[0..(pos-1)].split('').length if pos > 0
|
|
pos = _ktext_length(txt[0..(pos-1)]) if pos > 0
|
|
if pat.kind_of? String
|
|
#return [index("1.0 + #{pos} chars"), pat.split('').length]
|
|
return [index("1.0 + #{pos} chars"), _ktext_length(pat), pat.dup]
|
|
else
|
|
#return [index("1.0 + #{pos} chars"), $&.split('').length]
|
|
return [index("1.0 + #{pos} chars"), _ktext_length(match), match]
|
|
end
|
|
else
|
|
txt = get('1.0','end - 1 char')
|
|
if (pos = txt.rindex(pat))
|
|
match = $&
|
|
#pos = txt[0..(pos-1)].split('').length if pos > 0
|
|
pos = _ktext_length(txt[0..(pos-1)]) if pos > 0
|
|
if pat.kind_of? String
|
|
#return [index("1.0 + #{pos} chars"), pat.split('').length]
|
|
return [index("1.0 + #{pos} chars"), _ktext_length(pat), pat.dup]
|
|
else
|
|
#return [index("1.0 + #{pos} chars"), $&.split('').length]
|
|
return [index("1.0 + #{pos} chars"), _ktext_length(match), match]
|
|
end
|
|
else
|
|
return ["", 0]
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
def rsearch(pat,start,stop=None)
|
|
rsearch_with_length(pat,start,stop)[0]
|
|
end
|
|
|
|
def dump(type_info, *index, &block)
|
|
args = type_info.collect{|inf| '-' + inf}
|
|
args << '-command' << block if block
|
|
str = tk_send('dump', *(args + index))
|
|
result = []
|
|
sel = nil
|
|
i = 0
|
|
while i < str.size
|
|
# retrieve key
|
|
idx = str.index(/ /, i)
|
|
result.push str[i..(idx-1)]
|
|
i = idx + 1
|
|
|
|
# retrieve value
|
|
case result[-1]
|
|
when 'text'
|
|
if str[i] == ?{
|
|
# text formed as {...}
|
|
val, i = _retrieve_braced_text(str, i)
|
|
result.push val
|
|
else
|
|
# text which may contain backslahes
|
|
val, i = _retrieve_backslashed_text(str, i)
|
|
result.push val
|
|
end
|
|
else
|
|
idx = str.index(/ /, i)
|
|
val = str[i..(idx-1)]
|
|
case result[-1]
|
|
when 'mark'
|
|
case val
|
|
when 'insert'
|
|
result.push TkTextMarkInsert.new(self)
|
|
when 'current'
|
|
result.push TkTextMarkCurrent.new(self)
|
|
when 'anchor'
|
|
result.push TkTextMarkAnchor.new(self)
|
|
else
|
|
result.push tk_tcl2ruby(val)
|
|
end
|
|
when 'tagon'
|
|
if val == 'sel'
|
|
if sel
|
|
result.push sel
|
|
else
|
|
result.push TkTextTagSel.new(self)
|
|
end
|
|
else
|
|
result.push tk_tcl2ruby(val)
|
|
end
|
|
when 'tagoff'
|
|
result.push tk_tcl2ruby(val)
|
|
when 'window'
|
|
result.push tk_tcl2ruby(val)
|
|
end
|
|
i = idx + 1
|
|
end
|
|
|
|
# retrieve index
|
|
idx = str.index(/ /, i)
|
|
if idx
|
|
result.push str[i..(idx-1)]
|
|
i = idx + 1
|
|
else
|
|
result.push str[i..-1]
|
|
break
|
|
end
|
|
end
|
|
|
|
kvis = []
|
|
until result.empty?
|
|
kvis.push [result.shift, result.shift, result.shift]
|
|
end
|
|
kvis # result is [[key1, value1, index1], [key2, value2, index2], ...]
|
|
end
|
|
|
|
def _retrieve_braced_text(str, i)
|
|
cnt = 0
|
|
idx = i
|
|
while idx < str.size
|
|
case str[idx]
|
|
when ?{
|
|
cnt += 1
|
|
when ?}
|
|
cnt -= 1
|
|
if cnt == 0
|
|
break
|
|
end
|
|
end
|
|
idx += 1
|
|
end
|
|
return str[i+1..idx-1], idx + 2
|
|
end
|
|
private :_retrieve_braced_text
|
|
|
|
def _retrieve_backslashed_text(str, i)
|
|
j = i
|
|
idx = nil
|
|
loop {
|
|
idx = str.index(/ /, j)
|
|
if str[idx-1] == ?\\
|
|
j += 1
|
|
else
|
|
break
|
|
end
|
|
}
|
|
val = str[i..(idx-1)]
|
|
val.gsub!(/\\( |\{|\})/, '\1')
|
|
return val, idx + 1
|
|
end
|
|
private :_retrieve_backslashed_text
|
|
|
|
def dump_all(*index, &block)
|
|
dump(['all'], *index, &block)
|
|
end
|
|
def dump_mark(*index, &block)
|
|
dump(['mark'], *index, &block)
|
|
end
|
|
def dump_tag(*index, &block)
|
|
dump(['tag'], *index, &block)
|
|
end
|
|
def dump_text(*index, &block)
|
|
dump(['text'], *index, &block)
|
|
end
|
|
def dump_window(*index, &block)
|
|
dump(['window'], *index, &block)
|
|
end
|
|
def dump_image(*index, &block)
|
|
dump(['image'], *index, &block)
|
|
end
|
|
end
|
|
|
|
class TkTextTag<TkObject
|
|
include TkTreatTagFont
|
|
|
|
TTagID_TBL = {}
|
|
Tk_TextTag_ID = ['tag0000']
|
|
|
|
TkComm.__add_target_for_init__(self)
|
|
|
|
def self.__init_tables__
|
|
TTagID_TBL.clear
|
|
Tk_TextTag_ID[0] = 'tag0000'
|
|
end
|
|
|
|
def TkTextTag.id2obj(text, id)
|
|
tpath = text.path
|
|
return id unless TTagID_TBL[tpath]
|
|
TTagID_TBL[tpath][id]? TTagID_TBL[tpath][id]: id
|
|
end
|
|
|
|
def initialize(parent, *args)
|
|
if not parent.kind_of?(TkText)
|
|
fail format("%s need to be TkText", parent.inspect)
|
|
end
|
|
@parent = @t = parent
|
|
@tpath = parent.path
|
|
@path = @id = Tk_TextTag_ID[0]
|
|
TTagID_TBL[@id] = self
|
|
TTagID_TBL[@tpath] = {} unless TTagID_TBL[@tpath]
|
|
TTagID_TBL[@tpath][@id] = self
|
|
Tk_TextTag_ID[0] = Tk_TextTag_ID[0].succ
|
|
#tk_call @t.path, "tag", "configure", @id, *hash_kv(keys)
|
|
if args != [] then
|
|
keys = args.pop
|
|
if keys.kind_of? Hash then
|
|
add(*args) if args != []
|
|
configure(keys)
|
|
else
|
|
args.push keys
|
|
add(*args)
|
|
end
|
|
end
|
|
@t._addtag id, self
|
|
end
|
|
|
|
def id
|
|
@id
|
|
end
|
|
|
|
def first
|
|
@id + '.first'
|
|
end
|
|
|
|
def last
|
|
@id + '.last'
|
|
end
|
|
|
|
def add(*index)
|
|
tk_call @t.path, 'tag', 'add', @id, *index
|
|
self
|
|
end
|
|
|
|
def remove(*index)
|
|
tk_call @t.path, 'tag', 'remove', @id, *index
|
|
self
|
|
end
|
|
|
|
def ranges
|
|
l = tk_split_simplelist(tk_call(@t.path, 'tag', 'ranges', @id))
|
|
r = []
|
|
while key=l.shift
|
|
r.push [key, l.shift]
|
|
end
|
|
r
|
|
end
|
|
|
|
def nextrange(first, last=None)
|
|
tk_split_list(tk_call(@t.path, 'tag', 'nextrange', @id, first, last))
|
|
end
|
|
|
|
def prevrange(first, last=None)
|
|
tk_split_list(tk_call(@t.path, 'tag', 'prevrange', @id, first, last))
|
|
end
|
|
|
|
def [](key)
|
|
cget key
|
|
end
|
|
|
|
def []=(key,val)
|
|
configure key, val
|
|
end
|
|
|
|
def cget(key)
|
|
case key.to_s
|
|
when 'text', 'label', 'show', 'data', 'file'
|
|
tk_call @t.path, 'tag', 'cget', @id, "-#{key}"
|
|
else
|
|
tk_tcl2ruby tk_call(@t.path, 'tag', 'cget', @id, "-#{key}")
|
|
end
|
|
end
|
|
|
|
def configure(key, val=None)
|
|
@t.tag_configure @id, key, val
|
|
end
|
|
# def configure(key, val=None)
|
|
# if key.kind_of? Hash
|
|
# tk_call @t.path, 'tag', 'configure', @id, *hash_kv(key)
|
|
# else
|
|
# tk_call @t.path, 'tag', 'configure', @id, "-#{key}", val
|
|
# end
|
|
# end
|
|
# def configure(key, value)
|
|
# if value == FALSE
|
|
# value = "0"
|
|
# elsif value.kind_of? Proc
|
|
# value = install_cmd(value)
|
|
# end
|
|
# tk_call @t.path, 'tag', 'configure', @id, "-#{key}", value
|
|
# end
|
|
|
|
def configinfo(key=nil)
|
|
@t.tag_configinfo @id, key
|
|
end
|
|
|
|
def bind(seq, cmd=Proc.new, args=nil)
|
|
_bind([@t.path, 'tag', 'bind', @id], seq, cmd, args)
|
|
self
|
|
end
|
|
|
|
def bind_append(seq, cmd=Proc.new, args=nil)
|
|
_bind_append([@t.path, 'tag', 'bind', @id], seq, cmd, args)
|
|
self
|
|
end
|
|
|
|
def bind_remove(seq)
|
|
_bind_remove([@t.path, 'tag', 'bind', @id], seq)
|
|
self
|
|
end
|
|
|
|
def bindinfo(context=nil)
|
|
_bindinfo([@t.path, 'tag', 'bind', @id], context)
|
|
end
|
|
|
|
def raise(above=None)
|
|
tk_call @t.path, 'tag', 'raise', @id, above
|
|
self
|
|
end
|
|
|
|
def lower(below=None)
|
|
tk_call @t.path, 'tag', 'lower', @id, below
|
|
self
|
|
end
|
|
|
|
def destroy
|
|
tk_call @t.path, 'tag', 'delete', @id
|
|
TTagID_TBL[@tpath].delete(@id) if TTagID_TBL[@tpath]
|
|
self
|
|
end
|
|
end
|
|
|
|
class TkTextNamedTag<TkTextTag
|
|
def self.new(parent, name, *args)
|
|
if TTagID_TBL[parent.path] && TTagID_TBL[parent.path][name]
|
|
tagobj = TTagID_TBL[parent.path][name]
|
|
if args != [] then
|
|
keys = args.pop
|
|
if keys.kind_of? Hash then
|
|
tagobj.add(*args) if args != []
|
|
tagobj.configure(keys)
|
|
else
|
|
args.push keys
|
|
tagobj.add(*args)
|
|
end
|
|
end
|
|
return tagobj
|
|
else
|
|
super(parent, name, *args)
|
|
end
|
|
end
|
|
|
|
def initialize(parent, name, *args)
|
|
if not parent.kind_of?(TkText)
|
|
fail format("%s need to be TkText", parent.inspect)
|
|
end
|
|
@parent = @t = parent
|
|
@tpath = parent.path
|
|
@path = @id = name
|
|
TTagID_TBL[@tpath] = {} unless TTagID_TBL[@tpath]
|
|
TTagID_TBL[@tpath][@id] = self unless TTagID_TBL[@tpath][@id]
|
|
#if mode
|
|
# tk_call @t.path, "addtag", @id, *args
|
|
#end
|
|
if args != [] then
|
|
keys = args.pop
|
|
if keys.kind_of? Hash then
|
|
add(*args) if args != []
|
|
configure(keys)
|
|
else
|
|
args.push keys
|
|
add(*args)
|
|
end
|
|
end
|
|
@t._addtag id, self
|
|
end
|
|
end
|
|
|
|
class TkTextTagSel<TkTextNamedTag
|
|
def self.new(parent, *args)
|
|
super(parent, 'sel', *args)
|
|
end
|
|
end
|
|
|
|
class TkTextMark<TkObject
|
|
TMarkID_TBL = {}
|
|
Tk_TextMark_ID = ['mark0000']
|
|
|
|
TkComm.__add_target_for_init__(self)
|
|
|
|
def self.__init_tables__
|
|
TMarkID_TBL.clear
|
|
Tk_TextMark_ID[0] = 'mark0000'
|
|
end
|
|
|
|
def TkTextMark.id2obj(text, id)
|
|
tpath = text.path
|
|
return id unless TMarkID_TBL[tpath]
|
|
TMarkID_TBL[tpath][id]? TMarkID_TBL[tpath][id]: id
|
|
end
|
|
|
|
def initialize(parent, index)
|
|
if not parent.kind_of?(TkText)
|
|
fail format("%s need to be TkText", parent.inspect)
|
|
end
|
|
@parent = @t = parent
|
|
@tpath = parent.path
|
|
@path = @id = Tk_TextMark_ID[0]
|
|
TMarkID_TBL[@id] = self
|
|
TMarkID_TBL[@tpath] = {} unless TMarkID_TBL[@tpath]
|
|
TMarkID_TBL[@tpath][@id] = self
|
|
Tk_TextMark_ID[0] = Tk_TextMark_ID[0].succ
|
|
tk_call @t.path, 'mark', 'set', @id, index
|
|
@t._addtag id, self
|
|
end
|
|
|
|
def id
|
|
@id
|
|
end
|
|
|
|
def +(mod)
|
|
@id + ' + ' + mod
|
|
end
|
|
def -(mod)
|
|
@id + ' - ' + mod
|
|
end
|
|
|
|
def set(where)
|
|
tk_call @t.path, 'mark', 'set', @id, where
|
|
self
|
|
end
|
|
|
|
def unset
|
|
tk_call @t.path, 'mark', 'unset', @id
|
|
self
|
|
end
|
|
alias destroy unset
|
|
|
|
def gravity
|
|
tk_call @t.path, 'mark', 'gravity', @id
|
|
end
|
|
|
|
def gravity=(direction)
|
|
tk_call @t.path, 'mark', 'gravity', @id, direction
|
|
self
|
|
end
|
|
|
|
def next(index = nil)
|
|
if index
|
|
@t.tagid2obj(tk_call(@t.path, 'mark', 'next', index))
|
|
else
|
|
@t.tagid2obj(tk_call(@t.path, 'mark', 'next', @id))
|
|
end
|
|
end
|
|
|
|
def previous(index = nil)
|
|
if index
|
|
@t.tagid2obj(tk_call(@t.path, 'mark', 'previous', index))
|
|
else
|
|
@t.tagid2obj(tk_call(@t.path, 'mark', 'previous', @id))
|
|
end
|
|
end
|
|
end
|
|
|
|
class TkTextNamedMark<TkTextMark
|
|
def self.new(parent, name, *args)
|
|
if TMarkID_TBL[parent.path] && TMarkID_TBL[parent.path][name]
|
|
return TMarkID_TBL[parent.path][name]
|
|
else
|
|
super(parent, name, *args)
|
|
end
|
|
end
|
|
|
|
def initialize(parent, name, index=nil)
|
|
if not parent.kind_of?(TkText)
|
|
fail format("%s need to be TkText", parent.inspect)
|
|
end
|
|
@parent = @t = parent
|
|
@tpath = parent.path
|
|
@path = @id = name
|
|
TMarkID_TBL[@id] = self
|
|
TMarkID_TBL[@tpath] = {} unless TMarkID_TBL[@tpath]
|
|
TMarkID_TBL[@tpath][@id] = self unless TMarkID_TBL[@tpath][@id]
|
|
tk_call @t.path, 'mark', 'set', @id, index if index
|
|
@t._addtag id, self
|
|
end
|
|
end
|
|
|
|
class TkTextMarkInsert<TkTextNamedMark
|
|
def self.new(parent,*args)
|
|
super(parent, 'insert', *args)
|
|
end
|
|
end
|
|
|
|
class TkTextMarkCurrent<TkTextMark
|
|
def self.new(parent,*args)
|
|
super(parent, 'current', *args)
|
|
end
|
|
end
|
|
|
|
class TkTextMarkAnchor<TkTextMark
|
|
def self.new(parent,*args)
|
|
super(parent, 'anchor', *args)
|
|
end
|
|
end
|
|
|
|
class TkTextWindow<TkObject
|
|
def initialize(parent, index, keys)
|
|
if not parent.kind_of?(TkText)
|
|
fail format("%s need to be TkText", parent.inspect)
|
|
end
|
|
@t = parent
|
|
if index == 'end'
|
|
@path = TkTextMark.new(@t, tk_call(@t.path, 'index', 'end - 1 chars'))
|
|
elsif index.kind_of? TkTextMark
|
|
if tk_call(@t.path,'index',index.path) == tk_call(@t.path,'index','end')
|
|
@path = TkTextMark.new(@t, tk_call(@t.path, 'index', 'end - 1 chars'))
|
|
else
|
|
@path = TkTextMark.new(@t, tk_call(@t.path, 'index', index.path))
|
|
end
|
|
else
|
|
@path = TkTextMark.new(@t, tk_call(@t.path, 'index', index))
|
|
end
|
|
@path.gravity = 'left'
|
|
@index = @path.path
|
|
keys = _symbolkey2str(keys)
|
|
@id = keys['window']
|
|
if keys['create']
|
|
@p_create = keys['create']
|
|
if @p_create.kind_of? Proc
|
|
keys['create'] = install_cmd(proc{@id = @p_create.call; @id.path})
|
|
end
|
|
end
|
|
tk_call @t.path, 'window', 'create', @index, *hash_kv(keys)
|
|
end
|
|
|
|
def [](slot)
|
|
cget(slot)
|
|
end
|
|
def []=(slot, value)
|
|
configure(slot, value)
|
|
end
|
|
|
|
def cget(slot)
|
|
@t.window_cget(@index, slot)
|
|
end
|
|
|
|
def configure(slot, value=None)
|
|
if slot.kind_of? Hash
|
|
slot = _symbolkey2str(slot)
|
|
@id = slot['window'] if slot['window']
|
|
if slot['create']
|
|
self.create=value
|
|
slot['create']=nil
|
|
end
|
|
if slot.size > 0
|
|
tk_call(@t.path, 'window', 'configure', @index, *hash_kv(slot))
|
|
end
|
|
else
|
|
@id = value if slot == 'window' || slot == :window
|
|
if slot == 'create' || slot == :create
|
|
self.create=value
|
|
else
|
|
tk_call(@t.path, 'window', 'configure', @index, "-#{slot}", value)
|
|
end
|
|
end
|
|
self
|
|
end
|
|
|
|
def configinfo(slot = nil)
|
|
@t.window_configinfo(@index, slot)
|
|
end
|
|
|
|
def window
|
|
@id
|
|
end
|
|
|
|
def window=(value)
|
|
tk_call @t.path, 'window', 'configure', @index, '-window', value
|
|
@id = value
|
|
end
|
|
|
|
def create
|
|
@p_create
|
|
end
|
|
|
|
def create=(value)
|
|
@p_create = value
|
|
if @p_create.kind_of? Proc
|
|
value = install_cmd(proc{@id = @p_create.call})
|
|
end
|
|
tk_call @t.path, 'window', 'configure', @index, '-create', value
|
|
end
|
|
end
|
|
|
|
class TkTextImage<TkObject
|
|
def initialize(parent, index, keys)
|
|
if not parent.kind_of?(TkText)
|
|
fail format("%s need to be TkText", parent.inspect)
|
|
end
|
|
@t = parent
|
|
if index == 'end'
|
|
@path = TkTextMark.new(@t, tk_call(@t.path, 'index', 'end - 1 chars'))
|
|
elsif index.kind_of? TkTextMark
|
|
if tk_call(@t.path,'index',index.path) == tk_call(@t.path,'index','end')
|
|
@path = TkTextMark.new(@t, tk_call(@t.path, 'index', 'end - 1 chars'))
|
|
else
|
|
@path = TkTextMark.new(@t, tk_call(@t.path, 'index', index.path))
|
|
end
|
|
else
|
|
@path = TkTextMark.new(@t, tk_call(@t.path, 'index', index))
|
|
end
|
|
@path.gravity = 'left'
|
|
@index = @path.path
|
|
@id = tk_call(@t.path, 'image', 'create', @index, *hash_kv(keys))
|
|
end
|
|
|
|
def [](slot)
|
|
cget(slot)
|
|
end
|
|
def []=(slot, value)
|
|
configure(slot, value)
|
|
end
|
|
|
|
def cget(slot)
|
|
@t.image_cget(@index, slot)
|
|
end
|
|
|
|
def configure(slot, value=None)
|
|
@t.image_configure(@index, slot, value)
|
|
self
|
|
end
|
|
# def configure(slot, value)
|
|
# tk_call @t.path, 'image', 'configure', @index, "-#{slot}", value
|
|
# end
|
|
|
|
def configinfo(slot = nil)
|
|
@t.image_configinfo(@index, slot)
|
|
end
|
|
|
|
def image
|
|
img = tk_call(@t.path, 'image', 'configure', @index, '-image')
|
|
TkImage::Tk_IMGTBL[img]? TkImage::Tk_IMGTBL[img] : img
|
|
end
|
|
|
|
def image=(value)
|
|
tk_call @t.path, 'image', 'configure', @index, '-image', value
|
|
self
|
|
end
|
|
end
|