Spaces:
Runtime error
Runtime error
| # incremental search panel | |
| # based on code from gitk, Copyright (C) Paul Mackerras | |
| class searchbar { | |
| field w | |
| field ctext | |
| field searchstring {} | |
| field regexpsearch | |
| field default_regexpsearch | |
| field casesensitive | |
| field default_casesensitive | |
| field smartcase | |
| field searchdirn -forwards | |
| field history | |
| field history_index | |
| field smarktop | |
| field smarkbot | |
| constructor new {i_w i_text args} { | |
| global use_ttk NS | |
| set w $i_w | |
| set ctext $i_text | |
| set default_regexpsearch [is_config_true gui.search.regexp] | |
| switch -- [get_config gui.search.case] { | |
| no { | |
| set default_casesensitive 0 | |
| set smartcase 0 | |
| } | |
| smart { | |
| set default_casesensitive 0 | |
| set smartcase 1 | |
| } | |
| yes - | |
| default { | |
| set default_casesensitive 1 | |
| set smartcase 0 | |
| } | |
| } | |
| set history [list] | |
| ${NS}::frame $w | |
| ${NS}::label $w.l -text [mc Find:] | |
| tentry $w.ent -textvariable ${__this}::searchstring -background lightgreen | |
| ${NS}::button $w.bn -text [mc Next] -command [cb find_next] | |
| ${NS}::button $w.bp -text [mc Prev] -command [cb find_prev] | |
| ${NS}::checkbutton $w.re -text [mc RegExp] \ | |
| -variable ${__this}::regexpsearch -command [cb _incrsearch] | |
| ${NS}::checkbutton $w.cs -text [mc Case] \ | |
| -variable ${__this}::casesensitive -command [cb _incrsearch] | |
| pack $w.l -side left | |
| pack $w.cs -side right | |
| pack $w.re -side right | |
| pack $w.bp -side right | |
| pack $w.bn -side right | |
| pack $w.ent -side left -expand 1 -fill x | |
| eval grid conf $w -sticky we $args | |
| grid remove $w | |
| trace add variable searchstring write [cb _incrsearch_cb] | |
| bind $w.ent <Return> [cb find_next] | |
| bind $w.ent <Shift-Return> [cb find_prev] | |
| bind $w.ent <Key-Up> [cb _prev_search] | |
| bind $w.ent <Key-Down> [cb _next_search] | |
| bind $w <Destroy> [list delete_this $this] | |
| return $this | |
| } | |
| method show {} { | |
| if {![visible $this]} { | |
| grid $w | |
| $w.ent delete 0 end | |
| set regexpsearch $default_regexpsearch | |
| set casesensitive $default_casesensitive | |
| set history_index [llength $history] | |
| } | |
| focus -force $w.ent | |
| } | |
| method hide {} { | |
| if {[visible $this]} { | |
| focus $ctext | |
| grid remove $w | |
| _save_search $this | |
| } | |
| } | |
| method visible {} { | |
| return [winfo ismapped $w] | |
| } | |
| method editor {} { | |
| return $w.ent | |
| } | |
| method _get_new_anchor {} { | |
| # use start of selection if it is visible, | |
| # or the bounds of the visible area | |
| set top [$ctext index @0,0] | |
| set bottom [$ctext index @0,[winfo height $ctext]] | |
| set sel [$ctext tag ranges sel] | |
| if {$sel ne {}} { | |
| set spos [lindex $sel 0] | |
| if {[lindex $spos 0] >= [lindex $top 0] && | |
| [lindex $spos 0] <= [lindex $bottom 0]} { | |
| return $spos | |
| } | |
| } | |
| if {$searchdirn eq "-forwards"} { | |
| return $top | |
| } else { | |
| return $bottom | |
| } | |
| } | |
| method _get_wrap_anchor {dir} { | |
| if {$dir eq "-forwards"} { | |
| return 1.0 | |
| } else { | |
| return end | |
| } | |
| } | |
| method _do_search {start {mlenvar {}} {dir {}} {endbound {}}} { | |
| set cmd [list $ctext search] | |
| if {$mlenvar ne {}} { | |
| upvar $mlenvar mlen | |
| lappend cmd -count mlen | |
| } | |
| if {$regexpsearch} { | |
| lappend cmd -regexp | |
| } | |
| if {!$casesensitive} { | |
| lappend cmd -nocase | |
| } | |
| if {$dir eq {}} { | |
| set dir $searchdirn | |
| } | |
| lappend cmd $dir -- $searchstring | |
| if {[catch { | |
| if {$endbound ne {}} { | |
| set here [eval $cmd [list $start] [list $endbound]] | |
| } else { | |
| set here [eval $cmd [list $start]] | |
| if {$here eq {}} { | |
| set here [eval $cmd [_get_wrap_anchor $this $dir]] | |
| } | |
| } | |
| } err]} { set here {} } | |
| return $here | |
| } | |
| method _incrsearch_cb {name ix op} { | |
| after idle [cb _incrsearch] | |
| } | |
| method _incrsearch {} { | |
| $ctext tag remove found 1.0 end | |
| if {[catch {$ctext index anchor}]} { | |
| $ctext mark set anchor [_get_new_anchor $this] | |
| } | |
| if {$searchstring ne {}} { | |
| if {$smartcase && [regexp {[[:upper:]]} $searchstring]} { | |
| set casesensitive 1 | |
| } | |
| set here [_do_search $this anchor mlen] | |
| if {$here ne {}} { | |
| $ctext see $here | |
| $ctext tag remove sel 1.0 end | |
| $ctext tag add sel $here "$here + $mlen c" | |
| #$w.ent configure -background lightgreen | |
| $w.ent state !pressed | |
| _set_marks $this 1 | |
| } else { | |
| #$w.ent configure -background lightpink | |
| $w.ent state pressed | |
| } | |
| } elseif {$smartcase} { | |
| # clearing the field resets the smart case detection | |
| set casesensitive 0 | |
| } | |
| } | |
| method _save_search {} { | |
| if {$searchstring eq {}} { | |
| return | |
| } | |
| if {[llength $history] > 0} { | |
| foreach {s_regexp s_case s_expr} [lindex $history end] break | |
| } else { | |
| set s_regexp $regexpsearch | |
| set s_case $casesensitive | |
| set s_expr "" | |
| } | |
| if {$searchstring eq $s_expr} { | |
| # update modes | |
| set history [lreplace $history end end \ | |
| [list $regexpsearch $casesensitive $searchstring]] | |
| } else { | |
| lappend history [list $regexpsearch $casesensitive $searchstring] | |
| } | |
| set history_index [llength $history] | |
| } | |
| method _prev_search {} { | |
| if {$history_index > 0} { | |
| incr history_index -1 | |
| foreach {s_regexp s_case s_expr} [lindex $history $history_index] break | |
| $w.ent delete 0 end | |
| $w.ent insert 0 $s_expr | |
| set regexpsearch $s_regexp | |
| set casesensitive $s_case | |
| } | |
| } | |
| method _next_search {} { | |
| if {$history_index < [llength $history]} { | |
| incr history_index | |
| } | |
| if {$history_index < [llength $history]} { | |
| foreach {s_regexp s_case s_expr} [lindex $history $history_index] break | |
| } else { | |
| set s_regexp $default_regexpsearch | |
| set s_case $default_casesensitive | |
| set s_expr "" | |
| } | |
| $w.ent delete 0 end | |
| $w.ent insert 0 $s_expr | |
| set regexpsearch $s_regexp | |
| set casesensitive $s_case | |
| } | |
| method find_prev {} { | |
| find_next $this -backwards | |
| } | |
| method find_next {{dir -forwards}} { | |
| focus $w.ent | |
| $w.ent icursor end | |
| set searchdirn $dir | |
| $ctext mark unset anchor | |
| if {$searchstring ne {}} { | |
| _save_search $this | |
| set start [_get_new_anchor $this] | |
| if {$dir eq "-forwards"} { | |
| set start "$start + 1c" | |
| } | |
| set match [_do_search $this $start mlen] | |
| $ctext tag remove sel 1.0 end | |
| if {$match ne {}} { | |
| $ctext see $match | |
| $ctext tag add sel $match "$match + $mlen c" | |
| } | |
| } | |
| } | |
| method _mark_range {first last} { | |
| set mend $first.0 | |
| while {1} { | |
| set match [_do_search $this $mend mlen -forwards $last.end] | |
| if {$match eq {}} break | |
| set mend "$match + $mlen c" | |
| $ctext tag add found $match $mend | |
| } | |
| } | |
| method _set_marks {doall} { | |
| set topline [lindex [split [$ctext index @0,0] .] 0] | |
| set botline [lindex [split [$ctext index @0,[winfo height $ctext]] .] 0] | |
| if {$doall || $botline < $smarktop || $topline > $smarkbot} { | |
| # no overlap with previous | |
| _mark_range $this $topline $botline | |
| set smarktop $topline | |
| set smarkbot $botline | |
| } else { | |
| if {$topline < $smarktop} { | |
| _mark_range $this $topline [expr {$smarktop-1}] | |
| set smarktop $topline | |
| } | |
| if {$botline > $smarkbot} { | |
| _mark_range $this [expr {$smarkbot+1}] $botline | |
| set smarkbot $botline | |
| } | |
| } | |
| } | |
| method scrolled {} { | |
| if {$searchstring ne {}} { | |
| after idle [cb _set_marks 0] | |
| } | |
| } | |
| } | |