ffi-tk 2009.11.29

Sign up to get free protection for your applications and to get access to all the features.
Files changed (189) hide show
  1. data/CHANGELOG +748 -0
  2. data/MANIFEST +188 -0
  3. data/README.md +85 -0
  4. data/Rakefile +47 -0
  5. data/TODO.md +62 -0
  6. data/bin/rwish +33 -0
  7. data/doc/MIT_LICENSE +18 -0
  8. data/doc/TCL_LICENSE +39 -0
  9. data/example/choose_color.rb +22 -0
  10. data/example/choose_directory.rb +22 -0
  11. data/example/dialog.rb +37 -0
  12. data/example/hello.rb +11 -0
  13. data/example/message_box.rb +26 -0
  14. data/example/option_menu.rb +17 -0
  15. data/example/popup.rb +24 -0
  16. data/example/set_palette.rb +32 -0
  17. data/example/text.rb +47 -0
  18. data/example/tile/kroc_demo_small.rb +123 -0
  19. data/example/tile/kroc_rb_demo.rb +135 -0
  20. data/example/tile/notebook.rb +48 -0
  21. data/example/tile/theme_hello.rb +38 -0
  22. data/example/tile/treeview.rb +71 -0
  23. data/example/various.rb +25 -0
  24. data/example/wait.rb +16 -0
  25. data/ffi-tk.gemspec +33 -0
  26. data/lib/ffi-tk.rb +76 -0
  27. data/lib/ffi-tk/command.rb +39 -0
  28. data/lib/ffi-tk/command/after.rb +36 -0
  29. data/lib/ffi-tk/command/bell.rb +34 -0
  30. data/lib/ffi-tk/command/bind.rb +11 -0
  31. data/lib/ffi-tk/command/bindtags.rb +69 -0
  32. data/lib/ffi-tk/command/cget.rb +92 -0
  33. data/lib/ffi-tk/command/choose_color.rb +29 -0
  34. data/lib/ffi-tk/command/choose_directory.rb +45 -0
  35. data/lib/ffi-tk/command/clipboard.rb +102 -0
  36. data/lib/ffi-tk/command/configure.rb +88 -0
  37. data/lib/ffi-tk/command/destroy.rb +12 -0
  38. data/lib/ffi-tk/command/dialog.rb +54 -0
  39. data/lib/ffi-tk/command/event.rb +79 -0
  40. data/lib/ffi-tk/command/focus.rb +70 -0
  41. data/lib/ffi-tk/command/font.rb +124 -0
  42. data/lib/ffi-tk/command/get_open_file.rb +85 -0
  43. data/lib/ffi-tk/command/get_save_file.rb +83 -0
  44. data/lib/ffi-tk/command/grab.rb +141 -0
  45. data/lib/ffi-tk/command/grid.rb +246 -0
  46. data/lib/ffi-tk/command/image.rb +79 -0
  47. data/lib/ffi-tk/command/lower.rb +23 -0
  48. data/lib/ffi-tk/command/message_box.rb +65 -0
  49. data/lib/ffi-tk/command/option_menu.rb +8 -0
  50. data/lib/ffi-tk/command/pack.rb +99 -0
  51. data/lib/ffi-tk/command/place.rb +91 -0
  52. data/lib/ffi-tk/command/popup.rb +14 -0
  53. data/lib/ffi-tk/command/raise.rb +25 -0
  54. data/lib/ffi-tk/command/scrollable.rb +151 -0
  55. data/lib/ffi-tk/command/selection.rb +132 -0
  56. data/lib/ffi-tk/command/set_palette.rb +9 -0
  57. data/lib/ffi-tk/command/tk_cmd.rb +155 -0
  58. data/lib/ffi-tk/command/vars.rb +82 -0
  59. data/lib/ffi-tk/command/wait.rb +39 -0
  60. data/lib/ffi-tk/command/winfo.rb +668 -0
  61. data/lib/ffi-tk/command/wm.rb +1025 -0
  62. data/lib/ffi-tk/core_extensions.rb +154 -0
  63. data/lib/ffi-tk/event/data.rb +60 -0
  64. data/lib/ffi-tk/event/handler.rb +44 -0
  65. data/lib/ffi-tk/ffi/tcl.rb +92 -0
  66. data/lib/ffi-tk/ffi/tcl/cmd_proc.rb +10 -0
  67. data/lib/ffi-tk/ffi/tcl/eval_result.rb +148 -0
  68. data/lib/ffi-tk/ffi/tcl/interp.rb +95 -0
  69. data/lib/ffi-tk/ffi/tcl/obj.rb +89 -0
  70. data/lib/ffi-tk/ffi/tcl/time.rb +36 -0
  71. data/lib/ffi-tk/ffi/tk.rb +35 -0
  72. data/lib/ffi-tk/geometry.rb +32 -0
  73. data/lib/ffi-tk/thread_sender.rb +26 -0
  74. data/lib/ffi-tk/tk.rb +222 -0
  75. data/lib/ffi-tk/variable.rb +46 -0
  76. data/lib/ffi-tk/widget.rb +68 -0
  77. data/lib/ffi-tk/widget/button.rb +41 -0
  78. data/lib/ffi-tk/widget/canvas.rb +806 -0
  79. data/lib/ffi-tk/widget/canvas/arc.rb +18 -0
  80. data/lib/ffi-tk/widget/canvas/bitmap.rb +13 -0
  81. data/lib/ffi-tk/widget/canvas/image.rb +10 -0
  82. data/lib/ffi-tk/widget/canvas/item.rb +170 -0
  83. data/lib/ffi-tk/widget/canvas/line.rb +16 -0
  84. data/lib/ffi-tk/widget/canvas/oval.rb +15 -0
  85. data/lib/ffi-tk/widget/canvas/polygon.rb +16 -0
  86. data/lib/ffi-tk/widget/canvas/rectangle.rb +15 -0
  87. data/lib/ffi-tk/widget/canvas/text.rb +15 -0
  88. data/lib/ffi-tk/widget/canvas/window.rb +11 -0
  89. data/lib/ffi-tk/widget/checkbutton.rb +63 -0
  90. data/lib/ffi-tk/widget/entry.rb +208 -0
  91. data/lib/ffi-tk/widget/frame.rb +12 -0
  92. data/lib/ffi-tk/widget/label.rb +26 -0
  93. data/lib/ffi-tk/widget/labelframe.rb +7 -0
  94. data/lib/ffi-tk/widget/listbox.rb +192 -0
  95. data/lib/ffi-tk/widget/menu.rb +318 -0
  96. data/lib/ffi-tk/widget/menubutton.rb +7 -0
  97. data/lib/ffi-tk/widget/message.rb +36 -0
  98. data/lib/ffi-tk/widget/panedwindow.rb +164 -0
  99. data/lib/ffi-tk/widget/radiobutton.rb +43 -0
  100. data/lib/ffi-tk/widget/root.rb +8 -0
  101. data/lib/ffi-tk/widget/scale.rb +44 -0
  102. data/lib/ffi-tk/widget/scrollbar.rb +114 -0
  103. data/lib/ffi-tk/widget/spinbox.rb +198 -0
  104. data/lib/ffi-tk/widget/text.rb +893 -0
  105. data/lib/ffi-tk/widget/text/peer.rb +10 -0
  106. data/lib/ffi-tk/widget/tile.rb +70 -0
  107. data/lib/ffi-tk/widget/tile/button.rb +8 -0
  108. data/lib/ffi-tk/widget/tile/checkbutton.rb +8 -0
  109. data/lib/ffi-tk/widget/tile/combobox.rb +43 -0
  110. data/lib/ffi-tk/widget/tile/entry.rb +8 -0
  111. data/lib/ffi-tk/widget/tile/frame.rb +13 -0
  112. data/lib/ffi-tk/widget/tile/label.rb +9 -0
  113. data/lib/ffi-tk/widget/tile/labelframe.rb +8 -0
  114. data/lib/ffi-tk/widget/tile/menubutton.rb +8 -0
  115. data/lib/ffi-tk/widget/tile/notebook.rb +93 -0
  116. data/lib/ffi-tk/widget/tile/panedwindow.rb +9 -0
  117. data/lib/ffi-tk/widget/tile/progressbar.rb +59 -0
  118. data/lib/ffi-tk/widget/tile/radiobutton.rb +8 -0
  119. data/lib/ffi-tk/widget/tile/scale.rb +8 -0
  120. data/lib/ffi-tk/widget/tile/scrollbar.rb +41 -0
  121. data/lib/ffi-tk/widget/tile/separator.rb +23 -0
  122. data/lib/ffi-tk/widget/tile/sizegrip.rb +24 -0
  123. data/lib/ffi-tk/widget/tile/style.rb +114 -0
  124. data/lib/ffi-tk/widget/tile/treeview.rb +414 -0
  125. data/lib/ffi-tk/widget/toplevel.rb +14 -0
  126. data/spec/ffi-tk/command/bindtags.rb +18 -0
  127. data/spec/ffi-tk/command/clipboard.rb +18 -0
  128. data/spec/ffi-tk/command/font.rb +67 -0
  129. data/spec/ffi-tk/command/grid.rb +6 -0
  130. data/spec/ffi-tk/command/image.rb +26 -0
  131. data/spec/ffi-tk/command/pack.rb +20 -0
  132. data/spec/ffi-tk/command/place.rb +20 -0
  133. data/spec/ffi-tk/command/selection.rb +13 -0
  134. data/spec/ffi-tk/command/vars.rb +32 -0
  135. data/spec/ffi-tk/command/winfo.rb +233 -0
  136. data/spec/ffi-tk/command/wm.rb +185 -0
  137. data/spec/ffi-tk/event.rb +95 -0
  138. data/spec/ffi-tk/tile/button.rb +51 -0
  139. data/spec/ffi-tk/tile/checkbutton.rb +13 -0
  140. data/spec/ffi-tk/tile/combobox.rb +65 -0
  141. data/spec/ffi-tk/tile/entry.rb +61 -0
  142. data/spec/ffi-tk/tile/frame.rb +65 -0
  143. data/spec/ffi-tk/tile/label.rb +17 -0
  144. data/spec/ffi-tk/tile/labelframe.rb +13 -0
  145. data/spec/ffi-tk/tile/menubutton.rb +13 -0
  146. data/spec/ffi-tk/tile/notebook.rb +103 -0
  147. data/spec/ffi-tk/tile/panedwindow.rb +13 -0
  148. data/spec/ffi-tk/tile/progressbar.rb +78 -0
  149. data/spec/ffi-tk/tile/radiobutton.rb +13 -0
  150. data/spec/ffi-tk/tile/scale.rb +13 -0
  151. data/spec/ffi-tk/tile/scrollbar.rb +43 -0
  152. data/spec/ffi-tk/tile/separator.rb +22 -0
  153. data/spec/ffi-tk/tile/sizegrip.rb +13 -0
  154. data/spec/ffi-tk/tile/style.rb +161 -0
  155. data/spec/ffi-tk/tile/treeview.rb +101 -0
  156. data/spec/ffi-tk/variable.rb +24 -0
  157. data/spec/ffi-tk/widget/button.rb +22 -0
  158. data/spec/ffi-tk/widget/canvas.rb +169 -0
  159. data/spec/ffi-tk/widget/checkbutton.rb +44 -0
  160. data/spec/ffi-tk/widget/entry.rb +155 -0
  161. data/spec/ffi-tk/widget/frame.rb +8 -0
  162. data/spec/ffi-tk/widget/label.rb +16 -0
  163. data/spec/ffi-tk/widget/labelframe.rb +12 -0
  164. data/spec/ffi-tk/widget/listbox.rb +19 -0
  165. data/spec/ffi-tk/widget/menu.rb +12 -0
  166. data/spec/ffi-tk/widget/menubutton.rb +12 -0
  167. data/spec/ffi-tk/widget/message.rb +12 -0
  168. data/spec/ffi-tk/widget/panedwindow.rb +12 -0
  169. data/spec/ffi-tk/widget/radiobutton.rb +12 -0
  170. data/spec/ffi-tk/widget/root.rb +9 -0
  171. data/spec/ffi-tk/widget/scale.rb +12 -0
  172. data/spec/ffi-tk/widget/scrollbar.rb +12 -0
  173. data/spec/ffi-tk/widget/spinbox.rb +12 -0
  174. data/spec/ffi-tk/widget/text.rb +246 -0
  175. data/spec/ffi-tk/widget/toplevel.rb +12 -0
  176. data/spec/helper.rb +3 -0
  177. data/tasks/authors.rake +21 -0
  178. data/tasks/bacon.rake +66 -0
  179. data/tasks/changelog.rake +18 -0
  180. data/tasks/gem.rake +22 -0
  181. data/tasks/gem_setup.rake +113 -0
  182. data/tasks/grancher.rake +12 -0
  183. data/tasks/manifest.rake +4 -0
  184. data/tasks/rcov.rake +17 -0
  185. data/tasks/release.rake +65 -0
  186. data/tasks/reversion.rake +8 -0
  187. data/tasks/setup.rake +12 -0
  188. data/tasks/ycov.rake +84 -0
  189. metadata +261 -0
