git-clone: exit early if repo isn't specified
[git.git] / gitk
diff --git a/gitk b/gitk
index 4e66d86..03cd475 100755 (executable)
--- a/gitk
+++ b/gitk
@@ -39,6 +39,7 @@ proc start_rev_list {rlargs} {
     set startmsecs [clock clicks -milliseconds]
     set nextupdate [expr {$startmsecs + 100}]
     set ncmupdate 1
     set startmsecs [clock clicks -milliseconds]
     set nextupdate [expr {$startmsecs + 100}]
     set ncmupdate 1
+    initlayout
     set order "--topo-order"
     if {$datemode} {
        set order "--date-order"
     set order "--topo-order"
     if {$datemode} {
        set order "--date-order"
@@ -61,16 +62,8 @@ proc start_rev_list {rlargs} {
 }
 
 proc getcommits {rargs} {
 }
 
 proc getcommits {rargs} {
-    global oldcommits commits phase canv mainfont env
+    global phase canv mainfont
 
 
-    # check that we can find a .git directory somewhere...
-    set gitdir [gitdir]
-    if {![file isdirectory $gitdir]} {
-       error_popup "Cannot find the git directory \"$gitdir\"."
-       exit 1
-    }
-    set oldcommits {}
-    set commits {}
     set phase getcommits
     start_rev_list [parse_args $rargs]
     $canv delete all
     set phase getcommits
     start_rev_list [parse_args $rargs]
     $canv delete all
@@ -79,10 +72,9 @@ proc getcommits {rargs} {
 }
 
 proc getcommitlines {commfd}  {
 }
 
 proc getcommitlines {commfd}  {
-    global oldcommits commits parents cdate children nchildren
-    global commitlisted phase nextupdate
-    global stopped leftover
-    global canv
+    global commitlisted nextupdate
+    global leftover
+    global displayorder commitidx commitrow commitdata
 
     set stuff [read $commfd]
     if {$stuff == {}} {
 
     set stuff [read $commfd]
     if {$stuff == {}} {
@@ -105,16 +97,19 @@ proc getcommitlines {commfd}  {
        exit 1
     }
     set start 0
        exit 1
     }
     set start 0
+    set gotsome 0
     while 1 {
        set i [string first "\0" $stuff $start]
        if {$i < 0} {
            append leftover [string range $stuff $start end]
            break
        }
     while 1 {
        set i [string first "\0" $stuff $start]
        if {$i < 0} {
            append leftover [string range $stuff $start end]
            break
        }
-       set cmit [string range $stuff $start [expr {$i - 1}]]
        if {$start == 0} {
        if {$start == 0} {
-           set cmit "$leftover$cmit"
+           set cmit $leftover
+           append cmit [string range $stuff 0 [expr {$i - 1}]]
            set leftover {}
            set leftover {}
+       } else {
+           set cmit [string range $stuff $start [expr {$i - 1}]]
        }
        set start [expr {$i + 1}]
        set j [string first "\n" $cmit]
        }
        set start [expr {$i + 1}]
        set j [string first "\n" $cmit]
@@ -123,7 +118,7 @@ proc getcommitlines {commfd}  {
            set ids [string range $cmit 0 [expr {$j - 1}]]
            set ok 1
            foreach id $ids {
            set ids [string range $cmit 0 [expr {$j - 1}]]
            set ok 1
            foreach id $ids {
-               if {![regexp {^[0-9a-f]{40}$} $id]} {
+               if {[string length $id] != 40} {
                    set ok 0
                    break
                }
                    set ok 0
                    break
                }
@@ -139,13 +134,17 @@ proc getcommitlines {commfd}  {
        }
        set id [lindex $ids 0]
        set olds [lrange $ids 1 end]
        }
        set id [lindex $ids 0]
        set olds [lrange $ids 1 end]
-       set cmit [string range $cmit [expr {$j + 1}] end]
-       lappend commits $id
        set commitlisted($id) 1
        set commitlisted($id) 1
-       parsecommit $id $cmit 1 [lrange $ids 1 end]
-       drawcommit $id 1
+       updatechildren $id $olds
+       set commitdata($id) [string range $cmit [expr {$j + 1}] end]
+       set commitrow($id) $commitidx
+       incr commitidx
+       lappend displayorder $id
+       set gotsome 1
+    }
+    if {$gotsome} {
+       layoutmore
     }
     }
-    layoutmore
     if {[clock clicks -milliseconds] >= $nextupdate} {
        doupdate 1
     }
     if {[clock clicks -milliseconds] >= $nextupdate} {
        doupdate 1
     }
@@ -173,97 +172,23 @@ proc doupdate {reading} {
 
 proc readcommit {id} {
     if {[catch {set contents [exec git-cat-file commit $id]}]} return
 
 proc readcommit {id} {
     if {[catch {set contents [exec git-cat-file commit $id]}]} return
-    parsecommit $id $contents 0 {}
+    updatechildren $id {}
+    parsecommit $id $contents 0
 }
 
 proc updatecommits {rargs} {
 }
 
 proc updatecommits {rargs} {
-    global commitlisted commfd phase
-    global startmsecs nextupdate ncmupdate
-    global idtags idheads idotherrefs
-    global leftover
-    global parsed_args
-    global canv mainfont
-    global oldcommits commits
-    global parents nchildren children
-
-    set old_args $parsed_args
-    parse_args $rargs
-
-    if {$phase == "getcommits" || $phase == "incrdraw"} {
-       # havent read all the old commits, just start again from scratch
-       stopfindproc
-       set oldcommits {}
-       set commits {}
-       foreach v {children nchildren parents commitlisted commitinfo
-                  selectedline matchinglines treediffs
-                  mergefilelist currentid rowtextx} {
-           global $v
-           catch {unset $v}
-       }
-       readrefs
-       if {$phase == "incrdraw"} {
-           allcanvs delete all
-           $canv create text 3 3 -anchor nw -text "Reading commits..." \
-               -font $mainfont -tags textitems
-           set phase getcommits
-       }
-       start_rev_list $parsed_args
-       return
-    }
-
-    foreach id $old_args {
-       if {![regexp {^[0-9a-f]{40}$} $id]} continue
-       if {[info exists oldref($id)]} continue
-       set oldref($id) $id
-       lappend ignoreold "^$id"
-    }
-    foreach id $parsed_args {
-       if {![regexp {^[0-9a-f]{40}$} $id]} continue
-       if {[info exists ref($id)]} continue
-       set ref($id) $id
-       lappend ignorenew "^$id"
-    }
-
-    foreach a $old_args {
-       if {![info exists ref($a)]} {
-           lappend ignorenew $a
-       }
-    }
-
-    set phase updatecommits
-    set oldcommits $commits
-    set commits {}
-    set removed_commits [split [eval exec git-rev-list $ignorenew] "\n" ]
-    if {[llength $removed_commits] > 0} {
-       allcanvs delete all
-       foreach c $removed_commits {
-           set i [lsearch -exact $oldcommits $c]
-           if {$i >= 0} {
-               set oldcommits [lreplace $oldcommits $i $i]
-               unset commitlisted($c)
-               foreach p $parents($c) {
-                   if {[info exists nchildren($p)]} {
-                       set j [lsearch -exact $children($p) $c]
-                       if {$j >= 0} {
-                           set children($p) [lreplace $children($p) $j $j]
-                           incr nchildren($p) -1
-                       }
-                   }
-               }
-           }
-       }
-       set phase removecommits
-    }
-
-    set args {}
-    foreach a $parsed_args {
-       if {![info exists oldref($a)]} {
-           lappend args $a
-       }
+    stopfindproc
+    foreach v {children nchildren parents nparents commitlisted
+       colormap selectedline matchinglines treediffs
+       mergefilelist currentid rowtextx commitrow
+       rowidlist rowoffsets idrowranges idrangedrawn iddrawn
+       linesegends crossings cornercrossings} {
+       global $v
+       catch {unset $v}
     }
     }
-
+    allcanvs delete all
     readrefs
     readrefs
-    start_rev_list [concat $ignoreold $args]
+    getcommits $rargs
 }
 
 proc updatechildren {id olds} {
 }
 
 proc updatechildren {id olds} {
@@ -286,7 +211,7 @@ proc updatechildren {id olds} {
     }
 }
 
     }
 }
 
-proc parsecommit {id contents listed olds} {
+proc parsecommit {id contents listed} {
     global commitinfo cdate
 
     set inhdr 1
     global commitinfo cdate
 
     set inhdr 1
@@ -296,7 +221,6 @@ proc parsecommit {id contents listed olds} {
     set audate {}
     set comname {}
     set comdate {}
     set audate {}
     set comname {}
     set comdate {}
-    updatechildren $id $olds
     set hdrend [string first "\n\n" $contents]
     if {$hdrend < 0} {
        # should never happen...
     set hdrend [string first "\n\n" $contents]
     if {$hdrend < 0} {
        # should never happen...
@@ -340,6 +264,21 @@ proc parsecommit {id contents listed olds} {
                             $comname $comdate $comment]
 }
 
                             $comname $comdate $comment]
 }
 
+proc getcommit {id} {
+    global commitdata commitinfo nparents
+
+    if {[info exists commitdata($id)]} {
+       parsecommit $id $commitdata($id) 1
+    } else {
+       readcommit $id
+       if {![info exists commitinfo($id)]} {
+           set commitinfo($id) {"No commit information available"}
+           set nparents($id) 0
+       }
+    }
+    return 1
+}
+
 proc readrefs {} {
     global tagids idtags headids idheads tagcontents
     global otherrefids idotherrefs
 proc readrefs {} {
     global tagids idtags headids idheads tagcontents
     global otherrefids idotherrefs
@@ -393,6 +332,7 @@ proc error_popup msg {
     button $w.ok -text OK -command "destroy $w"
     pack $w.ok -side bottom -fill x
     bind $w <Visibility> "grab $w; focus $w"
     button $w.ok -text OK -command "destroy $w"
     pack $w.ok -side bottom -fill x
     bind $w <Visibility> "grab $w; focus $w"
+    bind $w <Key-Return> "destroy $w"
     tkwait window $w
 }
 
     tkwait window $w
 }
 
@@ -825,30 +765,30 @@ proc sanity {row {full 0}} {
     global rowidlist rowoffsets
 
     set col -1
     global rowidlist rowoffsets
 
     set col -1
-    set ids $rowidlist($row)
+    set ids [lindex $rowidlist $row]
     foreach id $ids {
        incr col
        if {$id eq {}} continue
        if {$col < [llength $ids] - 1 &&
            [lsearch -exact -start [expr {$col+1}] $ids $id] >= 0} {
     foreach id $ids {
        incr col
        if {$id eq {}} continue
        if {$col < [llength $ids] - 1 &&
            [lsearch -exact -start [expr {$col+1}] $ids $id] >= 0} {
-           puts "oops: [shortids $id] repeated in row $row col $col: {[shortids $rowidlist($row)]}"
+           puts "oops: [shortids $id] repeated in row $row col $col: {[shortids [lindex $rowidlist $row]]}"
        }
        }
-       set o [lindex $rowoffsets($row) $col]
+       set o [lindex $rowoffsets $row $col]
        set y $row
        set x $col
        while {$o ne {}} {
            incr y -1
            incr x $o
        set y $row
        set x $col
        while {$o ne {}} {
            incr y -1
            incr x $o
-           if {[lindex $rowidlist($y) $x] != $id} {
+           if {[lindex $rowidlist $y $x] != $id} {
                puts "oops: rowoffsets wrong at row [expr {$y+1}] col [expr {$x-$o}]"
                puts "  id=[shortids $id] check started at row $row"
                for {set i $row} {$i >= $y} {incr i -1} {
                puts "oops: rowoffsets wrong at row [expr {$y+1}] col [expr {$x-$o}]"
                puts "  id=[shortids $id] check started at row $row"
                for {set i $row} {$i >= $y} {incr i -1} {
-                   puts "  row $i ids={[shortids $rowidlist($i)]} offs={$rowoffsets($i)}"
+                   puts "  row $i ids={[shortids [lindex $rowidlist $i]]} offs={[lindex $rowoffsets $i]}"
                }
                break
            }
            if {!$full} break
                }
                break
            }
            if {!$full} break
-           set o [lindex $rowoffsets($y) $x]
+           set o [lindex $rowoffsets $y $x]
        }
     }
 }
        }
     }
 }
@@ -859,10 +799,10 @@ proc makeuparrow {oid x y z} {
     for {set i 1} {$i < $uparrowlen && $y > 1} {incr i} {
        incr y -1
        incr x $z
     for {set i 1} {$i < $uparrowlen && $y > 1} {incr i} {
        incr y -1
        incr x $z
-       set off0 $rowoffsets($y)
+       set off0 [lindex $rowoffsets $y]
        for {set x0 $x} {1} {incr x0} {
            if {$x0 >= [llength $off0]} {
        for {set x0 $x} {1} {incr x0} {
            if {$x0 >= [llength $off0]} {
-               set x0 [llength $rowoffsets([expr {$y-1}])]
+               set x0 [llength [lindex $rowoffsets [expr {$y-1}]]]
                break
            }
            set z [lindex $off0 $x0]
                break
            }
            set z [lindex $off0 $x0]
@@ -872,11 +812,11 @@ proc makeuparrow {oid x y z} {
            }
        }
        set z [expr {$x0 - $x}]
            }
        }
        set z [expr {$x0 - $x}]
-       set rowidlist($y) [linsert $rowidlist($y) $x $oid]
-       set rowoffsets($y) [linsert $rowoffsets($y) $x $z]
+       lset rowidlist $y [linsert [lindex $rowidlist $y] $x $oid]
+       lset rowoffsets $y [linsert [lindex $rowoffsets $y] $x $z]
     }
     }
-    set tmp [lreplace $rowoffsets($y) $x $x {}]
-    set rowoffsets($y) [incrange $tmp [expr {$x+1}] -1]
+    set tmp [lreplace [lindex $rowoffsets $y] $x $x {}]
+    lset rowoffsets $y [incrange $tmp [expr {$x+1}] -1]
     lappend idrowranges($oid) $y
 }
 
     lappend idrowranges($oid) $y
 }
 
@@ -884,9 +824,15 @@ proc initlayout {} {
     global rowidlist rowoffsets displayorder
     global rowlaidout rowoptim
     global idinlist rowchk
     global rowidlist rowoffsets displayorder
     global rowlaidout rowoptim
     global idinlist rowchk
+    global commitidx numcommits
+    global nextcolor
 
 
-    set rowidlist(0) {}
-    set rowoffsets(0) {}
+    set commitidx 0
+    set numcommits 0
+    set displayorder {}
+    set nextcolor 0
+    set rowidlist {{}}
+    set rowoffsets {{}}
     catch {unset idinlist}
     catch {unset rowchk}
     set rowlaidout 0
     catch {unset idinlist}
     catch {unset rowchk}
     set rowlaidout 0
@@ -935,6 +881,11 @@ proc showstuff {canshow} {
     global canvy0 linespc
     global linesegends idrowranges idrangedrawn
 
     global canvy0 linespc
     global linesegends idrowranges idrangedrawn
 
+    if {$numcommits == 0} {
+       global phase
+       set phase "incrdraw"
+       allcanvs delete all
+    }
     set row $numcommits
     set numcommits $canshow
     allcanvs conf -scrollregion \
     set row $numcommits
     set numcommits $canshow
     allcanvs conf -scrollregion \
@@ -950,7 +901,7 @@ proc showstuff {canshow} {
                    incr i
                    if {$e ne {} && $e < $numcommits && $s <= $r1 && $e >= $r0
                        && ![info exists idrangedrawn($id,$i)]} {
                    incr i
                    if {$e ne {} && $e < $numcommits && $s <= $r1 && $e >= $r0
                        && ![info exists idrangedrawn($id,$i)]} {
-                       drawlineseg $id $i 1
+                       drawlineseg $id $i
                        set idrangedrawn($id,$i) 1
                    }
                }
                        set idrangedrawn($id,$i) 1
                    }
                }
@@ -974,8 +925,8 @@ proc layoutrows {row endrow last} {
     global commitidx
     global idinlist rowchk
 
     global commitidx
     global idinlist rowchk
 
-    set idlist $rowidlist($row)
-    set offs $rowoffsets($row)
+    set idlist [lindex $rowidlist $row]
+    set offs [lindex $rowoffsets $row]
     while {$row < $endrow} {
        set id [lindex $displayorder $row]
        set oldolds {}
     while {$row < $endrow} {
        set id [lindex $displayorder $row]
        set oldolds {}
@@ -1001,29 +952,30 @@ proc layoutrows {row endrow last} {
                        set offs [lreplace $offs $x $x]
                        set offs [incrange $offs $x 1]
                        set idinlist($i) 0
                        set offs [lreplace $offs $x $x]
                        set offs [incrange $offs $x 1]
                        set idinlist($i) 0
-                       lappend linesegends($row) $i
-                       lappend idrowranges($i) [expr {$row-1}]
+                       set rm1 [expr {$row - 1}]
+                       lappend linesegends($rm1) $i
+                       lappend idrowranges($i) $rm1
                        if {[incr nev -1] <= 0} break
                        continue
                    }
                    set rowchk($id) [expr {$row + $r}]
                }
            }
                        if {[incr nev -1] <= 0} break
                        continue
                    }
                    set rowchk($id) [expr {$row + $r}]
                }
            }
-           set rowidlist($row) $idlist
-           set rowoffsets($row) $offs
+           lset rowidlist $row $idlist
+           lset rowoffsets $row $offs
        }
        set col [lsearch -exact $idlist $id]
        if {$col < 0} {
            set col [llength $idlist]
            lappend idlist $id
        }
        set col [lsearch -exact $idlist $id]
        if {$col < 0} {
            set col [llength $idlist]
            lappend idlist $id
-           set rowidlist($row) $idlist
+           lset rowidlist $row $idlist
            set z {}
            if {$nchildren($id) > 0} {
            set z {}
            if {$nchildren($id) > 0} {
-               set z [expr {[llength $rowidlist([expr {$row-1}])] - $col}]
+               set z [expr {[llength [lindex $rowidlist [expr {$row-1}]]] - $col}]
                unset idinlist($id)
            }
            lappend offs $z
                unset idinlist($id)
            }
            lappend offs $z
-           set rowoffsets($row) $offs
+           lset rowoffsets $row $offs
            if {$z ne {}} {
                makeuparrow $id $col $row $z
            }
            if {$z ne {}} {
                makeuparrow $id $col $row $z
            }
@@ -1031,7 +983,6 @@ proc layoutrows {row endrow last} {
            unset idinlist($id)
        }
        if {[info exists idrowranges($id)]} {
            unset idinlist($id)
        }
        if {[info exists idrowranges($id)]} {
-           lappend linesegends($row) $id
            lappend idrowranges($id) $row
        }
        incr row
            lappend idrowranges($id) $row
        }
        incr row
@@ -1065,20 +1016,19 @@ proc layoutrows {row endrow last} {
            makeuparrow $oid $col $row $o
            incr col
        }
            makeuparrow $oid $col $row $o
            incr col
        }
-       set rowidlist($row) $idlist
-       set rowoffsets($row) $offs
+       lappend rowidlist $idlist
+       lappend rowoffsets $offs
     }
     return $row
 }
 
 proc addextraid {id row} {
     }
     return $row
 }
 
 proc addextraid {id row} {
-    global displayorder commitrow lineid commitinfo nparents
+    global displayorder commitrow commitinfo nparents
     global commitidx
 
     incr commitidx
     lappend displayorder $id
     set commitrow($id) $row
     global commitidx
 
     incr commitidx
     lappend displayorder $id
     set commitrow($id) $row
-    set lineid($row) $id
     readcommit $id
     if {![info exists commitinfo($id)]} {
        set commitinfo($id) {"No commit information available"}
     readcommit $id
     if {![info exists commitinfo($id)]} {
        set commitinfo($id) {"No commit information available"}
@@ -1088,32 +1038,32 @@ proc addextraid {id row} {
 
 proc layouttail {} {
     global rowidlist rowoffsets idinlist commitidx
 
 proc layouttail {} {
     global rowidlist rowoffsets idinlist commitidx
-    global idrowranges linesegends
+    global idrowranges
 
     set row $commitidx
 
     set row $commitidx
-    set idlist $rowidlist($row)
+    set idlist [lindex $rowidlist $row]
     while {$idlist ne {}} {
        set col [expr {[llength $idlist] - 1}]
        set id [lindex $idlist $col]
        addextraid $id $row
        unset idinlist($id)
     while {$idlist ne {}} {
        set col [expr {[llength $idlist] - 1}]
        set id [lindex $idlist $col]
        addextraid $id $row
        unset idinlist($id)
-       lappend linesegends($row) $id
        lappend idrowranges($id) $row
        incr row
        set offs [ntimes $col 0]
        set idlist [lreplace $idlist $col $col]
        lappend idrowranges($id) $row
        incr row
        set offs [ntimes $col 0]
        set idlist [lreplace $idlist $col $col]
-       set rowidlist($row) $idlist
-       set rowoffsets($row) $offs
+       lappend rowidlist $idlist
+       lappend rowoffsets $offs
     }
 
     foreach id [array names idinlist] {
        addextraid $id $row
     }
 
     foreach id [array names idinlist] {
        addextraid $id $row
-       set rowidlist($row) [list $id]
-       set rowoffsets($row) 0
+       lset rowidlist $row [list $id]
+       lset rowoffsets $row 0
        makeuparrow $id 0 $row 0
        makeuparrow $id 0 $row 0
-       lappend linesegends($row) $id
        lappend idrowranges($id) $row
        incr row
        lappend idrowranges($id) $row
        incr row
+       lappend rowidlist {}
+       lappend rowoffsets {}
     }
 }
 
     }
 }
 
@@ -1121,18 +1071,29 @@ proc insert_pad {row col npad} {
     global rowidlist rowoffsets
 
     set pad [ntimes $npad {}]
     global rowidlist rowoffsets
 
     set pad [ntimes $npad {}]
-    set rowidlist($row) [eval linsert \$rowidlist($row) $col $pad]
-    set tmp [eval linsert \$rowoffsets($row) $col $pad]
-    set rowoffsets($row) [incrange $tmp [expr {$col + $npad}] [expr {-$npad}]]
+    lset rowidlist $row [eval linsert [list [lindex $rowidlist $row]] $col $pad]
+    set tmp [eval linsert [list [lindex $rowoffsets $row]] $col $pad]
+    lset rowoffsets $row [incrange $tmp [expr {$col + $npad}] [expr {-$npad}]]
 }
 
 proc optimize_rows {row col endrow} {
 }
 
 proc optimize_rows {row col endrow} {
-    global rowidlist rowoffsets idrowranges
+    global rowidlist rowoffsets idrowranges linesegends displayorder
 
     for {} {$row < $endrow} {incr row} {
 
     for {} {$row < $endrow} {incr row} {
-       set idlist $rowidlist($row)
-       set offs $rowoffsets($row)
+       set idlist [lindex $rowidlist $row]
+       set offs [lindex $rowoffsets $row]
        set haspad 0
        set haspad 0
+       set downarrowcols {}
+       if {[info exists linesegends($row)]} {
+           set downarrowcols $linesegends($row)
+           if {$col > 0} {
+               while {$downarrowcols ne {}} {
+                   set i [lsearch -exact $idlist [lindex $downarrowcols 0]]
+                   if {$i < 0 || $i >= $col} break
+                   set downarrowcols [lrange $downarrowcols 1 end]
+               }
+           }
+       }
        for {} {$col < [llength $offs]} {incr col} {
            if {[lindex $idlist $col] eq {}} {
                set haspad 1
        for {} {$col < [llength $offs]} {incr col} {
            if {[lindex $idlist $col] eq {}} {
                set haspad 1
@@ -1143,13 +1104,17 @@ proc optimize_rows {row col endrow} {
            set isarrow 0
            set x0 [expr {$col + $z}]
            set y0 [expr {$row - 1}]
            set isarrow 0
            set x0 [expr {$col + $z}]
            set y0 [expr {$row - 1}]
-           set z0 [lindex $rowoffsets($y0) $x0]
+           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 isarrow 1
                }
            if {$z0 eq {}} {
                set id [lindex $idlist $col]
                if {[info exists idrowranges($id)] &&
                    $y0 > [lindex $idrowranges($id) 0]} {
                    set isarrow 1
                }
+           } elseif {$downarrowcols ne {} &&
+                     [lindex $idlist $col] eq [lindex $downarrowcols 0]} {
+               set downarrowcols [lrange $downarrowcols 1 end]
+               set isarrow 1
            }
            if {$z < -1 || ($z < 0 && $isarrow)} {
                set npad [expr {-1 - $z + $isarrow}]
            }
            if {$z < -1 || ($z < 0 && $isarrow)} {
                set npad [expr {-1 - $z + $isarrow}]
@@ -1160,11 +1125,11 @@ proc optimize_rows {row col endrow} {
                }
                set z [lindex $offs $col]
                set x0 [expr {$col + $z}]
                }
                set z [lindex $offs $col]
                set x0 [expr {$col + $z}]
-               set z0 [lindex $rowoffsets($y0) $x0]
+               set z0 [lindex $rowoffsets $y0 $x0]
            } elseif {$z > 1 || ($z > 0 && $isarrow)} {
                set npad [expr {$z - 1 + $isarrow}]
                set y1 [expr {$row + 1}]
            } elseif {$z > 1 || ($z > 0 && $isarrow)} {
                set npad [expr {$z - 1 + $isarrow}]
                set y1 [expr {$row + 1}]
-               set offs2 $rowoffsets($y1)
+               set offs2 [lindex $rowoffsets $y1]
                set x1 -1
                foreach z $offs2 {
                    incr x1
                set x1 -1
                foreach z $offs2 {
                    incr x1
@@ -1172,7 +1137,7 @@ proc optimize_rows {row col endrow} {
                    if {$x1 + $z > $col} {
                        incr npad
                    }
                    if {$x1 + $z > $col} {
                        incr npad
                    }
-                   set rowoffsets($y1) [incrange $offs2 $x1 $npad]
+                   lset rowoffsets $y1 [incrange $offs2 $x1 $npad]
                    break
                }
                set pad [ntimes $npad {}]
                    break
                }
                set pad [ntimes $npad {}]
@@ -1183,6 +1148,15 @@ proc optimize_rows {row col endrow} {
                set z [lindex $offs $col]
                set haspad 1
            }
                set z [lindex $offs $col]
                set haspad 1
            }
+           if {$z0 eq {} && !$isarrow} {
+               # this line links to its first child on row $row-2
+               set rm2 [expr {$row - 2}]
+               set id [lindex $displayorder $rm2]
+               set xc [lsearch -exact [lindex $rowidlist $rm2] $id]
+               if {$xc >= 0} {
+                   set z0 [expr {$xc - $x0}]
+               }
+           }
            if {$z0 ne {} && $z < 0 && $z0 > 0} {
                insert_pad $y0 $x0 1
                set offs [incrange $offs $col 1]
            if {$z0 ne {} && $z < 0 && $z0 > 0} {
                insert_pad $y0 $x0 1
                set offs [incrange $offs $col 1]
@@ -1190,18 +1164,33 @@ proc optimize_rows {row col endrow} {
            }
        }
        if {!$haspad} {
            }
        }
        if {!$haspad} {
+           set o {}
            for {set col [llength $idlist]} {[incr col -1] >= 0} {} {
                set o [lindex $offs $col]
            for {set col [llength $idlist]} {[incr col -1] >= 0} {} {
                set o [lindex $offs $col]
+               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]} {
+                       # it is, work out offset to child
+                       set y0 [expr {$row - 1}]
+                       set id [lindex $displayorder $y0]
+                       set x0 [lsearch -exact [lindex $rowidlist $y0] $id]
+                       if {$x0 >= 0} {
+                           set o [expr {$x0 - $col}]
+                       }
+                   }
+               }
                if {$o eq {} || $o <= 0} break
            }
                if {$o eq {} || $o <= 0} break
            }
-           if {[incr col] < [llength $idlist]} {
+           if {$o ne {} && [incr col] < [llength $idlist]} {
                set y1 [expr {$row + 1}]
                set y1 [expr {$row + 1}]
-               set offs2 $rowoffsets($y1)
+               set offs2 [lindex $rowoffsets $y1]
                set x1 -1
                foreach z $offs2 {
                    incr x1
                    if {$z eq {} || $x1 + $z < $col} continue
                set x1 -1
                foreach z $offs2 {
                    incr x1
                    if {$z eq {} || $x1 + $z < $col} continue
-                   set rowoffsets($y1) [incrange $offs2 $x1 1]
+                   lset rowoffsets $y1 [incrange $offs2 $x1 1]
                    break
                }
                set idlist [linsert $idlist $col {}]
                    break
                }
                set idlist [linsert $idlist $col {}]
@@ -1210,8 +1199,8 @@ proc optimize_rows {row col endrow} {
                set offs [incrange $tmp $col -1]
            }
        }
                set offs [incrange $tmp $col -1]
            }
        }
-       set rowidlist($row) $idlist
-       set rowoffsets($row) $offs
+       lset rowidlist $row $idlist
+       lset rowoffsets $row $offs
        set col 0
     }
 }
        set col 0
     }
 }
@@ -1226,16 +1215,27 @@ proc yc {row} {
     return [expr {$canvy0 + $row * $linespc}]
 }
 
     return [expr {$canvy0 + $row * $linespc}]
 }
 
-proc drawlineseg {id i wid} {
+proc linewidth {id} {
+    global thickerline lthickness
+
+    set wid $lthickness
+    if {[info exists thickerline] && $id eq $thickerline} {
+       set wid [expr {2 * $lthickness}]
+    }
+    return $wid
+}
+
+proc drawlineseg {id i} {
     global rowoffsets rowidlist idrowranges
     global rowoffsets rowidlist idrowranges
-    global canv colormap lthickness
+    global displayorder
+    global canv colormap
 
     set startrow [lindex $idrowranges($id) [expr {2 * $i}]]
     set row [lindex $idrowranges($id) [expr {2 * $i + 1}]]
     if {$startrow == $row} return
     assigncolor $id
     set coords {}
 
     set startrow [lindex $idrowranges($id) [expr {2 * $i}]]
     set row [lindex $idrowranges($id) [expr {2 * $i + 1}]]
     if {$startrow == $row} return
     assigncolor $id
     set coords {}
-    set col [lsearch -exact $rowidlist($row) $id]
+    set col [lsearch -exact [lindex $rowidlist $row] $id]
     if {$col < 0} {
        puts "oops: drawline: id $id not on row $row"
        return
     if {$col < 0} {
        puts "oops: drawline: id $id not on row $row"
        return
@@ -1243,7 +1243,7 @@ proc drawlineseg {id i wid} {
     set lasto {}
     set ns 0
     while {1} {
     set lasto {}
     set ns 0
     while {1} {
-       set o [lindex $rowoffsets($row) $col]
+       set o [lindex $rowoffsets $row $col]
        if {$o eq {}} break
        if {$o ne $lasto} {
            # changing direction
        if {$o eq {}} break
        if {$o ne $lasto} {
            # changing direction
@@ -1255,33 +1255,52 @@ proc drawlineseg {id i wid} {
        incr col $o
        incr row -1
     }
        incr col $o
        incr row -1
     }
-    if {$coords eq {}} return
-    set last [expr {[llength $idrowranges($id)] / 2 - 1}]
-    set arrow [expr {2 * ($i > 0) + ($i < $last)}]
-    set arrow [lindex {none first last both} $arrow]
-    set wid [expr {$wid * $lthickness}]
     set x [xc $row $col]
     set y [yc $row]
     lappend coords $x $y
     set x [xc $row $col]
     set y [yc $row]
     lappend coords $x $y
-    set t [$canv create line $coords -width $wid \
+    if {$i == 0} {
+       # draw the link to the first child as part of this line
+       incr row -1
+       set child [lindex $displayorder $row]
+       set ccol [lsearch -exact [lindex $rowidlist $row] $child]
+       if {$ccol >= 0} {
+           set x [xc $row $ccol]
+           set y [yc $row]
+           if {$ccol < $col - 1} {
+               lappend coords [xc $row [expr {$col - 1}]] [yc $row]
+           } elseif {$ccol > $col + 1} {
+               lappend coords [xc $row [expr {$col + 1}]] [yc $row]
+           }
+           lappend coords $x $y
+       }
+    }
+    if {[llength $coords] < 4} return
+    set last [expr {[llength $idrowranges($id)] / 2 - 1}]
+    set arrow [expr {2 * ($i > 0) + ($i < $last)}]
+    set arrow [lindex {none first last both} $arrow]
+    set t [$canv create line $coords -width [linewidth $id] \
               -fill $colormap($id) -tags lines.$id -arrow $arrow]
     $canv lower $t
     bindline $t $id
 }
 
               -fill $colormap($id) -tags lines.$id -arrow $arrow]
     $canv lower $t
     bindline $t $id
 }
 
-proc drawparentlinks {id row col olds wid} {
-    global rowoffsets rowidlist canv colormap lthickness
+proc drawparentlinks {id row col olds} {
+    global rowidlist canv colormap idrowranges
 
     set row2 [expr {$row + 1}]
     set x [xc $row $col]
     set y [yc $row]
     set y2 [yc $row2]
 
     set row2 [expr {$row + 1}]
     set x [xc $row $col]
     set y [yc $row]
     set y2 [yc $row2]
-    set ids $rowidlist($row2)
-    set offs $rowidlist($row2)
+    set ids [lindex $rowidlist $row2]
     # rmx = right-most X coord used
     set rmx 0
     # rmx = right-most X coord used
     set rmx 0
-    set wid [expr {$wid * $lthickness}]
     foreach p $olds {
     foreach p $olds {
+       if {[info exists idrowranges($p)] &&
+           $row2 == [lindex $idrowranges($p) 0] &&
+           $row2 < [lindex $idrowranges($p) 1]} {
+           # drawlineseg will do this one for us
+           continue
+       }
        set i [lsearch -exact $ids $p]
        if {$i < 0} {
            puts "oops, parent $p of $id not in list"
        set i [lsearch -exact $ids $p]
        if {$i < 0} {
            puts "oops, parent $p of $id not in list"
@@ -1300,7 +1319,7 @@ proc drawparentlinks {id row col olds wid} {
            set rmx $x2
        }
        lappend coords $x2 $y2
            set rmx $x2
        }
        lappend coords $x2 $y2
-       set t [$canv create line $coords -width $wid \
+       set t [$canv create line $coords -width [linewidth $p] \
                   -fill $colormap($p) -tags lines.$p]
        $canv lower $t
        bindline $t $p
                   -fill $colormap($p) -tags lines.$p]
        $canv lower $t
        bindline $t $p
@@ -1308,26 +1327,25 @@ proc drawparentlinks {id row col olds wid} {
     return $rmx
 }
 
     return $rmx
 }
 
-proc drawlines {id xtra} {
+proc drawlines {id} {
     global colormap canv
     global idrowranges idrangedrawn
     global children iddrawn commitrow rowidlist
 
     $canv delete lines.$id
     global colormap canv
     global idrowranges idrangedrawn
     global children iddrawn commitrow rowidlist
 
     $canv delete lines.$id
-    set wid [expr {$xtra + 1}]
     set nr [expr {[llength $idrowranges($id)] / 2}]
     for {set i 0} {$i < $nr} {incr i} {
        if {[info exists idrangedrawn($id,$i)]} {
     set nr [expr {[llength $idrowranges($id)] / 2}]
     for {set i 0} {$i < $nr} {incr i} {
        if {[info exists idrangedrawn($id,$i)]} {
-           drawlineseg $id $i $wid
+           drawlineseg $id $i
        }
     }
     if {[info exists children($id)]} {
        foreach child $children($id) {
            if {[info exists iddrawn($child)]} {
                set row $commitrow($child)
        }
     }
     if {[info exists children($id)]} {
        foreach child $children($id) {
            if {[info exists iddrawn($child)]} {
                set row $commitrow($child)
-               set col [lsearch -exact $rowidlist($row) $child]
+               set col [lsearch -exact [lindex $rowidlist $row] $child]
                if {$col >= 0} {
                if {$col >= 0} {
-                   drawparentlinks $child $row $col [list $id] $wid
+                   drawparentlinks $child $row $col [list $id]
                }
            }
        }
                }
            }
        }
@@ -1350,7 +1368,7 @@ proc drawcmittext {id row col rmx} {
               -fill $ofill -outline black -width 1]
     $canv raise $t
     $canv bind $t <1> {selcanvline {} %x %y}
               -fill $ofill -outline black -width 1]
     $canv raise $t
     $canv bind $t <1> {selcanvline {} %x %y}
-    set xt [xc $row [llength $rowidlist($row)]]
+    set xt [xc $row [llength [lindex $rowidlist $row]]]
     if {$xt < $rmx} {
        set xt $rmx
     }
     if {$xt < $rmx} {
        set xt $rmx
     }
@@ -1374,12 +1392,12 @@ proc drawcmittext {id row col rmx} {
 }
 
 proc drawcmitrow {row} {
 }
 
 proc drawcmitrow {row} {
-    global displayorder rowidlist rowoffsets
+    global displayorder rowidlist
     global idrowranges idrangedrawn iddrawn
     global commitinfo commitlisted parents numcommits
 
     global idrowranges idrangedrawn iddrawn
     global commitinfo commitlisted parents numcommits
 
-    if {![info exists rowidlist($row)]} return
-    foreach id $rowidlist($row) {
+    if {$row >= $numcommits} return
+    foreach id [lindex $rowidlist $row] {
        if {![info exists idrowranges($id)]} continue
        set i -1
        foreach {s e} $idrowranges($id) {
        if {![info exists idrowranges($id)]} continue
        set i -1
        foreach {s e} $idrowranges($id) {
@@ -1388,7 +1406,7 @@ proc drawcmitrow {row} {
            if {$e eq {}} break
            if {$row <= $e} {
                if {$e < $numcommits && ![info exists idrangedrawn($id,$i)]} {
            if {$e eq {}} break
            if {$row <= $e} {
                if {$e < $numcommits && ![info exists idrangedrawn($id,$i)]} {
-                   drawlineseg $id $i 1
+                   drawlineseg $id $i
                    set idrangedrawn($id,$i) 1
                }
                break
                    set idrangedrawn($id,$i) 1
                }
                break
@@ -1398,22 +1416,18 @@ proc drawcmitrow {row} {
 
     set id [lindex $displayorder $row]
     if {[info exists iddrawn($id)]} return
 
     set id [lindex $displayorder $row]
     if {[info exists iddrawn($id)]} return
-    set col [lsearch -exact $rowidlist($row) $id]
+    set col [lsearch -exact [lindex $rowidlist $row] $id]
     if {$col < 0} {
        puts "oops, row $row id $id not in list"
        return
     }
     if {![info exists commitinfo($id)]} {
     if {$col < 0} {
        puts "oops, row $row id $id not in list"
        return
     }
     if {![info exists commitinfo($id)]} {
-       readcommit $id
-       if {![info exists commitinfo($id)]} {
-           set commitinfo($id) {"No commit information available"}
-           set nparents($id) 0
-       }
+       getcommit $id
     }
     assigncolor $id
     if {[info exists commitlisted($id)] && [info exists parents($id)]
        && $parents($id) ne {}} {
     }
     assigncolor $id
     if {[info exists commitlisted($id)] && [info exists parents($id)]
        && $parents($id) ne {}} {
-       set rmx [drawparentlinks $id $row $col $parents($id) 1]
+       set rmx [drawparentlinks $id $row $col $parents($id)]
     } else {
        set rmx 0
     }
     } else {
        set rmx 0
     }
@@ -1456,7 +1470,7 @@ proc clear_display {} {
 }
 
 proc assigncolor {id} {
 }
 
 proc assigncolor {id} {
-    global colormap commcolors colors nextcolor
+    global colormap colors nextcolor
     global parents nparents children nchildren
     global cornercrossings crossings
 
     global parents nparents children nchildren
     global cornercrossings crossings
 
@@ -1526,19 +1540,6 @@ proc assigncolor {id} {
     set colormap($id) $c
 }
 
     set colormap($id) $c
 }
 
-proc initgraph {} {
-    global numcommits nextcolor linespc
-    global nchildren
-
-    allcanvs delete all
-    set nextcolor 0
-    set numcommits 0
-    foreach v {colormap cornercrossings        crossings lineid} {
-       global $v
-       catch {unset $v}
-    }
-}
-
 proc bindline {t id} {
     global canv
 
 proc bindline {t id} {
     global canv
 
@@ -1620,9 +1621,9 @@ proc checkcrossings {row endrow} {
 
     for {} {$row < $endrow} {incr row} {
        set id [lindex $displayorder $row]
 
     for {} {$row < $endrow} {incr row} {
        set id [lindex $displayorder $row]
-       set i [lsearch -exact $rowidlist($row) $id]
+       set i [lsearch -exact [lindex $rowidlist $row] $id]
        if {$i < 0} continue
        if {$i < 0} continue
-       set idlist $rowidlist([expr {$row+1}])
+       set idlist [lindex $rowidlist [expr {$row+1}]]
        foreach p $parents($id) {
            set j [lsearch -exact $idlist $p]
            if {$j > 0} {
        foreach p $parents($id) {
            set j [lsearch -exact $idlist $p]
            if {$j > 0} {
@@ -1640,7 +1641,7 @@ proc notecrossings {row id lo hi corner} {
     global rowidlist crossings cornercrossings
 
     for {set i $lo} {[incr i] < $hi} {} {
     global rowidlist crossings cornercrossings
 
     for {set i $lo} {[incr i] < $hi} {} {
-       set p [lindex $rowidlist($row) $i]
+       set p [lindex [lindex $rowidlist $row] $i]
        if {$p == {}} continue
        if {$i == $corner} {
            if {![info exists cornercrossings($id)]
        if {$p == {}} continue
        if {$i == $corner} {
            if {![info exists cornercrossings($id)]
@@ -1676,50 +1677,23 @@ proc xcoord {i level ln} {
     return $x
 }
 
     return $x
 }
 
-proc drawcommit {id reading} {
-    global phase todo nchildren nextupdate
-    global displayorder parents
-    global commitrow commitidx lineid
-
-    if {$phase != "incrdraw"} {
-       set phase incrdraw
-       set displayorder {}
-       set todo {}
-       set commitidx 0
-       initlayout
-       initgraph
-    }
-    set commitrow($id) $commitidx
-    set lineid($commitidx) $id
-    incr commitidx
-    lappend displayorder $id
-}
-
 proc finishcommits {} {
 proc finishcommits {} {
-    global phase oldcommits commits
+    global commitidx phase
     global canv mainfont ctext maincursor textcursor
     global canv mainfont ctext maincursor textcursor
-    global parents todo
+    global findinprogress
 
 
-    if {$phase == "incrdraw" || $phase == "removecommits"} {
-       foreach id $oldcommits {
-           lappend commits $id
-           drawcommit $id 0
-       }
-       set oldcommits {}
+    if {$commitidx > 0} {
        drawrest
        drawrest
-    } elseif {$phase == "updatecommits"} {
-       # there were no new commits, in fact
-       set commits $oldcommits
-       set oldcommits {}
-       set phase {}
     } else {
        $canv delete all
        $canv create text 3 3 -anchor nw -text "No commits selected" \
            -font $mainfont -tags textitems
     } else {
        $canv delete all
        $canv create text 3 3 -anchor nw -text "No commits selected" \
            -font $mainfont -tags textitems
-       set phase {}
     }
     }
-    . config -cursor $maincursor
-    settextcursor $textcursor
+    if {![info exists findinprogress]} {
+       . config -cursor $maincursor
+       settextcursor $textcursor
+    }
+    set phase {}
 }
 
 # Don't change the text pane cursor if it is currently the hand cursor,
 }
 
 # Don't change the text pane cursor if it is currently the hand cursor,
@@ -1734,7 +1708,6 @@ proc settextcursor {c} {
 }
 
 proc drawrest {} {
 }
 
 proc drawrest {} {
-    global phase
     global numcommits
     global startmsecs
     global canvy0 numcommits linespc
     global numcommits
     global startmsecs
     global canvy0 numcommits linespc
@@ -1746,7 +1719,6 @@ proc drawrest {} {
     optimize_rows $row 0 $commitidx
     showstuff $commitidx
 
     optimize_rows $row 0 $commitidx
     showstuff $commitidx
 
-    set phase {}
     set drawmsecs [expr {[clock clicks -milliseconds] - $startmsecs}]
     #puts "overall $drawmsecs ms for $numcommits commits"
 }
     set drawmsecs [expr {[clock clicks -milliseconds] - $startmsecs}]
     #puts "overall $drawmsecs ms for $numcommits commits"
 }
@@ -1773,9 +1745,10 @@ proc findmatches {f} {
 
 proc dofind {} {
     global findtype findloc findstring markedmatches commitinfo
 
 proc dofind {} {
     global findtype findloc findstring markedmatches commitinfo
-    global numcommits lineid linehtag linentag linedtag
+    global numcommits displayorder linehtag linentag linedtag
     global mainfont namefont canv canv2 canv3 selectedline
     global mainfont namefont canv canv2 canv3 selectedline
-    global matchinglines foundstring foundstrlen
+    global matchinglines foundstring foundstrlen matchstring
+    global commitdata
 
     stopfindproc
     unmarkmatches
 
     stopfindproc
     unmarkmatches
@@ -1792,6 +1765,8 @@ proc dofind {} {
     }
     set foundstrlen [string length $findstring]
     if {$foundstrlen == 0} return
     }
     set foundstrlen [string length $findstring]
     if {$foundstrlen == 0} return
+    regsub -all {[*?\[\\]} $foundstring {\\&} matchstring
+    set matchstring "*$matchstring*"
     if {$findloc == "Files"} {
        findfiles
        return
     if {$findloc == "Files"} {
        findfiles
        return
@@ -1803,8 +1778,21 @@ proc dofind {} {
     }
     set didsel 0
     set fldtypes {Headline Author Date Committer CDate Comment}
     }
     set didsel 0
     set fldtypes {Headline Author Date Committer CDate Comment}
-    for {set l 0} {$l < $numcommits} {incr l} {
-       set id $lineid($l)
+    set l -1
+    foreach id $displayorder {
+       set d $commitdata($id)
+       incr l
+       if {$findtype == "Regexp"} {
+           set doesmatch [regexp $foundstring $d]
+       } elseif {$findtype == "IgnCase"} {
+           set doesmatch [string match -nocase $matchstring $d]
+       } else {
+           set doesmatch [string match $matchstring $d]
+       }
+       if {!$doesmatch} continue
+       if {![info exists commitinfo($id)]} {
+           getcommit $id
+       }
        set info $commitinfo($id)
        set doesmatch 0
        foreach f $info ty $fldtypes {
        set info $commitinfo($id)
        set doesmatch 0
        foreach f $info ty $fldtypes {
@@ -1929,7 +1917,7 @@ proc stopfindproc {{done 0}} {
 proc findpatches {} {
     global findstring selectedline numcommits
     global findprocpid findprocfile
 proc findpatches {} {
     global findstring selectedline numcommits
     global findprocpid findprocfile
-    global finddidsel ctext lineid findinprogress
+    global finddidsel ctext displayorder findinprogress
     global findinsertpos
 
     if {$numcommits == 0} return
     global findinsertpos
 
     if {$numcommits == 0} return
@@ -1946,7 +1934,7 @@ proc findpatches {} {
        if {[incr l] >= $numcommits} {
            set l 0
        }
        if {[incr l] >= $numcommits} {
            set l 0
        }
-       append inputids $lineid($l) "\n"
+       append inputids [lindex $displayorder $l] "\n"
     }
 
     if {[catch {
     }
 
     if {[catch {
@@ -2017,7 +2005,7 @@ proc insertmatch {l id} {
 }
 
 proc findfiles {} {
 }
 
 proc findfiles {} {
-    global selectedline numcommits lineid ctext
+    global selectedline numcommits displayorder ctext
     global ffileline finddidsel parents nparents
     global findinprogress findstartline findinsertpos
     global treediffs fdiffid fdiffsneeded fdiffpos
     global ffileline finddidsel parents nparents
     global findinprogress findstartline findinsertpos
     global treediffs fdiffid fdiffsneeded fdiffpos
@@ -2035,7 +2023,7 @@ proc findfiles {} {
     set diffsneeded {}
     set fdiffsneeded {}
     while 1 {
     set diffsneeded {}
     set fdiffsneeded {}
     while 1 {
-       set id $lineid($l)
+       set id [lindex $displayorder $l]
        if {$findmergefiles || $nparents($id) == 1} {
            if {![info exists treediffs($id)]} {
                append diffsneeded "$id\n"
        if {$findmergefiles || $nparents($id) == 1} {
            if {![info exists treediffs($id)]} {
                append diffsneeded "$id\n"
@@ -2064,7 +2052,7 @@ proc findfiles {} {
 
     set finddidsel 0
     set findinsertpos end
 
     set finddidsel 0
     set findinsertpos end
-    set id $lineid($l)
+    set id [lindex $displayorder $l]
     . config -cursor watch
     settextcursor watch
     set findinprogress 1
     . config -cursor watch
     settextcursor watch
     set findinprogress 1
@@ -2134,7 +2122,7 @@ proc donefilediff {} {
 proc findcont {id} {
     global findid treediffs parents nparents
     global ffileline findstartline finddidsel
 proc findcont {id} {
     global findid treediffs parents nparents
     global ffileline findstartline finddidsel
-    global lineid numcommits matchinglines findinprogress
+    global displayorder numcommits matchinglines findinprogress
     global findmergefiles
 
     set l $ffileline
     global findmergefiles
 
     set l $ffileline
@@ -2161,7 +2149,7 @@ proc findcont {id} {
            set l 0
        }
        if {$l == $findstartline} break
            set l 0
        }
        if {$l == $findstartline} break
-       set id $lineid($l)
+       set id [lindex $displayorder $l]
     }
     stopfindproc
     if {!$finddidsel} {
     }
     stopfindproc
     if {!$finddidsel} {
@@ -2172,7 +2160,7 @@ proc findcont {id} {
 # mark a commit as matching by putting a yellow background
 # behind the headline
 proc markheadline {l id} {
 # mark a commit as matching by putting a yellow background
 # behind the headline
 proc markheadline {l id} {
-    global canv mainfont linehtag commitinfo
+    global canv mainfont linehtag
 
     drawcmitrow $l
     set bbox [$canv bbox $linehtag($l)]
 
     drawcmitrow $l
     set bbox [$canv bbox $linehtag($l)]
@@ -2260,15 +2248,15 @@ proc appendwithlinks {text} {
 
 proc selectline {l isnew} {
     global canv canv2 canv3 ctext commitinfo selectedline
 
 proc selectline {l isnew} {
     global canv canv2 canv3 ctext commitinfo selectedline
-    global lineid linehtag linentag linedtag
+    global displayorder linehtag linentag linedtag
     global canvy0 linespc parents nparents children
     global cflist currentid sha1entry
     global commentend idtags linknum
     global canvy0 linespc parents nparents children
     global cflist currentid sha1entry
     global commentend idtags linknum
-    global mergemax
+    global mergemax numcommits
 
     $canv delete hover
     normalline
 
     $canv delete hover
     normalline
-    if {![info exists lineid($l)]} return
+    if {$l < 0 || $l >= $numcommits} return
     set y [expr {$canvy0 + $l * $linespc}]
     set ymax [lindex [$canv cget -scrollregion] 3]
     set ytop [expr {$y - $linespc - 1}]
     set y [expr {$canvy0 + $l * $linespc}]
     set ymax [lindex [$canv cget -scrollregion] 3]
     set ytop [expr {$y - $linespc - 1}]
@@ -2325,7 +2313,7 @@ proc selectline {l isnew} {
 
     set selectedline $l
 
 
     set selectedline $l
 
-    set id $lineid($l)
+    set id [lindex $displayorder $l]
     set currentid $id
     $sha1entry delete 0 end
     $sha1entry insert 0 $id
     set currentid $id
     $sha1entry delete 0 end
     $sha1entry insert 0 $id
@@ -2463,9 +2451,10 @@ proc goforw {} {
 
 proc mergediff {id} {
     global parents diffmergeid diffopts mdifffd
 
 proc mergediff {id} {
     global parents diffmergeid diffopts mdifffd
-    global difffilestart
+    global difffilestart diffids
 
     set diffmergeid $id
 
     set diffmergeid $id
+    set diffids $id
     catch {unset difffilestart}
     # this doesn't seem to actually affect anything...
     set env(GIT_DIFF_OPTS) $diffopts
     catch {unset difffilestart}
     # this doesn't seem to actually affect anything...
     set env(GIT_DIFF_OPTS) $diffopts
@@ -2482,7 +2471,7 @@ proc mergediff {id} {
 
 proc getmergediffline {mdf id} {
     global diffmergeid ctext cflist nextupdate nparents mergemax
 
 proc getmergediffline {mdf id} {
     global diffmergeid ctext cflist nextupdate nparents mergemax
-    global difffilestart
+    global difffilestart mdifffd
 
     set n [gets $mdf line]
     if {$n < 0} {
 
     set n [gets $mdf line]
     if {$n < 0} {
@@ -2491,7 +2480,8 @@ proc getmergediffline {mdf id} {
        }
        return
     }
        }
        return
     }
-    if {![info exists diffmergeid] || $id != $diffmergeid} {
+    if {![info exists diffmergeid] || $id != $diffmergeid
+       || $mdf != $mdifffd($id)} {
        return
     }
     $ctext conf -state normal
        return
     }
     $ctext conf -state normal
@@ -2601,13 +2591,11 @@ proc gettreediffline {gdtf ids} {
        set treediffs($ids) $treediff
        unset treepending
        if {$ids != $diffids} {
        set treediffs($ids) $treediff
        unset treepending
        if {$ids != $diffids} {
-           gettreediffs $diffids
-       } else {
-           if {[info exists diffmergeid]} {
-               contmergediff $ids
-           } else {
-               addtocflist $ids
+           if {![info exists diffmergeid]} {
+               gettreediffs $diffids
            }
            }
+       } else {
+           addtocflist $ids
        }
        return
     }
        }
        return
     }
@@ -2683,7 +2671,9 @@ proc getblobdiffline {bdf ids} {
        set pad [string range "----------------------------------------" 1 $l]
        $ctext insert end "$pad $header $pad\n" filesep
        set diffinhdr 1
        set pad [string range "----------------------------------------" 1 $l]
        $ctext insert end "$pad $header $pad\n" filesep
        set diffinhdr 1
-    } elseif {[regexp {^(---|\+\+\+)} $line]} {
+    } elseif {$diffinhdr && [string compare -length 3 $line "---"] == 0} {
+       # do nothing
+    } elseif {$diffinhdr && [string compare -length 3 $line "+++"] == 0} {
        set diffinhdr 0
     } elseif {[regexp {^@@ -([0-9]+),([0-9]+) \+([0-9]+),([0-9]+) @@(.*)} \
                   $line match f1l f1c f2l f2c rest]} {
        set diffinhdr 0
     } elseif {[regexp {^@@ -([0-9]+),([0-9]+) \+([0-9]+),([0-9]+) @@(.*)} \
                   $line match f1l f1c f2l f2c rest]} {
@@ -2818,7 +2808,7 @@ proc sha1change {n1 n2 op} {
 
 proc gotocommit {} {
     global sha1string currentid commitrow tagids
 
 proc gotocommit {} {
     global sha1string currentid commitrow tagids
-    global lineid numcommits
+    global displayorder numcommits
 
     if {$sha1string == {}
        || ([info exists currentid] && $sha1string == $currentid)} return
 
     if {$sha1string == {}
        || ([info exists currentid] && $sha1string == $currentid)} return
@@ -2828,9 +2818,9 @@ proc gotocommit {} {
        set id [string tolower $sha1string]
        if {[regexp {^[0-9a-f]{4,39}$} $id]} {
            set matches {}
        set id [string tolower $sha1string]
        if {[regexp {^[0-9a-f]{4,39}$} $id]} {
            set matches {}
-           for {set l 0} {$l < $numcommits} {incr l} {
-               if {[string match $id* $lineid($l)]} {
-                   lappend matches $lineid($l)
+           foreach i $displayorder {
+               if {[string match $id* $i]} {
+                   lappend matches $i
                }
            }
            if {$matches ne {}} {
                }
            }
            if {$matches ne {}} {
@@ -2858,7 +2848,7 @@ proc lineenter {x y id} {
     global hoverx hovery hoverid hovertimer
     global commitinfo canv
 
     global hoverx hovery hoverid hovertimer
     global commitinfo canv
 
-    if {![info exists commitinfo($id)]} return
+    if {![info exists commitinfo($id)] && ![getcommit $id]} return
     set hoverx $x
     set hovery $y
     set hoverid $id
     set hoverx $x
     set hovery $y
     set hoverid $id
@@ -2952,13 +2942,14 @@ proc arrowjump {id n y} {
 proc lineclick {x y id isnew} {
     global ctext commitinfo children cflist canv thickerline
 
 proc lineclick {x y id isnew} {
     global ctext commitinfo children cflist canv thickerline
 
+    if {![info exists commitinfo($id)] && ![getcommit $id]} return
     unmarkmatches
     unselectline
     normalline
     $canv delete hover
     # draw this line thicker than normal
     unmarkmatches
     unselectline
     normalline
     $canv delete hover
     # draw this line thicker than normal
-    drawlines $id 1
     set thickerline $id
     set thickerline $id
+    drawlines $id
     if {$isnew} {
        set ymax [lindex [$canv cget -scrollregion] 3]
        if {$ymax eq {}} return
     if {$isnew} {
        set ymax [lindex [$canv cget -scrollregion] 3]
        if {$ymax eq {}} return
@@ -2993,6 +2984,7 @@ proc lineclick {x y id isnew} {
        set i 0
        foreach child $children($id) {
            incr i
        set i 0
        foreach child $children($id) {
            incr i
+           if {![info exists commitinfo($child)] && ![getcommit $child]} continue
            set info $commitinfo($child)
            $ctext insert end "\n\t"
            $ctext insert end $child [list link link$i]
            set info $commitinfo($child)
            $ctext insert end "\n\t"
            $ctext insert end $child [list link link$i]
@@ -3011,8 +3003,9 @@ proc lineclick {x y id isnew} {
 proc normalline {} {
     global thickerline
     if {[info exists thickerline]} {
 proc normalline {} {
     global thickerline
     if {[info exists thickerline]} {
-       drawlines $thickerline 0
+       set id $thickerline
        unset thickerline
        unset thickerline
+       drawlines $id
     }
 }
 
     }
 }
 
@@ -3047,15 +3040,15 @@ proc rowmenu {x y id} {
 }
 
 proc diffvssel {dirn} {
 }
 
 proc diffvssel {dirn} {
-    global rowmenuid selectedline lineid
+    global rowmenuid selectedline displayorder
 
     if {![info exists selectedline]} return
     if {$dirn} {
 
     if {![info exists selectedline]} return
     if {$dirn} {
-       set oldid $lineid($selectedline)
+       set oldid [lindex $displayorder $selectedline]
        set newid $rowmenuid
     } else {
        set oldid $rowmenuid
        set newid $rowmenuid
     } else {
        set oldid $rowmenuid
-       set newid $lineid($selectedline)
+       set newid [lindex $displayorder $selectedline]
     }
     addtohistory [list doseldiff $oldid $newid]
     doseldiff $oldid $newid
     }
     addtohistory [list doseldiff $oldid $newid]
     doseldiff $oldid $newid
@@ -3773,6 +3766,13 @@ foreach arg $argv {
     }
 }
 
     }
 }
 
+# check that we can find a .git directory somewhere...
+set gitdir [gitdir]
+if {![file isdirectory $gitdir]} {
+    error_popup "Cannot find the git directory \"$gitdir\"."
+    exit 1
+}
+
 set history {}
 set historyindex 0
 
 set history {}
 set historyindex 0