PageRenderTime 93ms CodeModel.GetById 27ms RepoModel.GetById 1ms app.codeStats 0ms

/ext/tk/lib/tk/text.rb

https://github.com/fizx/ruby
Ruby | 1604 lines | 1157 code | 126 blank | 321 comment | 158 complexity | 7e203fc501101ae9b9d921176b86b5ef MD5 | raw file
Possible License(s): LGPL-2.1, AGPL-3.0, GPL-2.0, BSD-3-Clause
  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. module TkTextTagConfig
  10. include TkTreatItemFont
  11. include TkItemConfigMethod
  12. def __item_cget_cmd(id) # id := [ type, tagOrId ]
  13. [self.path, id[0], 'cget', id[1]]
  14. end
  15. private :__item_cget_cmd
  16. def __item_config_cmd(id) # id := [ type, tagOrId ]
  17. [self.path, id[0], 'configure', id[1]]
  18. end
  19. private :__item_config_cmd
  20. def __item_pathname(id)
  21. if id.kind_of?(Array)
  22. id = tagid(id[1])
  23. end
  24. [self.path, id].join(';')
  25. end
  26. private :__item_pathname
  27. def tag_cget_tkstring(tagOrId, option)
  28. itemcget_tkstring(['tag', tagOrId], option)
  29. end
  30. def tag_cget(tagOrId, option)
  31. itemcget(['tag', tagOrId], option)
  32. end
  33. def tag_cget_strict(tagOrId, option)
  34. itemcget_strict(['tag', tagOrId], option)
  35. end
  36. def tag_configure(tagOrId, slot, value=None)
  37. itemconfigure(['tag', tagOrId], slot, value)
  38. end
  39. def tag_configinfo(tagOrId, slot=nil)
  40. itemconfiginfo(['tag', tagOrId], slot)
  41. end
  42. def current_tag_configinfo(tagOrId, slot=nil)
  43. current_itemconfiginfo(['tag', tagOrId], slot)
  44. end
  45. def window_cget_tkstring(tagOrId, option)
  46. itemcget_tkstring(['window', tagOrId], option)
  47. end
  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. private :itemcget_tkstring, :itemcget, :itemcget_strict
  64. private :itemconfigure, :itemconfiginfo, :current_itemconfiginfo
  65. end
  66. class Tk::Text<TkTextWin
  67. ItemConfCMD = ['tag'.freeze, 'configure'.freeze].freeze
  68. #include TkTreatTextTagFont
  69. include TkTextTagConfig
  70. include Scrollable
  71. #######################################
  72. module IndexModMethods
  73. def +(mod)
  74. return chars(mod) if mod.kind_of?(Numeric)
  75. mod = mod.to_s
  76. if mod =~ /^\s*[+-]?\d/
  77. Tk::Text::IndexString.new(String.new(id) << ' + ' << mod)
  78. else
  79. Tk::Text::IndexString.new(String.new(id) << ' ' << mod)
  80. end
  81. end
  82. def -(mod)
  83. return chars(-mod) if mod.kind_of?(Numeric)
  84. mod = mod.to_s
  85. if mod =~ /^\s*[+-]?\d/
  86. Tk::Text::IndexString.new(String.new(id) << ' - ' << mod)
  87. elsif mod =~ /^\s*[-]\s+(\d.*)$/
  88. Tk::Text::IndexString.new(String.new(id) << ' - -' << $1)
  89. else
  90. Tk::Text::IndexString.new(String.new(id) << ' ' << mod)
  91. end
  92. end
  93. def chars(mod)
  94. fail ArgumentError, 'expect Integer' unless mod.kind_of?(Integer)
  95. if mod < 0
  96. Tk::Text::IndexString.new(String.new(id) << ' ' << mod.to_s << ' chars')
  97. else
  98. Tk::Text::IndexString.new(String.new(id) << ' + ' << mod.to_s << ' chars')
  99. end
  100. end
  101. alias char chars
  102. def display_chars(mod)
  103. # Tk8.5 feature
  104. fail ArgumentError, 'expect Integer' unless mod.kind_of?(Integer)
  105. if mod < 0
  106. Tk::Text::IndexString.new(String.new(id) << ' ' << mod.to_s << ' display chars')
  107. else
  108. Tk::Text::IndexString.new(String.new(id) << ' + ' << mod.to_s << ' display chars')
  109. end
  110. end
  111. alias display_char display_chars
  112. def any_chars(mod)
  113. # Tk8.5 feature
  114. fail ArgumentError, 'expect Integer' unless mod.kind_of?(Integer)
  115. if mod < 0
  116. Tk::Text::IndexString.new(String.new(id) << ' ' << mod.to_s << ' any chars')
  117. else
  118. Tk::Text::IndexString.new(String.new(id) << ' + ' << mod.to_s << ' any chars')
  119. end
  120. end
  121. alias any_char any_chars
  122. def indices(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 << ' indices')
  127. else
  128. Tk::Text::IndexString.new(String.new(id) << ' + ' << mod.to_s << ' indices')
  129. end
  130. end
  131. def display_indices(mod)
  132. # Tk8.5 feature
  133. fail ArgumentError, 'expect Integer' unless mod.kind_of?(Integer)
  134. if mod < 0
  135. Tk::Text::IndexString.new(String.new(id) << ' ' << mod.to_s << ' display indices')
  136. else
  137. Tk::Text::IndexString.new(String.new(id) << ' + ' << mod.to_s << ' display indices')
  138. end
  139. end
  140. def any_indices(mod)
  141. # Tk8.5 feature
  142. fail ArgumentError, 'expect Integer' unless mod.kind_of?(Integer)
  143. if mod < 0
  144. Tk::Text::IndexString.new(String.new(id) << ' ' << mod.to_s << ' any indices')
  145. else
  146. Tk::Text::IndexString.new(String.new(id) << ' + ' << mod.to_s << ' any indices')
  147. end
  148. end
  149. def lines(mod)
  150. fail ArgumentError, 'expect Integer' unless mod.kind_of?(Integer)
  151. if mod < 0
  152. Tk::Text::IndexString.new(String.new(id) << ' ' << mod.to_s << ' lines')
  153. else
  154. Tk::Text::IndexString.new(String.new(id) << ' + ' << mod.to_s << ' lines')
  155. end
  156. end
  157. alias line lines
  158. def display_lines(mod)
  159. # Tk8.5 feature
  160. fail ArgumentError, 'expect Integer' unless mod.kind_of?(Integer)
  161. if mod < 0
  162. Tk::Text::IndexString.new(String.new(id) << ' ' << mod.to_s << ' display_lines')
  163. else
  164. Tk::Text::IndexString.new(String.new(id) << ' + ' << mod.to_s << ' display lines')
  165. end
  166. end
  167. alias display_line display_lines
  168. def any_lines(mod)
  169. # Tk8.5 feature
  170. fail ArgumentError, 'expect Integer' unless mod.kind_of?(Integer)
  171. if mod < 0
  172. Tk::Text::IndexString.new(String.new(id) << ' ' << mod.to_s << ' any_lines')
  173. else
  174. Tk::Text::IndexString.new(String.new(id) << ' + ' << mod.to_s << ' any lines')
  175. end
  176. end
  177. alias any_line any_lines
  178. def linestart
  179. Tk::Text::IndexString.new(String.new(id) << ' linestart')
  180. end
  181. def lineend
  182. Tk::Text::IndexString.new(String.new(id) << ' lineend')
  183. end
  184. def display_linestart
  185. # Tk8.5 feature
  186. Tk::Text::IndexString.new(String.new(id) << ' display linestart')
  187. end
  188. def display_lineend
  189. # Tk8.5 feature
  190. Tk::Text::IndexString.new(String.new(id) << ' display lineend')
  191. end
  192. def wordstart
  193. Tk::Text::IndexString.new(String.new(id) << ' wordstart')
  194. end
  195. def wordend
  196. Tk::Text::IndexString.new(String.new(id) << ' wordend')
  197. end
  198. def display_wordstart
  199. # Tk8.5 feature
  200. Tk::Text::IndexString.new(String.new(id) << ' display wordstart')
  201. end
  202. def display_wordend
  203. # Tk8.5 feature
  204. Tk::Text::IndexString.new(String.new(id) << ' display wordend')
  205. end
  206. end
  207. class IndexString < String
  208. include IndexModMethods
  209. def self.at(x,y)
  210. self.new("@#{x},#{y}")
  211. end
  212. def self.new(str)
  213. if str.kind_of?(String)
  214. super(str)
  215. elsif str.kind_of?(Symbol)
  216. super(str.to_s)
  217. else
  218. str
  219. end
  220. end
  221. def id
  222. self
  223. end
  224. end
  225. #######################################
  226. TkCommandNames = ['text'.freeze].freeze
  227. WidgetClassName = 'Text'.freeze
  228. WidgetClassNames[WidgetClassName] ||= self
  229. def self.new(*args, &block)
  230. obj = super(*args){}
  231. obj.init_instance_variable
  232. if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!!
  233. obj.instance_exec(obj, &block) if defined? yield
  234. else
  235. obj.instance_eval(&block) if defined? yield
  236. end
  237. obj
  238. end
  239. def init_instance_variable
  240. @cmdtbl = []
  241. @tags = {}
  242. end
  243. def __destroy_hook__
  244. TkTextTag::TTagID_TBL.mutex.synchronize{
  245. TkTextTag::TTagID_TBL.delete(@path)
  246. }
  247. TkTextTag::TMarkID_TBL.mutex.synchronize{
  248. TkTextMark::TMarkID_TBL.delete(@path)
  249. }
  250. end
  251. def create_self(keys)
  252. #if keys and keys != None
  253. # #tk_call_without_enc('text', @path, *hash_kv(keys, true))
  254. # tk_call_without_enc(self.class::TkCommandNames[0], @path,
  255. # *hash_kv(keys, true))
  256. #else
  257. # #tk_call_without_enc('text', @path)
  258. # tk_call_without_enc(self.class::TkCommandNames[0], @path)
  259. #end
  260. super(keys)
  261. init_instance_variable
  262. end
  263. private :create_self
  264. def __strval_optkeys
  265. super() << 'inactiveseletcionbackground'
  266. end
  267. private :__strval_optkeys
  268. def self.at(x, y)
  269. Tk::Text::IndexString.at(x, y)
  270. end
  271. def at(x, y)
  272. Tk::Text::IndexString.at(x, y)
  273. end
  274. def index(idx)
  275. Tk::Text::IndexString.new(tk_send_without_enc('index',
  276. _get_eval_enc_str(idx)))
  277. end
  278. def get_displaychars(*index)
  279. # Tk8.5 feature
  280. get('-displaychars', *index)
  281. end
  282. def value
  283. _fromUTF8(tk_send_without_enc('get', "1.0", "end - 1 char"))
  284. end
  285. def value= (val)
  286. tk_send_without_enc('delete', "1.0", 'end')
  287. tk_send_without_enc('insert', "1.0", _get_eval_enc_str(val))
  288. val
  289. end
  290. def clear
  291. tk_send_without_enc('delete', "1.0", 'end')
  292. self
  293. end
  294. alias erase clear
  295. def _addcmd(cmd)
  296. @cmdtbl.push cmd
  297. end
  298. def _addtag(name, obj)
  299. @tags[name] = obj
  300. end
  301. def tagid(tag)
  302. if tag.kind_of?(TkTextTag) \
  303. || tag.kind_of?(TkTextMark) \
  304. || tag.kind_of?(TkTextImage) \
  305. || tag.kind_of?(TkTextWindow)
  306. tag.id
  307. else
  308. tag # maybe an Array of configure paramters
  309. end
  310. end
  311. private :tagid
  312. def tagid2obj(tagid)
  313. if @tags[tagid]
  314. @tags[tagid]
  315. else
  316. tagid
  317. end
  318. end
  319. def tag_names(index=None)
  320. #tk_split_simplelist(_fromUTF8(tk_send_without_enc('tag', 'names', _get_eval_enc_str(index)))).collect{|elt|
  321. tk_split_simplelist(tk_send_without_enc('tag', 'names', _get_eval_enc_str(index)), false, true).collect{|elt|
  322. tagid2obj(elt)
  323. }
  324. end
  325. def mark_names
  326. #tk_split_simplelist(_fromUTF8(tk_send_without_enc('mark', 'names'))).collect{|elt|
  327. tk_split_simplelist(tk_send_without_enc('mark', 'names'), false, true).collect{|elt|
  328. tagid2obj(elt)
  329. }
  330. end
  331. def mark_gravity(mark, direction=nil)
  332. if direction
  333. tk_send_without_enc('mark', 'gravity',
  334. _get_eval_enc_str(mark), direction)
  335. self
  336. else
  337. tk_send_without_enc('mark', 'gravity', _get_eval_enc_str(mark))
  338. end
  339. end
  340. def mark_set(mark, index)
  341. tk_send_without_enc('mark', 'set', _get_eval_enc_str(mark),
  342. _get_eval_enc_str(index))
  343. self
  344. end
  345. alias set_mark mark_set
  346. def mark_unset(*marks)
  347. tk_send_without_enc('mark', 'unset',
  348. *(marks.collect{|mark| _get_eval_enc_str(mark)}))
  349. self
  350. end
  351. alias unset_mark mark_unset
  352. def mark_next(index)
  353. tagid2obj(_fromUTF8(tk_send_without_enc('mark', 'next',
  354. _get_eval_enc_str(index))))
  355. end
  356. alias next_mark mark_next
  357. def mark_previous(index)
  358. tagid2obj(_fromUTF8(tk_send_without_enc('mark', 'previous',
  359. _get_eval_enc_str(index))))
  360. end
  361. alias previous_mark mark_previous
  362. def image_cget_strict(index, slot)
  363. case slot.to_s
  364. when 'text', 'label', 'show', 'data', 'file'
  365. _fromUTF8(tk_send_without_enc('image', 'cget',
  366. _get_eval_enc_str(index), "-#{slot}"))
  367. else
  368. tk_tcl2ruby(_fromUTF8(tk_send_without_enc('image', 'cget',
  369. _get_eval_enc_str(index),
  370. "-#{slot}")))
  371. end
  372. end
  373. def image_cget(index, slot)
  374. unless TkItemConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__
  375. image_cget_strict(index, slot)
  376. else
  377. begin
  378. image_cget_strict(index, slot)
  379. rescue => e
  380. begin
  381. if current_image_configinfo(index).has_key?(slot.to_s)
  382. # not tag error & option is known -> error on known option
  383. fail e
  384. else
  385. # not tag error & option is unknown
  386. nil
  387. end
  388. rescue
  389. fail e # tag error
  390. end
  391. end
  392. end
  393. end
  394. def image_configure(index, slot, value=None)
  395. if slot.kind_of?(Hash)
  396. _fromUTF8(tk_send_without_enc('image', 'configure',
  397. _get_eval_enc_str(index),
  398. *hash_kv(slot, true)))
  399. else
  400. _fromUTF8(tk_send_without_enc('image', 'configure',
  401. _get_eval_enc_str(index),
  402. "-#{slot}",
  403. _get_eval_enc_str(value)))
  404. end
  405. self
  406. end
  407. def image_configinfo(index, slot = nil)
  408. if TkComm::GET_CONFIGINFO_AS_ARRAY
  409. if slot
  410. case slot.to_s
  411. when 'text', 'label', 'show', 'data', 'file'
  412. #conf = tk_split_simplelist(_fromUTF8(tk_send_without_enc('image', 'configure', _get_eval_enc_str(index), "-#{slot}")))
  413. conf = tk_split_simplelist(tk_send_without_enc('image', 'configure', _get_eval_enc_str(index), "-#{slot}"), false, true)
  414. else
  415. #conf = tk_split_list(_fromUTF8(tk_send_without_enc('image', 'configure', _get_eval_enc_str(index), "-#{slot}")))
  416. conf = tk_split_list(tk_send_without_enc('image', 'configure', _get_eval_enc_str(index), "-#{slot}"), 0, false, true)
  417. end
  418. conf[0] = conf[0][1..-1]
  419. conf
  420. else
  421. # tk_split_simplelist(_fromUTF8(tk_send_without_enc('image', 'configure', _get_eval_enc_str(index)))).collect{|conflist|
  422. # conf = tk_split_simplelist(conflist)
  423. tk_split_simplelist(tk_send_without_enc('image', 'configure', _get_eval_enc_str(index)), false, false).collect{|conflist|
  424. conf = tk_split_simplelist(conflist, false, true)
  425. conf[0] = conf[0][1..-1]
  426. case conf[0]
  427. when 'text', 'label', 'show', 'data', 'file'
  428. else
  429. if conf[3]
  430. if conf[3].index('{')
  431. conf[3] = tk_split_list(conf[3])
  432. else
  433. conf[3] = tk_tcl2ruby(conf[3])
  434. end
  435. end
  436. if conf[4]
  437. if conf[4].index('{')
  438. conf[4] = tk_split_list(conf[4])
  439. else
  440. conf[4] = tk_tcl2ruby(conf[4])
  441. end
  442. end
  443. end
  444. conf[1] = conf[1][1..-1] if conf.size == 2 # alias info
  445. conf
  446. }
  447. end
  448. else # ! TkComm::GET_CONFIGINFO_AS_ARRAY
  449. if slot
  450. case slot.to_s
  451. when 'text', 'label', 'show', 'data', 'file'
  452. #conf = tk_split_simplelist(_fromUTF8(tk_send_without_enc('image', 'configure', _get_eval_enc_str(index), "-#{slot}")))
  453. conf = tk_split_simplelist(tk_send_without_enc('image', 'configure', _get_eval_enc_str(index), "-#{slot}"), false, true)
  454. else
  455. #conf = tk_split_list(_fromUTF8(tk_send_without_enc('image', 'configure', _get_eval_enc_str(index), "-#{slot}")))
  456. conf = tk_split_list(tk_send_without_enc('image', 'configure', _get_eval_enc_str(index), "-#{slot}"), 0, false, true)
  457. end
  458. key = conf.shift[1..-1]
  459. { key => conf }
  460. else
  461. ret = {}
  462. #tk_split_simplelist(_fromUTF8(tk_send_without_enc('image', 'configure', _get_eval_enc_str(index)))).each{|conflist|
  463. # conf = tk_split_simplelist(conflist)
  464. tk_split_simplelist(tk_send_without_enc('image', 'configure', _get_eval_enc_str(index)), false, false).each{|conflist|
  465. conf = tk_split_simplelist(conflist, false, true)
  466. key = conf.shift[1..-1]
  467. case key
  468. when 'text', 'label', 'show', 'data', 'file'
  469. else
  470. if conf[2]
  471. if conf[2].index('{')
  472. conf[2] = tk_split_list(conf[2])
  473. else
  474. conf[2] = tk_tcl2ruby(conf[2])
  475. end
  476. end
  477. if conf[3]
  478. if conf[3].index('{')
  479. conf[3] = tk_split_list(conf[3])
  480. else
  481. conf[3] = tk_tcl2ruby(conf[3])
  482. end
  483. end
  484. end
  485. if conf.size == 1
  486. ret[key] = conf[0][1..-1] # alias info
  487. else
  488. ret[key] = conf
  489. end
  490. }
  491. ret
  492. end
  493. end
  494. end
  495. def current_image_configinfo(index, slot = nil)
  496. if TkComm::GET_CONFIGINFO_AS_ARRAY
  497. if slot
  498. conf = image_configinfo(index, slot)
  499. {conf[0] => conf[4]}
  500. else
  501. ret = {}
  502. image_configinfo(index).each{|conf|
  503. ret[conf[0]] = conf[4] if conf.size > 2
  504. }
  505. ret
  506. end
  507. else # ! TkComm::GET_CONFIGINFO_AS_ARRAY
  508. ret = {}
  509. image_configinfo(index, slot).each{|k, conf|
  510. ret[k] = conf[-1] if conf.kind_of?(Array)
  511. }
  512. ret
  513. end
  514. end
  515. def image_names
  516. #tk_split_simplelist(_fromUTF8(tk_send_without_enc('image', 'names'))).collect{|elt|
  517. tk_split_simplelist(tk_send_without_enc('image', 'names'), false, true).collect{|elt|
  518. tagid2obj(elt)
  519. }
  520. end
  521. def set_insert(index)
  522. tk_send_without_enc('mark','set','insert', _get_eval_enc_str(index))
  523. self
  524. end
  525. def set_current(index)
  526. tk_send_without_enc('mark','set','current', _get_eval_enc_str(index))
  527. self
  528. end
  529. def insert(index, chars, *tags)
  530. if tags[0].kind_of?(Array)
  531. # multiple chars-taglist argument :: str, [tag,...], str, [tag,...], ...
  532. args = [chars]
  533. while tags.size > 0
  534. args << tags.shift.collect{|x|_get_eval_string(x)}.join(' ') # taglist
  535. args << tags.shift if tags.size > 0 # chars
  536. end
  537. super(index, *args)
  538. else
  539. # single chars-taglist argument :: str, tag, tag, ...
  540. if tags.size == 0
  541. super(index, chars)
  542. else
  543. super(index, chars, tags.collect{|x|_get_eval_string(x)}.join(' '))
  544. end
  545. end
  546. end
  547. def destroy
  548. @tags = {} unless @tags
  549. @tags.each_value do |t|
  550. t.destroy
  551. end
  552. super()
  553. end
  554. def backspace
  555. self.delete 'insert'
  556. end
  557. def bbox(index)
  558. list(tk_send_without_enc('bbox', _get_eval_enc_str(index)))
  559. end
  560. def compare(idx1, op, idx2)
  561. bool(tk_send_without_enc('compare', _get_eval_enc_str(idx1),
  562. op, _get_eval_enc_str(idx2)))
  563. end
  564. def count(idx1, idx2, *opts)
  565. # opts are Tk8.5 feature
  566. cnt = 0
  567. args = opts.collect{|opt|
  568. str = opt.to_s
  569. cnt += 1 if str != 'update'
  570. '-' + str
  571. }
  572. args << _get_eval_enc_str(idx1) << _get_eval_enc_str(idx2)
  573. if cnt <= 1
  574. number(tk_send_without_enc('count', *opts))
  575. else
  576. list(tk_send_without_enc('count', *opts))
  577. end
  578. end
  579. def count_info(idx1, idx2, update=true)
  580. # Tk8.5 feature
  581. opts = [
  582. :chars, :displaychars, :displayindices, :displaylines,
  583. :indices, :lines, :xpixels, :ypixels
  584. ]
  585. if update
  586. lst = count(idx1, idx2, :update, *opts)
  587. else
  588. lst = count(idx1, idx2, *opts)
  589. end
  590. info = {}
  591. opts.each_with_index{|key, idx| info[key] = lst[idx]}
  592. info
  593. end
  594. def peer_names()
  595. # Tk8.5 feature
  596. list(tk_send_without_enc('peer', 'names'))
  597. end
  598. def replace(idx1, idx2, *opts)
  599. tk_send('replace', idx1, idx2, *opts)
  600. self
  601. end
  602. def debug
  603. bool(tk_send_without_enc('debug'))
  604. end
  605. def debug=(boolean)
  606. tk_send_without_enc('debug', boolean)
  607. #self
  608. boolean
  609. end
  610. def dlineinfo(index)
  611. list(tk_send_without_enc('dlineinfo', _get_eval_enc_str(index)))
  612. end
  613. def modified?
  614. bool(tk_send_without_enc('edit', 'modified'))
  615. end
  616. def modified(mode)
  617. tk_send_without_enc('edit', 'modified', mode)
  618. self
  619. end
  620. def modified=(mode)
  621. modified(mode)
  622. mode
  623. end
  624. def edit_redo
  625. tk_send_without_enc('edit', 'redo')
  626. self
  627. end
  628. def edit_reset
  629. tk_send_without_enc('edit', 'reset')
  630. self
  631. end
  632. def edit_separator
  633. tk_send_without_enc('edit', 'separator')
  634. self
  635. end
  636. def edit_undo
  637. tk_send_without_enc('edit', 'undo')
  638. self
  639. end
  640. def xview_pickplace(index)
  641. tk_send_without_enc('xview', '-pickplace', _get_eval_enc_str(index))
  642. self
  643. end
  644. def yview_pickplace(index)
  645. tk_send_without_enc('yview', '-pickplace', _get_eval_enc_str(index))
  646. self
  647. end
  648. def text_copy
  649. # Tk8.4 feature
  650. tk_call_without_enc('tk_textCopy', @path)
  651. self
  652. end
  653. def text_cut
  654. # Tk8.4 feature
  655. tk_call_without_enc('tk_textCut', @path)
  656. self
  657. end
  658. def text_paste
  659. # Tk8.4 feature
  660. tk_call_without_enc('tk_textPaste', @path)
  661. self
  662. end
  663. def tag_add(tag, index1, index2=None)
  664. tk_send_without_enc('tag', 'add', _get_eval_enc_str(tag),
  665. _get_eval_enc_str(index1),
  666. _get_eval_enc_str(index2))
  667. self
  668. end
  669. alias addtag tag_add
  670. alias add_tag tag_add
  671. def tag_delete(*tags)
  672. tk_send_without_enc('tag', 'delete',
  673. *(tags.collect{|tag| _get_eval_enc_str(tag)}))
  674. TkTextTag::TTagID_TBL.mutex.synchronize{
  675. if TkTextTag::TTagID_TBL[@path]
  676. tags.each{|tag|
  677. if tag.kind_of?(TkTextTag)
  678. TkTextTag::TTagID_TBL[@path].delete(tag.id)
  679. else
  680. TkTextTag::TTagID_TBL[@path].delete(tag)
  681. end
  682. }
  683. end
  684. }
  685. self
  686. end
  687. alias deltag tag_delete
  688. alias delete_tag tag_delete
  689. #def tag_bind(tag, seq, cmd=Proc.new, *args)
  690. # _bind([@path, 'tag', 'bind', tag], seq, cmd, *args)
  691. # self
  692. #end
  693. def tag_bind(tag, seq, *args)
  694. # if args[0].kind_of?(Proc) || args[0].kind_of?(Method)
  695. if TkComm._callback_entry?(args[0]) || !block_given?
  696. cmd = args.shift
  697. else
  698. cmd = Proc.new
  699. end
  700. _bind([@path, 'tag', 'bind', tag], seq, cmd, *args)
  701. self
  702. end
  703. #def tag_bind_append(tag, seq, cmd=Proc.new, *args)
  704. # _bind_append([@path, 'tag', 'bind', tag], seq, cmd, *args)
  705. # self
  706. #end
  707. def tag_bind_append(tag, seq, *args)
  708. # if args[0].kind_of?(Proc) || args[0].kind_of?(Method)
  709. if TkComm._callback_entry?(args[0]) || !block_given?
  710. cmd = args.shift
  711. else
  712. cmd = Proc.new
  713. end
  714. _bind_append([@path, 'tag', 'bind', tag], seq, cmd, *args)
  715. self
  716. end
  717. def tag_bind_remove(tag, seq)
  718. _bind_remove([@path, 'tag', 'bind', tag], seq)
  719. self
  720. end
  721. def tag_bindinfo(tag, context=nil)
  722. _bindinfo([@path, 'tag', 'bind', tag], context)
  723. end
  724. =begin
  725. def tag_cget(tag, key)
  726. case key.to_s
  727. when 'text', 'label', 'show', 'data', 'file'
  728. tk_call_without_enc(@path, 'tag', 'cget',
  729. _get_eval_enc_str(tag), "-#{key}")
  730. when 'font', 'kanjifont'
  731. #fnt = tk_tcl2ruby(tk_send('tag', 'cget', tag, "-#{key}"))
  732. fnt = tk_tcl2ruby(_fromUTF8(tk_send_without_enc('tag','cget',_get_eval_enc_str(tag),'-font')))
  733. unless fnt.kind_of?(TkFont)
  734. fnt = tagfontobj(tag, fnt)
  735. end
  736. if key.to_s == 'kanjifont' && JAPANIZED_TK && TK_VERSION =~ /^4\.*/
  737. # obsolete; just for compatibility
  738. fnt.kanji_font
  739. else
  740. fnt
  741. end
  742. else
  743. tk_tcl2ruby(_fromUTF8(tk_call_without_enc(@path,'tag','cget',_get_eval_enc_str(tag),"-#{key}")))
  744. end
  745. end
  746. def tag_configure(tag, key, val=None)
  747. if key.kind_of?(Hash)
  748. key = _symbolkey2str(key)
  749. if ( key['font'] || key['kanjifont'] \
  750. || key['latinfont'] || key['asciifont'] )
  751. tagfont_configure(tag, key)
  752. else
  753. tk_send_without_enc('tag', 'configure', _get_eval_enc_str(tag),
  754. *hash_kv(key, true))
  755. end
  756. else
  757. if key == 'font' || key == :font ||
  758. key == 'kanjifont' || key == :kanjifont ||
  759. key == 'latinfont' || key == :latinfont ||
  760. key == 'asciifont' || key == :asciifont
  761. if val == None
  762. tagfontobj(tag)
  763. else
  764. tagfont_configure(tag, {key=>val})
  765. end
  766. else
  767. tk_send_without_enc('tag', 'configure', _get_eval_enc_str(tag),
  768. "-#{key}", _get_eval_enc_str(val))
  769. end
  770. end
  771. self
  772. end
  773. def tag_configinfo(tag, key=nil)
  774. if TkComm::GET_CONFIGINFO_AS_ARRAY
  775. if key
  776. case key.to_s
  777. when 'text', 'label', 'show', 'data', 'file'
  778. conf = tk_split_simplelist(_fromUTF8(tk_send_without_enc('tag','configure',_get_eval_enc_str(tag),"-#{key}")))
  779. when 'font', 'kanjifont'
  780. conf = tk_split_simplelist(_fromUTF8(tk_send_without_enc('tag','configure',_get_eval_enc_str(tag),"-#{key}")))
  781. conf[4] = tagfont_configinfo(tag, conf[4])
  782. else
  783. conf = tk_split_list(_fromUTF8(tk_send_without_enc('tag','configure',_get_eval_enc_str(tag),"-#{key}")))
  784. end
  785. conf[0] = conf[0][1..-1]
  786. conf
  787. else
  788. ret = tk_split_simplelist(_fromUTF8(tk_send('tag','configure',_get_eval_enc_str(tag)))).collect{|conflist|
  789. conf = tk_split_simplelist(conflist)
  790. conf[0] = conf[0][1..-1]
  791. case conf[0]
  792. when 'text', 'label', 'show', 'data', 'file'
  793. else
  794. if conf[3]
  795. if conf[3].index('{')
  796. conf[3] = tk_split_list(conf[3])
  797. else
  798. conf[3] = tk_tcl2ruby(conf[3])
  799. end
  800. end
  801. if conf[4]
  802. if conf[4].index('{')
  803. conf[4] = tk_split_list(conf[4])
  804. else
  805. conf[4] = tk_tcl2ruby(conf[4])
  806. end
  807. end
  808. end
  809. conf[1] = conf[1][1..-1] if conf.size == 2 # alias info
  810. conf
  811. }
  812. fontconf = ret.assoc('font')
  813. if fontconf
  814. ret.delete_if{|item| item[0] == 'font' || item[0] == 'kanjifont'}
  815. fontconf[4] = tagfont_configinfo(tag, fontconf[4])
  816. ret.push(fontconf)
  817. else
  818. ret
  819. end
  820. end
  821. else # ! TkComm::GET_CONFIGINFO_AS_ARRAY
  822. if key
  823. case key.to_s
  824. when 'text', 'label', 'show', 'data', 'file'
  825. conf = tk_split_simplelist(_fromUTF8(tk_send_without_enc('tag','configure',_get_eval_enc_str(tag),"-#{key}")))
  826. when 'font', 'kanjifont'
  827. conf = tk_split_simplelist(_fromUTF8(tk_send_without_enc('tag','configure',_get_eval_enc_str(tag),"-#{key}")))
  828. conf[4] = tagfont_configinfo(tag, conf[4])
  829. else
  830. conf = tk_split_list(_fromUTF8(tk_send_without_enc('tag','configure',_get_eval_enc_str(tag),"-#{key}")))
  831. end
  832. key = conf.shift[1..-1]
  833. { key => conf }
  834. else
  835. ret = {}
  836. tk_split_simplelist(_fromUTF8(tk_send('tag','configure',_get_eval_enc_str(tag)))).each{|conflist|
  837. conf = tk_split_simplelist(conflist)
  838. key = conf.shift[1..-1]
  839. case key
  840. when 'text', 'label', 'show', 'data', 'file'
  841. else
  842. if conf[2]
  843. if conf[2].index('{')
  844. conf[2] = tk_split_list(conf[2])
  845. else
  846. conf[2] = tk_tcl2ruby(conf[2])
  847. end
  848. end
  849. if conf[3]
  850. if conf[3].index('{')
  851. conf[3] = tk_split_list(conf[3])
  852. else
  853. conf[3] = tk_tcl2ruby(conf[3])
  854. end
  855. end
  856. end
  857. if conf.size == 1
  858. ret[key] = conf[0][1..-1] # alias info
  859. else
  860. ret[key] = conf
  861. end
  862. }
  863. fontconf = ret['font']
  864. if fontconf
  865. ret.delete('font')
  866. ret.delete('kanjifont')
  867. fontconf[3] = tagfont_configinfo(tag, fontconf[3])
  868. ret['font'] = fontconf
  869. end
  870. ret
  871. end
  872. end
  873. end
  874. def current_tag_configinfo(tag, key=nil)
  875. if TkComm::GET_CONFIGINFO_AS_ARRAY
  876. if key
  877. conf = tag_configinfo(tag, key)
  878. {conf[0] => conf[4]}
  879. else
  880. ret = {}
  881. tag_configinfo(tag).each{|conf|
  882. ret[conf[0]] = conf[4] if conf.size > 2
  883. }
  884. ret
  885. end
  886. else # ! TkComm::GET_CONFIGINFO_AS_ARRAY
  887. ret = {}
  888. tag_configinfo(tag, key).each{|k, conf|
  889. ret[k] = conf[-1] if conf.kind_of?(Array)
  890. }
  891. ret
  892. end
  893. end
  894. =end
  895. def tag_raise(tag, above=None)
  896. tk_send_without_enc('tag', 'raise', _get_eval_enc_str(tag),
  897. _get_eval_enc_str(above))
  898. self
  899. end
  900. def tag_lower(tag, below=None)
  901. tk_send_without_enc('tag', 'lower', _get_eval_enc_str(tag),
  902. _get_eval_enc_str(below))
  903. self
  904. end
  905. def tag_remove(tag, *indices)
  906. tk_send_without_enc('tag', 'remove', _get_eval_enc_str(tag),
  907. *(indices.collect{|idx| _get_eval_enc_str(idx)}))
  908. self
  909. end
  910. def tag_ranges(tag)
  911. #l = tk_split_simplelist(tk_send_without_enc('tag', 'ranges',
  912. # _get_eval_enc_str(tag)))
  913. l = tk_split_simplelist(tk_send_without_enc('tag', 'ranges',
  914. _get_eval_enc_str(tag)),
  915. false, true)
  916. r = []
  917. while key=l.shift
  918. r.push [Tk::Text::IndexString.new(key), Tk::Text::IndexString.new(l.shift)]
  919. end
  920. r
  921. end
  922. def tag_nextrange(tag, first, last=None)
  923. simplelist(tk_send_without_enc('tag', 'nextrange',
  924. _get_eval_enc_str(tag),
  925. _get_eval_enc_str(first),
  926. _get_eval_enc_str(last))).collect{|idx|
  927. Tk::Text::IndexString.new(idx)
  928. }
  929. end
  930. def tag_prevrange(tag, first, last=None)
  931. simplelist(tk_send_without_enc('tag', 'prevrange',
  932. _get_eval_enc_str(tag),
  933. _get_eval_enc_str(first),
  934. _get_eval_enc_str(last))).collect{|idx|
  935. Tk::Text::IndexString.new(idx)
  936. }
  937. end
  938. =begin
  939. def window_cget(index, slot)
  940. case slot.to_s
  941. when 'text', 'label', 'show', 'data', 'file'
  942. _fromUTF8(tk_send_without_enc('window', 'cget',
  943. _get_eval_enc_str(index), "-#{slot}"))
  944. when 'font', 'kanjifont'
  945. #fnt = tk_tcl2ruby(tk_send('window', 'cget', index, "-#{slot}"))
  946. fnt = tk_tcl2ruby(_fromUTF8(tk_send_without_enc('window', 'cget', _get_eval_enc_str(index), '-font')))
  947. unless fnt.kind_of?(TkFont)
  948. fnt = tagfontobj(index, fnt)
  949. end
  950. if slot.to_s == 'kanjifont' && JAPANIZED_TK && TK_VERSION =~ /^4\.*/
  951. # obsolete; just for compatibility
  952. fnt.kanji_font
  953. else
  954. fnt
  955. end
  956. else
  957. tk_tcl2ruby(_fromUTF8(tk_send_without_enc('window', 'cget', _get_eval_enc_str(index), "-#{slot}")))
  958. end
  959. end
  960. def window_configure(index, slot, value=None)
  961. if index.kind_of?(TkTextWindow)
  962. index.configure(slot, value)
  963. else
  964. if slot.kind_of?(Hash)
  965. slot = _symbolkey2str(slot)
  966. win = slot['window']
  967. # slot['window'] = win.epath if win.kind_of?(TkWindow)
  968. slot['window'] = _epath(win) if win
  969. if slot['create']
  970. p_create = slot['create']
  971. if p_create.kind_of?(Proc)
  972. #=begin
  973. slot['create'] = install_cmd(proc{
  974. id = p_create.call
  975. if id.kind_of?(TkWindow)
  976. id.epath
  977. else
  978. id
  979. end
  980. })
  981. #=end
  982. slot['create'] = install_cmd(proc{_epath(p_create.call)})
  983. end
  984. end
  985. tk_send_without_enc('window', 'configure',
  986. _get_eval_enc_str(index),
  987. *hash_kv(slot, true))
  988. else
  989. if slot == 'window' || slot == :window
  990. # id = value
  991. # value = id.epath if id.kind_of?(TkWindow)
  992. value = _epath(value)
  993. end
  994. if slot == 'create' || slot == :create
  995. p_create = value
  996. if p_create.kind_of?(Proc)
  997. #=begin
  998. value = install_cmd(proc{
  999. id = p_create.call
  1000. if id.kind_of?(TkWindow)
  1001. id.epath
  1002. else
  1003. id
  1004. end
  1005. })
  1006. #=end
  1007. value = install_cmd(proc{_epath(p_create.call)})
  1008. end
  1009. end
  1010. tk_send_without_enc('window', 'configure',
  1011. _get_eval_enc_str(index),
  1012. "-#{slot}", _get_eval_enc_str(value))
  1013. end
  1014. end
  1015. self
  1016. end
  1017. def window_configinfo(win, slot = nil)
  1018. if TkComm::GET_CONFIGINFO_AS_ARRAY
  1019. if slot
  1020. case slot.to_s
  1021. when 'text', 'label', 'show', 'data', 'file'
  1022. conf = tk_split_simplelist(_fromUTF8(tk_send('window', 'configure', _get_eval_enc_str(win), "-#{slot}")))
  1023. else
  1024. conf = tk_split_list(_fromUTF8(tk_send('window', 'configure', _get_eval_enc_str(win), "-#{slot}")))
  1025. end
  1026. conf[0] = conf[0][1..-1]
  1027. conf
  1028. else
  1029. tk_split_simplelist(_fromUTF8(tk_send('window', 'configure', _get_eval_enc_str(win)))).collect{|conflist|
  1030. conf = tk_split_simplelist(conflist)
  1031. conf[0] = conf[0][1..-1]
  1032. case conf[0]
  1033. when 'text', 'label', 'show', 'data', 'file'
  1034. else
  1035. if conf[3]
  1036. if conf[3].index('{')
  1037. conf[3] = tk_split_list(conf[3])
  1038. else
  1039. conf[3] = tk_tcl2ruby(conf[3])
  1040. end
  1041. end
  1042. if conf[4]
  1043. if conf[4].index('{')
  1044. conf[4] = tk_split_list(conf[4])
  1045. else
  1046. conf[4] = tk_tcl2ruby(conf[4])
  1047. end
  1048. end
  1049. end
  1050. conf[1] = conf[1][1..-1] if conf.size == 2 # alias info
  1051. conf
  1052. }
  1053. end
  1054. else # ! TkComm::GET_CONFIGINFO_AS_ARRAY
  1055. if slot
  1056. case slot.to_s
  1057. when 'text', 'label', 'show', 'data', 'file'
  1058. conf = tk_split_simplelist(_fromUTF8(tk_send('window', 'configure', _get_eval_enc_str(win), "-#{slot}")))
  1059. else
  1060. conf = tk_split_list(_fromUTF8(tk_send('window', 'configure', _get_eval_enc_str(win), "-#{slot}")))
  1061. end
  1062. key = conf.shift[1..-1]
  1063. { key => conf }
  1064. else
  1065. ret = {}
  1066. tk_split_simplelist(_fromUTF8(tk_send('window', 'configure', _get_eval_enc_str(win)))).each{|conflist|
  1067. conf = tk_split_simplelist(conflist)
  1068. key = conf.shift[1..-1]
  1069. case key
  1070. when 'text', 'label', 'show', 'data', 'file'
  1071. else
  1072. if conf[2]
  1073. if conf[2].index('{')
  1074. conf[2] = tk_split_list(conf[2])
  1075. else
  1076. conf[2] = tk_tcl2ruby(conf[2])
  1077. end
  1078. end
  1079. if conf[3]
  1080. if conf[3].index('{')
  1081. conf[3] = tk_split_list(conf[3])
  1082. else
  1083. conf[3] = tk_tcl2ruby(conf[3])
  1084. end
  1085. end
  1086. end
  1087. if conf.size == 1
  1088. ret[key] = conf[0][1..-1] # alias info
  1089. else
  1090. ret[key] = conf
  1091. end
  1092. }
  1093. ret
  1094. end
  1095. end
  1096. end
  1097. def current_window_configinfo(win, slot = nil)
  1098. if TkComm::GET_CONFIGINFO_AS_ARRAY
  1099. if slot
  1100. conf = window_configinfo(win, slot)
  1101. {conf[0] => conf[4]}
  1102. else
  1103. ret = {}
  1104. window_configinfo(win).each{|conf|
  1105. ret[conf[0]] = conf[4] if conf.size > 2
  1106. }
  1107. ret
  1108. end
  1109. else # ! TkComm::GET_CONFIGINFO_AS_ARRAY
  1110. ret = {}
  1111. window_configinfo(win, slot).each{|k, conf|
  1112. ret[k] = conf[-1] if conf.kind_of?(Array)
  1113. }
  1114. ret
  1115. end
  1116. end
  1117. =end
  1118. def window_names
  1119. # tk_split_simplelist(_fromUTF8(tk_send_without_enc('window', 'names'))).collect{|elt|
  1120. tk_split_simplelist(tk_send_without_enc('window', 'names'), false, true).collect{|elt|
  1121. tagid2obj(elt)
  1122. }
  1123. end
  1124. def _ktext_length(txt)
  1125. if TkCore::WITH_ENCODING ### Ruby 1.9 !!!!!!!!!!!!!
  1126. return txt.length
  1127. end
  1128. ###########################
  1129. if $KCODE !~ /n/i
  1130. return txt.gsub(/[^\Wa-zA-Z_\d]/, ' ').length
  1131. end
  1132. # $KCODE == 'NONE'
  1133. if JAPANIZED_TK
  1134. tk_call_without_enc('kstring', 'length',
  1135. _get_eval_enc_str(txt)).to_i
  1136. else
  1137. begin
  1138. tk_call_without_enc('encoding', 'convertto', 'ascii',
  1139. _get_eval_enc_str(txt)).length
  1140. rescue StandardError, NameError
  1141. # sorry, I have no plan
  1142. txt.length
  1143. end
  1144. end
  1145. end
  1146. private :_ktext_length
  1147. def tksearch(*args)
  1148. # call 'search' subcommand of text widget
  1149. # args ::= [<array_of_opts>] <pattern> <start_index> [<stop_index>]
  1150. # If <pattern> is regexp, then it must be a regular expression of Tcl
  1151. nocase = false
  1152. if args[0].kind_of?(Array)
  1153. opts = args.shift.collect{|opt|
  1154. s_opt = opt.to_s
  1155. nocase = true if s_opt == 'nocase'
  1156. '-' + s_opt
  1157. }
  1158. else
  1159. opts = []
  1160. end
  1161. if args[0].kind_of?(Regexp)
  1162. regexp = args.shift
  1163. if !nocase && (regexp.options & Regexp::IGNORECASE) != 0
  1164. opts << '-nocase'
  1165. end
  1166. args.unshift(regexp.source)
  1167. end
  1168. opts << '--'
  1169. ret = tk_send('search', *(opts + args))
  1170. if ret == ""
  1171. nil
  1172. else
  1173. Tk::Text::IndexString.new(ret)
  1174. end
  1175. end
  1176. def tksearch_with_count(*args)
  1177. # call 'search' subcommand of text widget
  1178. # args ::= [<array_of_opts>] <var> <pattern> <start_index> [<stop_index>]
  1179. # If <pattern> is regexp, then it must be a regular expression of Tcl
  1180. nocase = false
  1181. if args[0].kind_of?(Array)
  1182. opts = args.shift.collect{|opt|
  1183. s_opt = opt.to_s
  1184. nocase = true if s_opt == 'nocase'
  1185. '-' + s_opt
  1186. }
  1187. else
  1188. opts = []
  1189. end
  1190. opts << '-count' << args.shift
  1191. if args[0].kind_of?(Regexp)
  1192. regexp = args.shift
  1193. if !nocase && (regexp.options & Regexp::IGNORECASE) != 0
  1194. opts << '-nocase'
  1195. end
  1196. args.unshift(regexp.source)
  1197. end
  1198. opts << '--'
  1199. ret = tk_send('search', *(opts + args))
  1200. if ret == ""
  1201. nil
  1202. else
  1203. Tk::Text::IndexString.new(ret)
  1204. end
  1205. end
  1206. def search_with_length(pat,start,stop=None)
  1207. pat = pat.chr if pat.kind_of?(Integer)
  1208. if stop != None
  1209. return ["", 0] if compare(start,'>=',stop)
  1210. txt = get(start,stop)
  1211. if (pos = txt.index(pat))
  1212. match = $&
  1213. #pos = txt[0..(pos-1)].split('').length if pos > 0
  1214. pos = _ktext_length(txt[0..(pos-1)]) if pos > 0
  1215. if pat.kind_of?(String)
  1216. #return [index(start + " + #{pos} chars"), pat.split('').length]
  1217. return [index(start + " + #{pos} chars"),
  1218. _ktext_length(pat), pat.dup]
  1219. else
  1220. #return [index(start + " + #{pos} chars"), $&.split('').length]
  1221. return [index(start + " + #{pos} chars"),
  1222. _ktext_length(match), match]
  1223. end
  1224. else
  1225. return ["", 0]
  1226. end
  1227. else
  1228. txt = get(start,'end - 1 char')
  1229. if (pos = txt.index(pat))
  1230. match = $&
  1231. #pos = txt[0..(pos-1)].split('').length if pos > 0
  1232. pos = _ktext_length(txt[0..(pos-1)]) if pos > 0
  1233. if pat.kind_of?(String)
  1234. #return [index(start + " + #{pos} chars"), pat.split('').length]
  1235. return [index(start + " + #{pos} chars"),
  1236. _ktext_length(pat), pat.dup]
  1237. else
  1238. #return [index(start + " + #{pos} chars"), $&.split('').length]
  1239. return [index(start + " + #{pos} chars"),
  1240. _ktext_length(match), match]
  1241. end
  1242. else
  1243. txt = get('1.0','end - 1 char')
  1244. if (pos = txt.index(pat))
  1245. match = $&
  1246. #pos = txt[0..(pos-1)].split('').length if pos > 0
  1247. pos = _ktext_length(txt[0..(pos-1)]) if pos > 0
  1248. if pat.kind_of?(String)
  1249. #return [index("1.0 + #{pos} chars"), pat.split('').length]
  1250. return [index("1.0 + #{pos} chars"),
  1251. _ktext_length(pat), pat.dup]
  1252. else
  1253. #return [index("1.0 + #{pos} chars"), $&.split('').length]
  1254. return [index("1.0 + #{pos} chars"), _ktext_length(match), match]
  1255. end
  1256. else
  1257. return ["", 0]
  1258. end
  1259. end
  1260. end
  1261. end
  1262. def search(pat,start,stop=None)
  1263. search_with_length(pat,start,stop)[0]
  1264. end
  1265. def rsearch_with_length(pat,start,stop=None)
  1266. pat = pat.chr if pat.kind_of?(Integer)
  1267. if stop != None
  1268. return ["", 0] if compare(start,'<=',stop)
  1269. txt = get(stop,start)
  1270. if (pos = txt.rindex(pat))
  1271. match = $&
  1272. #pos = txt[0..(pos-1)].split('').length if pos > 0
  1273. pos = _ktext_length(txt[0..(pos-1)]) if pos > 0
  1274. if pat.kind_of?(String)
  1275. #return [index(stop + " + #{pos} chars"), pat.split('').length]
  1276. return [index(stop + " + #{pos} chars"), _ktext_length(pat), pat.dup]
  1277. else
  1278. #return [index(stop + " + #{pos} chars"), $&.split('').length]
  1279. return [index(stop + " + #{pos} chars"), _ktext_length(match), match]
  1280. end
  1281. else
  1282. return ["", 0]
  1283. end
  1284. else
  1285. txt = get('1.0',start)
  1286. if (pos = txt.rindex(pat))
  1287. match = $&
  1288. #pos = txt[0..(pos-1)].split('').length if pos > 0
  1289. pos = _ktext_length(txt[0..(pos-1)]) if pos > 0
  1290. if pat.kind_of?(String)
  1291. #return [index("1.0 + #{pos} chars"), pat.split('').length]
  1292. return [index("1.0 + #{pos} chars"), _ktext_length(pat), pat.dup]
  1293. else
  1294. #return [index("1.0 + #{pos} chars"), $&.split('').length]
  1295. return [index("1.0 + #{pos} chars"), _ktext_length(match), match]
  1296. end
  1297. else
  1298. txt = get('1.0','end - 1 char')
  1299. if (pos = txt.rindex(pat))
  1300. match = $&
  1301. #pos = txt[0..(pos-1)].split('').length if pos > 0
  1302. pos = _ktext_length(txt[0..(pos-1)]) if pos > 0
  1303. if pat.kind_of?(String)
  1304. #return [index("1.0 + #{pos} chars"), pat.split('').length]
  1305. return [index("1.0 + #{pos} chars"), _ktext_length(pat), pat.dup]
  1306. else
  1307. #return [index("1.0 + #{pos} chars"), $&.split('').length]
  1308. return [index("1.0 + #{pos} chars"), _ktext_length(match), match]
  1309. end
  1310. else
  1311. return ["", 0]
  1312. end
  1313. end
  1314. end
  1315. end
  1316. def rsearch(pat,start,stop=None)
  1317. rsearch_with_length(pat,start,stop)[0]
  1318. end
  1319. def dump(type_info, *index, &block)
  1320. if type_info.kind_of?(Symbol)
  1321. type_info = [ type_info.to_s ]
  1322. elsif type_info.kind_of?(String)
  1323. type_info = [ type_info ]
  1324. end
  1325. args = type_info.collect{|inf| '-' + inf}
  1326. args << '-command' << block if block
  1327. str = tk_send('dump', *(args + index))
  1328. result = []
  1329. sel = nil
  1330. i = 0
  1331. while i < str.size
  1332. # retrieve key
  1333. idx = str.index(/ /, i)
  1334. result.push str[i..(idx-1)]
  1335. i = idx + 1
  1336. # retrieve value
  1337. case result[-1]
  1338. when 'text'
  1339. if str[i] == ?{
  1340. # text formed as {...}
  1341. val, i = _retrieve_braced_text(str, i)
  1342. result.push val
  1343. else
  1344. # text which may contain backslahes
  1345. val, i = _retrieve_backslashed_text(str, i)
  1346. result.push val
  1347. end
  1348. else
  1349. idx = str.index(/ /, i)
  1350. val = str[i..(idx-1)]
  1351. case result[-1]
  1352. when 'mark'
  1353. case val
  1354. when 'insert'
  1355. result.push TkTextMarkInsert.new(self)
  1356. when 'current'
  1357. result.push TkTextMarkCurrent.new(self)
  1358. when 'anchor'
  1359. result.push TkTextMarkAnchor.new(self)
  1360. else
  1361. result.push tk_tcl2ruby(val)
  1362. end
  1363. when 'tagon'
  1364. if val == 'sel'
  1365. if sel
  1366. result.push sel
  1367. else
  1368. result.push TkTextTagSel.new(self)
  1369. end
  1370. else
  1371. result.push tk_tcl2ruby(val)
  1372. end
  1373. when 'tagoff'
  1374. result.push tk_tcl2ruby(val)
  1375. when 'window'
  1376. result.push tk_tcl2ruby(val)
  1377. when 'image'
  1378. result.push tk_tcl2ruby(val)
  1379. end
  1380. i = idx + 1
  1381. end
  1382. # retrieve index
  1383. idx = str.index(/ /, i)
  1384. if idx
  1385. result.push(Tk::Text::IndexString.new(str[i..(idx-1)]))
  1386. i = idx + 1
  1387. else
  1388. result.push(Tk::Text::IndexString.new(str[i..-1]))
  1389. break
  1390. end
  1391. end
  1392. kvis = []
  1393. until result.empty?
  1394. kvis.push [result.shift, result.shift, result.shift]
  1395. end
  1396. kvis # result is [[key1, value1, index1], [key2, value2, index2], ...]
  1397. end
  1398. def _retrieve_braced_text(str, i)
  1399. cnt = 0
  1400. idx = i
  1401. while idx < str.size
  1402. case str[idx]
  1403. when ?{
  1404. cnt += 1
  1405. when ?}
  1406. cnt -= 1
  1407. if cnt == 0
  1408. break
  1409. end
  1410. end
  1411. idx += 1
  1412. end
  1413. return str[i+1..idx-1], idx + 2
  1414. end
  1415. private :_retrieve_braced_text
  1416. def _retrieve_backslashed_text(str, i)
  1417. j = i
  1418. idx = nil
  1419. loop {
  1420. idx = str.index(/ /, j)
  1421. if str[idx-1] == ?\\
  1422. j += 1
  1423. else
  1424. break
  1425. end
  1426. }
  1427. val = str[i..(idx-1)]
  1428. val.gsub!(/\\( |\{|\})/, '\1')
  1429. return val, idx + 1
  1430. end
  1431. private :_retrieve_backslashed_text
  1432. def dump_all(*index, &block)
  1433. dump(['all'], *index, &block)
  1434. end
  1435. def dump_mark(*index, &block)
  1436. dump(['mark'], *index, &block)
  1437. end
  1438. def dump_tag(*index, &block)
  1439. dump(['tag'], *index, &block)
  1440. end
  1441. def dump_text(*index, &block)
  1442. dump(['text'], *index, &block)
  1443. end
  1444. def dump_window(*index, &block)
  1445. dump(['window'], *index, &block)
  1446. end
  1447. def dump_image(*index, &block)
  1448. dump(['image'], *index, &block)
  1449. end
  1450. end
  1451. #TkText = Tk::Text unless Object.const_defined? :TkText
  1452. #Tk.__set_toplevel_aliases__(:Tk, Tk::Text, :TkText)
  1453. Tk.__set_loaded_toplevel_aliases__('tk/text.rb', :Tk, Tk::Text, :TkText)
  1454. #######################################
  1455. class Tk::Text::Peer < Tk::Text
  1456. # Tk8.5 feature
  1457. def initialize(text, parent=nil, keys={})
  1458. unless text.kind_of?(Tk::Text)
  1459. fail ArgumentError, "Tk::Text is expected for 1st argument"
  1460. end
  1461. @src_text = text
  1462. super(parent, keys)
  1463. end
  1464. def create_self(keys)
  1465. if keys and keys != None
  1466. tk_call_without_enc(@src_text.path, 'peer', 'create',
  1467. @path, *hash_kv(keys, true))
  1468. else
  1469. tk_call_without_enc(@src_text.path, 'peer', 'create', @path)
  1470. end
  1471. end
  1472. private :create_self
  1473. end