gitk: Remember the view in the history list
[git.git] / gitk
diff --git a/gitk b/gitk
index cfd0a3a..305aa2e 100755 (executable)
--- a/gitk
+++ b/gitk
@@ -80,6 +80,18 @@ proc start_rev_list {rlargs} {
     settextcursor watch
 }
 
+proc stop_rev_list {} {
+    global commfd
+
+    if {![info exists commfd]} return
+    catch {
+       set pid [pid $commfd]
+       exec kill $pid
+    }
+    catch {close $commfd}
+    unset commfd
+}
+
 proc getcommits {rargs} {
     global phase canv mainfont
 
@@ -173,6 +185,7 @@ proc getcommitlines {commfd}  {
        lappend parentlist $olds
        if {[info exists children($id)]} {
            lappend childlist $children($id)
+           unset children($id)
        } else {
            lappend childlist {}
        }
@@ -217,12 +230,17 @@ proc readcommit {id} {
 }
 
 proc updatecommits {} {
-    global viewdata curview revtreeargs
+    global viewdata curview revtreeargs phase
 
+    if {$phase ne {}} {
+       stop_rev_list
+       set phase {}
+    }
     set n $curview
     set curview -1
     catch {unset viewdata($n)}
     parse_args $revtreeargs
+    readrefs
     showview $n
 }
 
@@ -351,7 +369,8 @@ proc error_popup msg {
 }
 
 proc makewindow {} {
-    global canv canv2 canv3 linespc charspc ctext cflist textfont mainfont uifont
+    global canv canv2 canv3 linespc charspc ctext cflist
+    global textfont mainfont uifont
     global findtype findtypemenu findloc findstring fstring geometry
     global entries sha1entry sha1string sha1but
     global maincursor textcursor curtextcursor
@@ -369,7 +388,7 @@ proc makewindow {} {
     .bar add cascade -label "Edit" -menu .bar.edit
     .bar.edit add command -label "Preferences" -command doprefs
     .bar.edit configure -font $uifont
-    menu .bar.view
+    menu .bar.view -font $uifont
     .bar add cascade -label "View" -menu .bar.view
     .bar.view add command -label "New view..." -command newview
     .bar.view add command -label "Delete view" -command delview -state disabled
@@ -881,6 +900,25 @@ proc delview {} {
     showview 0
 }
 
+proc flatten {var} {
+    global $var
+
+    set ret {}
+    foreach i [array names $var] {
+       lappend ret $i [set $var\($i\)]
+    }
+    return $ret
+}
+
+proc unflatten {var l} {
+    global $var
+
+    catch {unset $var}
+    foreach {i v} $l {
+       set $var\($i\) $v
+    }
+}
+
 proc showview {n} {
     global curview viewdata viewfiles
     global displayorder parentlist childlist rowidlist rowoffsets
@@ -890,6 +928,8 @@ proc showview {n} {
     global matchinglines treediffs
     global parsed_args
     global pending_select phase
+    global commitidx rowlaidout rowoptim linesegends leftover
+    global commfd nextupdate
 
     if {$n == $curview} return
     set selid {}
@@ -907,16 +947,28 @@ proc showview {n} {
        }
     }
     unselectline
+    normalline
     stopfindproc
-    if {$curview >= 0 && $phase eq {} && ![info exists viewdata($curview)]} {
-       set viewdata($curview) \
-           [list $displayorder $parentlist $childlist $rowidlist \
-                $rowoffsets $rowrangelist $commitlisted]
+    if {$curview >= 0} {
+       if {$phase ne {}} {
+           set viewdata($curview) \
+               [list $phase $displayorder $parentlist $childlist $rowidlist \
+                    $rowoffsets $rowrangelist $commitlisted \
+                    [flatten children] [flatten idrowranges] \
+                    [flatten idinlist] \
+                    $commitidx $rowlaidout $rowoptim $numcommits \
+                    $linesegends $leftover $commfd]
+           fileevent $commfd readable {}
+       } elseif {![info exists viewdata($curview)]
+                 || [lindex $viewdata($curview) 0] ne {}} {
+           set viewdata($curview) \
+               [list {} $displayorder $parentlist $childlist $rowidlist \
+                    $rowoffsets $rowrangelist $commitlisted]
+       }
     }
     catch {unset matchinglines}
     catch {unset treediffs}
     clear_display
-    readrefs
 
     set curview $n
     .bar.view entryconf 2 -state [expr {$n == 0? "disabled": "normal"}]
@@ -931,18 +983,37 @@ proc showview {n} {
        return
     }
 
-    set displayorder [lindex $viewdata($n) 0]
-    set parentlist [lindex $viewdata($n) 1]
-    set childlist [lindex $viewdata($n) 2]
-    set rowidlist [lindex $viewdata($n) 3]
-    set rowoffsets [lindex $viewdata($n) 4]
-    set rowrangelist [lindex $viewdata($n) 5]
-    set commitlisted [lindex $viewdata($n) 6]
-    set numcommits [llength $displayorder]
+    set v $viewdata($n)
+    set phase [lindex $v 0]
+    set displayorder [lindex $v 1]
+    set parentlist [lindex $v 2]
+    set childlist [lindex $v 3]
+    set rowidlist [lindex $v 4]
+    set rowoffsets [lindex $v 5]
+    set rowrangelist [lindex $v 6]
+    set commitlisted [lindex $v 7]
+    if {$phase eq {}} {
+       set numcommits [llength $displayorder]
+       catch {unset idrowranges}
+       catch {unset children}
+    } else {
+       unflatten children [lindex $v 8]
+       unflatten idrowranges [lindex $v 9]
+       unflatten idinlist [lindex $v 10]
+       set commitidx [lindex $v 11]
+       set rowlaidout [lindex $v 12]
+       set rowoptim [lindex $v 13]
+       set numcommits [lindex $v 14]
+       set linesegends [lindex $v 15]
+       set leftover [lindex $v 16]
+       set commfd [lindex $v 17]
+       fileevent $commfd readable [list getcommitlines $commfd]
+       set nextupdate [expr {[clock clicks -milliseconds] + 100}]
+    }
+
     catch {unset colormap}
     catch {unset rowtextx}
     catch {unset commitrow}
-    catch {unset idrowranges}
     set curview $n
     set row 0
     foreach id $displayorder {
@@ -965,6 +1036,14 @@ proc showview {n} {
     allcanvs yview moveto $yf
     drawvisible
     selectline $row 0
+    if {$phase eq {}} {
+       global maincursor textcursor
+       . config -cursor $maincursor
+       settextcursor $textcursor
+    } else {
+       . config -cursor watch
+       settextcursor watch
+    }
 }
 
 proc shortids {ids} {
@@ -1002,20 +1081,21 @@ proc ntimes {n o} {
 }
 
 proc usedinrange {id l1 l2} {
-    global children commitrow
+    global children commitrow childlist
 
     if {[info exists commitrow($id)]} {
        set r $commitrow($id)
        if {$l1 <= $r && $r <= $l2} {
            return [expr {$r - $l1 + 1}]
        }
+       set kids [lindex $childlist $r]
+    } else {
+       set kids $children($id)
     }
-    foreach c $children($id) {
-       if {[info exists commitrow($c)]} {
-           set r $commitrow($c)
-           if {$l1 <= $r && $r <= $l2} {
-               return [expr {$r - $l1 + 1}]
-           }
+    foreach c $kids {
+       set r $commitrow($c)
+       if {$l1 <= $r && $r <= $l2} {
+           return [expr {$r - $l1 + 1}]
        }
     }
     return 0
@@ -1110,7 +1190,7 @@ proc initlayout {} {
     catch {unset rowtextx}
     catch {unset commitrow}
     catch {unset idrowranges}
-    catch {unset linesegends}
+    set linesegends {}
 }
 
 proc setcanvscroll {} {
@@ -1159,7 +1239,7 @@ proc layoutmore {} {
 }
 
 proc showstuff {canshow} {
-    global numcommits commitrow pending_select
+    global numcommits commitrow pending_select selectedline
     global linesegends idrowranges idrangedrawn
 
     if {$numcommits == 0} {
@@ -1175,16 +1255,14 @@ proc showstuff {canshow} {
     set r1 [lindex $rows 1]
     set selrow -1
     for {set r $row} {$r < $canshow} {incr r} {
-       if {[info exists linesegends($r)]} {
-           foreach id $linesegends($r) {
-               set i -1
-               foreach {s e} $idrowranges($id) {
-                   incr i
-                   if {$e ne {} && $e < $numcommits && $s <= $r1 && $e >= $r0
-                       && ![info exists idrangedrawn($id,$i)]} {
-                       drawlineseg $id $i
-                       set idrangedrawn($id,$i) 1
-                   }
+       foreach id [lindex $linesegends [expr {$r+1}]] {
+           set i -1
+           foreach {s e} [rowranges $id] {
+               incr i
+               if {$e ne {} && $e < $numcommits && $s <= $r1 && $e >= $r0
+                   && ![info exists idrangedrawn($id,$i)]} {
+                   drawlineseg $id $i
+                   set idrangedrawn($id,$i) 1
                }
            }
        }
@@ -1201,6 +1279,9 @@ proc showstuff {canshow} {
        $commitrow($pending_select) < $numcommits} {
        selectline $commitrow($pending_select) 1
     }
+    if {![info exists selectedline] && ![info exists pending_select]} {
+       selectline 0 1
+    }
 }
 
 proc layoutrows {row endrow last} {
@@ -1224,6 +1305,7 @@ proc layoutrows {row endrow last} {
                lappend oldolds $p
            }
        }
+       set lse {}
        set nev [expr {[llength $idlist] + [llength $newolds]
                       + [llength $oldolds] - $maxwidth + 1}]
        if {$nev > 0} {
@@ -1239,7 +1321,7 @@ proc layoutrows {row endrow last} {
                        set offs [incrange $offs $x 1]
                        set idinlist($i) 0
                        set rm1 [expr {$row - 1}]
-                       lappend linesegends($rm1) $i
+                       lappend lse $i
                        lappend idrowranges($i) $rm1
                        if {[incr nev -1] <= 0} break
                        continue
@@ -1250,6 +1332,7 @@ proc layoutrows {row endrow last} {
            lset rowidlist $row $idlist
            lset rowoffsets $row $offs
        }
+       lappend linesegends $lse
        set col [lsearch -exact $idlist $id]
        if {$col < 0} {
            set col [llength $idlist]
@@ -1270,8 +1353,9 @@ proc layoutrows {row endrow last} {
        }
        set ranges {}
        if {[info exists idrowranges($id)]} {
-           lappend idrowranges($id) $row
            set ranges $idrowranges($id)
+           lappend ranges $row
+           unset idrowranges($id)
        }
        lappend rowrangelist $ranges
        incr row
@@ -1326,6 +1410,7 @@ proc addextraid {id row} {
     }
     if {[info exists children($id)]} {
        lappend childlist $children($id)
+       unset children($id)
     } else {
        lappend childlist {}
     }
@@ -1344,6 +1429,7 @@ proc layouttail {} {
        unset idinlist($id)
        lappend idrowranges($id) $row
        lappend rowrangelist $idrowranges($id)
+       unset idrowranges($id)
        incr row
        set offs [ntimes $col 0]
        set idlist [lreplace $idlist $col $col]
@@ -1358,6 +1444,7 @@ proc layouttail {} {
        makeuparrow $id 0 $row 0
        lappend idrowranges($id) $row
        lappend rowrangelist $idrowranges($id)
+       unset idrowranges($id)
        incr row
        lappend rowidlist {}
        lappend rowoffsets {}
@@ -1393,8 +1480,8 @@ proc optimize_rows {row col endrow} {
            set z0 [lindex $rowoffsets $y0 $x0]
            if {$z0 eq {}} {
                set id [lindex $idlist $col]
-               if {[info exists idrowranges($id)] &&
-                   $y0 > [lindex $idrowranges($id) 0]} {
+               set ranges [rowranges $id]
+               if {$ranges ne {} && $y0 > [lindex $ranges 0]} {
                    set isarrow 1
                }
            }
@@ -1452,8 +1539,8 @@ proc optimize_rows {row col endrow} {
                if {$o eq {}} {
                    # check if this is the link to the first child
                    set id [lindex $idlist $col]
-                   if {[info exists idrowranges($id)] &&
-                       $row == [lindex $idrowranges($id) 0]} {
+                   set ranges [rowranges $id]
+                   if {$ranges ne {} && $row == [lindex $ranges 0]} {
                        # it is, work out offset to child
                        set y0 [expr {$row - 1}]
                        set id [lindex $displayorder $y0]
@@ -1508,10 +1595,11 @@ proc linewidth {id} {
 }
 
 proc rowranges {id} {
-    global idrowranges commitrow numcommits rowrangelist
+    global phase idrowranges commitrow rowlaidout rowrangelist
 
     set ranges {}
-    if {[info exists commitrow($id)] && $commitrow($id) < $numcommits} {
+    if {$phase eq {} ||
+       ([info exists commitrow($id)] && $commitrow($id) < $rowlaidout)} {
        set ranges [lindex $rowrangelist $commitrow($id)]
     } elseif {[info exists idrowranges($id)]} {
        set ranges $idrowranges($id)
@@ -1722,6 +1810,7 @@ proc drawcmitrow {row} {
 
     if {$row >= $numcommits} return
     foreach id [lindex $rowidlist $row] {
+       if {$id eq {}} continue
        set i -1
        foreach {s e} [rowranges $id] {
            incr i
@@ -1989,7 +2078,7 @@ proc xcoord {i level ln} {
 proc finishcommits {} {
     global commitidx phase
     global canv mainfont ctext maincursor textcursor
-    global findinprogress
+    global findinprogress pending_select
 
     if {$commitidx > 0} {
        drawrest
@@ -2003,6 +2092,7 @@ proc finishcommits {} {
        settextcursor $textcursor
     }
     set phase {}
+    catch {unset pending_select}
 }
 
 # Don't change the text pane cursor if it is currently the hand cursor,
@@ -2021,12 +2111,16 @@ proc drawrest {} {
     global startmsecs
     global canvy0 numcommits linespc
     global rowlaidout commitidx
+    global pending_select
 
     set row $rowlaidout
     layoutrows $rowlaidout $commitidx 1
     layouttail
     optimize_rows $row 0 $commitidx
     showstuff $commitidx
+    if {[info exists pending_select]} {
+       selectline 0 1
+    }
 
     set drawmsecs [expr {[clock clicks -milliseconds] - $startmsecs}]
     #puts "overall $drawmsecs ms for $numcommits commits"
@@ -2216,7 +2310,7 @@ proc stopfindproc {{done 0}} {
     }
     if {[info exists findinprogress]} {
        unset findinprogress
-       if {$phase != "incrdraw"} {
+       if {$phase eq {}} {
            . config -cursor $maincursor
            settextcursor $textcursor
        }
@@ -2755,17 +2849,18 @@ proc unselectline {} {
 }
 
 proc addtohistory {cmd} {
-    global history historyindex
+    global history historyindex curview
 
+    set elt [list $curview $cmd]
     if {$historyindex > 0
-       && [lindex $history [expr {$historyindex - 1}]] == $cmd} {
+       && [lindex $history [expr {$historyindex - 1}]] == $elt} {
        return
     }
 
     if {$historyindex < [llength $history]} {
-       set history [lreplace $history $historyindex end $cmd]
+       set history [lreplace $history $historyindex end $elt]
     } else {
-       lappend history $cmd
+       lappend history $elt
     }
     incr historyindex
     if {$historyindex > 1} {
@@ -2776,13 +2871,23 @@ proc addtohistory {cmd} {
     .ctop.top.bar.rightbut conf -state disabled
 }
 
+proc godo {elt} {
+    global curview
+
+    set view [lindex $elt 0]
+    set cmd [lindex $elt 1]
+    if {$curview != $view} {
+       showview $view
+    }
+    eval $cmd
+}
+
 proc goback {} {
     global history historyindex
 
     if {$historyindex > 1} {
        incr historyindex -1
-       set cmd [lindex $history [expr {$historyindex - 1}]]
-       eval $cmd
+       godo [lindex $history [expr {$historyindex - 1}]]
        .ctop.top.bar.rightbut conf -state normal
     }
     if {$historyindex <= 1} {
@@ -2796,7 +2901,7 @@ proc goforw {} {
     if {$historyindex < [llength $history]} {
        set cmd [lindex $history $historyindex]
        incr historyindex
-       eval $cmd
+       godo $cmd
        .ctop.top.bar.leftbut conf -state normal
     }
     if {$historyindex >= [llength $history]} {
@@ -3132,7 +3237,7 @@ proc incrfont {inc} {
     foreach e $entries {
        $e conf -font $mainfont
     }
-    if {$phase == "getcommits"} {
+    if {$phase eq "getcommits"} {
        $canv itemconf textitems -font $mainfont
     }
     redisplay