1 # incremental search panel
2 # based on code from gitk, Copyright (C) Paul Mackerras
11 field default_regexpsearch
13 field default_casesensitive
15 field searchdirn
-forwards
23 constructor new
{i_w i_text args
} {
28 set default_regexpsearch
[is_config_true gui.search.
regexp]
29 set smartcase
[is_config_true gui.search.smartcase
]
31 set default_casesensitive
0
33 set default_casesensitive
1
39 ${NS
}::label $w.l
-text [mc Find
:]
40 tentry
$w.ent
-textvariable ${__this
}::searchstring -background lightgreen
41 ${NS
}::button $w.bn
-text [mc Next
] -command [cb find_next
]
42 ${NS
}::button $w.bp
-text [mc Prev
] -command [cb find_prev
]
43 ${NS
}::checkbutton $w.re
-text [mc RegExp
] \
44 -variable ${__this
}::regexpsearch -command [cb _incrsearch
]
45 ${NS
}::checkbutton $w.cs
-text [mc Case
] \
46 -variable ${__this
}::casesensitive -command [cb _incrsearch
]
48 pack $w.cs
-side right
49 pack $w.re
-side right
50 pack $w.bp
-side right
51 pack $w.bn
-side right
52 pack $w.ent
-side left
-expand 1 -fill x
54 eval grid conf
$w -sticky we
$args
57 trace add
variable searchstring write
[cb _incrsearch_cb
]
58 bind $w.ent
<Return
> [cb find_next
]
59 bind $w.ent
<Shift-Return
> [cb find_prev
]
60 bind $w.ent
<Key-Up
> [cb _prev_search
]
61 bind $w.ent
<Key-Down
> [cb _next_search
]
63 bind $w <Destroy
> [list delete_this
$this]
68 if {![visible
$this]} {
71 set regexpsearch
$default_regexpsearch
72 set casesensitive
$default_casesensitive
73 set history_index
[llength $history]
79 if {[visible
$this]} {
87 return [winfo ismapped
$w]
94 method _get_new_anchor
{} {
95 # use start of selection if it is visible,
96 # or the bounds of the visible area
97 set top
[$ctext index
@0,0]
98 set bottom
[$ctext index
@0,[winfo height
$ctext]]
99 set sel
[$ctext tag ranges sel
]
101 set spos
[lindex $sel 0]
102 if {[lindex $spos 0] >= [lindex $top 0] &&
103 [lindex $spos 0] <= [lindex $bottom 0]} {
107 if {$searchdirn eq
"-forwards"} {
114 method _get_wrap_anchor
{dir
} {
115 if {$dir eq
"-forwards"} {
122 method _do_search
{start
{mlenvar
{}} {dir
{}} {endbound
{}}} {
123 set cmd
[list $ctext search
]
124 if {$mlenvar ne
{}} {
126 lappend cmd
-count mlen
131 if {!$casesensitive} {
137 lappend cmd
$dir -- $searchstring
139 if {$endbound ne
{}} {
140 set here
[eval $cmd [list $start] [list $endbound]]
142 set here
[eval $cmd [list $start]]
144 set here
[eval $cmd [_get_wrap_anchor
$this $dir]]
147 } err
]} { set here
{} }
151 method _incrsearch_cb
{name ix op
} {
152 after idle
[cb _incrsearch
]
155 method _incrsearch
{} {
156 $ctext tag remove found
1.0 end
157 if {[catch {$ctext index anchor
}]} {
158 $ctext mark
set anchor
[_get_new_anchor
$this]
161 if {[regexp {[[:upper
:]]} $searchstring]} {
165 if {$searchstring ne
{}} {
166 set here
[_do_search
$this anchor mlen
]
169 $ctext tag remove sel
1.0 end
170 $ctext tag add sel
$here "$here + $mlen c"
171 #$w.ent configure -background lightgreen
172 $w.ent state
!pressed
175 #$w.ent configure -background lightpink
181 method _save_search
{} {
182 if {$searchstring eq
{}} {
185 if {[llength $history] > 0} {
186 foreach {s_regexp s_case s_expr
} [lindex $history end
] break
188 set s_regexp
$regexpsearch
189 set s_case
$casesensitive
192 if {$searchstring eq
$s_expr} {
194 set history [lreplace $history end end
\
195 [list $regexpsearch $casesensitive $searchstring]]
197 lappend history [list $regexpsearch $casesensitive $searchstring]
199 set history_index
[llength $history]
202 method _prev_search
{} {
203 if {$history_index > 0} {
204 incr history_index
-1
205 foreach {s_regexp s_case s_expr
} [lindex $history $history_index] break
207 $w.ent insert
0 $s_expr
208 set regexpsearch
$s_regexp
209 set casesensitive
$s_case
213 method _next_search
{} {
214 if {$history_index < [llength $history]} {
217 if {$history_index < [llength $history]} {
218 foreach {s_regexp s_case s_expr
} [lindex $history $history_index] break
220 set s_regexp
$default_regexpsearch
221 set s_case
$default_casesensitive
225 $w.ent insert
0 $s_expr
226 set regexpsearch
$s_regexp
227 set casesensitive
$s_case
230 method find_prev
{} {
231 find_next
$this -backwards
234 method find_next
{{dir
-forwards}} {
238 $ctext mark
unset anchor
239 if {$searchstring ne
{}} {
241 set start
[_get_new_anchor
$this]
242 if {$dir eq
"-forwards"} {
243 set start
"$start + 1c"
245 set match
[_do_search
$this $start mlen
]
246 $ctext tag remove sel
1.0 end
249 $ctext tag add sel
$match "$match + $mlen c"
254 method _mark_range
{first last
} {
257 set match
[_do_search
$this $mend mlen
-forwards $last.end
]
258 if {$match eq
{}} break
259 set mend
"$match + $mlen c"
260 $ctext tag add found
$match $mend
264 method _set_marks
{doall
} {
265 set topline
[lindex [split [$ctext index
@0,0] .
] 0]
266 set botline
[lindex [split [$ctext index
@0,[winfo height
$ctext]] .
] 0]
267 if {$doall ||
$botline < $smarktop ||
$topline > $smarkbot} {
268 # no overlap with previous
269 _mark_range
$this $topline $botline
270 set smarktop
$topline
271 set smarkbot
$botline
273 if {$topline < $smarktop} {
274 _mark_range
$this $topline [expr {$smarktop-1}]
275 set smarktop
$topline
277 if {$botline > $smarkbot} {
278 _mark_range
$this [expr {$smarkbot+1}] $botline
279 set smarkbot
$botline
285 if {$searchstring ne
{}} {
286 after idle
[cb _set_marks
0]