arcadia 0.12.2 → 0.13.0
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.
- data/README +25 -14
- data/conf/LC/en-UK.LANG +3 -1
- data/conf/arcadia.conf +10 -0
- data/conf/arcadia.res.rb +29 -1
- data/ext/ae-editor/ae-editor.rb +239 -48
- data/ext/ae-file-history/ae-file-history.conf +11 -1
- data/ext/ae-file-history/ae-file-history.rb +120 -2
- data/ext/ae-ruby-debug/ae-ruby-debug.rb +6 -5
- data/ext/ae-subprocess-inspector/ae-subprocess-inspector.rb +7 -3
- data/ext/ae-term/ae-term.rb +1 -1
- data/lib/a-commons.rb +72 -56
- data/lib/a-contracts.rb +23 -1
- data/lib/a-core.rb +136 -41
- data/lib/a-tkcommons.rb +127 -36
- data/tcl/fsdialog/fsdialog.tcl +2 -2
- data/tcl/ptwidgets-1.1.0/COPYRIGHT +10 -0
- data/tcl/ptwidgets-1.1.0/ChangeLog +194 -0
- data/tcl/ptwidgets-1.1.0/README +50 -0
- data/tcl/ptwidgets-1.1.0/common/stacktrace.tcl +29 -0
- data/tcl/ptwidgets-1.1.0/common/tokenframe.tcl +200 -0
- data/tcl/ptwidgets-1.1.0/doc/img/toggleswitch_off.png +0 -0
- data/tcl/ptwidgets-1.1.0/doc/img/toggleswitch_on.png +0 -0
- data/tcl/ptwidgets-1.1.0/doc/img/tokenentry.png +0 -0
- data/tcl/ptwidgets-1.1.0/doc/img/tokensearch_popup_example.png +0 -0
- data/tcl/ptwidgets-1.1.0/doc/img/tokensearch_popup_example2.png +0 -0
- data/tcl/ptwidgets-1.1.0/doc/img/wmarkentry.png +0 -0
- data/tcl/ptwidgets-1.1.0/doc/toggleswitch.html +402 -0
- data/tcl/ptwidgets-1.1.0/doc/tokenentry.html +1366 -0
- data/tcl/ptwidgets-1.1.0/doc/tokensearch.html +1549 -0
- data/tcl/ptwidgets-1.1.0/doc/wmarkentry.html +634 -0
- data/tcl/ptwidgets-1.1.0/library/toggleswitch.tcl +432 -0
- data/tcl/ptwidgets-1.1.0/library/tokenentry.tcl +2208 -0
- data/tcl/ptwidgets-1.1.0/library/tokensearch.tcl +2488 -0
- data/tcl/ptwidgets-1.1.0/library/wmarkentry.tcl +630 -0
- data/tcl/ptwidgets-1.1.0/pkgIndex.tcl +10 -0
- data/tcl/ptwidgets-1.1.0/test/Makefile +3 -0
- data/tcl/ptwidgets-1.1.0/test/run.tcl +3 -0
- data/tcl/ptwidgets-1.1.0/test/test.tcl +89 -0
- data/tcl/ptwidgets-1.1.0/test/toggleswitch.test +562 -0
- data/tcl/ptwidgets-1.1.0/test/tokenentry.test +1023 -0
- data/tcl/ptwidgets-1.1.0/test/tokensearch.test +1023 -0
- data/tcl/ptwidgets-1.1.0/test/wmarkentry.test +1325 -0
- data/tcl/themes/altTheme.tcl +101 -0
- data/tcl/themes/aquaTheme.tcl +59 -0
- data/tcl/themes/clamTheme.tcl +140 -0
- data/tcl/themes/classicTheme.tcl +108 -0
- data/tcl/themes/pkgIndex.tcl +3 -0
- data/tcl/themes/ttk.tcl +176 -0
- data/tcl/themes/vistaTheme.tcl +224 -0
- data/tcl/themes/winTheme.tcl +80 -0
- data/tcl/themes/xpTheme.tcl +65 -0
- data/tcl/tkfbox/folder.gif +0 -0
- data/tcl/tkfbox/textfile.gif +0 -0
- data/tcl/tkfbox/tkfbox.tcl +1 -0
- data/tcl/tkfbox/tkfbox.tcl~ +1 -0
- data/tcl/tkfbox/updir.xbm +1 -0
- metadata +43 -2
@@ -0,0 +1,2488 @@
|
|
1
|
+
#===============================================================
|
2
|
+
# Main tokensearch package module
|
3
|
+
#
|
4
|
+
# Copyright (c) 2011-2012 Trevor Williams (phase1geo@gmail.com)
|
5
|
+
#===============================================================
|
6
|
+
|
7
|
+
package provide tokensearch 1.0
|
8
|
+
|
9
|
+
source [file join [tokensearch::DIR] common tokenframe.tcl]
|
10
|
+
|
11
|
+
namespace eval tokensearch {
|
12
|
+
|
13
|
+
array set token_index {}
|
14
|
+
array set active_token {}
|
15
|
+
array set options {}
|
16
|
+
array set dont_tokenize {}
|
17
|
+
array set old_focus {}
|
18
|
+
array set old_grab {}
|
19
|
+
array set dropdown_token {}
|
20
|
+
array set images {}
|
21
|
+
array set pressed_token {}
|
22
|
+
array set token_count {}
|
23
|
+
array set token_shapes {}
|
24
|
+
array set categoryopt_vars {}
|
25
|
+
array set edit_info {}
|
26
|
+
array set dont_deselect {}
|
27
|
+
array set state {}
|
28
|
+
|
29
|
+
array set text_options {
|
30
|
+
-background 1
|
31
|
+
-bg 1
|
32
|
+
-borderwidth 1
|
33
|
+
-bd 1
|
34
|
+
-exportselection 1
|
35
|
+
-font 1
|
36
|
+
-foreground 1
|
37
|
+
-fg 1
|
38
|
+
-highlightbackground 1
|
39
|
+
-highlightcolor 1
|
40
|
+
-highlightthickness 1
|
41
|
+
-insertbackground 1
|
42
|
+
-insertborderwidth 1
|
43
|
+
-insertofftime 1
|
44
|
+
-insertontime 1
|
45
|
+
-insertwidth 1
|
46
|
+
-padx 1
|
47
|
+
-pady 1
|
48
|
+
-relief 1
|
49
|
+
-selectbackground 1
|
50
|
+
-selectborderwidth 1
|
51
|
+
-selectforeground 1
|
52
|
+
-setgrid 1
|
53
|
+
-state 1
|
54
|
+
-takefocus 1
|
55
|
+
-xscrollcommand 1
|
56
|
+
-yscrollcommand 1
|
57
|
+
-autoseparators 1
|
58
|
+
}
|
59
|
+
|
60
|
+
array set widget_options {
|
61
|
+
-autoseparators {autoSeparators AutoSeparators}
|
62
|
+
-background {background Background}
|
63
|
+
-bg -background
|
64
|
+
-borderwidth {borderWidth BorderWidth}
|
65
|
+
-bd -borderwidth
|
66
|
+
-categories {categories Categories}
|
67
|
+
-categorybd {categoryBorderWidth CategoryBorderWidth}
|
68
|
+
-categorybg {categoryBackground CategoryBackground}
|
69
|
+
-categorycursor {categoryCursor Cursor}
|
70
|
+
-categoryfont {categoryFont CategoryFont}
|
71
|
+
-categoryopts {categoryOpts CategoryOpts}
|
72
|
+
-categoryrelief {categoryRelief CategoryRelief}
|
73
|
+
-dropdownheight {dropDownHeight DropDownHeight}
|
74
|
+
-dropdownmaxheight {dropDownMaxHeight DropDownMaxHeight}
|
75
|
+
-exportselection {exportSelection ExportSelection}
|
76
|
+
-font {font Font}
|
77
|
+
-foreground {foreground Foreground}
|
78
|
+
-fg -foreground
|
79
|
+
-height {height Height}
|
80
|
+
-highlightbackground {highlightBackground HighlightBackground}
|
81
|
+
-highlightcolor {highlightColor HighlightColor}
|
82
|
+
-highlightthickness {highlightThickness HighlightThickness}
|
83
|
+
-historyvar {historyVar HistoryVar}
|
84
|
+
-insertbackground {insertBackground InsertBackground}
|
85
|
+
-insertborderwidth {insertBorderWidth InsertBorderWidth}
|
86
|
+
-insertofftime {insertOffTime InsertOffTime}
|
87
|
+
-insertontime {insertOnTime InsertOnTime}
|
88
|
+
-insertwidth {insertWidth InsertWidth}
|
89
|
+
-matchcase {matchCase MatchCase}
|
90
|
+
-matchmode {matchMode MatchMode}
|
91
|
+
-padx {padX Pad}
|
92
|
+
-pady {padY Pad}
|
93
|
+
-relief {relief Relief}
|
94
|
+
-selectbackground {selectBackground Background}
|
95
|
+
-selectborderwidth {selectBorderWidth BorderWidth}
|
96
|
+
-selectforeground {selectForeground Foreground}
|
97
|
+
-setgrid {setGrid SetGrid}
|
98
|
+
-state {state State}
|
99
|
+
-takefocus {takeFocus TakeFocus}
|
100
|
+
-tokenbg {tokenBackground TokenBackground}
|
101
|
+
-tokenbordercolor {tokenBorderColor TokenBorderColor}
|
102
|
+
-tokenfg {tokenForeground TokenForeground}
|
103
|
+
-tokenselectbg {tokenSelectBackground TokenSelectBackground}
|
104
|
+
-tokenselectbordercolor {tokenSelectBorderColor TokenSelectBorderColor}
|
105
|
+
-tokenselectfg {tokenSelectForeground TokenSelectForeground}
|
106
|
+
-tokenshape {tokenShape TokenShape}
|
107
|
+
-tokenvar {tokenVar TokenVar}
|
108
|
+
-watermark {watermark Watermark}
|
109
|
+
-watermarkforeground {watermarkForeground Foreground}
|
110
|
+
-width {width Width}
|
111
|
+
-wrap {wrap Wrap}
|
112
|
+
-xscrollcommand {xScrollCommand ScrollCommand}
|
113
|
+
-yscrollcommand {yScrollCommand ScrollCommand}
|
114
|
+
}
|
115
|
+
|
116
|
+
variable img_arrow
|
117
|
+
variable img_blank
|
118
|
+
|
119
|
+
set img_arrow [image create photo -data "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"]
|
120
|
+
set img_blank [image create photo -data "R0lGODlhBwAHAIAAAP///wAAACH5BAkKAAEAIf8 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"]
|
121
|
+
|
122
|
+
###########################################################################
|
123
|
+
# Main procedure which creates the given window and initializes it.
|
124
|
+
proc tokensearch {w args} {
|
125
|
+
|
126
|
+
variable token_index
|
127
|
+
variable options
|
128
|
+
variable dont_tokenize
|
129
|
+
variable dont_deselect
|
130
|
+
variable active_token
|
131
|
+
variable pressed_token
|
132
|
+
variable token_count
|
133
|
+
variable widget_options
|
134
|
+
variable dropdown_token
|
135
|
+
variable state
|
136
|
+
|
137
|
+
# Create the widget frame
|
138
|
+
frame $w -class TokenSearch -takefocus 0
|
139
|
+
|
140
|
+
# Initially, we pack the frame with an entry widget
|
141
|
+
text $w.txt -highlightthickness 0 -relief flat -bg white -spacing1 2 -spacing2 2 -spacing3 2 -takefocus 1
|
142
|
+
|
143
|
+
# Pack the text widget
|
144
|
+
pack $w.txt -side left -fill both -expand yes
|
145
|
+
|
146
|
+
# Create the category menu
|
147
|
+
menu $w.mnu -tearoff 0
|
148
|
+
|
149
|
+
# Create the popup window that might be used by this widget
|
150
|
+
toplevel $w.top
|
151
|
+
listbox $w.top.list -selectmode browse -background white -yscrollcommand "$w.top.vsb set" -exportselection 0 -borderwidth 0 -cursor top_left_arrow
|
152
|
+
ttk::scrollbar $w.top.vsb -command "$w.top.list yview"
|
153
|
+
|
154
|
+
pack $w.top.list -side left -fill both -expand y
|
155
|
+
|
156
|
+
# Handle the popup
|
157
|
+
wm overrideredirect $w.top 1
|
158
|
+
wm transient $w.top [winfo toplevel $w]
|
159
|
+
wm group $w.top [winfo parent $w]
|
160
|
+
wm withdraw $w.top
|
161
|
+
|
162
|
+
# Initialize default options
|
163
|
+
if {[array size token_index] == 0} {
|
164
|
+
foreach opt [array names widget_options] {
|
165
|
+
if {![catch "$w.txt configure $opt" rc]} {
|
166
|
+
if {[llength $widget_options($opt)] != 1} {
|
167
|
+
if {$opt eq "-wrap"} {
|
168
|
+
set default_value 0
|
169
|
+
} elseif {$opt eq "-height"} {
|
170
|
+
set default_value 1
|
171
|
+
} elseif {$opt eq "-background"} {
|
172
|
+
set default_value "white"
|
173
|
+
} elseif {$opt eq "-relief"} {
|
174
|
+
set default_value "ridge"
|
175
|
+
} else {
|
176
|
+
set default_value [lindex $rc 4]
|
177
|
+
}
|
178
|
+
option add *TokenSearch.[lindex $rc 1] $default_value widgetDefault
|
179
|
+
}
|
180
|
+
}
|
181
|
+
}
|
182
|
+
option add *TokenSearch.tokenForeground [list "white" "black"] widgetDefault
|
183
|
+
option add *TokenSearch.tokenBackground [list "dark blue" "light blue"] widgetDefault
|
184
|
+
option add *TokenSearch.tokenBorderColor [list "dark blue" "light blue"] widgetDefault
|
185
|
+
option add *TokenSearch.tokenSelectForeground "white" widgetDefault
|
186
|
+
option add *TokenSearch.tokenSelectBackground "blue" widgetDefault
|
187
|
+
option add *TokenSearch.tokenSelectBorderColor "blue" widgetDefault
|
188
|
+
option add *TokenSearch.dropDownHeight 0 widgetDefault
|
189
|
+
option add *TokenSearch.dropDownMaxHeight 5 widgetDefault
|
190
|
+
option add *TokenSearch.matchMode glob widgetDefault
|
191
|
+
option add *TokenSearch.matchCase 0 widgetDefault
|
192
|
+
option add *TokenSearch.historyVar "" widgetDefault
|
193
|
+
option add *TokenSearch.tokenVar "" widgetDefault
|
194
|
+
option add *TokenSearch.tokenShape pill widgetDefault
|
195
|
+
option add *TokenSearch.dropDownFormatString "%s" widgetDefault
|
196
|
+
option add *TokenSearch.categories [list {Categories Name}] widgetDefault
|
197
|
+
option add *TokenSearch.categoryBackground white widgetDefault
|
198
|
+
option add *TokenSearch.categoryRelief groove widgetDefault
|
199
|
+
option add *TokenSearch.categoryBorderWidth 1 widgetDefault
|
200
|
+
option add *TokenSearch.categoryFont [font create -size 8] widgetDefault
|
201
|
+
option add *TokenSearch.categoryCursor "" widgetDefault
|
202
|
+
option add *TokenSearch.watermark "" widgetDefault
|
203
|
+
option add *TokenSearch.watermarkForeground "light gray" widgetDefault
|
204
|
+
}
|
205
|
+
|
206
|
+
# Initialize variables
|
207
|
+
set token_index($w) 0
|
208
|
+
set active_token($w) ""
|
209
|
+
set dont_tokenize($w) 0
|
210
|
+
set dropdown_token($w) ""
|
211
|
+
set pressed_token($w) ""
|
212
|
+
set token_count($w) 0
|
213
|
+
set dont_deselect($w) 0
|
214
|
+
set state($w) "unknown"
|
215
|
+
|
216
|
+
# Initialize the options array
|
217
|
+
foreach opt [array names widget_options] {
|
218
|
+
set options($w,$opt) [option get $w [lindex $widget_options($opt) 0] [lindex $widget_options($opt) 1]]
|
219
|
+
}
|
220
|
+
|
221
|
+
# Setup bindings
|
222
|
+
bind $w.txt <FocusOut> "set tokensearch::dont_tokenize($w) 0; tokensearch::tokenize $w"
|
223
|
+
bind $w.txt <Return> "tokensearch::key_return $w; break"
|
224
|
+
bind $w.txt <Tab> "tokensearch::focus_next $w; break"
|
225
|
+
bind $w.txt <Left> {
|
226
|
+
tokensearch::key_left_right [winfo parent %W] left
|
227
|
+
if {[tokensearch::handle_text_movement [winfo parent %W]]} {
|
228
|
+
break
|
229
|
+
}
|
230
|
+
}
|
231
|
+
bind $w.txt <Right> {
|
232
|
+
tokensearch::key_left_right [winfo parent %W] right
|
233
|
+
if {[tokensearch::handle_text_movement [winfo parent %W]]} {
|
234
|
+
break
|
235
|
+
}
|
236
|
+
}
|
237
|
+
bind $w.txt <Down> {
|
238
|
+
tokensearch::key_down [winfo parent %W]
|
239
|
+
if {[tokensearch::handle_text_movement [winfo parent %W]]} {
|
240
|
+
break
|
241
|
+
}
|
242
|
+
}
|
243
|
+
bind $w.txt <Up> {
|
244
|
+
tokensearch::key_up [winfo parent %W]
|
245
|
+
if {[tokensearch::handle_text_movement [winfo parent %W]]} {
|
246
|
+
break
|
247
|
+
}
|
248
|
+
}
|
249
|
+
bind $w.txt <Escape> "tokensearch::close_dropdown $w"
|
250
|
+
bind $w.txt <Button-1> {
|
251
|
+
tokensearch::close_dropdown [winfo parent %W]
|
252
|
+
if {[tokensearch::handle_text_movement [winfo parent %W]]} {
|
253
|
+
break
|
254
|
+
}
|
255
|
+
}
|
256
|
+
bind $w.txt <B1-Motion> {
|
257
|
+
if {[tokensearch::handle_text_movement [winfo parent %W]]} {
|
258
|
+
break
|
259
|
+
}
|
260
|
+
}
|
261
|
+
bind $w.txt <B1-Leave> {
|
262
|
+
if {[tokensearch::handle_text_movement [winfo parent %W]]} {
|
263
|
+
break
|
264
|
+
}
|
265
|
+
}
|
266
|
+
bind $w.txt <Any-KeyPress> "tokensearch::keypress $w"
|
267
|
+
bind $w.top.list <Motion> "tokensearch::motion_dropdown $w %x %y"
|
268
|
+
bind $w.top.list <Button-1> "tokensearch::key_return $w; focus $w.txt"
|
269
|
+
bind $w.txt <<Modified>> "tokensearch::modified $w"
|
270
|
+
bind $w.txt <<Selection>> "tokensearch::handle_selection_change $w"
|
271
|
+
bind $w.txt <Destroy> "tokensearch::handle_destroy $w"
|
272
|
+
if {[tk windowingsystem] eq "aqua"} {
|
273
|
+
bind $w.txt <Command-x> "tokensearch::handle_cut $w"
|
274
|
+
bind $w.txt <Command-c> "tokensearch::handle_copy $w"
|
275
|
+
bind $w.txt <Command-v> "tokensearch::handle_paste $w"
|
276
|
+
} else {
|
277
|
+
bind $w.txt <Control-x> "tokensearch::handle_cut $w"
|
278
|
+
bind $w.txt <Control-c> "tokensearch::handle_copy $w"
|
279
|
+
bind $w.txt <Control-v> "tokensearch::handle_paste $w"
|
280
|
+
}
|
281
|
+
|
282
|
+
# Configure the widget
|
283
|
+
eval "configure 1 $w $args"
|
284
|
+
|
285
|
+
# Rename and alias the tokensearch window
|
286
|
+
rename ::$w $w
|
287
|
+
interp alias {} ::$w {} tokensearch::widget_cmd $w
|
288
|
+
|
289
|
+
return $w
|
290
|
+
|
291
|
+
}
|
292
|
+
|
293
|
+
###########################################################################
|
294
|
+
# This procedure is called when the widget is destroyed.
|
295
|
+
proc handle_destroy {w} {
|
296
|
+
|
297
|
+
variable images
|
298
|
+
|
299
|
+
# Delete the images
|
300
|
+
foreach {key value} [array get images $w,*] {
|
301
|
+
image delete $value
|
302
|
+
}
|
303
|
+
|
304
|
+
# Delete the image array
|
305
|
+
array unset images $w,*
|
306
|
+
|
307
|
+
}
|
308
|
+
|
309
|
+
###########################################################################
|
310
|
+
# Changes focus to the next window after w.
|
311
|
+
proc focus_next {w} {
|
312
|
+
|
313
|
+
# Change the focus
|
314
|
+
focus [tk_focusNext $w.txt]
|
315
|
+
|
316
|
+
}
|
317
|
+
|
318
|
+
###########################################################################
|
319
|
+
# This procedure is called when the text widget is modified.
|
320
|
+
proc modified {w} {
|
321
|
+
|
322
|
+
variable token_count
|
323
|
+
variable options
|
324
|
+
variable state
|
325
|
+
|
326
|
+
if {[$w.txt edit modified]} {
|
327
|
+
|
328
|
+
set last_value [$w.txt get {insert - 1 chars} insert]
|
329
|
+
|
330
|
+
if {($last_value eq "\n") || ($last_value eq "\t")} {
|
331
|
+
$w.txt delete {insert - 1 chars} insert
|
332
|
+
handle_state $w 1
|
333
|
+
}
|
334
|
+
|
335
|
+
# Reset the modified flag
|
336
|
+
$w.txt edit modified false
|
337
|
+
|
338
|
+
# Generate the TokenSearchModified event if our token count has changed
|
339
|
+
set tokens [llength [$w.txt window names]]
|
340
|
+
if {$token_count($w) != $tokens} {
|
341
|
+
set token_count($w) $tokens
|
342
|
+
if {$options($w,-tokenvar) ne ""} {
|
343
|
+
upvar #0 $options($w,-tokenvar) var
|
344
|
+
set var [get_tokens $w]
|
345
|
+
}
|
346
|
+
event generate $w <<TokenSearchModified>>
|
347
|
+
}
|
348
|
+
|
349
|
+
}
|
350
|
+
|
351
|
+
}
|
352
|
+
|
353
|
+
###########################################################################
|
354
|
+
# If the selection of the text box changes, make sure that any selected
|
355
|
+
# tokens are updated appropriately.
|
356
|
+
proc handle_selection_change {w} {
|
357
|
+
|
358
|
+
# Don't allow the selection to contain tokens
|
359
|
+
foreach token [$w.txt window names] {
|
360
|
+
if {[lsearch [$w.txt tag names $token] sel] != -1} {
|
361
|
+
$w.txt tag remove sel $token
|
362
|
+
}
|
363
|
+
}
|
364
|
+
|
365
|
+
}
|
366
|
+
|
367
|
+
###########################################################################
|
368
|
+
# Validation command.
|
369
|
+
proc validate {w str} {
|
370
|
+
|
371
|
+
variable options
|
372
|
+
|
373
|
+
if {$str eq ","} {
|
374
|
+
return 0
|
375
|
+
} elseif {$options($w,-validatecommand) ne ""} {
|
376
|
+
return [eval $options($w,-validatecommand) $str]
|
377
|
+
} else {
|
378
|
+
return 1
|
379
|
+
}
|
380
|
+
|
381
|
+
}
|
382
|
+
|
383
|
+
###########################################################################
|
384
|
+
# Handles a left or right arrow key event.
|
385
|
+
proc key_left_right {w dir {token ""}} {
|
386
|
+
|
387
|
+
variable options
|
388
|
+
variable active_token
|
389
|
+
|
390
|
+
if {$token eq ""} {
|
391
|
+
|
392
|
+
# Don't do anything if the current insertion cursor is the beginning or end
|
393
|
+
if {(([$w.txt index insert] ne "1.0") || ($dir eq "right")) && \
|
394
|
+
(([$w.txt index insert] ne [$w.txt index end]) || ($dir eq "left"))} {
|
395
|
+
|
396
|
+
# Get the current insertion index
|
397
|
+
if {$dir eq "left"} {
|
398
|
+
set index [$w.txt index "insert - 1 chars"]
|
399
|
+
} else {
|
400
|
+
set index [$w.txt index insert]
|
401
|
+
}
|
402
|
+
|
403
|
+
# If a token exists at the given index, select it.
|
404
|
+
foreach token [$w.txt window names] {
|
405
|
+
if {[$w.txt index $token] eq $index} {
|
406
|
+
reverse_token $w $token
|
407
|
+
set active_token($w) $index
|
408
|
+
focus $token
|
409
|
+
return
|
410
|
+
}
|
411
|
+
}
|
412
|
+
|
413
|
+
}
|
414
|
+
|
415
|
+
} else {
|
416
|
+
|
417
|
+
# Clear the active token
|
418
|
+
set active_token($w) ""
|
419
|
+
|
420
|
+
# Deselect the token
|
421
|
+
reverse_token $w $token
|
422
|
+
|
423
|
+
# Close the dropdown listbox if it is opened
|
424
|
+
close_dropdown $w
|
425
|
+
|
426
|
+
# If the direction was a positive direction, increase the insertion cursor by one character
|
427
|
+
if {($dir eq "right") && ([$w.txt index $token] eq [$w.txt index insert])} {
|
428
|
+
$w.txt mark set insert "insert + 1 chars"
|
429
|
+
}
|
430
|
+
|
431
|
+
# Get the text entry field the focus
|
432
|
+
focus $w.txt
|
433
|
+
|
434
|
+
}
|
435
|
+
|
436
|
+
}
|
437
|
+
|
438
|
+
###########################################################################
|
439
|
+
# This procedure is invoked when the user hits the down key when the text
|
440
|
+
# has the focus.
|
441
|
+
proc key_down {w {token ""}} {
|
442
|
+
|
443
|
+
if {[winfo ismapped $w.top]} {
|
444
|
+
tk::ListboxUpDown $w.top.list 1
|
445
|
+
return -code break
|
446
|
+
} elseif {$token ne ""} {
|
447
|
+
display_category_menu $w $token
|
448
|
+
}
|
449
|
+
|
450
|
+
}
|
451
|
+
|
452
|
+
###########################################################################
|
453
|
+
# This procedure is invoked when the user hits the shift-down key combination
|
454
|
+
# when the token has the focus. This invokes the history drop-down.
|
455
|
+
proc key_shift_down {w token} {
|
456
|
+
|
457
|
+
# Dislay the dropdown item list
|
458
|
+
display_dropdown_items $w $token
|
459
|
+
|
460
|
+
}
|
461
|
+
|
462
|
+
###########################################################################
|
463
|
+
# This procedure is invoked when the user hits the up key when the text
|
464
|
+
# has the focus.
|
465
|
+
proc key_up {w {token ""}} {
|
466
|
+
|
467
|
+
if {[winfo ismapped $w.top]} {
|
468
|
+
tk::ListboxUpDown $w.top.list -1
|
469
|
+
return -code break
|
470
|
+
} elseif {$token ne ""} {
|
471
|
+
close_dropdown $w
|
472
|
+
}
|
473
|
+
|
474
|
+
}
|
475
|
+
|
476
|
+
###########################################################################
|
477
|
+
# This procedure is invoked when the user hits the return key when the
|
478
|
+
# text has the focus.
|
479
|
+
proc key_return {w {token ""}} {
|
480
|
+
|
481
|
+
variable dropdown_token
|
482
|
+
variable options
|
483
|
+
variable dont_tokenize
|
484
|
+
|
485
|
+
# Allow the tokenization to occur
|
486
|
+
set dont_tokenize($w) 0
|
487
|
+
|
488
|
+
# If the dropdown window is shown, get the currently selected text and insert it into the textbox.
|
489
|
+
if {[winfo ismapped $w.top]} {
|
490
|
+
|
491
|
+
# Get the currently selected value
|
492
|
+
set value [$w.top.list get [$w.top.list curselection]]
|
493
|
+
|
494
|
+
# Figure out the position of the first character of text
|
495
|
+
set curr_index 1.0
|
496
|
+
set end_index [$w.txt index end]
|
497
|
+
while {($curr_index != $end_index) && ([$w.txt get $curr_index] eq "")} {
|
498
|
+
set curr_index [$w.txt index "$curr_index + 1 chars"]
|
499
|
+
}
|
500
|
+
|
501
|
+
# If the result is associated with a token, change the token text
|
502
|
+
if {$dropdown_token($w) ne ""} {
|
503
|
+
$dropdown_token($w).val.l1 configure -text $value
|
504
|
+
redraw_token $w $dropdown_token($w) 1
|
505
|
+
if {$options($w,-tokenvar) ne ""} {
|
506
|
+
upvar #0 $options($w,-tokenvar) var
|
507
|
+
set var [get_tokens $w]
|
508
|
+
}
|
509
|
+
event generate $w <<TokenSearchModified>>
|
510
|
+
|
511
|
+
# Otherwise, remove the current text and replace it with the given value
|
512
|
+
} else {
|
513
|
+
$w.txt delete $curr_index "$curr_index + [expr [string length $value] + 1] chars"
|
514
|
+
$w.txt insert $curr_index $value
|
515
|
+
tokenize $w
|
516
|
+
}
|
517
|
+
|
518
|
+
# Close the dropbox
|
519
|
+
close_dropdown $w
|
520
|
+
|
521
|
+
# If this return was hit for a token, detokenize the current token to make it editable
|
522
|
+
} elseif {$token ne ""} {
|
523
|
+
|
524
|
+
detokenize $w $token
|
525
|
+
|
526
|
+
} else {
|
527
|
+
|
528
|
+
# Tokenize the text
|
529
|
+
tokenize $w
|
530
|
+
|
531
|
+
}
|
532
|
+
|
533
|
+
}
|
534
|
+
|
535
|
+
###########################################################################
|
536
|
+
# This procedure is called whenever the escape key is pressed when a token
|
537
|
+
# has the focus. This will cause the dropdown listbox to be closed if
|
538
|
+
# it is currently opened.
|
539
|
+
proc key_escape {w token} {
|
540
|
+
|
541
|
+
# Just close the dropdown listbox
|
542
|
+
close_dropdown $w
|
543
|
+
|
544
|
+
}
|
545
|
+
|
546
|
+
###########################################################################
|
547
|
+
# This procedure is called whenever the user presses a key in the text box.
|
548
|
+
proc keypress {w} {
|
549
|
+
|
550
|
+
# Update the current state
|
551
|
+
handle_state $w 1
|
552
|
+
|
553
|
+
after idle [list tokensearch::handle_entry_key $w]
|
554
|
+
|
555
|
+
# Clear the listbox selection so that it's obvious what will happen if the user
|
556
|
+
# presses return.
|
557
|
+
$w.top.list see 0
|
558
|
+
$w.top.list selection clear 0 end
|
559
|
+
$w.top.list selection anchor 0
|
560
|
+
$w.top.list activate 0
|
561
|
+
|
562
|
+
}
|
563
|
+
|
564
|
+
###########################################################################
|
565
|
+
# Populates and shows the listbox with the matching values. If there are no
|
566
|
+
# matching values, the listbox is closed.
|
567
|
+
proc handle_entry_key {w} {
|
568
|
+
|
569
|
+
variable options
|
570
|
+
variable dont_tokenize
|
571
|
+
|
572
|
+
# Handle the current state
|
573
|
+
handle_state $w 1
|
574
|
+
|
575
|
+
# Make sure that we don't tokenize
|
576
|
+
set dont_tokenize($w) 1
|
577
|
+
|
578
|
+
# Get rid of any whitespace from around the value
|
579
|
+
set value [string trim [$w.txt get 1.0 end]]
|
580
|
+
|
581
|
+
# Clear the listbox
|
582
|
+
$w.top.list delete 0 end
|
583
|
+
|
584
|
+
# Populate the listbox with matching values
|
585
|
+
if {$value ne ""} {
|
586
|
+
if {$options($w,-historyvar) ne ""} {
|
587
|
+
upvar #0 $options($w,-historyvar) history
|
588
|
+
set cmdargs [list]
|
589
|
+
switch $options($w,-matchmode) {
|
590
|
+
glob {
|
591
|
+
lappend cmdargs "-glob"
|
592
|
+
set matchval "*$value*"
|
593
|
+
}
|
594
|
+
regexp {
|
595
|
+
lappend cmdargs "-regexp"
|
596
|
+
set matchval ".*$value.*"
|
597
|
+
}
|
598
|
+
default {
|
599
|
+
lappend cmdargs "-glob"
|
600
|
+
set matchval "*$value*"
|
601
|
+
}
|
602
|
+
}
|
603
|
+
if {!$options($w,-matchcase)} {
|
604
|
+
lappend cmdargs "-nocase"
|
605
|
+
}
|
606
|
+
lappend cmdargs "-all" "-inline"
|
607
|
+
foreach value [eval "lsearch $cmdargs {$history} {$matchval}"] {
|
608
|
+
$w.top.list insert end $value
|
609
|
+
}
|
610
|
+
}
|
611
|
+
}
|
612
|
+
|
613
|
+
# If the listbox is not empty, show it
|
614
|
+
if {[$w.top.list size] > 0} {
|
615
|
+
open_dropdown $w
|
616
|
+
$w.top.list activate 0
|
617
|
+
$w.top.list selection set 0
|
618
|
+
|
619
|
+
} else {
|
620
|
+
close_dropdown $w
|
621
|
+
}
|
622
|
+
|
623
|
+
}
|
624
|
+
|
625
|
+
###########################################################################
|
626
|
+
# Handles any sort of movement of the insertion cursor or selection within
|
627
|
+
# the text widget.
|
628
|
+
proc handle_text_movement {w} {
|
629
|
+
|
630
|
+
variable state
|
631
|
+
|
632
|
+
# If we are empty, always set the insertion cursor to 1.0
|
633
|
+
if {$state($w) eq "empty"} {
|
634
|
+
$w.txt mark set insert 1.0
|
635
|
+
$w.txt tag remove sel 1.0 end
|
636
|
+
focus $w.txt
|
637
|
+
return 1
|
638
|
+
}
|
639
|
+
|
640
|
+
return 0
|
641
|
+
|
642
|
+
}
|
643
|
+
|
644
|
+
###########################################################################
|
645
|
+
# Handles a Control-x binding on the given widget.
|
646
|
+
proc handle_cut {w} {
|
647
|
+
|
648
|
+
if {[focus] eq $w} {
|
649
|
+
set select [$w.txt tag ranges sel]
|
650
|
+
if {[llength $select] == 0} {
|
651
|
+
clipboard clear
|
652
|
+
clipboard append [$w.txt get 1.0 end]
|
653
|
+
# TBD - Need to delete only text
|
654
|
+
eval "$w.txt delete 1.0 end"
|
655
|
+
handle_state $w 1
|
656
|
+
} else {
|
657
|
+
clipboard clear
|
658
|
+
clipboard append [eval "$w.txt get $select"]
|
659
|
+
eval "$w.txt delete $select"
|
660
|
+
handle_state $w 1
|
661
|
+
}
|
662
|
+
} else {
|
663
|
+
clipboard clear
|
664
|
+
clipboard append [[focus].l1 cget -text]
|
665
|
+
eval "tokendelete $w $select"
|
666
|
+
}
|
667
|
+
|
668
|
+
}
|
669
|
+
|
670
|
+
###########################################################################
|
671
|
+
# Handles a Control-c binding on the given widget.
|
672
|
+
proc handle_copy {w} {
|
673
|
+
|
674
|
+
if {[focus] eq $w} {
|
675
|
+
set select [$w.txt tag ranges sel]
|
676
|
+
if {[llength $select] == 0} {
|
677
|
+
clipboard clear
|
678
|
+
clipboard append [$w.txt get 1.0 end]
|
679
|
+
} else {
|
680
|
+
clipboard clear
|
681
|
+
clipboard append [eval "$w.txt get $select"]
|
682
|
+
}
|
683
|
+
} else {
|
684
|
+
clipboard clear
|
685
|
+
clipboard append [[focus].l1 cget -text]
|
686
|
+
}
|
687
|
+
|
688
|
+
}
|
689
|
+
|
690
|
+
###########################################################################
|
691
|
+
# Handles a Control-v binding on the given widget.
|
692
|
+
proc handle_paste {w} {
|
693
|
+
|
694
|
+
# Handle the current state
|
695
|
+
handle_state $w 1
|
696
|
+
|
697
|
+
# Insert the clipboard text
|
698
|
+
$w.txt insert insert [clipboard get]
|
699
|
+
|
700
|
+
# Close the drop-down listbox
|
701
|
+
close_dropdown $w
|
702
|
+
|
703
|
+
}
|
704
|
+
|
705
|
+
###########################################################################
|
706
|
+
# Redraws the given token.
|
707
|
+
proc redraw_token {w token resize} {
|
708
|
+
|
709
|
+
variable options
|
710
|
+
variable images
|
711
|
+
variable token_shapes
|
712
|
+
|
713
|
+
# Get the border color from the token
|
714
|
+
set cat_usebc [$token.cat.l2.top cget -bg]
|
715
|
+
set val_usebc [$token.val.l2.top cget -bg]
|
716
|
+
set txt_bg [$w.txt cget -background]
|
717
|
+
|
718
|
+
# Figure out the width and height of the token text label
|
719
|
+
if {$resize} {
|
720
|
+
update idletasks
|
721
|
+
}
|
722
|
+
set l1_cat_width [winfo reqwidth $token.cat.l1]
|
723
|
+
set l1_val_width [winfo reqwidth $token.val.l1]
|
724
|
+
set l1_height [winfo reqheight $token.cat.l1]
|
725
|
+
|
726
|
+
# Get the needed shapes
|
727
|
+
set shape_left [lindex $token_shapes($token) 0]
|
728
|
+
set shape_right [lindex $token_shapes($token) end]
|
729
|
+
|
730
|
+
# Create the token images, if necessary
|
731
|
+
if {![info exists images($w,left,$l1_height,$cat_usebc,$txt_bg,$shape_left)]} {
|
732
|
+
set images($w,left,$l1_height,$cat_usebc,$txt_bg,$shape_left) [image create bitmap -data [eval "tokenframe::create_left $shape_left $l1_height"] -maskdata [eval "tokenframe::create_left_mask $shape_left $l1_height"] -foreground $cat_usebc -background $txt_bg]
|
733
|
+
}
|
734
|
+
if {![info exists images($w,cat_edge,$cat_usebc)]} {
|
735
|
+
set images($w,cat_edge,$cat_usebc) [image create bitmap -data "#define edge_width 7\n#define edge_height 2\nstatic char edge_bits\[\] = {\n0x7f, 0x7f};" -foreground $cat_usebc]
|
736
|
+
}
|
737
|
+
if {![info exists images($w,val_edge,$val_usebc)]} {
|
738
|
+
set images($w,val_edge,$val_usebc) [image create bitmap -data "#define edge_width 7\n#define edge_height 2\nstatic char edge_bits\[\] = {\n0x7f, 0x7f};" -foreground $val_usebc]
|
739
|
+
}
|
740
|
+
if {![info exists images($w,cat_middle,$l1_cat_width,$l1_height,$cat_usebc)]} {
|
741
|
+
set images($w,cat_middle,$l1_cat_width,$l1_height,$cat_usebc) [image create bitmap -data [tokenframe::create_middle $l1_cat_width $l1_height] -foreground $cat_usebc]
|
742
|
+
}
|
743
|
+
if {![info exists images($w,val_middle,$l1_val_width,$l1_height,$val_usebc)]} {
|
744
|
+
set images($w,val_middle,$l1_val_width,$l1_height,$val_usebc) [image create bitmap -data [tokenframe::create_middle $l1_val_width $l1_height] -foreground $val_usebc]
|
745
|
+
}
|
746
|
+
if {![info exists images($w,$l1_height,$val_usebc,$txt_bg,$shape_right)]} {
|
747
|
+
set images($w,right,$l1_height,$val_usebc,$txt_bg,$shape_right) [image create bitmap -data [eval "tokenframe::create_right $shape_right $l1_height"] -maskdata [eval "tokenframe::create_right_mask $shape_right $l1_height"] -foreground $val_usebc -background $txt_bg]
|
748
|
+
}
|
749
|
+
|
750
|
+
# Configure the label images
|
751
|
+
$token.ll configure -padx 0 -pady 0 -compound center -image $images($w,left,$l1_height,$cat_usebc,$txt_bg,$shape_left)
|
752
|
+
$token.cat.l1 configure -padx 0 -pady 0 -compound center -image $images($w,cat_middle,$l1_cat_width,$l1_height,$cat_usebc)
|
753
|
+
$token.cat.l2.top configure -padx 0 -pady 0 -compound center -image $images($w,cat_edge,$cat_usebc)
|
754
|
+
$token.cat.l2.bot configure -padx 0 -pady 0 -compound center -image $images($w,cat_edge,$cat_usebc)
|
755
|
+
$token.val.l1 configure -padx 0 -pady 0 -compound center -image $images($w,val_middle,$l1_val_width,$l1_height,$val_usebc)
|
756
|
+
$token.val.l2.top configure -padx 0 -pady 0 -compound center -image $images($w,val_edge,$val_usebc)
|
757
|
+
$token.val.l2.bot configure -padx 0 -pady 0 -compound center -image $images($w,val_edge,$val_usebc)
|
758
|
+
$token.lr configure -padx 0 -pady 0 -compound center -image $images($w,right,$l1_height,$val_usebc,$txt_bg,$shape_right)
|
759
|
+
|
760
|
+
}
|
761
|
+
|
762
|
+
###########################################################################
|
763
|
+
# Reverses the color scheme of the given token.
|
764
|
+
proc reverse_token {w token} {
|
765
|
+
|
766
|
+
# Get the current colors
|
767
|
+
set a_cat_bg [$token.cat.l1 cget -bg]
|
768
|
+
set a_cat_fg [$token.cat.l1 cget -fg]
|
769
|
+
set a_cat_bc [$token.cat.l2.top cget -bg]
|
770
|
+
set b_cat_bg [$token.cat.l2.top cget -fg]
|
771
|
+
set b_cat_fg [$token.cat.l2.mid cget -fg]
|
772
|
+
set b_cat_bc [$token.cat.l2.bot cget -fg]
|
773
|
+
|
774
|
+
set a_val_bg [$token.val.l1 cget -bg]
|
775
|
+
set a_val_fg [$token.val.l1 cget -fg]
|
776
|
+
set a_val_bc [$token.val.l2.top cget -bg]
|
777
|
+
set b_val_bg [$token.val.l2.top cget -fg]
|
778
|
+
set b_val_fg [$token.val.l2.mid cget -fg]
|
779
|
+
set b_val_bc [$token.val.l2.bot cget -fg]
|
780
|
+
|
781
|
+
# Reverse the color schemes
|
782
|
+
$token.ll configure -bg $b_cat_bg
|
783
|
+
$token.cat configure -bg $b_cat_bg
|
784
|
+
$token.cat.l1 configure -bg $b_cat_bg -fg $b_cat_fg
|
785
|
+
$token.cat.l2.top configure -bg $b_cat_bc -fg $a_cat_bg
|
786
|
+
$token.cat.l2.mid configure -bg $b_cat_bg -fg $a_cat_fg
|
787
|
+
$token.cat.l2.bot configure -bg $b_cat_bc -fg $a_cat_bc
|
788
|
+
$token.val configure -bg $b_val_bg
|
789
|
+
$token.val.l1 configure -bg $b_val_bg -fg $b_val_fg
|
790
|
+
$token.val.l2.top configure -bg $b_val_bc -fg $a_val_bg
|
791
|
+
$token.val.l2.mid configure -bg $b_val_bg -fg $a_val_fg
|
792
|
+
$token.val.l2.bot configure -bg $b_val_bc -fg $a_val_bc
|
793
|
+
$token.lr configure -bg $b_val_bg
|
794
|
+
|
795
|
+
# Redraw the token
|
796
|
+
redraw_token $w $token 0
|
797
|
+
|
798
|
+
}
|
799
|
+
|
800
|
+
###########################################################################
|
801
|
+
# Creates a token and inserts it into the textbox.
|
802
|
+
proc create_token {w index fg bg bordercolor selectfg selectbg selectbordercolor value} {
|
803
|
+
|
804
|
+
variable options
|
805
|
+
variable token_index
|
806
|
+
variable img_blank
|
807
|
+
variable token_shapes
|
808
|
+
|
809
|
+
# Get the first category in the categories list
|
810
|
+
set category [lindex $options($w,-categories) 0 1 0]
|
811
|
+
|
812
|
+
# Add the token (store the "store" colors and the select background color in unused slots)
|
813
|
+
set token [frame $w.txt.f$token_index($w) -relief flat]
|
814
|
+
set catf [frame $token.cat -bg [lindex $bg 0]]
|
815
|
+
set valf [frame $token.val -bg [lindex $bg end]]
|
816
|
+
|
817
|
+
label $token.ll -bd 0 -bg [lindex $bg 0] -fg [lindex $selectbg 0]
|
818
|
+
label $catf.l1 -bd 0 -text $category -fg [lindex $fg 0] -bg [lindex $bg 0] -font [$w.txt cget -font]
|
819
|
+
frame $catf.l2 -bg [lindex $bg 0]
|
820
|
+
label $catf.l2.top -bd 0 -bg [lindex $bordercolor 0] -fg [lindex $selectbg 0]
|
821
|
+
label $catf.l2.mid -bd 0 -bg [lindex $bg 0] -fg [lindex $selectfg 0] -image $img_blank
|
822
|
+
label $catf.l2.bot -bd 0 -bg [lindex $bordercolor 0] -fg [lindex $selectbordercolor 0]
|
823
|
+
label $valf.l1 -bd 0 -text $value -fg [lindex $fg end] -bg [lindex $bg end] -font [$w.txt cget -font]
|
824
|
+
frame $valf.l2 -bg [lindex $bg end]
|
825
|
+
label $valf.l2.top -bd 0 -bg [lindex $bordercolor end] -fg [lindex $selectbg end]
|
826
|
+
label $valf.l2.mid -bd 0 -bg [lindex $bg end] -fg [lindex $selectfg end] -image $img_blank
|
827
|
+
label $valf.l2.bot -bd 0 -bg [lindex $bordercolor end] -fg [lindex $selectbordercolor end]
|
828
|
+
label $token.lr -bd 0 -bg [lindex $bg end] -fg [lindex $selectbg end]
|
829
|
+
|
830
|
+
set token_shapes($token) $options($w,-tokenshape)
|
831
|
+
|
832
|
+
# Create the token frames
|
833
|
+
redraw_token $w $token 1
|
834
|
+
|
835
|
+
# Pack the labels
|
836
|
+
pack $catf.l2.top -anchor n
|
837
|
+
pack $catf.l2.mid -fill y -expand yes
|
838
|
+
pack $catf.l2.bot -anchor s
|
839
|
+
|
840
|
+
pack $catf.l1 -side left -padx 2
|
841
|
+
pack $catf.l2 -side left -padx 2
|
842
|
+
|
843
|
+
pack $valf.l2.top -anchor n
|
844
|
+
pack $valf.l2.mid -fill y -expand yes
|
845
|
+
pack $valf.l2.bot -anchor s
|
846
|
+
|
847
|
+
pack $valf.l1 -side left -padx 2
|
848
|
+
pack $valf.l2 -side left -padx 2
|
849
|
+
|
850
|
+
pack $token.ll -side left
|
851
|
+
pack $catf -side left
|
852
|
+
pack $valf -side left -fill both
|
853
|
+
pack $token.lr -side left
|
854
|
+
|
855
|
+
$w.txt window create $index -window $token -padx 2
|
856
|
+
|
857
|
+
# Add bindings to the new token
|
858
|
+
bind $token <FocusOut> "tokensearch::deselect_token $w $token"
|
859
|
+
bind $catf.l1 <ButtonPress-1> "tokensearch::handle_token_press $w $token %x %y"
|
860
|
+
bind $catf.l1 <Motion> "tokensearch::handle_token_drag $w %x %y"
|
861
|
+
bind $catf.l1 <ButtonRelease-1> "tokensearch::handle_token_release $w $token %x %y"
|
862
|
+
bind $catf.l2.mid <Button-1> "tokensearch::handle_cat_arrow_click $w $token %x %y"
|
863
|
+
bind $valf.l1 <ButtonPress-1> "tokensearch::handle_token_press $w $token %x %y"
|
864
|
+
bind $valf.l1 <Motion> "tokensearch::handle_token_drag $w %x %y"
|
865
|
+
bind $valf.l1 <ButtonRelease-1> "tokensearch::handle_token_release $w $token %x %y"
|
866
|
+
bind $valf.l2.mid <Button-1> "tokensearch::handle_val_arrow_click $w $token %x %y"
|
867
|
+
bind $catf <Enter> "tokensearch::handle_category_enter $w $token"
|
868
|
+
bind $valf <Enter> "tokensearch::handle_value_enter $w $token"
|
869
|
+
bind $token <Enter> "tokensearch::handle_token_enter $w $token"
|
870
|
+
bind $catf <Leave> "tokensearch::handle_category_leave $w $token"
|
871
|
+
bind $valf <Leave> "tokensearch::handle_value_leave $w $token"
|
872
|
+
bind $token <BackSpace> "tokensearch::delete_token $w $token"
|
873
|
+
bind $token <Left> "tokensearch::key_left_right $w left $token"
|
874
|
+
bind $token <Right> "tokensearch::key_left_right $w right $token"
|
875
|
+
bind $token <Down> "tokensearch::key_down $w $token"
|
876
|
+
bind $token <Shift-Down> "tokensearch::key_shift_down $w $token"
|
877
|
+
bind $token <Up> "tokensearch::key_up $w $token"
|
878
|
+
bind $token <Return> "tokensearch::key_return $w $token"
|
879
|
+
bind $token <Escape> "tokensearch::key_escape $w $token"
|
880
|
+
if {[tk windowingsystem] eq "aqua"} {
|
881
|
+
bind $token <Command-x> "tokensearch::handle_cut $w"
|
882
|
+
bind $token <Command-c> "tokensearch::handle_copy $w"
|
883
|
+
} else {
|
884
|
+
bind $token <Control-x> "tokensearch::handle_cut $w"
|
885
|
+
bind $token <Control-c> "tokensearch::handle_copy $w"
|
886
|
+
}
|
887
|
+
|
888
|
+
incr token_index($w)
|
889
|
+
|
890
|
+
return $token
|
891
|
+
|
892
|
+
}
|
893
|
+
|
894
|
+
###########################################################################
|
895
|
+
# Returns the text window position given an index.
|
896
|
+
proc index_to_position {w index} {
|
897
|
+
|
898
|
+
set indices [list]
|
899
|
+
foreach token [$w.txt window names] {
|
900
|
+
lappend indices [$w.txt index $token]
|
901
|
+
}
|
902
|
+
|
903
|
+
return [lindex [lsort -real $indices] $index]
|
904
|
+
|
905
|
+
}
|
906
|
+
|
907
|
+
###########################################################################
|
908
|
+
# Returns the name of the token at the given index.
|
909
|
+
proc index_to_token {w index} {
|
910
|
+
|
911
|
+
set indices [list]
|
912
|
+
foreach token [$w.txt window names] {
|
913
|
+
lappend indices [list [$w.txt index $token] $token]
|
914
|
+
}
|
915
|
+
|
916
|
+
return [lindex [lsort -real -index 0 $indices] $index 1]
|
917
|
+
|
918
|
+
}
|
919
|
+
|
920
|
+
###########################################################################
|
921
|
+
# Returns true if the given token is currently selected; otherwise, returns
|
922
|
+
# false.
|
923
|
+
proc is_selected {token} {
|
924
|
+
|
925
|
+
if {([$token.ll cget -fg] eq [$token.cat.l1 cget -bg]) && ([$token.lr cget -fg] eq [$token.val.l1 cget -bg])} {
|
926
|
+
return 1
|
927
|
+
} else {
|
928
|
+
return 0
|
929
|
+
}
|
930
|
+
|
931
|
+
}
|
932
|
+
|
933
|
+
###########################################################################
|
934
|
+
# Creates a token out of the given text, deletes the text.
|
935
|
+
proc tokenize {w} {
|
936
|
+
|
937
|
+
variable token_index
|
938
|
+
variable options
|
939
|
+
variable dont_tokenize
|
940
|
+
variable img_blank
|
941
|
+
variable edit_info
|
942
|
+
variable categoryopt_vars
|
943
|
+
variable state
|
944
|
+
|
945
|
+
if {$dont_tokenize($w)} {
|
946
|
+
set dont_tokenize($w) 0
|
947
|
+
return
|
948
|
+
}
|
949
|
+
|
950
|
+
# If our current state is empty, be done
|
951
|
+
if {$state($w) eq "empty"} {
|
952
|
+
return
|
953
|
+
}
|
954
|
+
|
955
|
+
# Get the current string in the entry field
|
956
|
+
set token_str [string trim [$w.txt get 1.0 end]]
|
957
|
+
|
958
|
+
# Figure out the position of the first character of text
|
959
|
+
set curr_index 1.0
|
960
|
+
set end_index [$w.txt index end]
|
961
|
+
while {($curr_index != $end_index) && ([$w.txt get $curr_index] eq "")} {
|
962
|
+
set curr_index [$w.txt index "$curr_index + 1 chars"]
|
963
|
+
}
|
964
|
+
|
965
|
+
# Create and add the token and add the token string to the history variable
|
966
|
+
if {$token_str ne ""} {
|
967
|
+
set token [create_token $w $curr_index $options($w,-tokenfg) $options($w,-tokenbg) $options($w,-tokenbordercolor) \
|
968
|
+
$options($w,-tokenselectfg) $options($w,-tokenselectbg) $options($w,-tokenselectbordercolor) $token_str]
|
969
|
+
if {$options($w,-historyvar) ne ""} {
|
970
|
+
upvar #0 $options($w,-historyvar) historyvar
|
971
|
+
if {[lsearch $historyvar $token_str] == -1} {
|
972
|
+
lappend historyvar $token_str
|
973
|
+
}
|
974
|
+
}
|
975
|
+
} else {
|
976
|
+
set token ""
|
977
|
+
}
|
978
|
+
|
979
|
+
# If we have edited this token, clear our recent buffer and populate the new
|
980
|
+
# token with the previous information.
|
981
|
+
if {[info exists edit_info($w)]} {
|
982
|
+
|
983
|
+
if {$token ne ""} {
|
984
|
+
|
985
|
+
# Set the category
|
986
|
+
$token.cat.l1 configure -text [lindex $edit_info($w) 0]
|
987
|
+
|
988
|
+
# Set the category options
|
989
|
+
set optnum 0
|
990
|
+
foreach opt [lrange $edit_info($w) 1 end] {
|
991
|
+
set categoryopt_vars($w,$token,$optnum) $opt
|
992
|
+
incr optnum
|
993
|
+
}
|
994
|
+
|
995
|
+
}
|
996
|
+
|
997
|
+
# Clear the edit information
|
998
|
+
unset edit_info($w)
|
999
|
+
|
1000
|
+
} else {
|
1001
|
+
|
1002
|
+
if {$token ne ""} {
|
1003
|
+
|
1004
|
+
# Create the categoryopt_vars for the given token
|
1005
|
+
set optnum 0
|
1006
|
+
foreach categoryopt $options($w,-categoryopts) {
|
1007
|
+
set categoryopt_vars($w,$token,$optnum) [lindex $categoryopt 2]
|
1008
|
+
incr optnum
|
1009
|
+
}
|
1010
|
+
|
1011
|
+
}
|
1012
|
+
|
1013
|
+
}
|
1014
|
+
|
1015
|
+
# Clear the text field
|
1016
|
+
$w.txt delete "$curr_index + 1 chars" "$curr_index + [expr [string length $token_str] + 1] chars"
|
1017
|
+
|
1018
|
+
# Make sure that the insertion cursor is visible
|
1019
|
+
$w.txt see 1.0
|
1020
|
+
update
|
1021
|
+
$w.txt see insert
|
1022
|
+
|
1023
|
+
# Finally, close the dropdown window if it is currently opened
|
1024
|
+
close_dropdown $w
|
1025
|
+
|
1026
|
+
return $token
|
1027
|
+
|
1028
|
+
}
|
1029
|
+
|
1030
|
+
###########################################################################
|
1031
|
+
# Deletes the token and replaces it with the original text.
|
1032
|
+
proc detokenize {w token} {
|
1033
|
+
|
1034
|
+
variable dont_tokenize
|
1035
|
+
variable active_token
|
1036
|
+
variable edit_info
|
1037
|
+
variable categoryopt_vars
|
1038
|
+
|
1039
|
+
# Save the category and category options information to the edit_info array
|
1040
|
+
set edit_info($w) [list [$token.cat.l1 cget -text]]
|
1041
|
+
set optnum 0
|
1042
|
+
while {[info exists categoryopt_vars($w,$token,$optnum)]} {
|
1043
|
+
lappend edit_info($w) $categoryopt_vars($w,$token,$optnum)
|
1044
|
+
array unset categoryopt_vars($w,$token,$optnum)
|
1045
|
+
incr optnum
|
1046
|
+
}
|
1047
|
+
|
1048
|
+
# Change the focus to the textbox prior to deleting the token to avoid
|
1049
|
+
# having the token be tokenized immediately
|
1050
|
+
focus $w.txt
|
1051
|
+
|
1052
|
+
# Get some information from the token (position and text)
|
1053
|
+
set token_pos [$w.txt index $token]
|
1054
|
+
set token_text [$token.val.l1 cget -text]
|
1055
|
+
|
1056
|
+
# Delete the token
|
1057
|
+
$w.txt delete $token
|
1058
|
+
|
1059
|
+
# Insert the label text
|
1060
|
+
$w.txt insert $token_pos $token_text
|
1061
|
+
|
1062
|
+
# Set the selection to the inserted text
|
1063
|
+
$w.txt tag add sel $token_pos "$token_pos + [string length $token_text] chars"
|
1064
|
+
|
1065
|
+
# Set the insertion cursor to the end of the text
|
1066
|
+
$w.txt mark set insert "$token_pos + [string length $token_text] chars"
|
1067
|
+
|
1068
|
+
# Make sure that we don't tokenize this string
|
1069
|
+
set dont_tokenize($w) 1
|
1070
|
+
|
1071
|
+
# Clear the active token
|
1072
|
+
set active_token($w) ""
|
1073
|
+
|
1074
|
+
}
|
1075
|
+
|
1076
|
+
###########################################################################
|
1077
|
+
# Removes a token from the entry field.
|
1078
|
+
proc delete_token {w token} {
|
1079
|
+
|
1080
|
+
variable options
|
1081
|
+
variable active_token
|
1082
|
+
|
1083
|
+
set last_pos ""
|
1084
|
+
|
1085
|
+
foreach token [$w.txt window names] {
|
1086
|
+
if {[$token.cat.l1 cget -bg] eq $options($w,-tokenselectbg)} {
|
1087
|
+
set last_pos [$w.txt index $token]
|
1088
|
+
$w.txt delete $token
|
1089
|
+
handle_state $w 1
|
1090
|
+
}
|
1091
|
+
}
|
1092
|
+
|
1093
|
+
# Set the insertion cursor to the end
|
1094
|
+
if {$last_pos ne ""} {
|
1095
|
+
$w.txt mark set insert $last_pos
|
1096
|
+
}
|
1097
|
+
|
1098
|
+
# Clear the active token
|
1099
|
+
set active_token($w) ""
|
1100
|
+
|
1101
|
+
# Set the focus back to the entry
|
1102
|
+
focus $w.txt
|
1103
|
+
|
1104
|
+
}
|
1105
|
+
|
1106
|
+
###########################################################################
|
1107
|
+
# This procedure is called when the text token receives the focus. It
|
1108
|
+
# deselects any currently selected tokens.
|
1109
|
+
proc deselect_token {w token} {
|
1110
|
+
|
1111
|
+
variable options
|
1112
|
+
variable img_blank
|
1113
|
+
variable active_token
|
1114
|
+
variable dont_deselect
|
1115
|
+
|
1116
|
+
# If we are disabled, do nothing
|
1117
|
+
if {$options($w,-state) eq "disabled"} {
|
1118
|
+
return
|
1119
|
+
}
|
1120
|
+
|
1121
|
+
if {$dont_deselect($w) == 0} {
|
1122
|
+
|
1123
|
+
# If we are selected, reverse the token
|
1124
|
+
if {[is_selected $token]} {
|
1125
|
+
reverse_token $w $token
|
1126
|
+
}
|
1127
|
+
|
1128
|
+
# Clear the active token
|
1129
|
+
set active_token($w) ""
|
1130
|
+
|
1131
|
+
} else {
|
1132
|
+
|
1133
|
+
set dont_deselect($w) 0
|
1134
|
+
|
1135
|
+
}
|
1136
|
+
|
1137
|
+
# Clear the arrow image
|
1138
|
+
$token.cat.l2.mid configure -image $img_blank
|
1139
|
+
$token.val.l2.mid configure -image $img_blank
|
1140
|
+
|
1141
|
+
}
|
1142
|
+
|
1143
|
+
###########################################################################
|
1144
|
+
# This procedure is called whenever a token is left-pressed. It allows a
|
1145
|
+
# drag and drop option to move the token.
|
1146
|
+
proc handle_token_press {w token x y} {
|
1147
|
+
|
1148
|
+
variable pressed_token
|
1149
|
+
variable options
|
1150
|
+
variable dont_tokenize
|
1151
|
+
|
1152
|
+
# If we are disabled, do nothing
|
1153
|
+
if {$options($w,-state) eq "disabled"} {
|
1154
|
+
return
|
1155
|
+
}
|
1156
|
+
|
1157
|
+
# Save the pressed token
|
1158
|
+
set pressed_token($w) [list $token $x]
|
1159
|
+
|
1160
|
+
# Close the dropdown list if it is opened
|
1161
|
+
close_dropdown $w
|
1162
|
+
|
1163
|
+
# If there is anything that needs to be tokenized, do it now
|
1164
|
+
set dont_tokenize($w) 0
|
1165
|
+
tokenize $w
|
1166
|
+
|
1167
|
+
}
|
1168
|
+
|
1169
|
+
###########################################################################
|
1170
|
+
# This procedure is called whenever a token is moved.
|
1171
|
+
proc handle_token_drag {w x y} {
|
1172
|
+
|
1173
|
+
variable pressed_token
|
1174
|
+
|
1175
|
+
if {$pressed_token($w) ne ""} {
|
1176
|
+
|
1177
|
+
# Make sure that the text widget has the focus
|
1178
|
+
focus $w.txt
|
1179
|
+
|
1180
|
+
# Change the cursor to a hand
|
1181
|
+
[lindex $pressed_token($w) 0] configure -cursor left_side
|
1182
|
+
|
1183
|
+
set index [$w.txt index @[expr [winfo x [lindex $pressed_token($w) 0]] + $x + 8],$y]
|
1184
|
+
|
1185
|
+
# Get the current location and set the insertion cursor
|
1186
|
+
if {$x < [lindex $pressed_token($w) 1]} {
|
1187
|
+
$w.txt mark set insert $index
|
1188
|
+
} else {
|
1189
|
+
$w.txt mark set insert "$index + 1 chars"
|
1190
|
+
}
|
1191
|
+
|
1192
|
+
}
|
1193
|
+
|
1194
|
+
}
|
1195
|
+
|
1196
|
+
###########################################################################
|
1197
|
+
# This procedure is called whenever a token is left-clicked. It changes
|
1198
|
+
# the state of the token.
|
1199
|
+
proc handle_token_release {w token x y} {
|
1200
|
+
|
1201
|
+
variable options
|
1202
|
+
variable pressed_token
|
1203
|
+
variable active_token
|
1204
|
+
|
1205
|
+
# If we are disabled, stop now.
|
1206
|
+
if {$options($w,-state) eq "disabled"} {
|
1207
|
+
return
|
1208
|
+
}
|
1209
|
+
|
1210
|
+
set start_index [$w.txt index $token]
|
1211
|
+
set end_index [$w.txt index @[expr [winfo x [lindex $pressed_token($w) 0]] + $x + 8],$y]
|
1212
|
+
|
1213
|
+
# If the token was not moved, treat the click as a selection/detokenization
|
1214
|
+
if {$start_index == $end_index} {
|
1215
|
+
|
1216
|
+
# If the token is currently selected, detokenize the selection
|
1217
|
+
if {$active_token($w) == [$w.txt index $token]} {
|
1218
|
+
|
1219
|
+
detokenize $w $token
|
1220
|
+
|
1221
|
+
# Clear the pressed token
|
1222
|
+
set pressed_token($w) ""
|
1223
|
+
|
1224
|
+
return
|
1225
|
+
|
1226
|
+
} else {
|
1227
|
+
|
1228
|
+
# Reverse the color scheme
|
1229
|
+
reverse_token $w $token
|
1230
|
+
|
1231
|
+
# Set the active token
|
1232
|
+
set active_token($w) [$w.txt index $token]
|
1233
|
+
|
1234
|
+
# Make sure that the current token keeps the focus
|
1235
|
+
focus $token
|
1236
|
+
|
1237
|
+
# Generate the TokenSearchSelected event
|
1238
|
+
event generate $w <<TokenSearchSelected>>
|
1239
|
+
|
1240
|
+
}
|
1241
|
+
|
1242
|
+
# Otherwise, the token has been dragged to a new position -- delete it and recreate it in the new position
|
1243
|
+
} else {
|
1244
|
+
|
1245
|
+
# Move the window to the new position
|
1246
|
+
if {$x < [lindex $pressed_token($w) 1]} {
|
1247
|
+
$w.txt window create $end_index -window $token -padx 2
|
1248
|
+
} else {
|
1249
|
+
$w.txt window create "$end_index + 1 chars" -window $token -padx 2
|
1250
|
+
}
|
1251
|
+
|
1252
|
+
# Delete the previous position if the starting position is less than the ending position
|
1253
|
+
if {$start_index < $end_index} {
|
1254
|
+
$w.txt delete $start_index
|
1255
|
+
}
|
1256
|
+
|
1257
|
+
# Update the tokenvar variable, if it has been set
|
1258
|
+
if {$options($w,-tokenvar) ne ""} {
|
1259
|
+
upvar #0 $options($w,-tokenvar) var
|
1260
|
+
set var [get_tokens $w]
|
1261
|
+
}
|
1262
|
+
|
1263
|
+
# Generate a TokenSearchModified event
|
1264
|
+
event generate $w <<TokenSearchModified>>
|
1265
|
+
|
1266
|
+
}
|
1267
|
+
|
1268
|
+
# Change cursor on pressed token to arrow
|
1269
|
+
[lindex $pressed_token($w) 0] configure -cursor top_left_arrow
|
1270
|
+
|
1271
|
+
# Clear the pressed token
|
1272
|
+
set pressed_token($w) ""
|
1273
|
+
|
1274
|
+
}
|
1275
|
+
|
1276
|
+
###########################################################################
|
1277
|
+
# Displays the popup menu for the given token.
|
1278
|
+
proc display_category_menu {w token} {
|
1279
|
+
|
1280
|
+
variable options
|
1281
|
+
variable dont_deselect
|
1282
|
+
|
1283
|
+
# Clear the menu
|
1284
|
+
$w.mnu delete 0 end
|
1285
|
+
|
1286
|
+
# Populate the menu with the given categories
|
1287
|
+
foreach category $options($w,-categories) {
|
1288
|
+
$w.mnu insert end command -label [lindex $category 0] -state disabled
|
1289
|
+
foreach value [lindex $category 1] {
|
1290
|
+
$w.mnu insert end command -label " $value" -command "$token.cat.l1 configure -text [list $value]; focus -force $token; event generate $w <<TokenSearchModified>>"
|
1291
|
+
}
|
1292
|
+
}
|
1293
|
+
|
1294
|
+
# Add the category options
|
1295
|
+
if {[llength $options($w,-categoryopts)] > 0} {
|
1296
|
+
$w.mnu insert end command -label "Category Options" -state disabled
|
1297
|
+
set optnum 0
|
1298
|
+
set last_type ""
|
1299
|
+
foreach categoryopt $options($w,-categoryopts) {
|
1300
|
+
if {[llength $categoryopt] != 3} {
|
1301
|
+
return -code error "Incorrect number of values specified in -categoryopt ($category). Must be {type {value(s)} default_value}"
|
1302
|
+
}
|
1303
|
+
if {[lindex $categoryopt 0] eq "checkbutton"} {
|
1304
|
+
if {$last_type eq "radiobutton"} {
|
1305
|
+
$w.mnu insert end separator
|
1306
|
+
}
|
1307
|
+
$w.mnu insert end checkbutton -label " [lindex $categoryopt 1]" -variable tokensearch::categoryopt_vars($w,$token,$optnum) -command "focus -force $token; event generate $w <<TokenSearchModified>>"
|
1308
|
+
} elseif {[lindex $categoryopt 0] eq "radiobutton"} {
|
1309
|
+
$w.mnu insert end separator
|
1310
|
+
foreach item [lindex $categoryopt 1] {
|
1311
|
+
$w.mnu insert end radiobutton -label " $item" -variable tokensearch::categoryopt_vars($w,$token,$optnum) -value $item -command "focus -force $token; event generate $w <<TokenSearchModified>>"
|
1312
|
+
}
|
1313
|
+
} else {
|
1314
|
+
return -code error "Illegal -categoryopts option type ([lindex $categoryopt 0])"
|
1315
|
+
}
|
1316
|
+
set last_type [lindex $categoryopt 0]
|
1317
|
+
incr optnum
|
1318
|
+
}
|
1319
|
+
}
|
1320
|
+
|
1321
|
+
# Specify that we should not perform a focusout deselection
|
1322
|
+
set dont_deselect($w) 1
|
1323
|
+
|
1324
|
+
# Display the popup menu
|
1325
|
+
tk_popup $w.mnu [winfo rootx $token.cat.l1] [expr [winfo rooty $token.cat.l1] + [winfo reqheight $token.cat.l1]]
|
1326
|
+
|
1327
|
+
}
|
1328
|
+
|
1329
|
+
###########################################################################
|
1330
|
+
# This procedure is called whenever an arrow token is left-clicked. It changes
|
1331
|
+
# the state of the token.
|
1332
|
+
proc handle_cat_arrow_click {w token x y} {
|
1333
|
+
|
1334
|
+
variable active_token
|
1335
|
+
variable options
|
1336
|
+
variable img_blank
|
1337
|
+
|
1338
|
+
# If we are disabled, stop now.
|
1339
|
+
if {$options($w,-state) eq "disabled"} {
|
1340
|
+
return
|
1341
|
+
}
|
1342
|
+
|
1343
|
+
if {[$token.cat.l2.mid cget -image] eq $img_blank} {
|
1344
|
+
handle_token_press $w $token $x $y
|
1345
|
+
handle_token_release $w $token $x $y
|
1346
|
+
} else {
|
1347
|
+
display_category_menu $w $token
|
1348
|
+
}
|
1349
|
+
|
1350
|
+
}
|
1351
|
+
|
1352
|
+
###########################################################################
|
1353
|
+
# Populates the dropdown listbox with the items from the -historyvar list
|
1354
|
+
# and displays the listbox.
|
1355
|
+
proc display_dropdown_items {w token} {
|
1356
|
+
|
1357
|
+
variable options
|
1358
|
+
|
1359
|
+
if {[info exists options($w,-historyvar)] && ($options($w,-historyvar) ne "")} {
|
1360
|
+
|
1361
|
+
upvar #0 $options($w,-historyvar) history
|
1362
|
+
|
1363
|
+
# Remove all of the items from the dropdown list
|
1364
|
+
$w.top.list delete 0 end
|
1365
|
+
|
1366
|
+
# Populate the dropdown list with the list of items from historyvar
|
1367
|
+
eval "$w.top.list insert end $history"
|
1368
|
+
|
1369
|
+
# Activate and select the first item in the list
|
1370
|
+
$w.top.list activate 0
|
1371
|
+
$w.top.list selection set 0
|
1372
|
+
|
1373
|
+
# Show the dropdown list
|
1374
|
+
open_dropdown $w $token
|
1375
|
+
|
1376
|
+
}
|
1377
|
+
|
1378
|
+
}
|
1379
|
+
|
1380
|
+
###########################################################################
|
1381
|
+
# This procedure is called whenever an arrow token in the value portion of
|
1382
|
+
# the token is left-clicked. It pops down a search history drop-down listbox.
|
1383
|
+
proc handle_val_arrow_click {w token x y} {
|
1384
|
+
|
1385
|
+
variable active_token
|
1386
|
+
variable options
|
1387
|
+
variable img_blank
|
1388
|
+
|
1389
|
+
# If we are disabled, stop now.
|
1390
|
+
if {$options($w,-state) eq "disabled"} {
|
1391
|
+
return
|
1392
|
+
}
|
1393
|
+
|
1394
|
+
if {[$token.val.l2.mid cget -image] eq $img_blank} {
|
1395
|
+
handle_token_press $w $token $x $y
|
1396
|
+
handle_token_release $w $token $x $y
|
1397
|
+
} else {
|
1398
|
+
display_dropdown_items $w $token
|
1399
|
+
}
|
1400
|
+
|
1401
|
+
}
|
1402
|
+
|
1403
|
+
###########################################################################
|
1404
|
+
# This procedirue is called when the cursor enters a token area.
|
1405
|
+
proc handle_token_enter {w token} {
|
1406
|
+
|
1407
|
+
variable options
|
1408
|
+
variable img_arrow
|
1409
|
+
|
1410
|
+
# If we are disabled, do nothing
|
1411
|
+
if {$options($w,-state) eq "disabled"} {
|
1412
|
+
return
|
1413
|
+
}
|
1414
|
+
|
1415
|
+
# Change the cursor
|
1416
|
+
$token configure -cursor top_left_arrow
|
1417
|
+
|
1418
|
+
}
|
1419
|
+
|
1420
|
+
###########################################################################
|
1421
|
+
# This procedure is called when the cursor enters the category portion of
|
1422
|
+
# a token area.
|
1423
|
+
proc handle_category_enter {w token} {
|
1424
|
+
|
1425
|
+
variable options
|
1426
|
+
variable img_arrow
|
1427
|
+
|
1428
|
+
# If we are disabled, do nothing
|
1429
|
+
if {$options($w,-state) eq "disabled"} {
|
1430
|
+
return
|
1431
|
+
}
|
1432
|
+
|
1433
|
+
# Draw an arrow if we have categories
|
1434
|
+
if {[llength $options($w,-categories)] > 0} {
|
1435
|
+
$token.cat.l2.mid configure -image $img_arrow
|
1436
|
+
}
|
1437
|
+
|
1438
|
+
}
|
1439
|
+
|
1440
|
+
###########################################################################
|
1441
|
+
# This procedure is called when the cursor enters the value portion of a
|
1442
|
+
# token area.
|
1443
|
+
proc handle_value_enter {w token} {
|
1444
|
+
|
1445
|
+
variable options
|
1446
|
+
variable img_arrow
|
1447
|
+
|
1448
|
+
# If we are disabled, do nothing
|
1449
|
+
if {$options($w,-state) eq "disabled"} {
|
1450
|
+
return
|
1451
|
+
}
|
1452
|
+
|
1453
|
+
# Draw an arrow if we have history
|
1454
|
+
if {$options($w,-historyvar) ne ""} {
|
1455
|
+
upvar #0 $options($w,-historyvar) history
|
1456
|
+
if {[llength $history] > 0} {
|
1457
|
+
$token.val.l2.mid configure -image $img_arrow
|
1458
|
+
}
|
1459
|
+
}
|
1460
|
+
|
1461
|
+
}
|
1462
|
+
|
1463
|
+
###########################################################################
|
1464
|
+
# This procedure is called when the cursor leaves the category portion of
|
1465
|
+
# a token.
|
1466
|
+
proc handle_category_leave {w token} {
|
1467
|
+
|
1468
|
+
variable options
|
1469
|
+
variable img_arrow
|
1470
|
+
variable img_blank
|
1471
|
+
|
1472
|
+
# If we are disabled, do nothing
|
1473
|
+
if {$options($w,-state) eq "disabled"} {
|
1474
|
+
return
|
1475
|
+
}
|
1476
|
+
|
1477
|
+
if {([$token.cat.l2.mid cget -image] eq $img_arrow) && ([$token.cat.l2.mid cget -bg] eq [lindex $options($w,-tokenbg) 0])} {
|
1478
|
+
$token.cat.l2.mid configure -image $img_blank
|
1479
|
+
}
|
1480
|
+
|
1481
|
+
}
|
1482
|
+
|
1483
|
+
###########################################################################
|
1484
|
+
# This procedure is called when the cursor leaves the value portion of a
|
1485
|
+
# token.
|
1486
|
+
proc handle_value_leave {w token} {
|
1487
|
+
|
1488
|
+
variable options
|
1489
|
+
variable img_arrow
|
1490
|
+
variable img_blank
|
1491
|
+
|
1492
|
+
# If we are disabled, do nothing
|
1493
|
+
if {$options($w,-state) eq "disabled"} {
|
1494
|
+
return
|
1495
|
+
}
|
1496
|
+
|
1497
|
+
if {([$token.val.l2.mid cget -image] eq $img_arrow) && ([$token.val.l2.mid cget -bg] eq [lindex $options($w,-tokenbg) end])} {
|
1498
|
+
$token.val.l2.mid configure -image $img_blank
|
1499
|
+
}
|
1500
|
+
|
1501
|
+
}
|
1502
|
+
|
1503
|
+
###########################################################################
|
1504
|
+
# Calculates the geometry of the given window.
|
1505
|
+
proc compute_geometry {w} {
|
1506
|
+
|
1507
|
+
variable options
|
1508
|
+
|
1509
|
+
if {($options($w,-dropdownheight) == 0) && ($options($w,-dropdownmaxheight) != 0)} {
|
1510
|
+
set nitems [$w.top.list size]
|
1511
|
+
if {$nitems > $options($w,-dropdownmaxheight)} {
|
1512
|
+
$w.top.list configure -height $options($w,-dropdownmaxheight)
|
1513
|
+
} else {
|
1514
|
+
$w.top.list configure -height 0
|
1515
|
+
}
|
1516
|
+
update idletasks
|
1517
|
+
}
|
1518
|
+
|
1519
|
+
# Compute the height and width of the dropdown list
|
1520
|
+
set bd [$w.top cget -borderwidth]
|
1521
|
+
set height [expr [winfo reqheight $w.top] + $bd + $bd]
|
1522
|
+
set width [winfo width $w]
|
1523
|
+
|
1524
|
+
# Figure out where to place it on the screen
|
1525
|
+
set screen_width [winfo screenwidth $w]
|
1526
|
+
set screen_height [winfo screenheight $w]
|
1527
|
+
set rootx [winfo rootx $w]
|
1528
|
+
set rooty [winfo rooty $w]
|
1529
|
+
set vrootx [winfo vrootx $w]
|
1530
|
+
set vrooty [winfo vrooty $w]
|
1531
|
+
|
1532
|
+
set x [expr $rootx + $vrootx]
|
1533
|
+
set y [expr $rooty + $vrooty + [winfo reqheight $w] + 1]
|
1534
|
+
set bottom_edge [expr $y + $height]
|
1535
|
+
|
1536
|
+
# If it extends beyond our screen, trim the list and add a scrollbar
|
1537
|
+
if {$bottom_edge >= $screen_height} {
|
1538
|
+
set y [expr ($rooty - $height - 1) + $vrooty]
|
1539
|
+
if {$y < 0} {
|
1540
|
+
if {$rooty > [expr $screen_height / 2]} {
|
1541
|
+
set y 1
|
1542
|
+
set height [expr $rooty - 1 - $y]
|
1543
|
+
} else {
|
1544
|
+
set y [expr $rooty + $vrooty + [winfo reqheight $w] + 1]
|
1545
|
+
set height [expr $screen_height - $y]
|
1546
|
+
}
|
1547
|
+
handle_scrollbar $w crop
|
1548
|
+
}
|
1549
|
+
}
|
1550
|
+
|
1551
|
+
if {$y < 0} {
|
1552
|
+
set y 0
|
1553
|
+
set height $screen_height
|
1554
|
+
}
|
1555
|
+
|
1556
|
+
set geometry [format "=%dx%d+%d+%d" $width $height $x $y]
|
1557
|
+
|
1558
|
+
return $geometry
|
1559
|
+
|
1560
|
+
}
|
1561
|
+
|
1562
|
+
###########################################################################
|
1563
|
+
# Hides/Displays the scrollbar in the dropdown listbox.
|
1564
|
+
proc handle_scrollbar {w {action "unknown"}} {
|
1565
|
+
|
1566
|
+
variable options
|
1567
|
+
|
1568
|
+
if {$options($w,-dropdownheight) == 0} {
|
1569
|
+
set hlimit $options($w,-dropdownmaxheight)
|
1570
|
+
} else {
|
1571
|
+
set hlimit $options($w,-dropdownheight)
|
1572
|
+
}
|
1573
|
+
|
1574
|
+
switch $action {
|
1575
|
+
"grow" {
|
1576
|
+
if {($hlimit > 0) && ([$w.top.list size] > $hlimit)} {
|
1577
|
+
pack forget $w.top.list
|
1578
|
+
pack $w.top.vsb -side right -fill y -expand n
|
1579
|
+
pack $w.top.list -side left -fill both -expand y
|
1580
|
+
}
|
1581
|
+
}
|
1582
|
+
"shrink" {
|
1583
|
+
if {($hlimit > 0) && ([$w.top.list size] <= $hlimit)} {
|
1584
|
+
pack forget $w.top.vsb
|
1585
|
+
}
|
1586
|
+
}
|
1587
|
+
"crop" {
|
1588
|
+
pack forget $w.top.list
|
1589
|
+
pack $w.top.vsb -side right -fill y -expand n
|
1590
|
+
pack $w.top.list -side left -fill both -expand y
|
1591
|
+
}
|
1592
|
+
default {
|
1593
|
+
if {($hlimit > 0) && ([$w.top.list size] > $hlimit)} {
|
1594
|
+
pack forget $w.top.list
|
1595
|
+
pack $w.top.vsb -side right -fill y -expand n
|
1596
|
+
pack $w.top.list -side left -fill both -expand y
|
1597
|
+
} else {
|
1598
|
+
pack forget $w.top.vsb
|
1599
|
+
}
|
1600
|
+
}
|
1601
|
+
}
|
1602
|
+
|
1603
|
+
return ""
|
1604
|
+
|
1605
|
+
}
|
1606
|
+
|
1607
|
+
###########################################################################
|
1608
|
+
# This procedure is invoked by various events and displays the dropdown
|
1609
|
+
# listbox containing a list of selectable values.
|
1610
|
+
proc open_dropdown {w {token ""}} {
|
1611
|
+
|
1612
|
+
variable options
|
1613
|
+
variable old_focus
|
1614
|
+
variable old_grab
|
1615
|
+
variable dropdown_token
|
1616
|
+
|
1617
|
+
# If the user has not provided any values to display, skip opening the window
|
1618
|
+
if {$options($w,-historyvar) ne ""} {
|
1619
|
+
upvar #0 $options($w,-historyvar) historyvar
|
1620
|
+
if {[llength $historyvar] == 0} {
|
1621
|
+
return 0
|
1622
|
+
}
|
1623
|
+
}
|
1624
|
+
|
1625
|
+
# Update the scrollbar appropriately
|
1626
|
+
handle_scrollbar $w
|
1627
|
+
|
1628
|
+
# Compute the geometry of the window to pop up, set it, and force the window manager to
|
1629
|
+
# take notice
|
1630
|
+
set geometry [compute_geometry $w]
|
1631
|
+
wm geometry $w.top $geometry
|
1632
|
+
update idletasks
|
1633
|
+
|
1634
|
+
# If we are already open, stop
|
1635
|
+
if {[winfo ismapped $w.top]} {
|
1636
|
+
return 0
|
1637
|
+
}
|
1638
|
+
|
1639
|
+
# Set the reason
|
1640
|
+
set dropdown_token($w) $token
|
1641
|
+
|
1642
|
+
# Save the current focus
|
1643
|
+
set old_focus($w) [focus]
|
1644
|
+
|
1645
|
+
# Make the list pop up
|
1646
|
+
wm deiconify $w.top
|
1647
|
+
update idletasks
|
1648
|
+
raise $w.top
|
1649
|
+
|
1650
|
+
# Force the focus so we can handle keypress events for traversal
|
1651
|
+
if {$token eq ""} {
|
1652
|
+
focus -force $w.txt
|
1653
|
+
} else {
|
1654
|
+
focus -force $token
|
1655
|
+
}
|
1656
|
+
|
1657
|
+
# Save the current grab state
|
1658
|
+
set status "none"
|
1659
|
+
set grab [grab current $w]
|
1660
|
+
if {$grab != ""} {
|
1661
|
+
set status [grab status $grab]
|
1662
|
+
}
|
1663
|
+
set old_grab($w) [list $grab $status]
|
1664
|
+
unset grab status
|
1665
|
+
|
1666
|
+
grab -global $w
|
1667
|
+
|
1668
|
+
# Fake the listbox into thinking it has focus.
|
1669
|
+
event generate $w.top.list <B1-Enter>
|
1670
|
+
|
1671
|
+
return 1
|
1672
|
+
|
1673
|
+
}
|
1674
|
+
|
1675
|
+
###########################################################################
|
1676
|
+
# This procedure is invoked when the user hits the Escape key or makes a
|
1677
|
+
# a listbox selection. It removes the dropdown listbox and returns the focus
|
1678
|
+
# to the text box.
|
1679
|
+
proc close_dropdown {w} {
|
1680
|
+
|
1681
|
+
variable old_focus
|
1682
|
+
variable old_grab
|
1683
|
+
variable dropdown_token
|
1684
|
+
|
1685
|
+
# If the window is already unmapped, stop
|
1686
|
+
if {![winfo ismapped $w.top]} {
|
1687
|
+
return 0
|
1688
|
+
}
|
1689
|
+
|
1690
|
+
catch { focus $old_focus($w) } result
|
1691
|
+
catch { grab release $w }
|
1692
|
+
catch {
|
1693
|
+
set status [lindex $old_grab($w) 1]
|
1694
|
+
if {$status eq "global"} {
|
1695
|
+
grab -global [lindex $old_grab($w) 0]
|
1696
|
+
} elseif {$status eq "local"} {
|
1697
|
+
grab [lindex $old_grab($w) 0]
|
1698
|
+
}
|
1699
|
+
unset status
|
1700
|
+
}
|
1701
|
+
|
1702
|
+
# Clear the reason
|
1703
|
+
set dropdown_token($w) ""
|
1704
|
+
|
1705
|
+
# Hide the listbox
|
1706
|
+
wm withdraw $w.top
|
1707
|
+
|
1708
|
+
# Magic Tcl stuff (see tk.tcl in the distribution lib directory)
|
1709
|
+
tk::CancelRepeat
|
1710
|
+
|
1711
|
+
return 1
|
1712
|
+
|
1713
|
+
}
|
1714
|
+
|
1715
|
+
###########################################################################
|
1716
|
+
# This is called whenever the cursor moves over the listbox.
|
1717
|
+
proc motion_dropdown {w x y} {
|
1718
|
+
|
1719
|
+
# Set the cursor
|
1720
|
+
$w.top.list configure -cursor ""
|
1721
|
+
|
1722
|
+
# Clear the selections
|
1723
|
+
$w.top.list selection clear 0 end
|
1724
|
+
|
1725
|
+
# Set the selection to the current index
|
1726
|
+
$w.top.list selection set @$x,$y
|
1727
|
+
|
1728
|
+
}
|
1729
|
+
|
1730
|
+
###########################################################################
|
1731
|
+
# Returns a sorted list of all of the token values.
|
1732
|
+
proc get_tokens {w} {
|
1733
|
+
|
1734
|
+
variable categoryopt_vars
|
1735
|
+
|
1736
|
+
set tokens [list]
|
1737
|
+
set indices [list]
|
1738
|
+
|
1739
|
+
foreach token [$w.txt window names] {
|
1740
|
+
lappend indices [list [$w.txt index $token] $token]
|
1741
|
+
}
|
1742
|
+
|
1743
|
+
foreach index [lsort -real -index 0 $indices] {
|
1744
|
+
set values [list [[lindex $index 1].cat.l1 cget -text] [[lindex $index 1].val.l1 cget -text]]
|
1745
|
+
set optnum 0
|
1746
|
+
while {[info exists categoryopt_vars($w,[lindex $index 1],$optnum)]} {
|
1747
|
+
lappend values $categoryopt_vars($w,[lindex $index 1],$optnum)
|
1748
|
+
incr optnum
|
1749
|
+
}
|
1750
|
+
lappend tokens $values
|
1751
|
+
}
|
1752
|
+
|
1753
|
+
return $tokens
|
1754
|
+
|
1755
|
+
}
|
1756
|
+
|
1757
|
+
###########################################################################
|
1758
|
+
# Handles the current state of the widget (empty/non-empty) and handles
|
1759
|
+
# any watermark display (or removal of the display).
|
1760
|
+
proc handle_state {w keyed} {
|
1761
|
+
|
1762
|
+
variable state
|
1763
|
+
variable options
|
1764
|
+
|
1765
|
+
# If we are in the empty state
|
1766
|
+
if {$state($w) eq "empty"} {
|
1767
|
+
|
1768
|
+
$w.txt delete 1.0 end
|
1769
|
+
|
1770
|
+
if {$keyed} {
|
1771
|
+
set state($w) "non-empty"
|
1772
|
+
$w.txt configure -foreground $options($w,-foreground)
|
1773
|
+
} else {
|
1774
|
+
$w.txt configure -foreground $options($w,-watermarkforeground)
|
1775
|
+
$w.txt insert end $options($w,-watermark)
|
1776
|
+
$w.txt mark set insert 1.0
|
1777
|
+
}
|
1778
|
+
|
1779
|
+
# Otherwise, we are in the not-empty state
|
1780
|
+
} elseif {$state($w) eq "non-empty"} {
|
1781
|
+
|
1782
|
+
# If the widget is empty, set the state to empty and fill it with the
|
1783
|
+
# empty string.
|
1784
|
+
if {([string trim [$w.txt get 1.0 end]] eq "") && ([llength [$w.txt window names]] == 0)} {
|
1785
|
+
set state($w) "empty"
|
1786
|
+
$w.txt configure -foreground $options($w,-watermarkforeground)
|
1787
|
+
$w.txt insert end $options($w,-watermark)
|
1788
|
+
$w.txt mark set insert 1.0
|
1789
|
+
}
|
1790
|
+
|
1791
|
+
}
|
1792
|
+
|
1793
|
+
}
|
1794
|
+
|
1795
|
+
###########################################################################
|
1796
|
+
# Converts an entry index to a text index.
|
1797
|
+
proc entry_to_text_index {w index} {
|
1798
|
+
|
1799
|
+
set offset ""
|
1800
|
+
if {[regexp {(.+)\s*\-\s*(\d+)$} $index -> index offset]} {
|
1801
|
+
set offset " - $offset chars"
|
1802
|
+
}
|
1803
|
+
|
1804
|
+
if {[string is integer $index]} {
|
1805
|
+
return "1.$index$offset"
|
1806
|
+
} elseif {$index eq "anchor"} {
|
1807
|
+
return -code error "Illegal tokensearch index ($index)"
|
1808
|
+
} elseif {$index eq "end"} {
|
1809
|
+
return "1.end$offset"
|
1810
|
+
} elseif {$index eq "insert"} {
|
1811
|
+
return "[$w.txt index insert]$offset"
|
1812
|
+
} elseif {$index eq "sel.first"} {
|
1813
|
+
return "[lindex [$w.txt tag ranges sel] 0]$offset"
|
1814
|
+
} elseif {$index eq "sel.last"} {
|
1815
|
+
return "[lindex [$w.txt tag ranges sel] 1]$offset"
|
1816
|
+
} else {
|
1817
|
+
return -code error "Illegal tokensearch index ($index)"
|
1818
|
+
}
|
1819
|
+
|
1820
|
+
}
|
1821
|
+
|
1822
|
+
###########################################################################
|
1823
|
+
# Handles all commands.
|
1824
|
+
proc widget_cmd {w args} {
|
1825
|
+
|
1826
|
+
if {[llength $args] == 0} {
|
1827
|
+
return -code error "tokensearch widget called without a command"
|
1828
|
+
}
|
1829
|
+
|
1830
|
+
set cmd [lindex $args 0]
|
1831
|
+
set opts [lrange $args 1 end]
|
1832
|
+
|
1833
|
+
switch $cmd {
|
1834
|
+
configure { eval "tokensearch::configure 0 $w $opts" }
|
1835
|
+
cget { return [eval "tokensearch::cget $w $opts"] }
|
1836
|
+
tokenindex { return [eval "tokensearch::tokenindex $w $opts"] }
|
1837
|
+
tokenselection { eval "tokensearch::tokenselection $w $opts" }
|
1838
|
+
tokenget { return [eval "tokensearch::get_tokens $w"] }
|
1839
|
+
tokenconfigure { eval "tokensearch::tokenconfigure $w $opts" }
|
1840
|
+
tokencget { return [eval "tokensearch::tokencget $w $opts" }
|
1841
|
+
tokeninsert { eval "tokensearch::tokeninsert $w $opts" }
|
1842
|
+
tokendelete { eval "tokensearch::tokendelete $w $opts" }
|
1843
|
+
tokenedit { eval "tokensearch::tokenedit $w $opts" }
|
1844
|
+
entryget { return [$w.txt get 1.0 end] }
|
1845
|
+
insert { eval "tokensearch::insert $w $opts" }
|
1846
|
+
delete { eval "tokensearch::delete $w $opts" }
|
1847
|
+
get { return [eval "tokensearch::get $w $opts"] }
|
1848
|
+
icursor { eval "tokensearch::icursor $w $opts" }
|
1849
|
+
index { return [eval "tokensearch::index $w $opts"] }
|
1850
|
+
default { eval "$w.txt $cmd $opts" }
|
1851
|
+
}
|
1852
|
+
|
1853
|
+
}
|
1854
|
+
|
1855
|
+
###########################################################################
|
1856
|
+
# USER COMMANDS
|
1857
|
+
###########################################################################
|
1858
|
+
|
1859
|
+
###########################################################################
|
1860
|
+
# Main configuration routine.
|
1861
|
+
proc configure {initialize w args} {
|
1862
|
+
|
1863
|
+
variable options
|
1864
|
+
variable text_options
|
1865
|
+
variable widget_options
|
1866
|
+
variable state
|
1867
|
+
|
1868
|
+
if {([llength $args] == 0) && !$initialize} {
|
1869
|
+
|
1870
|
+
set results [list]
|
1871
|
+
|
1872
|
+
foreach opt [lsort [array names widget_options]] {
|
1873
|
+
if {[llength $widget_options($opt)] == 2} {
|
1874
|
+
set opt_name [lindex $widget_options($opt) 0]
|
1875
|
+
set opt_class [lindex $widget_options($opt) 1]
|
1876
|
+
set opt_default [option get $w $opt_name $opt_class]
|
1877
|
+
if {[info exists text_options($opt)]} {
|
1878
|
+
lappend results [list $opt $opt_name $opt_class $opt_default [$w.txt cget $opt]]
|
1879
|
+
} elseif {[info exists options($w,$opt)]} {
|
1880
|
+
lappend results [list $opt $opt_name $opt_class $opt_default $options($w,$opt)]
|
1881
|
+
} else {
|
1882
|
+
lappend results [list $opt $opt_name $opt_class $opt_default ""]
|
1883
|
+
}
|
1884
|
+
}
|
1885
|
+
}
|
1886
|
+
|
1887
|
+
return $results
|
1888
|
+
|
1889
|
+
} elseif {([llength $args] == 1) && !$initialize} {
|
1890
|
+
|
1891
|
+
set opt [lindex $args 0]
|
1892
|
+
|
1893
|
+
if {[info exists widget_options($opt)]} {
|
1894
|
+
if {[llength $widget_options($opt)] == 1} {
|
1895
|
+
set opt [lindex $widget_options($opt) 0]
|
1896
|
+
}
|
1897
|
+
set opt_name [lindex $widget_options($opt) 0]
|
1898
|
+
set opt_class [lindex $widget_options($opt) 1]
|
1899
|
+
set opt_default [option get $w $opt_name $opt_class]
|
1900
|
+
if {[info exists text_options($opt)]} {
|
1901
|
+
return [list $opt $opt_name $opt_class $opt_default [$w.txt cget $opt]]
|
1902
|
+
} elseif {[info exists options($w,$opt)]} {
|
1903
|
+
return [list $opt $opt_name $opt_class $opt_default $options($w,$opt)]
|
1904
|
+
} else {
|
1905
|
+
return [list $opt $opt_name $opt_class $opt_default ""]
|
1906
|
+
}
|
1907
|
+
}
|
1908
|
+
|
1909
|
+
return -code error "TokenSearch configuration option [lindex $args 0] does not exist"
|
1910
|
+
|
1911
|
+
} else {
|
1912
|
+
|
1913
|
+
# Save the original contents
|
1914
|
+
array set orig_options [array get options]
|
1915
|
+
|
1916
|
+
# Parse the arguments
|
1917
|
+
foreach {name value} $args {
|
1918
|
+
if {[info exists text_options($name)]} {
|
1919
|
+
$w.txt configure $name $value
|
1920
|
+
} elseif {[info exists options($w,$name)]} {
|
1921
|
+
set options($w,$name) $value
|
1922
|
+
} else {
|
1923
|
+
return -code error "Illegal option given to the tokensearch configure command ($name)"
|
1924
|
+
}
|
1925
|
+
}
|
1926
|
+
|
1927
|
+
# Update the GUI widgets
|
1928
|
+
# $w.txt configure -fg $options($w,-foreground) -bg $options($w,-background) -relief $options($w,-relief) -state $options($w,-state)
|
1929
|
+
if {$options($w,-width) ne ""} {
|
1930
|
+
$w.txt configure -width $options($w,-width)
|
1931
|
+
}
|
1932
|
+
if {$options($w,-height) ne ""} {
|
1933
|
+
$w.txt configure -height $options($w,-height)
|
1934
|
+
}
|
1935
|
+
$w.mnu configure -bg $options($w,-categorybg) -bd $options($w,-categorybd) -relief $options($w,-categoryrelief) -font $options($w,-categoryfont) -cursor $options($w,-categorycursor)
|
1936
|
+
|
1937
|
+
if {[string is boolean $options($w,-wrap)]} {
|
1938
|
+
if {$options($w,-wrap)} {
|
1939
|
+
$w.txt configure -wrap word
|
1940
|
+
} else {
|
1941
|
+
$w.txt configure -wrap none
|
1942
|
+
}
|
1943
|
+
} else {
|
1944
|
+
set options($w,-wrap) $orig_options($w,-wrap)
|
1945
|
+
return -code error "Value for -wrap option is not a boolean value ($options($w,-wrap))"
|
1946
|
+
}
|
1947
|
+
|
1948
|
+
# If the textbox is empty, configure it for the watermark
|
1949
|
+
if {$options($w,-watermark) ne ""} {
|
1950
|
+
set state($w) "empty"
|
1951
|
+
}
|
1952
|
+
handle_state $w 0
|
1953
|
+
|
1954
|
+
if {($orig_options($w,-dropdownheight) ne $options($w,-dropdownheight)) || \
|
1955
|
+
($orig_options($w,-dropdownmaxheight) ne $options($w,-dropdownmaxheight))} {
|
1956
|
+
handle_scrollbar $w
|
1957
|
+
}
|
1958
|
+
|
1959
|
+
# Update the tokens, if necessary
|
1960
|
+
if {($orig_options($w,-tokenbg) ne $options($w,-tokenbg)) || ($orig_options($w,-tokenfg) ne $options($w,-tokenfg)) || \
|
1961
|
+
($orig_options($w,-tokenselectbg) ne $options($w,-tokenselectbg)) || ($orig_options($w,-tokenselectfg) ne $options($w,-tokenselectfg)) || \
|
1962
|
+
($orig_options($w,-tokenshape) ne $options($w,-tokenshape))} {
|
1963
|
+
set token_num [llength [$w.txt window names]]
|
1964
|
+
for {set i 0} {$i < $token_num} {incr i} {
|
1965
|
+
tokenconfigure $w $i -bg $options($w,-tokenbg) -fg $options($w,-tokenfg) \
|
1966
|
+
-selectbg $options($w,-tokenselectbg) -selectfg $options($w,-tokenselectfg) \
|
1967
|
+
-shape $options($w,-tokenshape)
|
1968
|
+
}
|
1969
|
+
}
|
1970
|
+
|
1971
|
+
}
|
1972
|
+
|
1973
|
+
}
|
1974
|
+
|
1975
|
+
###########################################################################
|
1976
|
+
# Gets configuration option value(s).
|
1977
|
+
proc cget {w args} {
|
1978
|
+
|
1979
|
+
variable options
|
1980
|
+
variable text_options
|
1981
|
+
|
1982
|
+
if {[llength $args] != 1} {
|
1983
|
+
return -code error "Incorrect number of parameters given to the tokensearch cget command"
|
1984
|
+
}
|
1985
|
+
|
1986
|
+
if {[info exists text_options([lindex $args 0])]} {
|
1987
|
+
return [$w.txt cget [lindex $args 0]]
|
1988
|
+
} elseif {[info exists options($w,[lindex $args 0])]} {
|
1989
|
+
return $options($w,[lindex $args 0])
|
1990
|
+
} else {
|
1991
|
+
return -code error "Illegal option given to the tokensearch cget command ([lindex $args 0])"
|
1992
|
+
}
|
1993
|
+
|
1994
|
+
}
|
1995
|
+
|
1996
|
+
###########################################################################
|
1997
|
+
# Configures the token located at the given index.
|
1998
|
+
proc tokenconfigure {w args} {
|
1999
|
+
|
2000
|
+
variable token_shapes
|
2001
|
+
|
2002
|
+
if {[expr [llength $args] % 2] == 0} {
|
2003
|
+
return -code error "Incorrect number of parameters given to the tokenconfigure command"
|
2004
|
+
}
|
2005
|
+
|
2006
|
+
set index [index_to_position $w [lindex $args 0]]
|
2007
|
+
|
2008
|
+
# Retrieve the current token pathname
|
2009
|
+
set token [$w.txt window cget $index -window]
|
2010
|
+
|
2011
|
+
# Figure out if the current token is selected or not
|
2012
|
+
set selected [is_selected $token]
|
2013
|
+
|
2014
|
+
set redraw 0
|
2015
|
+
set resize 0
|
2016
|
+
|
2017
|
+
foreach {option value} [lrange $args 1 end] {
|
2018
|
+
switch $option {
|
2019
|
+
-bg -
|
2020
|
+
-background {
|
2021
|
+
if {$selected} {
|
2022
|
+
$token.cat.l2.top configure -fg [lindex $value 0]
|
2023
|
+
$token.val.l2.top configure -fg [lindex $value end]
|
2024
|
+
} else {
|
2025
|
+
$token.ll configure -bg [lindex $value 0]
|
2026
|
+
$token.cat.l1 configure -bg [lindex $value 0]
|
2027
|
+
$token.cat.l2 configure -bg [lindex $value 0]
|
2028
|
+
$token.cat.l2.mid configure -bg [lindex $value 0]
|
2029
|
+
$token.val.l1 configure -bg [lindex $value end]
|
2030
|
+
$token.val.l2 configure -bg [lindex $value end]
|
2031
|
+
$token.val.l2.mid configure -bg [lindex $value end]
|
2032
|
+
$token.lr configure -bg [lindex $value end]
|
2033
|
+
set redraw 1
|
2034
|
+
}
|
2035
|
+
}
|
2036
|
+
-fg -
|
2037
|
+
-foreground {
|
2038
|
+
if {$selected} {
|
2039
|
+
$token.cat.l2.mid configure -fg [lindex $value 0]
|
2040
|
+
$token.val.l2.mid configure -fg [lindex $value end]
|
2041
|
+
} else {
|
2042
|
+
$token.cat.l1 configure -fg [lindex $value 0]
|
2043
|
+
$token.val.l1 configure -fg [lindex $value end]
|
2044
|
+
set redraw 1
|
2045
|
+
}
|
2046
|
+
}
|
2047
|
+
-bordercolor {
|
2048
|
+
if {$selected} {
|
2049
|
+
$token.cat.l2.bot configure -fg [lindex $value 0]
|
2050
|
+
$token.val.l2.bot configure -fg [lindex $value end]
|
2051
|
+
} else {
|
2052
|
+
$token.cat.l2.top configure -bg [lindex $value 0]
|
2053
|
+
$token.cat.l2.bot configure -bg [lindex $value 0]
|
2054
|
+
$token.val.l2.top configure -bg [lindex $value end]
|
2055
|
+
$token.val.l2.bot configure -bg [lindex $value end]
|
2056
|
+
set redraw 1
|
2057
|
+
}
|
2058
|
+
}
|
2059
|
+
-shape {
|
2060
|
+
if {([llength $value] < 0) || ([llength $value] > 2)} {
|
2061
|
+
return -code error "ERROR: Token -shape list must be contain either 1 or 2 values"
|
2062
|
+
}
|
2063
|
+
foreach val $value {
|
2064
|
+
switch $value {
|
2065
|
+
pill -
|
2066
|
+
tag -
|
2067
|
+
square -
|
2068
|
+
eased -
|
2069
|
+
ticket {}
|
2070
|
+
default {
|
2071
|
+
return -code error "ERROR: Token -shape is an unsupported value (pill, tag, square, eased, ticket)"
|
2072
|
+
}
|
2073
|
+
}
|
2074
|
+
set token_shapes($token) $value
|
2075
|
+
set redraw 1
|
2076
|
+
}
|
2077
|
+
}
|
2078
|
+
-selectbg -
|
2079
|
+
-selectbackground {
|
2080
|
+
if {$selected} {
|
2081
|
+
$token.ll configure -bg [lindex $value 0]
|
2082
|
+
$token.cat.l1 configure -bg [lindex $value 0]
|
2083
|
+
$token.cat.l2 configure -bg [lindex $value 0]
|
2084
|
+
$token.cat.l2.mid configure -bg [lindex $value 0]
|
2085
|
+
$token.val.l1 configure -bg [lindex $value end]
|
2086
|
+
$token.val.l2 configure -bg [lindex $value end]
|
2087
|
+
$token.val.l2.mid configure -bg [lindex $value end]
|
2088
|
+
$token.lr configure -bg [lindex $value end]
|
2089
|
+
set redraw 1
|
2090
|
+
} else {
|
2091
|
+
$token.cat.l2.top configure -fg [lindex $value 0]
|
2092
|
+
$token.val.l2.top configure -fg [lindex $value end]
|
2093
|
+
}
|
2094
|
+
}
|
2095
|
+
-selectfg -
|
2096
|
+
-selectforeground {
|
2097
|
+
if {$selected} {
|
2098
|
+
$token.cat.l1 configure -fg [lindex $value 0]
|
2099
|
+
$token.val.l1 configure -fg [lindex $value end]
|
2100
|
+
set redraw 1
|
2101
|
+
} else {
|
2102
|
+
$token.cat.l2.mid configure -fg [lindex $value 0]
|
2103
|
+
$token.val.l2.mid configure -fg [lindex $value end]
|
2104
|
+
}
|
2105
|
+
}
|
2106
|
+
-selectbordercolor {
|
2107
|
+
if {$selected} {
|
2108
|
+
$token.cat.l2.top configure -bg [lindex $value 0]
|
2109
|
+
$token.cat.l2.bot configure -bg [lindex $value 0]
|
2110
|
+
$token.val.l2.top configure -bg [lindex $value end]
|
2111
|
+
$token.val.l2.bot configure -bg [lindex $value end]
|
2112
|
+
set redraw 1
|
2113
|
+
} else {
|
2114
|
+
$token.cat.l2.bot configure -fg [lindex $value 0]
|
2115
|
+
$token.val.l2.bot configure -fg [lindex $value end]
|
2116
|
+
}
|
2117
|
+
}
|
2118
|
+
-categoryindex {
|
2119
|
+
$token.cat.l1 configure -text [lindex $options($w,-categories) $value]
|
2120
|
+
set redraw 1
|
2121
|
+
set resize 1
|
2122
|
+
}
|
2123
|
+
-value {
|
2124
|
+
$token.val.l1 configure -text $value
|
2125
|
+
set redraw 1
|
2126
|
+
set resize 1
|
2127
|
+
}
|
2128
|
+
default {
|
2129
|
+
return -code error "Illegal option to the tokenconfigure option ($option)"
|
2130
|
+
}
|
2131
|
+
}
|
2132
|
+
}
|
2133
|
+
|
2134
|
+
# If we need to redraw the token, do it now
|
2135
|
+
if {$redraw} {
|
2136
|
+
redraw_token $w $token $resize
|
2137
|
+
}
|
2138
|
+
|
2139
|
+
}
|
2140
|
+
|
2141
|
+
###########################################################################
|
2142
|
+
# Gets the configuration information located at the given index.
|
2143
|
+
proc tokencget {w args} {
|
2144
|
+
|
2145
|
+
variable token_shapes
|
2146
|
+
|
2147
|
+
if {[llength $args] != 2} {
|
2148
|
+
return -code error "Incorrect number of options given to the tokencget command"
|
2149
|
+
}
|
2150
|
+
|
2151
|
+
# Get the token index
|
2152
|
+
set index [index_to_position $w [lindex $args 0]]
|
2153
|
+
|
2154
|
+
# Get the token
|
2155
|
+
set token [$w.txt window cget $index -window]
|
2156
|
+
|
2157
|
+
# Figure out if the token is currently selected
|
2158
|
+
set selected [is_selected $token]
|
2159
|
+
|
2160
|
+
# Do an option lookup
|
2161
|
+
switch [lindex $args 1] {
|
2162
|
+
-bg -
|
2163
|
+
-background {
|
2164
|
+
if {$selected} {
|
2165
|
+
return [list [$token.cat.l2.top cget -fg] [$token.val.l2.top cget -fg]]
|
2166
|
+
} else {
|
2167
|
+
return [list [$token.cat.l1 cget -bg] [$token.val.l1 cget -bg]]
|
2168
|
+
}
|
2169
|
+
}
|
2170
|
+
-fg -
|
2171
|
+
-foreground {
|
2172
|
+
if {$selected} {
|
2173
|
+
return [list [$token.cat.l2.mid cget -fg] [$token.val.l2.mid cget -fg]]
|
2174
|
+
} else {
|
2175
|
+
return [list [$token.cat.l1 cget -fg] [$token.val.l1 cget -fg]]
|
2176
|
+
}
|
2177
|
+
}
|
2178
|
+
-bordercolor {
|
2179
|
+
if {$selected} {
|
2180
|
+
return [list [$token.cat.l2.bot cget -fg] [$token.val.l2.bot cget -fg]]
|
2181
|
+
} else {
|
2182
|
+
return [list [$token.cat.l2.top cget -bg] [$token.val.l2.top cget -bg]]
|
2183
|
+
}
|
2184
|
+
}
|
2185
|
+
-shape {
|
2186
|
+
return $token_shapes($token)
|
2187
|
+
}
|
2188
|
+
-selectbg -
|
2189
|
+
-selectbackground {
|
2190
|
+
if {$selected} {
|
2191
|
+
return [list [$token.cat.l1 cget -bg] [$token.val.l1 cget -bg]]
|
2192
|
+
} else {
|
2193
|
+
return [list [$token.cat.l2.top cget -fg] [$token.val.l2.top cget -fg]]
|
2194
|
+
}
|
2195
|
+
}
|
2196
|
+
-selectfg -
|
2197
|
+
-selectforeground {
|
2198
|
+
if {$selected} {
|
2199
|
+
return [list [$token.cat.l1 cget -fg] [$token.val.l1 cget -fg]]
|
2200
|
+
} else {
|
2201
|
+
return [list [$token.cat.l2.mid cget -fg] [$token.val.l2.mid cget -fg]]
|
2202
|
+
}
|
2203
|
+
}
|
2204
|
+
-selectbordercolor {
|
2205
|
+
if {$selected} {
|
2206
|
+
return [list [$token.cat.l2.top cget -bg] [$token.val.l2.top cget -bg]]
|
2207
|
+
} else {
|
2208
|
+
return [list [$token.cat.l2.bot cget -fg] [$token.val.l2.bot cget -fg]]
|
2209
|
+
}
|
2210
|
+
}
|
2211
|
+
-categoryindex {
|
2212
|
+
return [lsearch $options($w,-categories) [$token.cat.l1 cget -text]]
|
2213
|
+
}
|
2214
|
+
-value {
|
2215
|
+
return [$token.val.l1 cget -text]
|
2216
|
+
}
|
2217
|
+
default {
|
2218
|
+
return -code error "Illegal option to the tokencget option ([lindex $args 1])"
|
2219
|
+
}
|
2220
|
+
|
2221
|
+
}
|
2222
|
+
|
2223
|
+
}
|
2224
|
+
|
2225
|
+
###########################################################################
|
2226
|
+
# Returns the numerical index of the specified index.
|
2227
|
+
proc tokenindex {w args} {
|
2228
|
+
|
2229
|
+
variable active_token
|
2230
|
+
|
2231
|
+
if {[llength $args] != 1} {
|
2232
|
+
return -code error "Illegal options to the tokenindex command"
|
2233
|
+
} else {
|
2234
|
+
set index [lindex $args 0]
|
2235
|
+
if {$index eq "active"} {
|
2236
|
+
if {$active_token($w) eq ""} {
|
2237
|
+
return -1
|
2238
|
+
} else {
|
2239
|
+
return $active_token($w)
|
2240
|
+
}
|
2241
|
+
} else {
|
2242
|
+
return [lindex [$w.txt window names] $index]
|
2243
|
+
}
|
2244
|
+
}
|
2245
|
+
|
2246
|
+
}
|
2247
|
+
|
2248
|
+
###########################################################################
|
2249
|
+
# Handles the tokenselection command.
|
2250
|
+
proc tokenselection {w args} {
|
2251
|
+
|
2252
|
+
variable active_token
|
2253
|
+
variable options
|
2254
|
+
|
2255
|
+
if {[llength $args] == 0} {
|
2256
|
+
|
2257
|
+
return -code error "Incorrect number of options to the tokenselection command"
|
2258
|
+
|
2259
|
+
} else {
|
2260
|
+
|
2261
|
+
switch [lindex $args 0] {
|
2262
|
+
get {
|
2263
|
+
}
|
2264
|
+
clear {
|
2265
|
+
set start_index [index_to_position $w [lindex $args 1]]
|
2266
|
+
set end_index [index_to_position $w [lindex $args 2]]
|
2267
|
+
set index $start_index
|
2268
|
+
foreach token [lrange [$w.txt window names] $start_index $end_index] {
|
2269
|
+
$token configure -fg $options($w,-tokenfg) -bg $options($w,-tokenbg)
|
2270
|
+
incr start_index
|
2271
|
+
}
|
2272
|
+
set active_token($w) ""
|
2273
|
+
}
|
2274
|
+
set {
|
2275
|
+
set start_index [index_to_position $w [lindex $args 1]]
|
2276
|
+
set end_index [index_to_position $w [lindex $args 2]]
|
2277
|
+
set index $start_index
|
2278
|
+
foreach token [lrange [$w.txt window names] $start_index $end_index] {
|
2279
|
+
$token configure -fg $options($w,-tokenselectfg) -bg $options($w,-tokenselectbg)
|
2280
|
+
incr index
|
2281
|
+
}
|
2282
|
+
set active_token($w) $start_index
|
2283
|
+
}
|
2284
|
+
default {
|
2285
|
+
return -code error "Illegal token selection command ([lindex $args 0])"
|
2286
|
+
}
|
2287
|
+
}
|
2288
|
+
|
2289
|
+
}
|
2290
|
+
|
2291
|
+
}
|
2292
|
+
|
2293
|
+
###########################################################################
|
2294
|
+
# Handles the token insertion command.
|
2295
|
+
proc tokeninsert {w args} {
|
2296
|
+
|
2297
|
+
variable options
|
2298
|
+
variable dont_tokenize
|
2299
|
+
variable categoryopt_vars
|
2300
|
+
|
2301
|
+
if {[llength $args] != 2} {
|
2302
|
+
return -code error "Incorrect number of options to the tokeninsert command"
|
2303
|
+
}
|
2304
|
+
|
2305
|
+
set index [index_to_position $w [lindex $args 0]]
|
2306
|
+
|
2307
|
+
if {$index eq ""} {
|
2308
|
+
set index [$w.txt index "1.[lindex $args 0]"]
|
2309
|
+
}
|
2310
|
+
|
2311
|
+
# Make sure that all inserted text is tokenized
|
2312
|
+
set dont_tokenize($w) 0
|
2313
|
+
|
2314
|
+
# Create the tokens (we do this for performance purposes)
|
2315
|
+
foreach value [lreverse [lindex $args 1]] {
|
2316
|
+
|
2317
|
+
# Handle the current state
|
2318
|
+
handle_state $w 1
|
2319
|
+
|
2320
|
+
# Insert the text into the widget
|
2321
|
+
$w.txt insert $index [lindex $value 1]
|
2322
|
+
|
2323
|
+
# Turn the text into a token
|
2324
|
+
if {[set token [tokenize $w]] ne ""} {
|
2325
|
+
|
2326
|
+
# Set the category
|
2327
|
+
$token.cat.l1 configure -text [lindex $value 0]
|
2328
|
+
|
2329
|
+
# Set the category options
|
2330
|
+
set optnum 0
|
2331
|
+
foreach opt [lrange $value 2 end] {
|
2332
|
+
set categoryopt_vars($w,$token,$optnum) $opt
|
2333
|
+
incr optnum
|
2334
|
+
}
|
2335
|
+
|
2336
|
+
}
|
2337
|
+
|
2338
|
+
}
|
2339
|
+
|
2340
|
+
}
|
2341
|
+
|
2342
|
+
###########################################################################
|
2343
|
+
# Deletes one or more tokens from the text widget.
|
2344
|
+
proc tokendelete {w args} {
|
2345
|
+
|
2346
|
+
if {([llength $args] == 0) || ([llength $args] > 2)} {
|
2347
|
+
return -code error "Incorrect number of options to the tokendelete command"
|
2348
|
+
}
|
2349
|
+
|
2350
|
+
# If the user wants to delete a single item, do so
|
2351
|
+
if {[llength $args] == 1} {
|
2352
|
+
set index [index_to_position $w [lindex $args 0]]
|
2353
|
+
if {$index ne ""} {
|
2354
|
+
$w.txt delete $index
|
2355
|
+
handle_state $w 1
|
2356
|
+
}
|
2357
|
+
|
2358
|
+
# Otherwise, delete a range of items
|
2359
|
+
} else {
|
2360
|
+
set sindex [index_to_position $w [lindex $args 0]]
|
2361
|
+
set eindex [index_to_position $w [lindex $args 1]]
|
2362
|
+
if {$sindex ne ""} {
|
2363
|
+
if {$eindex eq ""} {
|
2364
|
+
$w.txt delete $sindex
|
2365
|
+
} else {
|
2366
|
+
$w.txt delete $sindex "$eindex + 1 chars"
|
2367
|
+
}
|
2368
|
+
handle_state $w 1
|
2369
|
+
}
|
2370
|
+
}
|
2371
|
+
|
2372
|
+
}
|
2373
|
+
|
2374
|
+
###########################################################################
|
2375
|
+
# Detokenizes the given token to make it editable.
|
2376
|
+
proc tokenedit {w args} {
|
2377
|
+
|
2378
|
+
if {[llength $args] != 1} {
|
2379
|
+
return -code error "Incorrect number of options to the tokenedit command"
|
2380
|
+
}
|
2381
|
+
|
2382
|
+
# Detokenize the given index
|
2383
|
+
if {[set token [index_to_token $w [lindex $args 0]]] ne ""} {
|
2384
|
+
detokenize $w $token
|
2385
|
+
}
|
2386
|
+
|
2387
|
+
}
|
2388
|
+
|
2389
|
+
###########################################################################
|
2390
|
+
# Overrides the text insert command to handle watermarks.
|
2391
|
+
proc insert {w args} {
|
2392
|
+
|
2393
|
+
if {([llength $args] != 1) && ([llength $args] != 2)} {
|
2394
|
+
return -code error "tokensearch::insert called with wrong arguments"
|
2395
|
+
}
|
2396
|
+
|
2397
|
+
# If the user has inserted a non-empty string of data, make sure the state
|
2398
|
+
# is handled properly.
|
2399
|
+
if {[lindex $args 1] ne ""} {
|
2400
|
+
handle_state $w 1
|
2401
|
+
} else {
|
2402
|
+
handle_state $w 0
|
2403
|
+
}
|
2404
|
+
|
2405
|
+
return [eval "$w.txt insert [entry_to_text_index $w [lindex $args 0]] [lindex $args 1]"]
|
2406
|
+
|
2407
|
+
}
|
2408
|
+
|
2409
|
+
###########################################################################
|
2410
|
+
# Converts tokenentry delete command to a text delete command.
|
2411
|
+
proc delete {w args} {
|
2412
|
+
|
2413
|
+
variable state
|
2414
|
+
|
2415
|
+
if {[llength $args] == 1} {
|
2416
|
+
if {$state($w) ne "empty"} {
|
2417
|
+
$w.txt delete [entry_to_text_index $w [lindex $args 0]]
|
2418
|
+
handle_state $w 0
|
2419
|
+
}
|
2420
|
+
} elseif {[llength $args] == 2} {
|
2421
|
+
if {$state($w) ne "empty"} {
|
2422
|
+
$w.txt delete [entry_to_text_index $w [lindex $args 0]] \
|
2423
|
+
[entry_to_text_index $w [lindex $args 1]]
|
2424
|
+
handle_state $w 0
|
2425
|
+
}
|
2426
|
+
} else {
|
2427
|
+
return -code error "tokensearch::delete called with wrong arguments"
|
2428
|
+
}
|
2429
|
+
|
2430
|
+
}
|
2431
|
+
|
2432
|
+
###########################################################################
|
2433
|
+
# Converts tokensearch get command to a text get command.
|
2434
|
+
proc get {w args} {
|
2435
|
+
|
2436
|
+
variable state
|
2437
|
+
|
2438
|
+
if {[llength $args] != 0} {
|
2439
|
+
return -code error "tokensearch::get called with wrong arguments"
|
2440
|
+
}
|
2441
|
+
|
2442
|
+
if {$state($w) eq "empty"} {
|
2443
|
+
return ""
|
2444
|
+
} else {
|
2445
|
+
return [$w.txt get 1.0 1.end]
|
2446
|
+
}
|
2447
|
+
|
2448
|
+
}
|
2449
|
+
|
2450
|
+
###########################################################################
|
2451
|
+
# Converts tokensearch icursor command to a text insertion cursor call.
|
2452
|
+
proc icursor {w args} {
|
2453
|
+
|
2454
|
+
variable state
|
2455
|
+
|
2456
|
+
if {[llength $args] != 1} {
|
2457
|
+
return -code error "tokensearch::icursor called with wrong arguments"
|
2458
|
+
}
|
2459
|
+
|
2460
|
+
if {$state($w) eq "empty"} {
|
2461
|
+
return [$w.txt mark set insert 1.0]
|
2462
|
+
} else {
|
2463
|
+
return [eval "$w.txt mark set insert [entry_to_text_index $w [lindex $args 0]]"]
|
2464
|
+
}
|
2465
|
+
|
2466
|
+
}
|
2467
|
+
|
2468
|
+
###########################################################################
|
2469
|
+
# Converts tokensearch index command to a text index command call.
|
2470
|
+
proc index {w args} {
|
2471
|
+
|
2472
|
+
variable state
|
2473
|
+
|
2474
|
+
if {[llength $args] != 1} {
|
2475
|
+
return -code error "tokensearch::index called with wrong arguments"
|
2476
|
+
}
|
2477
|
+
|
2478
|
+
if {$state($w) eq "empty"} {
|
2479
|
+
return 0
|
2480
|
+
} else {
|
2481
|
+
return [lindex [split [$w.txt index [entry_to_text_index $w [lindex $args 0]]] .] 1]
|
2482
|
+
}
|
2483
|
+
|
2484
|
+
}
|
2485
|
+
|
2486
|
+
namespace export *
|
2487
|
+
|
2488
|
+
}
|