Browse Source

gitk: Fix the find and highlight functions

This reworks the way that the "Find" button (and the /, ?, ^F, and ^G
keys) works.  Previously, pressing the "Find" button would cause gitk
to go off and scan through every commit to see which commits matched,
and the user interface was completely unreponsive during that time.
Now the searching is done in chunks using the scheduler, so the UI
still responds, and the search stops as soon as a matching commit is
found.

The highlighting of matches using a yellow background is now done in
the commit-drawing code and the highlighting code.  This ensures that
all the commits that are visible that match are highlighted without
the search code having to find them all.

This also fixes a bug where previously-drawn commits that need to be
highlighted were not being highlighted.

Signed-off-by: Paul Mackerras <paulus@samba.org>
maint
Paul Mackerras 18 years ago
parent
commit
4fb0fa197e
  1. 323
      gitk

323
gitk

@ -1758,7 +1758,7 @@ proc showview {n} {
global colormap rowtextx commitrow nextcolor canvxmax global colormap rowtextx commitrow nextcolor canvxmax
global numcommits rowrangelist commitlisted idrowranges rowchk global numcommits rowrangelist commitlisted idrowranges rowchk
global selectedline currentid canv canvy0 global selectedline currentid canv canvy0
global matchinglines treediffs global treediffs
global pending_select phase global pending_select phase
global commitidx rowlaidout rowoptim global commitidx rowlaidout rowoptim
global commfd global commfd
@ -1802,7 +1802,6 @@ proc showview {n} {
[list {} $rowidlist $rowoffsets $rowrangelist] [list {} $rowidlist $rowoffsets $rowrangelist]
} }
} }
catch {unset matchinglines}
catch {unset treediffs} catch {unset treediffs}
clear_display clear_display
if {[info exists hlview] && $hlview == $n} { if {[info exists hlview] && $hlview == $n} {
@ -2132,7 +2131,7 @@ proc readfhighlight {} {


proc find_change {name ix op} { proc find_change {name ix op} {
global nhighlights mainfont boldnamerows global nhighlights mainfont boldnamerows
global findstring findpattern findtype global findstring findpattern findtype markingmatches


# delete previous highlights, if any # delete previous highlights, if any
foreach row $boldnamerows { foreach row $boldnamerows {
@ -2141,17 +2140,32 @@ proc find_change {name ix op} {
set boldnamerows {} set boldnamerows {}
catch {unset nhighlights} catch {unset nhighlights}
unbolden unbolden
unmarkmatches
if {$findtype ne "Regexp"} { if {$findtype ne "Regexp"} {
set e [string map {"*" "\\*" "?" "\\?" "\[" "\\\[" "\\" "\\\\"} \ set e [string map {"*" "\\*" "?" "\\?" "\[" "\\\[" "\\" "\\\\"} \
$findstring] $findstring]
set findpattern "*$e*" set findpattern "*$e*"
} }
set markingmatches [expr {$findstring ne {}}]
drawvisible drawvisible
} }


proc doesmatch {f} {
global findtype findstring findpattern

if {$findtype eq "Regexp"} {
return [regexp $findstring $f]
} elseif {$findtype eq "IgnCase"} {
return [string match -nocase $findpattern $f]
} else {
return [string match $findpattern $f]
}
}

proc askfindhighlight {row id} { proc askfindhighlight {row id} {
global nhighlights commitinfo iddrawn mainfont global nhighlights commitinfo iddrawn mainfont
global findstring findtype findloc findpattern global findloc
global markingmatches


if {![info exists commitinfo($id)]} { if {![info exists commitinfo($id)]} {
getcommit $id getcommit $id
@ -2160,35 +2174,47 @@ proc askfindhighlight {row id} {
set isbold 0 set isbold 0
set fldtypes {Headline Author Date Committer CDate Comments} set fldtypes {Headline Author Date Committer CDate Comments}
foreach f $info ty $fldtypes { foreach f $info ty $fldtypes {
if {$findloc ne "All fields" && $findloc ne $ty} { if {($findloc eq "All fields" || $findloc eq $ty) &&
continue [doesmatch $f]} {
}
if {$findtype eq "Regexp"} {
set doesmatch [regexp $findstring $f]
} elseif {$findtype eq "IgnCase"} {
set doesmatch [string match -nocase $findpattern $f]
} else {
set doesmatch [string match $findpattern $f]
}
if {$doesmatch} {
if {$ty eq "Author"} { if {$ty eq "Author"} {
set isbold 2 set isbold 2
} else { break
set isbold 1
} }
set isbold 1
} }
} }
if {[info exists iddrawn($id)]} { if {$isbold && [info exists iddrawn($id)]} {
if {$isbold && ![ishighlighted $row]} { set f [concat $mainfont bold]
bolden $row [concat $mainfont bold] if {![ishighlighted $row]} {
bolden $row $f
if {$isbold > 1} {
bolden_name $row $f
}
} }
if {$isbold >= 2} { if {$markingmatches} {
bolden_name $row [concat $mainfont bold] markrowmatches $row [lindex $info 0] [lindex $info 1]
} }
} }
set nhighlights($row) $isbold set nhighlights($row) $isbold
} }


proc markrowmatches {row headline author} {
global canv canv2 linehtag linentag

$canv delete match$row
$canv2 delete match$row
set m [findmatches $headline]
if {$m ne {}} {
markmatches $canv $row $headline $linehtag($row) $m \
[$canv itemcget $linehtag($row) -font]
}
set m [findmatches $author]
if {$m ne {}} {
markmatches $canv2 $row $author $linentag($row) $m \
[$canv2 itemcget $linentag($row) -font]
}
}

proc vrel_change {name ix op} { proc vrel_change {name ix op} {
global highlight_related global highlight_related


@ -3309,7 +3335,7 @@ proc drawcmittext {id row col} {
global linespc canv canv2 canv3 canvy0 fgcolor global linespc canv canv2 canv3 canvy0 fgcolor
global commitlisted commitinfo rowidlist parentlist global commitlisted commitinfo rowidlist parentlist
global rowtextx idpos idtags idheads idotherrefs global rowtextx idpos idtags idheads idotherrefs
global linehtag linentag linedtag global linehtag linentag linedtag markingmatches
global mainfont canvxmax boldrows boldnamerows fgcolor nullid global mainfont canvxmax boldrows boldnamerows fgcolor nullid


if {$id eq $nullid} { if {$id eq $nullid} {
@ -3366,6 +3392,9 @@ proc drawcmittext {id row col} {
set linedtag($row) [$canv3 create text 3 $y -anchor w -fill $fgcolor \ set linedtag($row) [$canv3 create text 3 $y -anchor w -fill $fgcolor \
-text $date -font $mainfont -tags text] -text $date -font $mainfont -tags text]
set xr [expr {$xt + [font measure $mainfont $headline]}] set xr [expr {$xt + [font measure $mainfont $headline]}]
if {$markingmatches} {
markrowmatches $row $headline $name
}
if {$xr > $canvxmax} { if {$xr > $canvxmax} {
set canvxmax $xr set canvxmax $xr
setcanvscroll setcanvscroll
@ -3436,9 +3465,7 @@ proc drawcommits {row {endrow {}}} {
for {} {$r <= $er} {incr r} { for {} {$r <= $er} {incr r} {
set id [lindex $displayorder $r] set id [lindex $displayorder $r]
set wasdrawn [info exists iddrawn($id)] set wasdrawn [info exists iddrawn($id)]
if {!$wasdrawn} { drawcmitrow $r
drawcmitrow $r
}
if {$r == $er} break if {$r == $er} break
set nextid [lindex $displayorder [expr {$r + 1}]] set nextid [lindex $displayorder [expr {$r + 1}]]
if {$wasdrawn && [info exists iddrawn($nextid)]} { if {$wasdrawn && [info exists iddrawn($nextid)]} {
@ -3889,101 +3916,166 @@ proc notbusy {what} {
} }


proc findmatches {f} { proc findmatches {f} {
global findtype foundstring foundstrlen global findtype findstring
if {$findtype == "Regexp"} { if {$findtype == "Regexp"} {
set matches [regexp -indices -all -inline $foundstring $f] set matches [regexp -indices -all -inline $findstring $f]
} else { } else {
set fs $findstring
if {$findtype == "IgnCase"} { if {$findtype == "IgnCase"} {
set str [string tolower $f] set f [string tolower $f]
} else { set fs [string tolower $fs]
set str $f
} }
set matches {} set matches {}
set i 0 set i 0
while {[set j [string first $foundstring $str $i]] >= 0} { set l [string length $fs]
lappend matches [list $j [expr {$j+$foundstrlen-1}]] while {[set j [string first $fs $f $i]] >= 0} {
set i [expr {$j + $foundstrlen}] lappend matches [list $j [expr {$j+$l-1}]]
set i [expr {$j + $l}]
} }
} }
return $matches return $matches
} }


proc dofind {} { proc dofind {{rev 0}} {
global findtype findloc findstring markedmatches commitinfo global findstring findstartline findcurline selectedline numcommits
global numcommits displayorder linehtag linentag linedtag
global mainfont canv canv2 canv3 selectedline
global matchinglines foundstring foundstrlen matchstring
global commitdata


stopfindproc stopfindproc
unmarkmatches unmarkmatches
cancel_next_highlight cancel_next_highlight
focus . focus .
set matchinglines {} if {$findstring eq {} || $numcommits == 0} return
if {$findtype == "IgnCase"} { if {![info exists selectedline]} {
set foundstring [string tolower $findstring] set findstartline [lindex [visiblerows] $rev]
} else { } else {
set foundstring $findstring set findstartline $selectedline
} }
set foundstrlen [string length $findstring] set findcurline $findstartline
if {$foundstrlen == 0} return nowbusy finding
regsub -all {[*?\[\\]} $foundstring {\\&} matchstring if {!$rev} {
set matchstring "*$matchstring*" run findmore
if {![info exists selectedline]} {
set oldsel -1
} else { } else {
set oldsel $selectedline set findcurline $findstartline
if {$findcurline == 0} {
set findcurline $numcommits
}
incr findcurline -1
run findmorerev
} }
set didsel 0 }
set fldtypes {Headline Author Date Committer CDate Comments}
set l -1 proc findnext {restart} {
foreach id $displayorder { global findcurline
set d $commitdata($id) if {![info exists findcurline]} {
incr l if {$restart} {
if {$findtype == "Regexp"} { dofind
set doesmatch [regexp $foundstring $d]
} elseif {$findtype == "IgnCase"} {
set doesmatch [string match -nocase $matchstring $d]
} else { } else {
set doesmatch [string match $matchstring $d] bell
} }
if {!$doesmatch} continue } else {
run findmore
nowbusy finding
}
}

proc findprev {} {
global findcurline
if {![info exists findcurline]} {
dofind 1
} else {
run findmorerev
nowbusy finding
}
}

proc findmore {} {
global commitdata commitinfo numcommits findstring findpattern findloc
global findstartline findcurline markingmatches displayorder

set fldtypes {Headline Author Date Committer CDate Comments}
set l [expr {$findcurline + 1}]
if {$l >= $numcommits} {
set l 0
}
if {$l <= $findstartline} {
set lim [expr {$findstartline + 1}]
} else {
set lim $numcommits
}
if {$lim - $l > 500} {
set lim [expr {$l + 500}]
}
set last 0
for {} {$l < $lim} {incr l} {
set id [lindex $displayorder $l]
if {![doesmatch $commitdata($id)]} continue
if {![info exists commitinfo($id)]} { if {![info exists commitinfo($id)]} {
getcommit $id getcommit $id
} }
set info $commitinfo($id) set info $commitinfo($id)
set doesmatch 0
foreach f $info ty $fldtypes { foreach f $info ty $fldtypes {
if {$findloc != "All fields" && $findloc != $ty} { if {($findloc eq "All fields" || $findloc eq $ty) &&
continue [doesmatch $f]} {
} set markingmatches 1
set matches [findmatches $f] findselectline $l
if {$matches == {}} continue notbusy finding
set doesmatch 1 return 0
if {$ty == "Headline"} {
drawcommits $l
markmatches $canv $l $f $linehtag($l) $matches $mainfont
} elseif {$ty == "Author"} {
drawcommits $l
markmatches $canv2 $l $f $linentag($l) $matches $mainfont
} elseif {$ty == "Date"} {
drawcommits $l
markmatches $canv3 $l $f $linedtag($l) $matches $mainfont
} }
} }
if {$doesmatch} { }
lappend matchinglines $l if {$l == $findstartline + 1} {
if {!$didsel && $l > $oldsel} { bell
unset findcurline
notbusy finding
return 0
}
set findcurline [expr {$l - 1}]
return 1
}

proc findmorerev {} {
global commitdata commitinfo numcommits findstring findpattern findloc
global findstartline findcurline markingmatches displayorder

set fldtypes {Headline Author Date Committer CDate Comments}
set l $findcurline
if {$l == 0} {
set l $numcommits
}
incr l -1
if {$l >= $findstartline} {
set lim [expr {$findstartline - 1}]
} else {
set lim -1
}
if {$l - $lim > 500} {
set lim [expr {$l - 500}]
}
set last 0
for {} {$l > $lim} {incr l -1} {
set id [lindex $displayorder $l]
if {![doesmatch $commitdata($id)]} continue
if {![info exists commitinfo($id)]} {
getcommit $id
}
set info $commitinfo($id)
foreach f $info ty $fldtypes {
if {($findloc eq "All fields" || $findloc eq $ty) &&
[doesmatch $f]} {
set markingmatches 1
findselectline $l findselectline $l
set didsel 1 notbusy finding
return 0
} }
} }
} }
if {$matchinglines == {}} { if {$l == -1} {
bell bell
} elseif {!$didsel} { unset findcurline
findselectline [lindex $matchinglines 0] notbusy finding
return 0
} }
set findcurline [expr {$l + 1}]
return 1
} }


proc findselectline {l} { proc findselectline {l} {
@ -4001,43 +4093,6 @@ proc findselectline {l} {
} }
} }


proc findnext {restart} {
global matchinglines selectedline
if {![info exists matchinglines]} {
if {$restart} {
dofind
}
return
}
if {![info exists selectedline]} return
foreach l $matchinglines {
if {$l > $selectedline} {
findselectline $l
return
}
}
bell
}

proc findprev {} {
global matchinglines selectedline
if {![info exists matchinglines]} {
dofind
return
}
if {![info exists selectedline]} return
set prev {}
foreach l $matchinglines {
if {$l >= $selectedline} break
set prev $l
}
if {$prev != {}} {
findselectline $prev
} else {
bell
}
}

proc stopfindproc {{done 0}} { proc stopfindproc {{done 0}} {
global findprocpid findprocfile findids global findprocpid findprocfile findids
global ctext findoldcursor phase maincursor textcursor global ctext findoldcursor phase maincursor textcursor
@ -4055,18 +4110,7 @@ proc stopfindproc {{done 0}} {
notbusy find notbusy find
} }


# mark a commit as matching by putting a yellow background # mark the bits of a headline or author that match a find string
# behind the headline
proc markheadline {l id} {
global canv mainfont linehtag

drawcommits $l
set bbox [$canv bbox $linehtag($l)]
set t [$canv create rect $bbox -outline {} -tags matches -fill yellow]
$canv lower $t
}

# mark the bits of a headline, author or date that match a find string
proc markmatches {canv l str tag matches font} { proc markmatches {canv l str tag matches font} {
set bbox [$canv bbox $tag] set bbox [$canv bbox $tag]
set x0 [lindex $bbox 0] set x0 [lindex $bbox 0]
@ -4080,16 +4124,18 @@ proc markmatches {canv l str tag matches font} {
set xlen [font measure $font [string range $str 0 [expr {$end}]]] set xlen [font measure $font [string range $str 0 [expr {$end}]]]
set t [$canv create rect [expr {$x0+$xoff}] $y0 \ set t [$canv create rect [expr {$x0+$xoff}] $y0 \
[expr {$x0+$xlen+2}] $y1 \ [expr {$x0+$xlen+2}] $y1 \
-outline {} -tags matches -fill yellow] -outline {} -tags [list match$l matches] -fill yellow]
$canv lower $t $canv lower $t
} }
} }


proc unmarkmatches {} { proc unmarkmatches {} {
global matchinglines findids global findids markingmatches findcurline

allcanvs delete matches allcanvs delete matches
catch {unset matchinglines}
catch {unset findids} catch {unset findids}
set markingmatches 0
catch {unset findcurline}
} }


proc selcanvline {w x y} { proc selcanvline {w x y} {
@ -7471,6 +7517,7 @@ set searchdirn -forwards
set boldrows {} set boldrows {}
set boldnamerows {} set boldnamerows {}
set diffelide {0 0} set diffelide {0 0}
set markingmatches 0


set optim_delay 16 set optim_delay 16



Loading…
Cancel
Save