@@ -0,0 +1,893 @@
1
+ module Tk
2
+ class Text < Widget
3
+ include Cget, Configure, Scrollable
4
+
5
+ def self.tk_command; 'text'; end
6
+
7
+ autoload :Peer, 'ffi-tk/widget/text/peer'
8
+
9
+ SEARCH_MUTEX = Mutex.new
10
+
11
+ def initialize(parent = Tk.root, options = None)
12
+ @tag_commands = {}
13
+ super
14
+ end
15
+
16
+ def value
17
+ get '1.0', :end
18
+ end
19
+
20
+ def value=(string)
21
+ clear
22
+ insert :end, string
23
+ end
24
+
25
+ def clear
26
+ delete '0.0', :end
27
+ end
28
+
29
+ # Returns a list of four elements describing the screen area of the
30
+ # character given by index.
31
+ # The first two elements of the list give the x and y coordinates of the
32
+ # upper-left corner of the area occupied by the character, and the last two
33
+ # elements give the width and height of the area.
34
+ # If the character is only partially visible on the screen, then the return
35
+ # value reflects just the visible part.
36
+ # If the character is not visible on the screen then the return value is an
37
+ # empty list.
38
+ def bbox(index)
39
+ execute('bbox', index)
40
+ end
41
+
42
+ # Compares the indices given by index1 and index2 according to the
43
+ # relational operator given by op, and returns 1 if the relationship is
44
+ # satisfied and 0 if it is not.
45
+ # Op must be one of the operators <, <=, ==, >=, >, or !=.
46
+ # If op is == then true is returned if the two indices refer to the same
47
+ # character, if op is < then true is returned if index1 refers to an earlier
48
+ # character in the text than index2, and so on.
49
+ def compare(index1, op, index2)
50
+ execute('compare', index1, op, index2).to_boolean
51
+ end
52
+
53
+ # Counts the number of relevant things between the two indices.
54
+ # If index1 is after index2, the result will be a negative number (and this
55
+ # holds for each of the possible options).
56
+ # The actual items which are counted depend on the options given.
57
+ # The result is a list of integers, one for the result of each counting option given.
58
+ #
59
+ # Valid counting options are :chars, :displaychars, :displayindices,
60
+ # :displaylines, :indices, :lines, :xpixels and :ypixels.
61
+ # The default value, if no option is specified, is :indices.
62
+ # There is an additional possible option :update which is a modifier.
63
+ # If given, then all subsequent options ensure that any possible out of date
64
+ # information is recalculated.
65
+ # This currently only has any effect for the :ypixels count (which, if
66
+ # :update is not given, will use the text widget's current cached value for
67
+ # each line).
68
+ # The count options are interpreted as follows:
69
+ #
70
+ # :chars
71
+ # count all characters, whether elided or not. Do not count embedded
72
+ # windows or images.
73
+ # :displaychars
74
+ # count all non-elided characters.
75
+ # :displayindices
76
+ # count all non-elided characters, windows and images.
77
+ # :displaylines
78
+ # count all display lines (i.e. counting one for each time a line wraps)
79
+ # from the line of the first index up to, but not including the display
80
+ # line of the second index. Therefore if they are both on the same display
81
+ # line, zero will be returned. By definition displaylines are visible and
82
+ # therefore this only counts portions of actual visible lines.
83
+ # :indices
84
+ # count all characters and embedded windows or images (i.e. everything
85
+ # which counts in text-widget index space), whether they are elided or
86
+ # not.
87
+ # :lines
88
+ # count all logical lines (irrespective of wrapping) from the line of the
89
+ # first index up to, but not including the line of the second index.
90
+ # Therefore if they are both on the same line, zero will be returned.
91
+ # Logical lines are counted whether they are currently visible
92
+ # (non-elided) or not.
93
+ # :xpixels
94
+ # count the number of horizontal pixels from the first pixel of the first
95
+ # index to (but not including) the first pixel of the second index. To
96
+ # count the total desired width of the text widget (assuming wrapping is
97
+ # not enabled), first find the longest line and then use
98
+ # `text.count("#{line}.0", "#{line}.0", :xpixels)`.
99
+ # :ypixels
100
+ # count the number of vertical pixels from the first pixel of the first
101
+ # index to (but not including) the first pixel of the second index. If
102
+ # both indices are on the same display line, zero will be returned. To
103
+ # count the total number of vertical pixels in the text widget, use
104
+ # `text.count('1.0', 'end', :ypixels)`, and to ensure this is up to date,
105
+ # use `text.count('1.0', 'end', :update, :ypixels)`.
106
+ #
107
+ # The command returns a positive or negative integer corresponding to the
108
+ # number of items counted between the two indices. One such integer is
109
+ # returned for each counting option given, so a list is returned if more
110
+ # than one option was supplied. For example `text.count('1.3', '4.5',
111
+ # :xpixels, :ypixels` is perfectly valid and will return a list of two
112
+ # elements.
113
+ def count(index1, index2, *options)
114
+ args = options.map{|option| option.to_tcl_option }
115
+ execute('count', *args, index1, index2)
116
+ end
117
+
118
+ # If boolean is specified, then it must have one of the true or false values
119
+ # accepted by Tcl_GetBoolean.
120
+ # If the value is a true one then internal consistency checks will be turned
121
+ # on in the B-tree code associated with text widgets.
122
+ # If boolean has a false value then the debugging checks will be turned off.
123
+ # In either case the command returns an empty string.
124
+ # If boolean is not specified then the command returns on or off to indicate
125
+ # whether or not debugging is turned on.
126
+ # There is a single debugging switch shared by all text widgets: turning
127
+ # debugging on or off in any widget turns it on or off for all widgets.
128
+ # For widgets with large amounts of text, the consistency checks may cause a
129
+ # noticeable slow-down.
130
+ # When debugging is turned on, the drawing routines of the text widget set
131
+ # the global variables tk_textRedraw and tk_textRelayout to the lists of
132
+ # indices that are redrawn.
133
+ # The values of these variables are tested by Tk's test suite.
134
+ def debug(boolean = None)
135
+ if boolean == None
136
+ execute('debug') == 1
137
+ else
138
+ execute_only('debug', boolean ? true : false)
139
+ end
140
+ end
141
+
142
+ def debug?
143
+ execute('debug') == 1
144
+ end
145
+
146
+ # Delete a range of characters from the text.
147
+ # If both index1 and index2 are specified, then delete all the characters
148
+ # starting with the one given by index1 and stopping just before index2
149
+ # (i.e. the character at index2 is not deleted).
150
+ # If index2 does not specify a position later in the text than index1 then
151
+ # no characters are deleted.
152
+ # If index2 is not specified then the single character at index1 is deleted.
153
+ # It is not allowable to delete characters in a way that would leave the
154
+ # text without a newline as the last character.
155
+ # The command returns an empty string.
156
+ # If more indices are given, multiple ranges of text will be deleted.
157
+ # All indices are first checked for validity before any deletions are made.
158
+ # They are sorted and the text is removed from the last range to the first
159
+ # range to deleted text does not cause an undesired index shifting
160
+ # side-effects.
161
+ # If multiple ranges with the same start index are given, then the longest
162
+ # range is used.
163
+ # If overlapping ranges are given, then they will be merged into spans that
164
+ # do not cause deletion of text outside the given ranges due to text shifted
165
+ # during deletion.
166
+ def delete(index1, *rest)
167
+ execute('delete', index1, *rest)
168
+ end
169
+
170
+ # Returns a list with five elements describing the area occupied by the
171
+ # display line containing index.
172
+ # The first two elements of the list give the x and y coordinates of the
173
+ # upper-left corner of the area occupied by the line, the third and fourth
174
+ # elements give the width and height of the area, and the fifth element
175
+ # gives the position of the baseline for the line, measured down from the
176
+ # top of the area.
177
+ # All of this information is measured in pixels.
178
+ # If the current wrap mode is none and the line extends beyond the
179
+ # boundaries of the window, the area returned reflects the entire area of
180
+ # the line, including the portions that are out of the window.
181
+ # If the line is shorter than the full width of the window then the area
182
+ # returned reflects just the portion of the line that is occupied by
183
+ # characters and embedded windows.
184
+ # If the display line containing index is not visible on the screen then the
185
+ # return value is an empty list.
186
+ def dlineinfo(index)
187
+ info = execute('dlineinfo', index).to_a
188
+ info.empty? ? nil : info.map(&:to_i)
189
+ end
190
+
191
+ # Return the contents of the text widget from index1 up to, but not
192
+ # including index2, including the text and information about marks, tags,
193
+ # and embedded windows. If index2 is not specified, then it defaults to one
194
+ # character past index1. The information is returned in the following
195
+ # format:
196
+ #
197
+ # pathName dump ?switches? index1 ?index2?
198
+ def dump(*arguments, given_index)
199
+ arguments = arguments.dup
200
+ invocation = []
201
+ indices = [given_index]
202
+
203
+ while arg = arguments.shift
204
+ case arg.to_tcl
205
+ when '-command'
206
+ command = arguments.shift
207
+ invocation << ['-command', command]
208
+ when /^-(all|image|mark|tag|text|window)$/
209
+ invocation << tcl_option(arg)
210
+ else
211
+ indices.unshift(arg)
212
+ end
213
+ end
214
+
215
+ execute('dump', *invocation, *indices)
216
+ end
217
+
218
+ # If boolean is not specified, returns the modified flag of the widget.
219
+ # The insert, delete, edit undo and edit redo commands or the user can set
220
+ # or clear the modified flag.
221
+ # If boolean is specified, sets the modified flag of the widget to boolean.
222
+ def edit_modified(boolean = None)
223
+ if boolean == None
224
+ execute('edit', 'modified')
225
+ else
226
+ execute_only('edit', 'modified', boolean ? true : false)
227
+ end
228
+ end
229
+
230
+ def edit_modified?
231
+ execute('edit', 'modified').to_boolean
232
+ end
233
+
234
+ # When the -undo option is true, reapplies the last undone edits provided no
235
+ # other edits were done since then.
236
+ # Generates an error when the redo stack is empty.
237
+ # Does nothing when the -undo option is false.
238
+ def edit_redo
239
+ execute_only('edit', 'redo')
240
+ end
241
+
242
+ # Clears the undo and redo stacks.
243
+ def edit_reset
244
+ execute_only('edit', 'reset')
245
+ end
246
+
247
+ # Inserts a separator (boundary) on the undo stack. Does nothing when the
248
+ # -undo option is false.
249
+ def edit_separator
250
+ execute_only('edit', 'separator')
251
+ end
252
+
253
+ # Undoes the last edit action when the -undo option is true.
254
+ # An edit action is defined as all the insert and delete commands that are
255
+ # recorded on the undo stack in between two separators.
256
+ # Generates an error when the undo stack is empty.
257
+ # Does nothing when the -undo option is false.
258
+ def edit_undo
259
+ execute_only('edit', 'undo')
260
+ end
261
+
262
+ # Return a range of characters from the text.
263
+ #
264
+ # The return value will be all the characters in the text starting with the
265
+ # one whose index is index1 and ending just before the one whose index is
266
+ # index2 (the character at index2 will not be returned).
267
+ #
268
+ # If index2 is omitted then the single character at index1 is returned.
269
+ # If there are no characters in the specified range (e.g. index1 is past the
270
+ # end of the file or index2 is less than or equal to index1) then an empty
271
+ # string is returned.
272
+ #
273
+ # If the specified range contains embedded windows, no information about
274
+ # them is included in the returned string.
275
+ # If multiple index pairs are given, multiple ranges of text will be
276
+ # returned in a list.
277
+ # Invalid ranges will not be represented with empty strings in the list.
278
+ # The ranges are returned in the order passed to [get].
279
+ #
280
+ # @see get_displaychars
281
+ def get(index, *indices)
282
+ execute('get', index, *indices).to_s
283
+ end
284
+
285
+ # Same as [get], but within each range, only those characters which are not
286
+ # elided will be returned.
287
+ # This may have the effect that some of the returned ranges are empty
288
+ # strings.
289
+ def get_displaychars(index, *indices)
290
+ execute('get', '-displaychars', index, *indices)
291
+ end
292
+
293
+ def image_cget(index, option)
294
+ option = tcl_option(option)
295
+ Cget.option_to_ruby(option, execute('image', 'cget', index))
296
+ end
297
+
298
+ # Query or modify the configuration options for an embedded image.
299
+ # If no option is specified, returns a list describing all of the available
300
+ # options for the embedded image at index (see Tk_ConfigureInfo for
301
+ # information on the format of this list).
302
+ # If option is specified with no value, then the command returns a list
303
+ # describing the one named option (this list will be identical to the
304
+ # corresponding sublist of the value returned if no option is specified).
305
+ # If one or more option-value pairs are specified, then the command modifies
306
+ # the given option(s) to have the given value(s); in this case the command
307
+ # returns an empty string.
308
+ # See EMBEDDED IMAGES for information on the options that are supported.
309
+ def image_configure(index, options = None)
310
+ common_configure([:image, :configure, index], options)
311
+ end
312
+
313
+ # This command creates a new image annotation, which will appear in the text
314
+ # at the position given by index.
315
+ # Any number of option-value pairs may be specified to configure the
316
+ # annotation.
317
+ # Returns a unique identifier that may be used as an index to refer to this
318
+ # image.
319
+ # See EMBEDDED IMAGES for information on the options that are supported, and
320
+ # a description of the identifier returned.
321
+ def image_create(index, options = {})
322
+ execute('image', 'create', index, options.to_tcl_options)
323
+ end
324
+
325
+ def image_names
326
+ execute('image', 'names')
327
+ end
328
+
329
+ # Returns the position corresponding to index in the form line.char where
330
+ # line is the line number and char is the character number. Index may have
331
+ # any of the forms described under INDICES above.
332
+ def index(index)
333
+ execute('index', index)
334
+ end
335
+
336
+ # Inserts all of the chars arguments just before the character at index.
337
+ #
338
+ # If index refers to the end of the text (the character after the last
339
+ # newline) then the new text is inserted just before the last newline
340
+ # instead.
341
+ # If there is a single chars argument and no tagList, then the new text will
342
+ # receive any tags that are present on both the character before and the
343
+ # character after the insertion point; if a tag is present on only one of
344
+ # these characters then it will not be applied to the new text.
345
+ # If tagList is specified then it consists of a list of tag names; the new
346
+ # characters will receive all of the tags in this list and no others,
347
+ # regardless of the tags present around the insertion point.
348
+ # If multiple chars-tagList argument pairs are present, they produce the
349
+ # same effect as if a separate pathName insert widget command had been
350
+ # issued for each pair, in order.
351
+ # The last tagList argument may be omitted.
352
+ def insert(index, string, taglist = nil, *rest)
353
+ execute_only('insert', index, *[string, taglist, *rest].compact)
354
+ end
355
+
356
+ # If direction is not specified, returns left or right to indicate which of
357
+ # its adjacent characters markName is attached to.
358
+ # If direction is specified, it must be left or right; the gravity of
359
+ # markName is set to the given value.
360
+ def mark_gravity(name, direction = None)
361
+ if direction == None
362
+ execute('mark', 'gravity', name).to_sym?
363
+ else
364
+ execute_only('mark', 'gravity', name, direction)
365
+ end
366
+ end
367
+
368
+ # Returns a list whose elements are the names of all the marks that are
369
+ # currently set.
370
+ def mark_names
371
+ execute('mark', 'names').to_a.map(&:to_sym)
372
+ end
373
+
374
+ # Returns the name of the next mark at or after index.
375
+ # If index is specified in numerical form, then the search for the next mark
376
+ # begins at that index.
377
+ # If index is the name of a mark, then the search for the next mark begins
378
+ # immediately after that mark.
379
+ # This can still return a mark at the same position if there are multiple
380
+ # marks at the same index.
381
+ # These semantics mean that the mark next operation can be used to step
382
+ # through all the marks in a text widget in the same order as the mark
383
+ # information returned by the pathName dump operation.
384
+ # If a mark has been set to the special end index, then it appears to be
385
+ # after end with respect to the pathName mark next operation.
386
+ # nil is returned if there are no marks after index.
387
+ def mark_next(index)
388
+ execute('mark', 'next', index).to_sym?
389
+ end
390
+
391
+ # Returns the name of the mark at or before index.
392
+ # If index is specified in numerical form, then the search for the previous
393
+ # mark begins with the character just before that index.
394
+ # If index is the name of a mark, then the search for the next mark begins
395
+ # immediately before that mark.
396
+ # This can still return a mark at the same position if there are multiple
397
+ # marks at the same index.
398
+ # These semantics mean that the pathName mark previous operation can be used
399
+ # to step through all the marks in a text widget in the reverse order as the
400
+ # mark information returned by the pathName dump operation.
401
+ # nil is returned if there are no marks before index.
402
+ def mark_previous(index)
403
+ execute('mark', 'previous', index).to_sym?
404
+ end
405
+
406
+ # Sets the mark named markName to a position just before the character at
407
+ # index.
408
+ # If markName already exists, it is moved from its old position; if it does
409
+ # not exist, a new mark is created.
410
+ def mark_set(name, index)
411
+ execute_only('mark', 'set', name, index)
412
+ end
413
+
414
+ # Remove the mark corresponding to each of the markName arguments.
415
+ # The removed marks will not be usable in indices and will not be returned
416
+ # by future calls to [mark_names].
417
+ def mark_unset(*names)
418
+ execute_only('mark', 'unset', *names)
419
+ end
420
+
421
+ # Creates a peer text widget, and any optional standard configuration
422
+ # options (as for the text command).
423
+ # By default the peer will have the same start and end line as the parent
424
+ # widget, but these can be overridden with the standard configuration
425
+ # options.
426
+ def peer_create(options = {})
427
+ Peer.new(self, options)
428
+ end
429
+
430
+ # Returns a list of peers of this widget (this does not include the widget
431
+ # itself). The order within this list is undefined.
432
+ def peer_names
433
+ execute('peer', 'names').to_a.map(&:to_s)
434
+ end
435
+
436
+ # Replaces the range of characters between +index1+ and +index2+ with the
437
+ # given characters and tags.
438
+ # See the section on [insert] for an explanation of the handling of taglist
439
+ # arguments, and the docs of [delete] for an explanation of the handling of
440
+ # the indices.
441
+ # If +index2+ corresponds to an index earlier in the text than +index1+, an
442
+ # error will be generated.
443
+ # The deletion and insertion are arranged so that no unnecessary scrolling
444
+ # of the window or movement of insertion cursor occurs.
445
+ # In addition the undo/redo stack are correctly modified, if undo operations
446
+ # are active in the text widget.
447
+ # The command returns nil.
448
+ def replace(index1, index2, chars, *taglists_and_chars)
449
+ execute_only(:replace, index1, index2, chars, *taglists_and_chars)
450
+ end
451
+
452
+ # Records +x+ and +y+ and the current view in the text window, for use in
453
+ # conjunction with later pathName scan dragto commands.
454
+ # Typically this command is associated with a mouse button press in the
455
+ # widget.
456
+ # It returns nil.
457
+ def scan_mark(x, y)
458
+ execute_only(:scan, :mark, x, y)
459
+ end
460
+
461
+ # This command computes the difference between its +x+ and +y+ arguments and
462
+ # the +x+ and +y+ arguments to the last pathName scan mark command for the
463
+ # widget. It then adjusts the view by 10 times the difference in
464
+ # coordinates. This command is typically associated with mouse motion events
465
+ # in the widget, to produce the effect of dragging the text at high speed
466
+ # through the window.
467
+ # The return value is nil.
468
+ def scan_dargto(x, y)
469
+ execute_only(:scan, :dragto, x, y)
470
+ end
471
+
472
+ # Searches the text starting at index for a range of characters that matches
473
+ # pattern.
474
+ # If a match is found, the index of the first character in the match is
475
+ # returned as result; otherwise an empty string is returned.
476
+ # One or more of the following switches may be specified to control the
477
+ # search:
478
+ #
479
+ # :forwards
480
+ # The search will proceed forward through the text, finding the first
481
+ # matching range starting at or after the position given by index.
482
+ # This is the default.
483
+ #
484
+ # :backwards
485
+ # The search will proceed backward through the text, finding the
486
+ # matching range closest to index whose first character is before index
487
+ # (it is not allowed to be at index).
488
+ # Note that, for a variety of reasons, backwards searches can be
489
+ # substantially slower than forwards searches (particularly when using
490
+ # :regexp), so it is recommended that performance-critical code use
491
+ # forward searches.
492
+ #
493
+ # :exact
494
+ # Use exact matching: the characters in the matching range must be
495
+ # identical to those in pattern.
496
+ # This is the default.
497
+ #
498
+ # :regexp
499
+ # Treat pattern as a regular expression and match it against the text
500
+ # using the rules for regular expressions (see the regexp command for
501
+ # details). The default matching automatically passes both the
502
+ # :lineanchor and :linestop options to the regexp engine (unless
503
+ # :nolinestop is used), so that "^", "$" match beginning and end of
504
+ # line, and ".", "[^" sequences will never match the newline character
505
+ # "\n".
506
+ #
507
+ # :nolinestop
508
+ # This allows "." and "[^" sequences to match the newline character "\n",
509
+ # which they will otherwise not do (see the regexp command for details).
510
+ # This option is only meaningful if :regexp is also given, and an error
511
+ # will be thrown otherwise.
512
+ # For example, to match the entire text, use `text.search(/.*/m)`.
513
+ #
514
+ # :nocase
515
+ # Ignore case differences between the pattern and the text.
516
+ #
517
+ # :count varName
518
+ # The argument following :count gives the name of a variable; if a match
519
+ # is found, the number of index positions between beginning and end of
520
+ # the matching range will be stored in the variable.
521
+ # If there are no embedded images or windows in the matching range (and
522
+ # there are no elided characters if :elide is not given), this is
523
+ # equivalent to the number of characters matched.
524
+ # In either case, the range matchIdx to matchIdx + $count chars will
525
+ # return the entire matched text.
526
+ #
527
+ # :all
528
+ # Find all matches in the given range and return a list of the indices of
529
+ # the first character of each match.
530
+ #
531
+ # If a :count switch is given, then the returned array has two elements
532
+ # in the form of `[index, count]` for each successful match.
533
+ # Note that, even for exact searches, the elements of this list may be
534
+ # different, if there are embedded images, windows or hidden text.
535
+ # Searches with :all behave very similarly to the Tcl command regexp
536
+ # :all, in that overlapping matches are not normally returned.
537
+ # For example, applying an :all search of the pattern `\w+` against
538
+ # "hello there" will just match twice, once for each word, and
539
+ # matching `Z[a-z]+Z` against "ZooZooZoo" will just match once.
540
+ #
541
+ # :overlap
542
+ # When performing :all searches, the normal behaviour is that matches
543
+ # which overlap an already-found match will not be returned.
544
+ # This switch changes that behaviour so that all matches which are not
545
+ # totally enclosed within another match are returned.
546
+ # For example, applying an :overlap search of the pattern `\w+`
547
+ # against "hello there" will just match twice (i.e.
548
+ # no different to just :all), but matching `Z[a-z]+Z` against
549
+ # "ZooZooZoo" will now match twice.
550
+ # An error will be thrown if this switch is used without :all.
551
+ #
552
+ # :strictlimits
553
+ # When performing any search, the normal behaviour is that the start and
554
+ # stop limits are checked with respect to the start of the matching
555
+ # text. With the :strictlimits flag, the entire matching range must lie
556
+ # inside the start and stop limits specified for the match to be valid.
557
+ #
558
+ # :elide
559
+ # Find elided (hidden) text as well.
560
+ # By default only displayed text is searched.
561
+ #
562
+ # --
563
+ # This switch has no effect except to terminate the list of switches:
564
+ # the next argument will be treated as pattern even if it starts with -.
565
+ #
566
+ # The matching range may be within a single line of text, or run across
567
+ # multiple lines (if parts of the pattern can match a new-line).
568
+ # For regular expression matching one can use the various newline-matching
569
+ # features such as $ to match the end of a line, "^" to match the beginning
570
+ # of a line, and to control whether "." is allowed to match a new-line.
571
+ # If stop_index is specified, the search stops at that index: for forward
572
+ # searches, no match at or after stop_index will be considered; for backward
573
+ # searches, no match earlier in the text than stop_index will be considered.
574
+ # If stop_index is omitted, the entire text will be searched: when the
575
+ # beginning or end of the text is reached, the search continues at the other
576
+ # end until the starting location is reached again; if stop_index is
577
+ # specified, no wrap-around will occur.
578
+ # This means that, for example, if the search is :forwards but stop_index is
579
+ # earlier in the text than start_index, nothing will ever be found.
580
+ # See KNOWN BUGS in [Text] for a number of minor limitations of [search] method.
581
+ #
582
+ # pathName search ?switches? pattern index ?stopIndex?
583
+ #
584
+ # FUNNY: stdlib tk simply gets the text into the ruby side and performs
585
+ # matches using the core regexp methods, but doesn't give any way to
586
+ # call the tcl/tk search function, this is new land!
587
+ def search(pattern, from, to = None, *switches)
588
+ switches << :regexp if pattern.class < CoreExtensions::Regexp
589
+ to = :end if None == to
590
+
591
+ switches.map!{|switch| switch.to_s.to_tcl_option }
592
+ switches.uniq!
593
+
594
+ if switches.include?('-all') && switches.delete('-count')
595
+ count_all = 'RubyFFI::Text_search_count'
596
+ switches << '-count' << count_all
597
+ elsif switches.delete('-count')
598
+ count = 'RubyFFI::Text_search_count'
599
+ switches << '-count' << count
600
+ end
601
+
602
+ sep = TclString.new('--')
603
+
604
+ if count
605
+ SEARCH_MUTEX.synchronize do
606
+ list = execute(:search, *switches, sep, pattern, from, to).to_a
607
+ return list if list.empty?
608
+ count_value = Tk.execute('set', count)
609
+ [*list, count_value]
610
+ end
611
+ elsif count_all
612
+ SEARCH_MUTEX.synchronize do
613
+ list = execute(:search, *switches, sep, pattern, from, to).to_a
614
+ return list if list.empty?
615
+ count_list = Tk.execute('set', count_all)
616
+ list.zip(count_list)
617
+ end
618
+ else
619
+ execute(:search, *switches, sep, pattern, from, to).to_a
620
+ end
621
+ end
622
+
623
+ def rsearch(pattern, from, to, *switches)
624
+ search(pattern, from, to, *switches, :backwards)
625
+ end
626
+
627
+ # Adjusts the view in the window so that the character given by +index+ is
628
+ # completely visible.
629
+ # If +index+ is already visible then the command does nothing.
630
+ # If +index+ is a short distance out of view, the command adjusts the view
631
+ # just enough to make +index+ visible at the edge of the window.
632
+ # If +index+ is far out of view, then the command centers +index+ in the
633
+ # window.
634
+ def see(index)
635
+ execute_only(:see, index)
636
+ end
637
+
638
+ # Associate the tag tagName with all of the characters starting with index1
639
+ # and ending just before index2 (the character at index2 is not tagged).
640
+ # A single command may contain any number of index1-index2 pairs.
641
+ # If the last index2 is omitted then the single character at index1 is
642
+ # tagged. If there are no characters in the specified range (e.g.
643
+ # index1 is past the end of the file or index2 is less than or equal to
644
+ # index1) then the command has no effect.
645
+ def tag_add(tag_name, index1, index2 = None, *indices)
646
+ execute_only(:tag, :add, tag_name, index1, index2, *indices)
647
+ end
648
+
649
+ # This command associates script with the tag given by tagName.
650
+ # Whenever the event sequence given by sequence occurs for a character that
651
+ # has been tagged with tagName, the script will be invoked.
652
+ # This widget command is similar to the bind command except that it
653
+ # operates on characters in a text rather than entire widgets.
654
+ # See the bind manual entry for complete details on the syntax of sequence
655
+ # and the substitutions performed on script before invoking it.
656
+ # If all arguments are specified then a new binding is created, replacing
657
+ # any existing binding for the same sequence and tagName (if the first
658
+ # character of script is “+” then script augments an existing binding
659
+ # rather than replacing it).
660
+ # In this case the return value is an empty string.
661
+ # If script is omitted then the command returns the script associated
662
+ # with tagName and sequence (an error occurs if there is no such binding).
663
+ # If both script and sequence are omitted then the command returns a list
664
+ # of all the sequences for which bindings have been defined for tagName.
665
+ # The only events for which bindings may be specified are those related to
666
+ # the mouse and keyboard (such as Enter, Leave, ButtonPress, Motion, and
667
+ # KeyPress) or virtual events.
668
+ # Event bindings for a text widget use the current mark described under
669
+ # MARKS above.
670
+ # An Enter event triggers for a tag when the tag first becomes present on
671
+ # the current character, and a Leave event triggers for a tag when it
672
+ # ceases to be present on the current character.
673
+ # Enter and Leave events can happen either because the current mark moved
674
+ # or because the character at that position changed.
675
+ # Note that these events are different than Enter and Leave events for
676
+ # windows. Mouse and keyboard events are directed to the current character.
677
+ # If a virtual event is used in a binding, that binding can trigger only if
678
+ # the virtual event is defined by an underlying mouse-related or
679
+ # keyboard-related event.
680
+ # It is possible for the current character to have multiple tags, and for
681
+ # each of them to have a binding for a particular event sequence.
682
+ # When this occurs, one binding is invoked for each tag, in order from
683
+ # lowest-priority to highest priority.
684
+ # If there are multiple matching bindings for a single tag, then the most
685
+ # specific binding is chosen (see the manual entry for the bind command
686
+ # for details).
687
+ # continue and break commands within binding scripts are processed in the
688
+ # same way as for bindings created with the bind command.
689
+ # If bindings are created for the widget as a whole using the bind command,
690
+ # then those bindings will supplement the tag bindings.
691
+ # The tag bindings will be invoked first, followed by bindings for the
692
+ # window as a whole.
693
+ def tag_bind(tag_name, sequence = None, &script)
694
+ unless script
695
+ if None == sequence
696
+ return Tk.execute(:tag, :bind, tag_name)
697
+ else
698
+ return Tk.execute(:tag, :bind, tag_name, sequence)
699
+ end
700
+ end
701
+
702
+ # create name for command
703
+ name = "#{tk_pathname}_#{tag_name}".scan(/\w+/).join('_')
704
+ @events ||= {}
705
+ unregister_event(name)
706
+
707
+ Event::Handler.register_custom(script) do |id|
708
+ code = "%s tag bind %s %s { ::RubyFFI::event %d '' %s }"
709
+ props = Event::Data::PROPERTIES.transpose[0].join(' ')
710
+ tcl = code % [tk_pathname, tag_name, sequence, id, props]
711
+ Tk.interp.eval(tcl)
712
+ @events[name] = id
713
+ end
714
+ end
715
+
716
+ def unregister_event(name, id = @events[name])
717
+ return unless id
718
+ @events.delete(id)
719
+ Event::Handler.unregister(id)
720
+ end
721
+
722
+ # This command returns the current value of the option named option
723
+ # associated with the tag given by tagName.
724
+ # Option may have any of the values accepted by the pathName tag
725
+ # configure widget command.
726
+ def tag_cget(tag_name, option)
727
+ execute(:tag, :cget, tag_name, option.to_tcl_option)
728
+ end
729
+
730
+ # This command is similar to the pathName configure widget command except
731
+ # that it modifies options associated with the tag given by tagName instead
732
+ # of modifying options for the overall text widget.
733
+ # If no option is specified, the command returns a list describing all of
734
+ # the available options for tagName (see Tk_ConfigureInfo for information
735
+ # on the format of this list).
736
+ # If option is specified with no value, then the command returns a list
737
+ # describing the one named option (this list will be identical to the
738
+ # corresponding sublist of the value returned if no option is specified).
739
+ # If one or more option-value pairs are specified, then the command
740
+ # modifies the given option(s) to have the given value(s) in tagName; in
741
+ # this case the command returns an empty string.
742
+ # See TAGS above for details on the options available for tags.
743
+ def tag_configure(tag_name, options = None)
744
+ common_configure([:tag, :configure, tag_name], options)
745
+ end
746
+
747
+ # Deletes all tag information for each of the tagName arguments.
748
+ # The command removes the tags from all characters in the file and also
749
+ # deletes any other information associated with the tags, such as
750
+ # bindings and display information.
751
+ # The command returns an empty string.
752
+ def tag_delete(tag_name, *tag_names)
753
+ execute_only(:tag, :delete, tag_name, *tag_names)
754
+ end
755
+
756
+ # Changes the priority of tag tagName so that it is just lower in priority
757
+ # than the tag whose name is belowThis.
758
+ # If belowThis is omitted, then tagName's priority is changed to make it
759
+ # lowest priority of all tags.
760
+ def tag_lower(tag_name, below = None)
761
+ execute_only(:tag, :lower, tag_name, below)
762
+ end
763
+
764
+ # Returns a list whose elements are the names of all the tags that are
765
+ # active at the character position given by index.
766
+ # If index is omitted, then the return value will describe all of the tags
767
+ # that exist for the text (this includes all tags that have been named in a
768
+ # “pathName tag” widget command but have not been deleted by a “pathName
769
+ # tag delete” widget command, even if no characters are currently marked
770
+ # with the tag).
771
+ # The list will be sorted in order from lowest priority to highest
772
+ # priority.
773
+ def tag_names(index = None)
774
+ execute(:tag, :names, index).to_a
775
+ end
776
+
777
+ # This command searches the text for a range of characters tagged with
778
+ # tagName where the first character of the range is no earlier than the
779
+ # character at index1 and no later than the character just before index2 (a
780
+ # range starting at index2 will not be considered).
781
+ # If several matching ranges exist, the first one is chosen.
782
+ # The command's return value is a list containing two elements, which are
783
+ # the index of the first character of the range and the index of the
784
+ # character just after the last one in the range.
785
+ # If no matching range is found then the return value is an empty string.
786
+ # If index2 is not given then it defaults to the end of the text.
787
+ def tag_nextrange(tag_name, index1, index2 = None)
788
+ execute(:tag, :nextrange, tag_name, index1, index2).to_a
789
+ end
790
+
791
+ # This command searches the text for a range of characters tagged with
792
+ # tagName where the first character of the range is before the character at
793
+ # index1 and no earlier than the character at index2 (a range starting at
794
+ # index2 will be considered).
795
+ # If several matching ranges exist, the one closest to index1 is chosen.
796
+ # The command's return value is a list containing two elements, which are
797
+ # the index of the first character of the range and the index of the
798
+ # character just after the last one in the range.
799
+ # If no matching range is found then the return value is an empty string.
800
+ # If index2 is not given then it defaults to the beginning of the text.
801
+ def tag_prevrange(tag_name, index1, index2 = None)
802
+ execute(:tag, :prevrange, tag_name, index1, index2).to_a
803
+ end
804
+
805
+ # Changes the priority of tag tagName so that it is just higher in priority
806
+ # than the tag whose name is aboveThis.
807
+ # If aboveThis is omitted, then tagName's priority is changed to make it
808
+ # highest priority of all tags.
809
+ def tag_raise(tag_name, above = None)
810
+ execute_only(:tag, :raise, tag_name, above)
811
+ end
812
+
813
+ # Returns a list describing all of the ranges of text that have been tagged
814
+ # with tagName.
815
+ # The first two elements of the list describe the first tagged range in the
816
+ # text, the next two elements describe the second range, and so on.
817
+ # The first element of each pair contains the index of the first character
818
+ # of the range, and the second element of the pair contains the index of
819
+ # the character just after the last one in the range.
820
+ # If there are no characters tagged with tag then an empty string is
821
+ # returned.
822
+ def tag_ranges(tag_name)
823
+ [*execute(:tag, :ranges, tag_name)].each_slice(2).to_a
824
+ end
825
+
826
+ # Remove the tag tagName from all of the characters starting at index1 and
827
+ # ending just before index2 (the character at index2 is not affected).
828
+ # A single command may contain any number of index1-index2 pairs.
829
+ # If the last index2 is omitted then the tag is removed from the single
830
+ # character at index1.
831
+ # If there are no characters in the specified range (e.g.
832
+ # index1 is past the end of the file or index2 is less than or equal to
833
+ # index1) then the command has no effect.
834
+ # This command returns an empty string.
835
+ def tag_remove(tag_name, index1, index2 = None, *indices)
836
+ execute_only(:tag, :remove, tag_name, index1, index2, *indices)
837
+ end
838
+
839
+ # Returns the value of a configuration option for an embedded window.
840
+ # Index identifies the embedded window, and option specifies a particular
841
+ # configuration option, which must be one of the ones listed in the section
842
+ # EMBEDDED WINDOWS.
843
+ def window_cget(index, option)
844
+ execute(:window, :cget, index, option.to_tcl_option)
845
+ end
846
+
847
+ # Query or modify the configuration options for an embedded window.
848
+ # If no option is specified, returns a list describing all of the available
849
+ # options for the embedded window at index (see Tk_ConfigureInfo for
850
+ # information on the format of this list).
851
+ # If option is specified with no value, then the command returns a list
852
+ # describing the one named option (this list will be identical to the
853
+ # corresponding sublist of the value returned if no option is specified).
854
+ # If one or more option-value pairs are specified, then the command
855
+ # modifies the given option(s) to have the given value(s); in this case the
856
+ # command returns an empty string.
857
+ # See EMBEDDED WINDOWS for information on the options that are supported.
858
+ def window_configure(index, options = None)
859
+ common_configure([:window, :configure, index], options)
860
+ end
861
+
862
+ # This command creates a new window annotation, which will appear in the
863
+ # text at the position given by index.
864
+ # Any number of option-value pairs may be specified to configure the
865
+ # annotation. See EMBEDDED WINDOWS for information on the options that are
866
+ # supported. Returns an empty string.
867
+ def window_create(index, options = None)
868
+ if None == argument
869
+ execute(:window, :create, index)
870
+ else
871
+ execute(:window, :create, index, options.to_tcl_options)
872
+ end
873
+ end
874
+
875
+ # Returns a list whose elements are the names of all windows currently
876
+ # embedded in window.
877
+ def window_names
878
+ execute(:window, :names).to_a
879
+ end
880
+
881
+ def copy
882
+ Tk.execute(:tk_textCopy, self)
883
+ end
884
+
885
+ def cut
886
+ Tk.execute(:tk_textCut, self)
887
+ end
888
+
889
+ def paste
890
+ Tk.execute(:tk_textPaste, self)
891
+ end
892
+ end
893
+ end