1 # incremental search panel
2 # based on code from gitk, Copyright (C) Paul Mackerras
11 field default_regexpsearch
13 field default_casesensitive
14 field searchdirn
-forwards
22 constructor new
{i_w i_text args
} {
27 set default_regexpsearch
[is_config_true gui.search.
regexp]
28 if {[is_config_true gui.search.smartcase
]} {
29 set default_casesensitive
0
31 set default_casesensitive
1
37 ${NS
}::label $w.l
-text [mc Find
:]
38 entry $w.ent
-textvariable ${__this
}::searchstring -background lightgreen
39 ${NS
}::button $w.bn
-text [mc Next
] -command [cb find_next
]
40 ${NS
}::button $w.bp
-text [mc Prev
] -command [cb find_prev
]
41 ${NS
}::checkbutton $w.re
-text [mc RegExp
] \
42 -variable ${__this
}::regexpsearch -command [cb _incrsearch
]
43 ${NS
}::checkbutton $w.cs
-text [mc Case
] \
44 -variable ${__this
}::casesensitive -command [cb _incrsearch
]
46 pack $w.cs
-side right
47 pack $w.re
-side right
48 pack $w.bp
-side right
49 pack $w.bn
-side right
50 pack $w.ent
-side left
-expand 1 -fill x
52 eval grid conf
$w -sticky we
$args
55 trace add
variable searchstring write
[cb _incrsearch_cb
]
56 bind $w.ent
<Return
> [cb find_next
]
57 bind $w.ent
<Shift-Return
> [cb find_prev
]
58 bind $w.ent
<Key-Up
> [cb _prev_search
]
59 bind $w.ent
<Key-Down
> [cb _next_search
]
61 bind $w <Destroy
> [list delete_this
$this]
66 if {![visible
$this]} {
69 set regexpsearch
$default_regexpsearch
70 set casesensitive
$default_casesensitive
71 set history_index
[llength $history]
77 if {[visible
$this]} {
85 return [winfo ismapped
$w]
92 method _get_new_anchor
{} {
93 # use start of selection if it is visible,
94 # or the bounds of the visible area
95 set top
[$ctext index
@0,0]
96 set bottom
[$ctext index
@0,[winfo height
$ctext]]
97 set sel
[$ctext tag ranges sel
]
99 set spos
[lindex $sel 0]
100 if {[lindex $spos 0] >= [lindex $top 0] &&
101 [lindex $spos 0] <= [lindex $bottom 0]} {
105 if {$searchdirn eq
"-forwards"} {
112 method _get_wrap_anchor
{dir
} {
113 if {$dir eq
"-forwards"} {
120 method _do_search
{start
{mlenvar
{}} {dir
{}} {endbound
{}}} {
121 set cmd
[list $ctext search
]
122 if {$mlenvar ne
{}} {
124 lappend cmd
-count mlen
129 if {!$casesensitive} {
135 lappend cmd
$dir -- $searchstring
136 if {$endbound ne
{}} {
137 set here
[eval $cmd [list $start] [list $endbound]]
139 set here
[eval $cmd [list $start]]
141 set here
[eval $cmd [_get_wrap_anchor
$this $dir]]
147 method _incrsearch_cb
{name ix op
} {
148 after idle
[cb _incrsearch
]
151 method _incrsearch
{} {
152 $ctext tag remove found
1.0 end
153 if {[catch {$ctext index anchor
}]} {
154 $ctext mark
set anchor
[_get_new_anchor
$this]
156 if {[regexp {[[:upper
:]]} $searchstring]} {
159 if {$searchstring ne
{}} {
160 set here
[_do_search
$this anchor mlen
]
163 $ctext tag remove sel
1.0 end
164 $ctext tag add sel
$here "$here + $mlen c"
165 $w.ent configure
-background lightgreen
168 $w.ent configure
-background lightpink
173 method _save_search
{} {
174 if {$searchstring eq
{}} {
177 if {[llength $history] > 0} {
178 foreach {s_regexp s_case s_expr
} [lindex $history end
] break
180 set s_regexp
$regexpsearch
181 set s_case
$casesensitive
184 if {$searchstring eq
$s_expr} {
186 set history [lreplace $history end end
\
187 [list $regexpsearch $casesensitive $searchstring]]
189 lappend history [list $regexpsearch $casesensitive $searchstring]
191 set history_index
[llength $history]
194 method _prev_search
{} {
195 if {$history_index > 0} {
196 incr history_index
-1
197 foreach {s_regexp s_case s_expr
} [lindex $history $history_index] break
199 $w.ent insert
0 $s_expr
200 set regexpsearch
$s_regexp
201 set casesensitive
$s_case
205 method _next_search
{} {
206 if {$history_index < [llength $history]} {
209 if {$history_index < [llength $history]} {
210 foreach {s_regexp s_case s_expr
} [lindex $history $history_index] break
212 set s_regexp
$default_regexpsearch
213 set s_case
$default_casesensitive
217 $w.ent insert
0 $s_expr
218 set regexpsearch
$s_regexp
219 set casesensitive
$s_case
222 method find_prev
{} {
223 find_next
$this -backwards
226 method find_next
{{dir
-forwards}} {
230 $ctext mark
unset anchor
231 if {$searchstring ne
{}} {
233 set start
[_get_new_anchor
$this]
234 if {$dir eq
"-forwards"} {
235 set start
"$start + 1c"
237 set match
[_do_search
$this $start mlen
]
238 $ctext tag remove sel
1.0 end
241 $ctext tag add sel
$match "$match + $mlen c"
246 method _mark_range
{first last
} {
249 set match
[_do_search
$this $mend mlen
-forwards $last.end
]
250 if {$match eq
{}} break
251 set mend
"$match + $mlen c"
252 $ctext tag add found
$match $mend
256 method _set_marks
{doall
} {
257 set topline
[lindex [split [$ctext index
@0,0] .
] 0]
258 set botline
[lindex [split [$ctext index
@0,[winfo height
$ctext]] .
] 0]
259 if {$doall ||
$botline < $smarktop ||
$topline > $smarkbot} {
260 # no overlap with previous
261 _mark_range
$this $topline $botline
262 set smarktop
$topline
263 set smarkbot
$botline
265 if {$topline < $smarktop} {
266 _mark_range
$this $topline [expr {$smarktop-1}]
267 set smarktop
$topline
269 if {$botline > $smarkbot} {
270 _mark_range
$this [expr {$smarkbot+1}] $botline
271 set smarkbot
$botline
277 if {$searchstring ne
{}} {
278 after idle
[cb _set_marks
0]