ffi-tk 2009.11.29

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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