diff --git a/gitk b/gitk
index f4c662423c9..03cd475f095 100755
--- a/gitk
+++ b/gitk
@@ -34,13 +34,18 @@ proc parse_args {rargs} {
 
 proc start_rev_list {rlargs} {
     global startmsecs nextupdate ncmupdate
-    global commfd leftover tclencoding
+    global commfd leftover tclencoding datemode
 
     set startmsecs [clock clicks -milliseconds]
     set nextupdate [expr {$startmsecs + 100}]
     set ncmupdate 1
+    initlayout
+    set order "--topo-order"
+    if {$datemode} {
+	set order "--date-order"
+    }
     if {[catch {
-	set commfd [open [concat | git-rev-list --header --topo-order \
+	set commfd [open [concat | git-rev-list --header $order \
 			      --parents $rlargs] r]
     } err]} {
 	puts stderr "Error executing git-rev-list: $err"
@@ -57,16 +62,8 @@ proc start_rev_list {rlargs} {
 }
 
 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
@@ -75,10 +72,9 @@ proc getcommits {rargs} {
 }
 
 proc getcommitlines {commfd}  {
-    global oldcommits commits parents cdate children nchildren
-    global commitlisted phase nextupdate
-    global stopped redisplaying leftover
-    global canv
+    global commitlisted nextupdate
+    global leftover
+    global displayorder commitidx commitrow commitdata
 
     set stuff [read $commfd]
     if {$stuff == {}} {
@@ -101,16 +97,19 @@ proc getcommitlines {commfd}  {
 	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]
-	    return
+	    break
 	}
-	set cmit [string range $stuff $start [expr {$i - 1}]]
 	if {$start == 0} {
-	    set cmit "$leftover$cmit"
+	    set cmit $leftover
+	    append cmit [string range $stuff 0 [expr {$i - 1}]]
 	    set leftover {}
+	} else {
+	    set cmit [string range $stuff $start [expr {$i - 1}]]
 	}
 	set start [expr {$i + 1}]
 	set j [string first "\n" $cmit]
@@ -119,7 +118,7 @@ proc getcommitlines {commfd}  {
 	    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
 		}
@@ -135,28 +134,19 @@ proc getcommitlines {commfd}  {
 	}
 	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
-	parsecommit $id $cmit 1 [lrange $ids 1 end]
-	drawcommit $id 1
-	if {[clock clicks -milliseconds] >= $nextupdate} {
-	    doupdate 1
-	}
-	while {$redisplaying} {
-	    set redisplaying 0
-	    if {$stopped == 1} {
-		set stopped 0
-		set phase "getcommits"
-		foreach id $commits {
-		    drawcommit $id 1
-		    if {$stopped} break
-		    if {[clock clicks -milliseconds] >= $nextupdate} {
-			doupdate 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
+    }
+    if {[clock clicks -milliseconds] >= $nextupdate} {
+	doupdate 1
     }
 }
 
@@ -182,106 +172,31 @@ proc doupdate {reading} {
 
 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} {
-    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 ncleft
-
-    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
+    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}
     }
-
-    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
-	}
-    }
-
+    allcanvs delete all
     readrefs
-    start_rev_list [concat $ignoreold $args]
+    getcommits $rargs
 }
 
 proc updatechildren {id olds} {
-    global children nchildren parents nparents ncleft
+    global children nchildren parents nparents
 
     if {![info exists nchildren($id)]} {
 	set children($id) {}
 	set nchildren($id) 0
-	set ncleft($id) 0
     }
     set parents($id) $olds
     set nparents($id) [llength $olds]
@@ -289,16 +204,14 @@ proc updatechildren {id olds} {
 	if {![info exists nchildren($p)]} {
 	    set children($p) [list $id]
 	    set nchildren($p) 1
-	    set ncleft($p) 1
 	} elseif {[lsearch -exact $children($p) $id] < 0} {
 	    lappend children($p) $id
 	    incr nchildren($p)
-	    incr ncleft($p)
 	}
     }
 }
 
-proc parsecommit {id contents listed olds} {
+proc parsecommit {id contents listed} {
     global commitinfo cdate
 
     set inhdr 1
@@ -308,7 +221,6 @@ proc parsecommit {id contents listed olds} {
     set audate {}
     set comname {}
     set comdate {}
-    updatechildren $id $olds
     set hdrend [string first "\n\n" $contents]
     if {$hdrend < 0} {
 	# should never happen...
@@ -352,6 +264,21 @@ proc parsecommit {id contents listed olds} {
 			     $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
@@ -405,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"
+    bind $w <Key-Return> "destroy $w"
     tkwait window $w
 }
 
@@ -457,7 +385,7 @@ proc makewindow {rargs} {
     set canv .ctop.top.clist.canv
     canvas $canv -height $geometry(canvh) -width $geometry(canv1) \
 	-bg white -bd 0 \
-	-yscrollincr $linespc -yscrollcommand "$cscroll set"
+	-yscrollincr $linespc -yscrollcommand "scrollcanv $cscroll"
     .ctop.top.clist add $canv
     set canv2 .ctop.top.clist.canv2
     canvas $canv2 -height $geometry(canvh) -width $geometry(canv2) \
@@ -631,6 +559,11 @@ proc makewindow {rargs} {
     $rowctxmenu add command -label "Write commit to file" -command writecommit
 }
 
+proc scrollcanv {cscroll f0 f1} {
+    $cscroll set $f0 $f1
+    drawfrac $f0 $f1
+}
+
 # when we make a key binding for the toplevel, make sure
 # it doesn't get triggered when that key is pressed in the
 # find string entry widget.
@@ -763,9 +696,9 @@ proc about {} {
     toplevel $w
     wm title $w "About gitk"
     message $w.m -text {
-Gitk version 1.2
+Gitk - a commit viewer for git
 
-Copyright � 2005 Paul Mackerras
+Copyright � 2005-2006 Paul Mackerras
 
 Use and redistribute under the terms of the GNU General Public License} \
 	    -justify center -aspect 400
@@ -774,14 +707,776 @@ Use and redistribute under the terms of the GNU General Public License} \
     pack $w.ok -side bottom
 }
 
+proc shortids {ids} {
+    set res {}
+    foreach id $ids {
+	if {[llength $id] > 1} {
+	    lappend res [shortids $id]
+	} elseif {[regexp {^[0-9a-f]{40}$} $id]} {
+	    lappend res [string range $id 0 7]
+	} else {
+	    lappend res $id
+	}
+    }
+    return $res
+}
+
+proc incrange {l x o} {
+    set n [llength $l]
+    while {$x < $n} {
+	set e [lindex $l $x]
+	if {$e ne {}} {
+	    lset l $x [expr {$e + $o}]
+	}
+	incr x
+    }
+    return $l
+}
+
+proc ntimes {n o} {
+    set ret {}
+    for {} {$n > 0} {incr n -1} {
+	lappend ret $o
+    }
+    return $ret
+}
+
+proc usedinrange {id l1 l2} {
+    global children commitrow
+
+    if {[info exists commitrow($id)]} {
+	set r $commitrow($id)
+	if {$l1 <= $r && $r <= $l2} {
+	    return [expr {$r - $l1 + 1}]
+	}
+    }
+    foreach c $children($id) {
+	if {[info exists commitrow($c)]} {
+	    set r $commitrow($c)
+	    if {$l1 <= $r && $r <= $l2} {
+		return [expr {$r - $l1 + 1}]
+	    }
+	}
+    }
+    return 0
+}
+
+proc sanity {row {full 0}} {
+    global rowidlist rowoffsets
+
+    set col -1
+    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} {
+	    puts "oops: [shortids $id] repeated in row $row col $col: {[shortids [lindex $rowidlist $row]]}"
+	}
+	set o [lindex $rowoffsets $row $col]
+	set y $row
+	set x $col
+	while {$o ne {}} {
+	    incr y -1
+	    incr x $o
+	    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 "  row $i ids={[shortids [lindex $rowidlist $i]]} offs={[lindex $rowoffsets $i]}"
+		}
+		break
+	    }
+	    if {!$full} break
+	    set o [lindex $rowoffsets $y $x]
+	}
+    }
+}
+
+proc makeuparrow {oid x y z} {
+    global rowidlist rowoffsets uparrowlen idrowranges
+
+    for {set i 1} {$i < $uparrowlen && $y > 1} {incr i} {
+	incr y -1
+	incr x $z
+	set off0 [lindex $rowoffsets $y]
+	for {set x0 $x} {1} {incr x0} {
+	    if {$x0 >= [llength $off0]} {
+		set x0 [llength [lindex $rowoffsets [expr {$y-1}]]]
+		break
+	    }
+	    set z [lindex $off0 $x0]
+	    if {$z ne {}} {
+		incr x0 $z
+		break
+	    }
+	}
+	set z [expr {$x0 - $x}]
+	lset rowidlist $y [linsert [lindex $rowidlist $y] $x $oid]
+	lset rowoffsets $y [linsert [lindex $rowoffsets $y] $x $z]
+    }
+    set tmp [lreplace [lindex $rowoffsets $y] $x $x {}]
+    lset rowoffsets $y [incrange $tmp [expr {$x+1}] -1]
+    lappend idrowranges($oid) $y
+}
+
+proc initlayout {} {
+    global rowidlist rowoffsets displayorder
+    global rowlaidout rowoptim
+    global idinlist rowchk
+    global commitidx numcommits
+    global nextcolor
+
+    set commitidx 0
+    set numcommits 0
+    set displayorder {}
+    set nextcolor 0
+    set rowidlist {{}}
+    set rowoffsets {{}}
+    catch {unset idinlist}
+    catch {unset rowchk}
+    set rowlaidout 0
+    set rowoptim 0
+}
+
+proc visiblerows {} {
+    global canv numcommits linespc
+
+    set ymax [lindex [$canv cget -scrollregion] 3]
+    if {$ymax eq {} || $ymax == 0} return
+    set f [$canv yview]
+    set y0 [expr {int([lindex $f 0] * $ymax)}]
+    set r0 [expr {int(($y0 - 3) / $linespc) - 1}]
+    if {$r0 < 0} {
+	set r0 0
+    }
+    set y1 [expr {int([lindex $f 1] * $ymax)}]
+    set r1 [expr {int(($y1 - 3) / $linespc) + 1}]
+    if {$r1 >= $numcommits} {
+	set r1 [expr {$numcommits - 1}]
+    }
+    return [list $r0 $r1]
+}
+
+proc layoutmore {} {
+    global rowlaidout rowoptim commitidx numcommits optim_delay
+    global uparrowlen
+
+    set row $rowlaidout
+    set rowlaidout [layoutrows $row $commitidx 0]
+    set orow [expr {$rowlaidout - $uparrowlen - 1}]
+    if {$orow > $rowoptim} {
+	checkcrossings $rowoptim $orow
+	optimize_rows $rowoptim 0 $orow
+	set rowoptim $orow
+    }
+    set canshow [expr {$rowoptim - $optim_delay}]
+    if {$canshow > $numcommits} {
+	showstuff $canshow
+    }
+}
+
+proc showstuff {canshow} {
+    global numcommits
+    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 \
+	[list 0 0 0 [expr {$canvy0 + ($numcommits - 0.5) * $linespc + 2}]]
+    set rows [visiblerows]
+    set r0 [lindex $rows 0]
+    set r1 [lindex $rows 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
+		    }
+		}
+	    }
+	}
+    }
+    if {$canshow > $r1} {
+	set canshow $r1
+    }
+    while {$row < $canshow} {
+	drawcmitrow $row
+	incr row
+    }
+}
+
+proc layoutrows {row endrow last} {
+    global rowidlist rowoffsets displayorder
+    global uparrowlen downarrowlen maxwidth mingaplen
+    global nchildren parents nparents
+    global idrowranges linesegends
+    global commitidx
+    global idinlist rowchk
+
+    set idlist [lindex $rowidlist $row]
+    set offs [lindex $rowoffsets $row]
+    while {$row < $endrow} {
+	set id [lindex $displayorder $row]
+	set oldolds {}
+	set newolds {}
+	foreach p $parents($id) {
+	    if {![info exists idinlist($p)]} {
+		lappend newolds $p
+	    } elseif {!$idinlist($p)} {
+		lappend oldolds $p
+	    }
+	}
+	set nev [expr {[llength $idlist] + [llength $newolds]
+		       + [llength $oldolds] - $maxwidth + 1}]
+	if {$nev > 0} {
+	    if {!$last && $row + $uparrowlen + $mingaplen >= $commitidx} break
+	    for {set x [llength $idlist]} {[incr x -1] >= 0} {} {
+		set i [lindex $idlist $x]
+		if {![info exists rowchk($i)] || $row >= $rowchk($i)} {
+		    set r [usedinrange $i [expr {$row - $downarrowlen}] \
+			       [expr {$row + $uparrowlen + $mingaplen}]]
+		    if {$r == 0} {
+			set idlist [lreplace $idlist $x $x]
+			set offs [lreplace $offs $x $x]
+			set offs [incrange $offs $x 1]
+			set idinlist($i) 0
+			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}]
+		}
+	    }
+	    lset rowidlist $row $idlist
+	    lset rowoffsets $row $offs
+	}
+	set col [lsearch -exact $idlist $id]
+	if {$col < 0} {
+	    set col [llength $idlist]
+	    lappend idlist $id
+	    lset rowidlist $row $idlist
+	    set z {}
+	    if {$nchildren($id) > 0} {
+		set z [expr {[llength [lindex $rowidlist [expr {$row-1}]]] - $col}]
+		unset idinlist($id)
+	    }
+	    lappend offs $z
+	    lset rowoffsets $row $offs
+	    if {$z ne {}} {
+		makeuparrow $id $col $row $z
+	    }
+	} else {
+	    unset idinlist($id)
+	}
+	if {[info exists idrowranges($id)]} {
+	    lappend idrowranges($id) $row
+	}
+	incr row
+	set offs [ntimes [llength $idlist] 0]
+	set l [llength $newolds]
+	set idlist [eval lreplace \$idlist $col $col $newolds]
+	set o 0
+	if {$l != 1} {
+	    set offs [lrange $offs 0 [expr {$col - 1}]]
+	    foreach x $newolds {
+		lappend offs {}
+		incr o -1
+	    }
+	    incr o
+	    set tmp [expr {[llength $idlist] - [llength $offs]}]
+	    if {$tmp > 0} {
+		set offs [concat $offs [ntimes $tmp $o]]
+	    }
+	} else {
+	    lset offs $col {}
+	}
+	foreach i $newolds {
+	    set idinlist($i) 1
+	    set idrowranges($i) $row
+	}
+	incr col $l
+	foreach oid $oldolds {
+	    set idinlist($oid) 1
+	    set idlist [linsert $idlist $col $oid]
+	    set offs [linsert $offs $col $o]
+	    makeuparrow $oid $col $row $o
+	    incr col
+	}
+	lappend rowidlist $idlist
+	lappend rowoffsets $offs
+    }
+    return $row
+}
+
+proc addextraid {id row} {
+    global displayorder commitrow commitinfo nparents
+    global commitidx
+
+    incr commitidx
+    lappend displayorder $id
+    set commitrow($id) $row
+    readcommit $id
+    if {![info exists commitinfo($id)]} {
+	set commitinfo($id) {"No commit information available"}
+	set nparents($id) 0
+    }
+}
+
+proc layouttail {} {
+    global rowidlist rowoffsets idinlist commitidx
+    global idrowranges
+
+    set row $commitidx
+    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)
+	lappend idrowranges($id) $row
+	incr row
+	set offs [ntimes $col 0]
+	set idlist [lreplace $idlist $col $col]
+	lappend rowidlist $idlist
+	lappend rowoffsets $offs
+    }
+
+    foreach id [array names idinlist] {
+	addextraid $id $row
+	lset rowidlist $row [list $id]
+	lset rowoffsets $row 0
+	makeuparrow $id 0 $row 0
+	lappend idrowranges($id) $row
+	incr row
+	lappend rowidlist {}
+	lappend rowoffsets {}
+    }
+}
+
+proc insert_pad {row col npad} {
+    global rowidlist rowoffsets
+
+    set pad [ntimes $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} {
+    global rowidlist rowoffsets idrowranges linesegends displayorder
+
+    for {} {$row < $endrow} {incr row} {
+	set idlist [lindex $rowidlist $row]
+	set offs [lindex $rowoffsets $row]
+	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
+		continue
+	    }
+	    set z [lindex $offs $col]
+	    if {$z eq {}} continue
+	    set isarrow 0
+	    set x0 [expr {$col + $z}]
+	    set y0 [expr {$row - 1}]
+	    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
+		}
+	    } 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}]
+		set offs [incrange $offs $col $npad]
+		insert_pad $y0 $x0 $npad
+		if {$y0 > 0} {
+		    optimize_rows $y0 $x0 $row
+		}
+		set z [lindex $offs $col]
+		set x0 [expr {$col + $z}]
+		set z0 [lindex $rowoffsets $y0 $x0]
+	    } elseif {$z > 1 || ($z > 0 && $isarrow)} {
+		set npad [expr {$z - 1 + $isarrow}]
+		set y1 [expr {$row + 1}]
+		set offs2 [lindex $rowoffsets $y1]
+		set x1 -1
+		foreach z $offs2 {
+		    incr x1
+		    if {$z eq {} || $x1 + $z < $col} continue
+		    if {$x1 + $z > $col} {
+			incr npad
+		    }
+		    lset rowoffsets $y1 [incrange $offs2 $x1 $npad]
+		    break
+		}
+		set pad [ntimes $npad {}]
+		set idlist [eval linsert \$idlist $col $pad]
+		set tmp [eval linsert \$offs $col $pad]
+		incr col $npad
+		set offs [incrange $tmp $col [expr {-$npad}]]
+		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]
+		optimize_rows $y0 [expr {$x0 + 1}] $row
+	    }
+	}
+	if {!$haspad} {
+	    set o {}
+	    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 ne {} && [incr col] < [llength $idlist]} {
+		set y1 [expr {$row + 1}]
+		set offs2 [lindex $rowoffsets $y1]
+		set x1 -1
+		foreach z $offs2 {
+		    incr x1
+		    if {$z eq {} || $x1 + $z < $col} continue
+		    lset rowoffsets $y1 [incrange $offs2 $x1 1]
+		    break
+		}
+		set idlist [linsert $idlist $col {}]
+		set tmp [linsert $offs $col {}]
+		incr col
+		set offs [incrange $tmp $col -1]
+	    }
+	}
+	lset rowidlist $row $idlist
+	lset rowoffsets $row $offs
+	set col 0
+    }
+}
+
+proc xc {row col} {
+    global canvx0 linespc
+    return [expr {$canvx0 + $col * $linespc}]
+}
+
+proc yc {row} {
+    global canvy0 linespc
+    return [expr {$canvy0 + $row * $linespc}]
+}
+
+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 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 col [lsearch -exact [lindex $rowidlist $row] $id]
+    if {$col < 0} {
+	puts "oops: drawline: id $id not on row $row"
+	return
+    }
+    set lasto {}
+    set ns 0
+    while {1} {
+	set o [lindex $rowoffsets $row $col]
+	if {$o eq {}} break
+	if {$o ne $lasto} {
+	    # changing direction
+	    set x [xc $row $col]
+	    set y [yc $row]
+	    lappend coords $x $y
+	    set lasto $o
+	}
+	incr col $o
+	incr row -1
+    }
+    set x [xc $row $col]
+    set y [yc $row]
+    lappend coords $x $y
+    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
+}
+
+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 ids [lindex $rowidlist $row2]
+    # rmx = right-most X coord used
+    set rmx 0
+    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"
+	    continue
+	}
+	assigncolor $p
+	# should handle duplicated parents here...
+	set coords [list $x $y]
+	if {$i < $col - 1} {
+	    lappend coords [xc $row [expr {$i + 1}]] $y
+	} elseif {$i > $col + 1} {
+	    lappend coords [xc $row [expr {$i - 1}]] $y
+	}
+	set x2 [xc $row2 $i]
+	if {$x2 > $rmx} {
+	    set rmx $x2
+	}
+	lappend coords $x2 $y2
+	set t [$canv create line $coords -width [linewidth $p] \
+		   -fill $colormap($p) -tags lines.$p]
+	$canv lower $t
+	bindline $t $p
+    }
+    return $rmx
+}
+
+proc drawlines {id} {
+    global colormap canv
+    global idrowranges idrangedrawn
+    global children iddrawn commitrow rowidlist
+
+    $canv delete lines.$id
+    set nr [expr {[llength $idrowranges($id)] / 2}]
+    for {set i 0} {$i < $nr} {incr i} {
+	if {[info exists idrangedrawn($id,$i)]} {
+	    drawlineseg $id $i
+	}
+    }
+    if {[info exists children($id)]} {
+	foreach child $children($id) {
+	    if {[info exists iddrawn($child)]} {
+		set row $commitrow($child)
+		set col [lsearch -exact [lindex $rowidlist $row] $child]
+		if {$col >= 0} {
+		    drawparentlinks $child $row $col [list $id]
+		}
+	    }
+	}
+    }
+}
+
+proc drawcmittext {id row col rmx} {
+    global linespc canv canv2 canv3 canvy0
+    global commitlisted commitinfo rowidlist
+    global rowtextx idpos idtags idheads idotherrefs
+    global linehtag linentag linedtag
+    global mainfont namefont
+
+    set ofill [expr {[info exists commitlisted($id)]? "blue": "white"}]
+    set x [xc $row $col]
+    set y [yc $row]
+    set orad [expr {$linespc / 3}]
+    set t [$canv create oval [expr {$x - $orad}] [expr {$y - $orad}] \
+	       [expr {$x + $orad - 1}] [expr {$y + $orad - 1}] \
+	       -fill $ofill -outline black -width 1]
+    $canv raise $t
+    $canv bind $t <1> {selcanvline {} %x %y}
+    set xt [xc $row [llength [lindex $rowidlist $row]]]
+    if {$xt < $rmx} {
+	set xt $rmx
+    }
+    set rowtextx($row) $xt
+    set idpos($id) [list $x $xt $y]
+    if {[info exists idtags($id)] || [info exists idheads($id)]
+	|| [info exists idotherrefs($id)]} {
+	set xt [drawtags $id $x $xt $y]
+    }
+    set headline [lindex $commitinfo($id) 0]
+    set name [lindex $commitinfo($id) 1]
+    set date [lindex $commitinfo($id) 2]
+    set date [formatdate $date]
+    set linehtag($row) [$canv create text $xt $y -anchor w \
+			    -text $headline -font $mainfont ]
+    $canv bind $linehtag($row) <Button-3> "rowmenu %X %Y $id"
+    set linentag($row) [$canv2 create text 3 $y -anchor w \
+			    -text $name -font $namefont]
+    set linedtag($row) [$canv3 create text 3 $y -anchor w \
+			    -text $date -font $mainfont]
+}
+
+proc drawcmitrow {row} {
+    global displayorder rowidlist
+    global idrowranges idrangedrawn iddrawn
+    global commitinfo commitlisted parents numcommits
+
+    if {$row >= $numcommits} return
+    foreach id [lindex $rowidlist $row] {
+	if {![info exists idrowranges($id)]} continue
+	set i -1
+	foreach {s e} $idrowranges($id) {
+	    incr i
+	    if {$row < $s} continue
+	    if {$e eq {}} break
+	    if {$row <= $e} {
+		if {$e < $numcommits && ![info exists idrangedrawn($id,$i)]} {
+		    drawlineseg $id $i
+		    set idrangedrawn($id,$i) 1
+		}
+		break
+	    }
+	}
+    }
+
+    set id [lindex $displayorder $row]
+    if {[info exists iddrawn($id)]} return
+    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)]} {
+	getcommit $id
+    }
+    assigncolor $id
+    if {[info exists commitlisted($id)] && [info exists parents($id)]
+	&& $parents($id) ne {}} {
+	set rmx [drawparentlinks $id $row $col $parents($id)]
+    } else {
+	set rmx 0
+    }
+    drawcmittext $id $row $col $rmx
+    set iddrawn($id) 1
+}
+
+proc drawfrac {f0 f1} {
+    global numcommits canv
+    global linespc
+
+    set ymax [lindex [$canv cget -scrollregion] 3]
+    if {$ymax eq {} || $ymax == 0} return
+    set y0 [expr {int($f0 * $ymax)}]
+    set row [expr {int(($y0 - 3) / $linespc) - 1}]
+    if {$row < 0} {
+	set row 0
+    }
+    set y1 [expr {int($f1 * $ymax)}]
+    set endrow [expr {int(($y1 - 3) / $linespc) + 1}]
+    if {$endrow >= $numcommits} {
+	set endrow [expr {$numcommits - 1}]
+    }
+    for {} {$row <= $endrow} {incr row} {
+	drawcmitrow $row
+    }
+}
+
+proc drawvisible {} {
+    global canv
+    eval drawfrac [$canv yview]
+}
+
+proc clear_display {} {
+    global iddrawn idrangedrawn
+
+    allcanvs delete all
+    catch {unset iddrawn}
+    catch {unset idrangedrawn}
+}
+
 proc assigncolor {id} {
-    global colormap commcolors colors nextcolor
+    global colormap colors nextcolor
     global parents nparents children nchildren
     global cornercrossings crossings
 
     if {[info exists colormap($id)]} return
     set ncolors [llength $colors]
-    if {$nparents($id) <= 1 && $nchildren($id) == 1} {
+    if {$nchildren($id) == 1} {
 	set child [lindex $children($id) 0]
 	if {[info exists colormap($child)]
 	    && $nparents($child) == 1} {
@@ -845,28 +1540,6 @@ proc assigncolor {id} {
     set colormap($id) $c
 }
 
-proc initgraph {} {
-    global canvy canvy0 lineno numcommits nextcolor linespc
-    global nchildren ncleft
-    global displist nhyperspace
-
-    allcanvs delete all
-    set nextcolor 0
-    set canvy $canvy0
-    set lineno -1
-    set numcommits 0
-    foreach v {mainline mainlinearrow sidelines colormap cornercrossings
-		crossings idline lineid} {
-	global $v
-	catch {unset $v}
-    }
-    foreach id [array names nchildren] {
-	set ncleft($id) $nchildren($id)
-    }
-    set displist {}
-    set nhyperspace 0
-}
-
 proc bindline {t id} {
     global canv
 
@@ -876,121 +1549,10 @@ proc bindline {t id} {
     $canv bind $t <Button-1> "lineclick %x %y $id 1"
 }
 
-proc drawlines {id xtra delold} {
-    global mainline mainlinearrow sidelines lthickness colormap canv
-
-    if {$delold} {
-	$canv delete lines.$id
-    }
-    if {[info exists mainline($id)]} {
-	set t [$canv create line $mainline($id) \
-		   -width [expr {($xtra + 1) * $lthickness}] \
-		   -fill $colormap($id) -tags lines.$id \
-		   -arrow $mainlinearrow($id)]
-	$canv lower $t
-	bindline $t $id
-    }
-    if {[info exists sidelines($id)]} {
-	foreach ls $sidelines($id) {
-	    set coords [lindex $ls 0]
-	    set thick [lindex $ls 1]
-	    set arrow [lindex $ls 2]
-	    set t [$canv create line $coords -fill $colormap($id) \
-		       -width [expr {($thick + $xtra) * $lthickness}] \
-		       -arrow $arrow -tags lines.$id]
-	    $canv lower $t
-	    bindline $t $id
-	}
-    }
-}
-
-# level here is an index in displist
-proc drawcommitline {level} {
-    global parents children nparents displist
-    global canv canv2 canv3 mainfont namefont canvy linespc
-    global lineid linehtag linentag linedtag commitinfo
-    global colormap numcommits currentparents dupparents
-    global idtags idline idheads idotherrefs
-    global lineno lthickness mainline mainlinearrow sidelines
-    global commitlisted rowtextx idpos lastuse displist
-    global oldnlines olddlevel olddisplist
-
-    incr numcommits
-    incr lineno
-    set id [lindex $displist $level]
-    set lastuse($id) $lineno
-    set lineid($lineno) $id
-    set idline($id) $lineno
-    set ofill [expr {[info exists commitlisted($id)]? "blue": "white"}]
-    if {![info exists commitinfo($id)]} {
-	readcommit $id
-	if {![info exists commitinfo($id)]} {
-	    set commitinfo($id) {"No commit information available"}
-	    set nparents($id) 0
-	}
-    }
-    assigncolor $id
-    set currentparents {}
-    set dupparents {}
-    if {[info exists commitlisted($id)] && [info exists parents($id)]} {
-	foreach p $parents($id) {
-	    if {[lsearch -exact $currentparents $p] < 0} {
-		lappend currentparents $p
-	    } else {
-		# remember that this parent was listed twice
-		lappend dupparents $p
-	    }
-	}
-    }
-    set x [xcoord $level $level $lineno]
-    set y1 $canvy
-    set canvy [expr {$canvy + $linespc}]
-    allcanvs conf -scrollregion \
-	[list 0 0 0 [expr {$y1 + 0.5 * $linespc + 2}]]
-    if {[info exists mainline($id)]} {
-	lappend mainline($id) $x $y1
-	if {$mainlinearrow($id) ne "none"} {
-	    set mainline($id) [trimdiagstart $mainline($id)]
-	}
-    }
-    drawlines $id 0 0
-    set orad [expr {$linespc / 3}]
-    set t [$canv create oval [expr {$x - $orad}] [expr {$y1 - $orad}] \
-	       [expr {$x + $orad - 1}] [expr {$y1 + $orad - 1}] \
-	       -fill $ofill -outline black -width 1]
-    $canv raise $t
-    $canv bind $t <1> {selcanvline {} %x %y}
-    set xt [xcoord [llength $displist] $level $lineno]
-    if {[llength $currentparents] > 2} {
-	set xt [expr {$xt + ([llength $currentparents] - 2) * $linespc}]
-    }
-    set rowtextx($lineno) $xt
-    set idpos($id) [list $x $xt $y1]
-    if {[info exists idtags($id)] || [info exists idheads($id)]
-	|| [info exists idotherrefs($id)]} {
-	set xt [drawtags $id $x $xt $y1]
-    }
-    set headline [lindex $commitinfo($id) 0]
-    set name [lindex $commitinfo($id) 1]
-    set date [lindex $commitinfo($id) 2]
-    set date [formatdate $date]
-    set linehtag($lineno) [$canv create text $xt $y1 -anchor w \
-			       -text $headline -font $mainfont ]
-    $canv bind $linehtag($lineno) <Button-3> "rowmenu %X %Y $id"
-    set linentag($lineno) [$canv2 create text 3 $y1 -anchor w \
-			       -text $name -font $namefont]
-    set linedtag($lineno) [$canv3 create text 3 $y1 -anchor w \
-			       -text $date -font $mainfont]
-
-    set olddlevel $level
-    set olddisplist $displist
-    set oldnlines [llength $displist]
-}
-
 proc drawtags {id x xt y1} {
     global idtags idheads idotherrefs
     global linespc lthickness
-    global canv mainfont idline rowtextx
+    global canv mainfont commitrow rowtextx
 
     set marks {}
     set ntags 0
@@ -1033,7 +1595,7 @@ proc drawtags {id x xt y1} {
 		       $xr $yt $xr $yb $xl $yb $x [expr {$yb - $delta}] \
 		       -width 1 -outline black -fill yellow -tags tag.$id]
 	    $canv bind $t <1> [list showtag $tag 1]
-	    set rowtextx($idline($id)) [expr {$xr + $linespc}]
+	    set rowtextx($commitrow($id)) [expr {$xr + $linespc}]
 	} else {
 	    # draw a head or other ref
 	    if {[incr nheads -1] >= 0} {
@@ -1054,11 +1616,32 @@ proc drawtags {id x xt y1} {
     return $xt
 }
 
-proc notecrossings {id lo hi corner} {
-    global olddisplist crossings cornercrossings
+proc checkcrossings {row endrow} {
+    global displayorder parents rowidlist
+
+    for {} {$row < $endrow} {incr row} {
+	set id [lindex $displayorder $row]
+	set i [lsearch -exact [lindex $rowidlist $row] $id]
+	if {$i < 0} continue
+	set idlist [lindex $rowidlist [expr {$row+1}]]
+	foreach p $parents($id) {
+	    set j [lsearch -exact $idlist $p]
+	    if {$j > 0} {
+		if {$j < $i - 1} {
+		    notecrossings $row $p $j $i [expr {$j+1}]
+		} elseif {$j > $i + 1} {
+		    notecrossings $row $p $i $j [expr {$j-1}]
+		}
+	    }
+	}
+    }
+}
+
+proc notecrossings {row id lo hi corner} {
+    global rowidlist crossings cornercrossings
 
     for {set i $lo} {[incr i] < $hi} {} {
-	set p [lindex $olddisplist $i]
+	set p [lindex [lindex $rowidlist $row] $i]
 	if {$p == {}} continue
 	if {$i == $corner} {
 	    if {![info exists cornercrossings($id)]
@@ -1094,512 +1677,23 @@ proc xcoord {i level ln} {
     return $x
 }
 
-# it seems Tk can't draw arrows on the end of diagonal line segments...
-proc trimdiagend {line} {
-    while {[llength $line] > 4} {
-	set x1 [lindex $line end-3]
-	set y1 [lindex $line end-2]
-	set x2 [lindex $line end-1]
-	set y2 [lindex $line end]
-	if {($x1 == $x2) != ($y1 == $y2)} break
-	set line [lreplace $line end-1 end]
-    }
-    return $line
-}
-
-proc trimdiagstart {line} {
-    while {[llength $line] > 4} {
-	set x1 [lindex $line 0]
-	set y1 [lindex $line 1]
-	set x2 [lindex $line 2]
-	set y2 [lindex $line 3]
-	if {($x1 == $x2) != ($y1 == $y2)} break
-	set line [lreplace $line 0 1]
-    }
-    return $line
-}
-
-proc drawslants {id needonscreen nohs} {
-    global canv mainline mainlinearrow sidelines
-    global canvx0 canvy xspc1 xspc2 lthickness
-    global currentparents dupparents
-    global lthickness linespc canvy colormap lineno geometry
-    global maxgraphpct maxwidth
-    global displist onscreen lastuse
-    global parents commitlisted
-    global oldnlines olddlevel olddisplist
-    global nhyperspace numcommits nnewparents
-
-    if {$lineno < 0} {
-	lappend displist $id
-	set onscreen($id) 1
-	return 0
-    }
-
-    set y1 [expr {$canvy - $linespc}]
-    set y2 $canvy
-
-    # work out what we need to get back on screen
-    set reins {}
-    if {$onscreen($id) < 0} {
-	# next to do isn't displayed, better get it on screen...
-	lappend reins [list $id 0]
-    }
-    # make sure all the previous commits's parents are on the screen
-    foreach p $currentparents {
-	if {$onscreen($p) < 0} {
-	    lappend reins [list $p 0]
-	}
-    }
-    # bring back anything requested by caller
-    if {$needonscreen ne {}} {
-	lappend reins $needonscreen
-    }
-
-    # try the shortcut
-    if {$currentparents == $id && $onscreen($id) == 0 && $reins eq {}} {
-	set dlevel $olddlevel
-	set x [xcoord $dlevel $dlevel $lineno]
-	set mainline($id) [list $x $y1]
-	set mainlinearrow($id) none
-	set lastuse($id) $lineno
-	set displist [lreplace $displist $dlevel $dlevel $id]
-	set onscreen($id) 1
-	set xspc1([expr {$lineno + 1}]) $xspc1($lineno)
-	return $dlevel
-    }
-
-    # update displist
-    set displist [lreplace $displist $olddlevel $olddlevel]
-    set j $olddlevel
-    foreach p $currentparents {
-	set lastuse($p) $lineno
-	if {$onscreen($p) == 0} {
-	    set displist [linsert $displist $j $p]
-	    set onscreen($p) 1
-	    incr j
-	}
-    }
-    if {$onscreen($id) == 0} {
-	lappend displist $id
-	set onscreen($id) 1
-    }
-
-    # remove the null entry if present
-    set nullentry [lsearch -exact $displist {}]
-    if {$nullentry >= 0} {
-	set displist [lreplace $displist $nullentry $nullentry]
-    }
-
-    # bring back the ones we need now (if we did it earlier
-    # it would change displist and invalidate olddlevel)
-    foreach pi $reins {
-	# test again in case of duplicates in reins
-	set p [lindex $pi 0]
-	if {$onscreen($p) < 0} {
-	    set onscreen($p) 1
-	    set lastuse($p) $lineno
-	    set displist [linsert $displist [lindex $pi 1] $p]
-	    incr nhyperspace -1
-	}
-    }
-
-    set lastuse($id) $lineno
-
-    # see if we need to make any lines jump off into hyperspace
-    set displ [llength $displist]
-    if {$displ > $maxwidth} {
-	set ages {}
-	foreach x $displist {
-	    lappend ages [list $lastuse($x) $x]
-	}
-	set ages [lsort -integer -index 0 $ages]
-	set k 0
-	while {$displ > $maxwidth} {
-	    set use [lindex $ages $k 0]
-	    set victim [lindex $ages $k 1]
-	    if {$use >= $lineno - 5} break
-	    incr k
-	    if {[lsearch -exact $nohs $victim] >= 0} continue
-	    set i [lsearch -exact $displist $victim]
-	    set displist [lreplace $displist $i $i]
-	    set onscreen($victim) -1
-	    incr nhyperspace
-	    incr displ -1
-	    if {$i < $nullentry} {
-		incr nullentry -1
-	    }
-	    set x [lindex $mainline($victim) end-1]
-	    lappend mainline($victim) $x $y1
-	    set line [trimdiagend $mainline($victim)]
-	    set arrow "last"
-	    if {$mainlinearrow($victim) ne "none"} {
-		set line [trimdiagstart $line]
-		set arrow "both"
-	    }
-	    lappend sidelines($victim) [list $line 1 $arrow]
-	    unset mainline($victim)
-	}
-    }
-
-    set dlevel [lsearch -exact $displist $id]
-
-    # If we are reducing, put in a null entry
-    if {$displ < $oldnlines} {
-	# does the next line look like a merge?
-	# i.e. does it have > 1 new parent?
-	if {$nnewparents($id) > 1} {
-	    set i [expr {$dlevel + 1}]
-	} elseif {$nnewparents([lindex $olddisplist $olddlevel]) == 0} {
-	    set i $olddlevel
-	    if {$nullentry >= 0 && $nullentry < $i} {
-		incr i -1
-	    }
-	} elseif {$nullentry >= 0} {
-	    set i $nullentry
-	    while {$i < $displ
-		   && [lindex $olddisplist $i] == [lindex $displist $i]} {
-		incr i
-	    }
-	} else {
-	    set i $olddlevel
-	    if {$dlevel >= $i} {
-		incr i
-	    }
-	}
-	if {$i < $displ} {
-	    set displist [linsert $displist $i {}]
-	    incr displ
-	    if {$dlevel >= $i} {
-		incr dlevel
-	    }
-	}
-    }
-
-    # decide on the line spacing for the next line
-    set lj [expr {$lineno + 1}]
-    set maxw [expr {$maxgraphpct * $geometry(canv1) / 100}]
-    if {$displ <= 1 || $canvx0 + $displ * $xspc2 <= $maxw} {
-	set xspc1($lj) $xspc2
-    } else {
-	set xspc1($lj) [expr {($maxw - $canvx0 - $xspc2) / ($displ - 1)}]
-	if {$xspc1($lj) < $lthickness} {
-	    set xspc1($lj) $lthickness
-	}
-    }
-
-    foreach idi $reins {
-	set id [lindex $idi 0]
-	set j [lsearch -exact $displist $id]
-	set xj [xcoord $j $dlevel $lj]
-	set mainline($id) [list $xj $y2]
-	set mainlinearrow($id) first
-    }
-
-    set i -1
-    foreach id $olddisplist {
-	incr i
-	if {$id == {}} continue
-	if {$onscreen($id) <= 0} continue
-	set xi [xcoord $i $olddlevel $lineno]
-	if {$i == $olddlevel} {
-	    foreach p $currentparents {
-		set j [lsearch -exact $displist $p]
-		set coords [list $xi $y1]
-		set xj [xcoord $j $dlevel $lj]
-		if {$xj < $xi - $linespc} {
-		    lappend coords [expr {$xj + $linespc}] $y1
-		    notecrossings $p $j $i [expr {$j + 1}]
-		} elseif {$xj > $xi + $linespc} {
-		    lappend coords [expr {$xj - $linespc}] $y1
-		    notecrossings $p $i $j [expr {$j - 1}]
-		}
-		if {[lsearch -exact $dupparents $p] >= 0} {
-		    # draw a double-width line to indicate the doubled parent
-		    lappend coords $xj $y2
-		    lappend sidelines($p) [list $coords 2 none]
-		    if {![info exists mainline($p)]} {
-			set mainline($p) [list $xj $y2]
-			set mainlinearrow($p) none
-		    }
-		} else {
-		    # normal case, no parent duplicated
-		    set yb $y2
-		    set dx [expr {abs($xi - $xj)}]
-		    if {0 && $dx < $linespc} {
-			set yb [expr {$y1 + $dx}]
-		    }
-		    if {![info exists mainline($p)]} {
-			if {$xi != $xj} {
-			    lappend coords $xj $yb
-			}
-			set mainline($p) $coords
-			set mainlinearrow($p) none
-		    } else {
-			lappend coords $xj $yb
-			if {$yb < $y2} {
-			    lappend coords $xj $y2
-			}
-			lappend sidelines($p) [list $coords 1 none]
-		    }
-		}
-	    }
-	} else {
-	    set j $i
-	    if {[lindex $displist $i] != $id} {
-		set j [lsearch -exact $displist $id]
-	    }
-	    if {$j != $i || $xspc1($lineno) != $xspc1($lj)
-		|| ($olddlevel < $i && $i < $dlevel)
-		|| ($dlevel < $i && $i < $olddlevel)} {
-		set xj [xcoord $j $dlevel $lj]
-		lappend mainline($id) $xi $y1 $xj $y2
-	    }
-	}
-    }
-    return $dlevel
-}
-
-# search for x in a list of lists
-proc llsearch {llist x} {
-    set i 0
-    foreach l $llist {
-	if {$l == $x || [lsearch -exact $l $x] >= 0} {
-	    return $i
-	}
-	incr i
-    }
-    return -1
-}
-
-proc drawmore {reading} {
-    global displayorder numcommits ncmupdate nextupdate
-    global stopped nhyperspace parents commitlisted
-    global maxwidth onscreen displist currentparents olddlevel
-
-    set n [llength $displayorder]
-    while {$numcommits < $n} {
-	set id [lindex $displayorder $numcommits]
-	set ctxend [expr {$numcommits + 10}]
-	if {!$reading && $ctxend > $n} {
-	    set ctxend $n
-	}
-	set dlist {}
-	if {$numcommits > 0} {
-	    set dlist [lreplace $displist $olddlevel $olddlevel]
-	    set i $olddlevel
-	    foreach p $currentparents {
-		if {$onscreen($p) == 0} {
-		    set dlist [linsert $dlist $i $p]
-		    incr i
-		}
-	    }
-	}
-	set nohs {}
-	set reins {}
-	set isfat [expr {[llength $dlist] > $maxwidth}]
-	if {$nhyperspace > 0 || $isfat} {
-	    if {$ctxend > $n} break
-	    # work out what to bring back and
-	    # what we want to don't want to send into hyperspace
-	    set room 1
-	    for {set k $numcommits} {$k < $ctxend} {incr k} {
-		set x [lindex $displayorder $k]
-		set i [llsearch $dlist $x]
-		if {$i < 0} {
-		    set i [llength $dlist]
-		    lappend dlist $x
-		}
-		if {[lsearch -exact $nohs $x] < 0} {
-		    lappend nohs $x
-		}
-		if {$reins eq {} && $onscreen($x) < 0 && $room} {
-		    set reins [list $x $i]
-		}
-		set newp {}
-		if {[info exists commitlisted($x)]} {
-		    set right 0
-		    foreach p $parents($x) {
-			if {[llsearch $dlist $p] < 0} {
-			    lappend newp $p
-			    if {[lsearch -exact $nohs $p] < 0} {
-				lappend nohs $p
-			    }
-			    if {$reins eq {} && $onscreen($p) < 0 && $room} {
-				set reins [list $p [expr {$i + $right}]]
-			    }
-			}
-			set right 1
-		    }
-		}
-		set l [lindex $dlist $i]
-		if {[llength $l] == 1} {
-		    set l $newp
-		} else {
-		    set j [lsearch -exact $l $x]
-		    set l [concat [lreplace $l $j $j] $newp]
-		}
-		set dlist [lreplace $dlist $i $i $l]
-		if {$room && $isfat && [llength $newp] <= 1} {
-		    set room 0
-		}
-	    }
-	}
-
-	set dlevel [drawslants $id $reins $nohs]
-	drawcommitline $dlevel
-	if {[clock clicks -milliseconds] >= $nextupdate
-	    && $numcommits >= $ncmupdate} {
-	    doupdate $reading
-	    if {$stopped} break
-	}
-    }
-}
-
-# level here is an index in todo
-proc updatetodo {level noshortcut} {
-    global ncleft todo nnewparents
-    global commitlisted parents onscreen
-
-    set id [lindex $todo $level]
-    set olds {}
-    if {[info exists commitlisted($id)]} {
-	foreach p $parents($id) {
-	    if {[lsearch -exact $olds $p] < 0} {
-		lappend olds $p
-	    }
-	}
-    }
-    if {!$noshortcut && [llength $olds] == 1} {
-	set p [lindex $olds 0]
-	if {$ncleft($p) == 1 && [lsearch -exact $todo $p] < 0} {
-	    set ncleft($p) 0
-	    set todo [lreplace $todo $level $level $p]
-	    set onscreen($p) 0
-	    set nnewparents($id) 1
-	    return 0
-	}
-    }
-
-    set todo [lreplace $todo $level $level]
-    set i $level
-    set n 0
-    foreach p $olds {
-	incr ncleft($p) -1
-	set k [lsearch -exact $todo $p]
-	if {$k < 0} {
-	    set todo [linsert $todo $i $p]
-	    set onscreen($p) 0
-	    incr i
-	    incr n
-	}
-    }
-    set nnewparents($id) $n
-
-    return 1
-}
-
-proc decidenext {{noread 0}} {
-    global ncleft todo
-    global datemode cdate
-    global commitinfo
-
-    # choose which one to do next time around
-    set todol [llength $todo]
-    set level -1
-    set latest {}
-    for {set k $todol} {[incr k -1] >= 0} {} {
-	set p [lindex $todo $k]
-	if {$ncleft($p) == 0} {
-	    if {$datemode} {
-		if {![info exists commitinfo($p)]} {
-		    if {$noread} {
-			return {}
-		    }
-		    readcommit $p
-		}
-		if {$latest == {} || $cdate($p) > $latest} {
-		    set level $k
-		    set latest $cdate($p)
-		}
-	    } else {
-		set level $k
-		break
-	    }
-	}
-    }
-
-    return $level
-}
-
-proc drawcommit {id reading} {
-    global phase todo nchildren datemode nextupdate revlistorder ncleft
-    global numcommits ncmupdate displayorder todo onscreen parents
-    global commitlisted commitordered
-
-    if {$phase != "incrdraw"} {
-	set phase incrdraw
-	set displayorder {}
-	set todo {}
-	initgraph
-	catch {unset commitordered}
-    }
-    set commitordered($id) 1
-    if {$nchildren($id) == 0} {
-	lappend todo $id
-	set onscreen($id) 0
-    }
-    if {$revlistorder} {
-	set level [lsearch -exact $todo $id]
-	if {$level < 0} {
-	    error_popup "oops, $id isn't in todo"
-	    return
-	}
-	lappend displayorder $id
-	updatetodo $level 0
-    } else {
-	set level [decidenext 1]
-	if {$level == {} || $level < 0} return
-	while 1 {
-	    set id [lindex $todo $level]
-	    if {![info exists commitordered($id)]} {
-		break
-	    }
-	    lappend displayorder [lindex $todo $level]
-	    if {[updatetodo $level $datemode]} {
-		set level [decidenext 1]
-		if {$level == {} || $level < 0} break
-	    }
-	}
-    }
-    drawmore $reading
-}
-
 proc finishcommits {} {
-    global phase oldcommits commits
+    global commitidx phase
     global canv mainfont ctext maincursor textcursor
-    global parents displayorder todo
+    global findinprogress
 
-    if {$phase == "incrdraw" || $phase == "removecommits"} {
-	foreach id $oldcommits {
-	    lappend commits $id
-	    drawcommit $id 0
-	}
-	set oldcommits {}
+    if {$commitidx > 0} {
 	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
-	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,
@@ -1613,61 +1707,20 @@ proc settextcursor {c} {
     set curtextcursor $c
 }
 
-proc drawgraph {} {
-    global nextupdate startmsecs ncmupdate
-    global displayorder onscreen
-
-    if {$displayorder == {}} return
-    set startmsecs [clock clicks -milliseconds]
-    set nextupdate [expr {$startmsecs + 100}]
-    set ncmupdate 1
-    initgraph
-    foreach id $displayorder {
-	set onscreen($id) 0
-    }
-    drawmore 0
-}
-
 proc drawrest {} {
-    global phase stopped redisplaying selectedline
-    global datemode todo displayorder ncleft
-    global numcommits ncmupdate
-    global nextupdate startmsecs revlistorder
+    global numcommits
+    global startmsecs
+    global canvy0 numcommits linespc
+    global rowlaidout commitidx
 
-    set level [decidenext]
-    if {$level >= 0} {
-	set phase drawgraph
-	while 1 {
-	    lappend displayorder [lindex $todo $level]
-	    set hard [updatetodo $level $datemode]
-	    if {$hard} {
-		set level [decidenext]
-		if {$level < 0} break
-	    }
-	}
-    }
-    if {$todo != {}} {
-	puts "ERROR: none of the pending commits can be done yet:"
-	foreach p $todo {
-	    puts "  $p ($ncleft($p))"
-	}
-    }
+    set row $rowlaidout
+    layoutrows $rowlaidout $commitidx 1
+    layouttail
+    optimize_rows $row 0 $commitidx
+    showstuff $commitidx
 
-    drawmore 0
-    set phase {}
     set drawmsecs [expr {[clock clicks -milliseconds] - $startmsecs}]
     #puts "overall $drawmsecs ms for $numcommits commits"
-    if {$redisplaying} {
-	if {$stopped == 0 && [info exists selectedline]} {
-	    selectline $selectedline 0
-	}
-	if {$stopped == 1} {
-	    set stopped 0
-	    after idle drawgraph
-	} else {
-	    set redisplaying 0
-	}
-    }
 }
 
 proc findmatches {f} {
@@ -1692,9 +1745,10 @@ proc findmatches {f} {
 
 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 matchinglines foundstring foundstrlen
+    global matchinglines foundstring foundstrlen matchstring
+    global commitdata
 
     stopfindproc
     unmarkmatches
@@ -1711,6 +1765,8 @@ proc dofind {} {
     }
     set foundstrlen [string length $findstring]
     if {$foundstrlen == 0} return
+    regsub -all {[*?\[\\]} $foundstring {\\&} matchstring
+    set matchstring "*$matchstring*"
     if {$findloc == "Files"} {
 	findfiles
 	return
@@ -1722,8 +1778,21 @@ proc dofind {} {
     }
     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 {
@@ -1734,10 +1803,13 @@ proc dofind {} {
 	    if {$matches == {}} continue
 	    set doesmatch 1
 	    if {$ty == "Headline"} {
+		drawcmitrow $l
 		markmatches $canv $l $f $linehtag($l) $matches $mainfont
 	    } elseif {$ty == "Author"} {
+		drawcmitrow $l
 		markmatches $canv2 $l $f $linentag($l) $matches $namefont
 	    } elseif {$ty == "Date"} {
+		drawcmitrow $l
 		markmatches $canv3 $l $f $linedtag($l) $matches $mainfont
 	    }
 	}
@@ -1845,7 +1917,7 @@ proc stopfindproc {{done 0}} {
 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
@@ -1862,7 +1934,7 @@ proc findpatches {} {
 	if {[incr l] >= $numcommits} {
 	    set l 0
 	}
-	append inputids $lineid($l) "\n"
+	append inputids [lindex $displayorder $l] "\n"
     }
 
     if {[catch {
@@ -1886,7 +1958,7 @@ proc findpatches {} {
 
 proc readfindproc {} {
     global findprocfile finddidsel
-    global idline matchinglines findinsertpos
+    global commitrow matchinglines findinsertpos
 
     set n [gets $findprocfile line]
     if {$n < 0} {
@@ -1903,11 +1975,11 @@ proc readfindproc {} {
 	stopfindproc
 	return
     }
-    if {![info exists idline($id)]} {
+    if {![info exists commitrow($id)]} {
 	puts stderr "spurious id: $id"
 	return
     }
-    set l $idline($id)
+    set l $commitrow($id)
     insertmatch $l $id
 }
 
@@ -1933,7 +2005,7 @@ proc insertmatch {l id} {
 }
 
 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
@@ -1951,7 +2023,7 @@ proc findfiles {} {
     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"
@@ -1980,7 +2052,7 @@ proc findfiles {} {
 
     set finddidsel 0
     set findinsertpos end
-    set id $lineid($l)
+    set id [lindex $displayorder $l]
     . config -cursor watch
     settextcursor watch
     set findinprogress 1
@@ -2050,7 +2122,7 @@ proc donefilediff {} {
 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
@@ -2077,7 +2149,7 @@ proc findcont {id} {
 	    set l 0
 	}
 	if {$l == $findstartline} break
-	set id $lineid($l)
+	set id [lindex $displayorder $l]
     }
     stopfindproc
     if {!$finddidsel} {
@@ -2088,8 +2160,9 @@ proc findcont {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)]
     set t [$canv create rect $bbox -outline {} -tags matches -fill yellow]
     $canv lower $t
@@ -2123,7 +2196,7 @@ proc unmarkmatches {} {
 
 proc selcanvline {w x y} {
     global canv canvy0 ctext linespc
-    global lineid linehtag linentag linedtag rowtextx
+    global rowtextx
     set ymax [lindex [$canv cget -scrollregion] 3]
     if {$ymax == {}} return
     set yfrac [lindex [$canv yview] 0]
@@ -2151,7 +2224,7 @@ proc commit_descriptor {p} {
 # append some text to the ctext widget, and make any SHA1 ID
 # that we know about be a clickable link.
 proc appendwithlinks {text} {
-    global ctext idline linknum
+    global ctext commitrow linknum
 
     set start [$ctext index "end - 1c"]
     $ctext insert end $text
@@ -2161,11 +2234,11 @@ proc appendwithlinks {text} {
 	set s [lindex $l 0]
 	set e [lindex $l 1]
 	set linkid [string range $text $s $e]
-	if {![info exists idline($linkid)]} continue
+	if {![info exists commitrow($linkid)]} continue
 	incr e
 	$ctext tag add link "$start + $s c" "$start + $e c"
 	$ctext tag add link$linknum "$start + $s c" "$start + $e c"
-	$ctext tag bind link$linknum <1> [list selectline $idline($linkid) 1]
+	$ctext tag bind link$linknum <1> [list selectline $commitrow($linkid) 1]
 	incr linknum
     }
     $ctext tag conf link -foreground blue -underline 1
@@ -2175,27 +2248,15 @@ proc appendwithlinks {text} {
 
 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 idline linknum
-    global mergemax
+    global commentend idtags linknum
+    global mergemax numcommits
 
     $canv delete hover
     normalline
-    if {![info exists lineid($l)] || ![info exists linehtag($l)]} return
-    $canv delete secsel
-    set t [eval $canv create rect [$canv bbox $linehtag($l)] -outline {{}} \
-	       -tags secsel -fill [$canv cget -selectbackground]]
-    $canv lower $t
-    $canv2 delete secsel
-    set t [eval $canv2 create rect [$canv2 bbox $linentag($l)] -outline {{}} \
-	       -tags secsel -fill [$canv2 cget -selectbackground]]
-    $canv2 lower $t
-    $canv3 delete secsel
-    set t [eval $canv3 create rect [$canv3 bbox $linedtag($l)] -outline {{}} \
-	       -tags secsel -fill [$canv3 cget -selectbackground]]
-    $canv3 lower $t
+    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}]
@@ -2229,15 +2290,30 @@ proc selectline {l isnew} {
 	    set newtop 0
 	}
 	allcanvs yview moveto [expr {$newtop * 1.0 / $ymax}]
+	drawvisible
     }
 
+    if {![info exists linehtag($l)]} return
+    $canv delete secsel
+    set t [eval $canv create rect [$canv bbox $linehtag($l)] -outline {{}} \
+	       -tags secsel -fill [$canv cget -selectbackground]]
+    $canv lower $t
+    $canv2 delete secsel
+    set t [eval $canv2 create rect [$canv2 bbox $linentag($l)] -outline {{}} \
+	       -tags secsel -fill [$canv2 cget -selectbackground]]
+    $canv2 lower $t
+    $canv3 delete secsel
+    set t [eval $canv3 create rect [$canv3 bbox $linedtag($l)] -outline {{}} \
+	       -tags secsel -fill [$canv3 cget -selectbackground]]
+    $canv3 lower $t
+
     if {$isnew} {
 	addtohistory [list selectline $l 0]
     }
 
     set selectedline $l
 
-    set id $lineid($l)
+    set id [lindex $displayorder $l]
     set currentid $id
     $sha1entry delete 0 end
     $sha1entry insert 0 $id
@@ -2375,9 +2451,10 @@ proc goforw {} {
 
 proc mergediff {id} {
     global parents diffmergeid diffopts mdifffd
-    global difffilestart
+    global difffilestart diffids
 
     set diffmergeid $id
+    set diffids $id
     catch {unset difffilestart}
     # this doesn't seem to actually affect anything...
     set env(GIT_DIFF_OPTS) $diffopts
@@ -2394,7 +2471,7 @@ proc mergediff {id} {
 
 proc getmergediffline {mdf id} {
     global diffmergeid ctext cflist nextupdate nparents mergemax
-    global difffilestart
+    global difffilestart mdifffd
 
     set n [gets $mdf line]
     if {$n < 0} {
@@ -2403,7 +2480,8 @@ proc getmergediffline {mdf id} {
 	}
 	return
     }
-    if {![info exists diffmergeid] || $id != $diffmergeid} {
+    if {![info exists diffmergeid] || $id != $diffmergeid
+	|| $mdf != $mdifffd($id)} {
 	return
     }
     $ctext conf -state normal
@@ -2513,13 +2591,11 @@ proc gettreediffline {gdtf ids} {
 	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
     }
@@ -2595,7 +2671,9 @@ proc getblobdiffline {bdf ids} {
 	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]} {
@@ -2662,22 +2740,27 @@ proc setcoords {} {
 
     set linespc [font metrics $mainfont -linespace]
     set charspc [font measure $mainfont "m"]
-    set canvy0 [expr {3 + 0.5 * $linespc}]
-    set canvx0 [expr {3 + 0.5 * $linespc}]
+    set canvy0 [expr {int(3 + 0.5 * $linespc)}]
+    set canvx0 [expr {int(3 + 0.5 * $linespc)}]
     set lthickness [expr {int($linespc / 9) + 1}]
     set xspc1(0) $linespc
     set xspc2 $linespc
 }
 
 proc redisplay {} {
-    global stopped redisplaying phase
-    if {$stopped > 1} return
-    if {$phase == "getcommits"} return
-    set redisplaying 1
-    if {$phase == "drawgraph" || $phase == "incrdraw"} {
-	set stopped 1
-    } else {
-	drawgraph
+    global canv canvy0 linespc numcommits
+    global selectedline
+
+    set ymax [lindex [$canv cget -scrollregion] 3]
+    if {$ymax eq {} || $ymax == 0} return
+    set span [$canv yview]
+    clear_display
+    allcanvs conf -scrollregion \
+	[list 0 0 0 [expr {$canvy0 + ($numcommits - 0.5) * $linespc + 2}]]
+    allcanvs yview moveto [lindex $span 0]
+    drawvisible
+    if {[info exists selectedline]} {
+	selectline $selectedline 0
     }
 }
 
@@ -2724,8 +2807,8 @@ proc sha1change {n1 n2 op} {
 }
 
 proc gotocommit {} {
-    global sha1string currentid idline tagids
-    global lineid numcommits
+    global sha1string currentid commitrow tagids
+    global displayorder numcommits
 
     if {$sha1string == {}
 	|| ([info exists currentid] && $sha1string == $currentid)} return
@@ -2735,9 +2818,9 @@ proc gotocommit {} {
 	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 {}} {
@@ -2749,8 +2832,8 @@ proc gotocommit {} {
 	    }
 	}
     }
-    if {[info exists idline($id)]} {
-	selectline $idline($id) 1
+    if {[info exists commitrow($id)]} {
+	selectline $commitrow($id) 1
 	return
     }
     if {[regexp {^[0-9a-fA-F]{4,}$} $sha1string]} {
@@ -2765,7 +2848,7 @@ proc lineenter {x y id} {
     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
@@ -2825,65 +2908,26 @@ proc linehover {} {
 }
 
 proc clickisonarrow {id y} {
-    global mainline mainlinearrow sidelines lthickness
+    global lthickness idrowranges
 
     set thresh [expr {2 * $lthickness + 6}]
-    if {[info exists mainline($id)]} {
-	if {$mainlinearrow($id) ne "none"} {
-	    if {abs([lindex $mainline($id) 1] - $y) < $thresh} {
-		return "up"
-	    }
-	}
-    }
-    if {[info exists sidelines($id)]} {
-	foreach ls $sidelines($id) {
-	    set coords [lindex $ls 0]
-	    set arrow [lindex $ls 2]
-	    if {$arrow eq "first" || $arrow eq "both"} {
-		if {abs([lindex $coords 1] - $y) < $thresh} {
-		    return "up"
-		}
-	    }
-	    if {$arrow eq "last" || $arrow eq "both"} {
-		if {abs([lindex $coords end] - $y) < $thresh} {
-		    return "down"
-		}
-	    }
+    set n [expr {[llength $idrowranges($id)] - 1}]
+    for {set i 1} {$i < $n} {incr i} {
+	set row [lindex $idrowranges($id) $i]
+	if {abs([yc $row] - $y) < $thresh} {
+	    return $i
 	}
     }
     return {}
 }
 
-proc arrowjump {id dirn y} {
-    global mainline sidelines canv canv2 canv3
+proc arrowjump {id n y} {
+    global idrowranges canv
 
-    set yt {}
-    if {$dirn eq "down"} {
-	if {[info exists mainline($id)]} {
-	    set y1 [lindex $mainline($id) 1]
-	    if {$y1 > $y} {
-		set yt $y1
-	    }
-	}
-	if {[info exists sidelines($id)]} {
-	    foreach ls $sidelines($id) {
-		set y1 [lindex $ls 0 1]
-		if {$y1 > $y && ($yt eq {} || $y1 < $yt)} {
-		    set yt $y1
-		}
-	    }
-	}
-    } else {
-	if {[info exists sidelines($id)]} {
-	    foreach ls $sidelines($id) {
-		set y1 [lindex $ls 0 end]
-		if {$y1 < $y && ($yt eq {} || $y1 > $yt)} {
-		    set yt $y1
-		}
-	    }
-	}
-    }
-    if {$yt eq {}} return
+    # 1 <-> 2, 3 <-> 4, etc...
+    set n [expr {(($n - 1) ^ 1) + 1}]
+    set row [lindex $idrowranges($id) $n]
+    set yt [yc $row]
     set ymax [lindex [$canv cget -scrollregion] 3]
     if {$ymax eq {} || $ymax <= 0} return
     set view [$canv yview]
@@ -2892,21 +2936,20 @@ proc arrowjump {id dirn y} {
     if {$yfrac < 0} {
 	set yfrac 0
     }
-    $canv yview moveto $yfrac
-    $canv2 yview moveto $yfrac
-    $canv3 yview moveto $yfrac
+    allcanvs yview moveto $yfrac
 }
 
 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
-    drawlines $id 1 1
     set thickerline $id
+    drawlines $id
     if {$isnew} {
 	set ymax [lindex [$canv cget -scrollregion] 3]
 	if {$ymax eq {}} return
@@ -2941,6 +2984,7 @@ proc lineclick {x y id isnew} {
 	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]
@@ -2959,15 +3003,16 @@ proc lineclick {x y id isnew} {
 proc normalline {} {
     global thickerline
     if {[info exists thickerline]} {
-	drawlines $thickerline 0 1
+	set id $thickerline
 	unset thickerline
+	drawlines $id
     }
 }
 
 proc selbyid {id} {
-    global idline
-    if {[info exists idline($id)]} {
-	selectline $idline($id) 1
+    global commitrow
+    if {[info exists commitrow($id)]} {
+	selectline $commitrow($id) 1
     }
 }
 
@@ -2980,9 +3025,9 @@ proc mstime {} {
 }
 
 proc rowmenu {x y id} {
-    global rowctxmenu idline selectedline rowmenuid
+    global rowctxmenu commitrow selectedline rowmenuid
 
-    if {![info exists selectedline] || $idline($id) eq $selectedline} {
+    if {![info exists selectedline] || $commitrow($id) eq $selectedline} {
 	set state disabled
     } else {
 	set state normal
@@ -2995,15 +3040,15 @@ proc rowmenu {x y id} {
 }
 
 proc diffvssel {dirn} {
-    global rowmenuid selectedline lineid
+    global rowmenuid selectedline displayorder
 
     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 $lineid($selectedline)
+	set newid [lindex $displayorder $selectedline]
     }
     addtohistory [list doseldiff $oldid $newid]
     doseldiff $oldid $newid
@@ -3185,13 +3230,14 @@ proc domktag {} {
 }
 
 proc redrawtags {id} {
-    global canv linehtag idline idpos selectedline
+    global canv linehtag commitrow idpos selectedline
 
-    if {![info exists idline($id)]} return
+    if {![info exists commitrow($id)]} return
+    drawcmitrow $commitrow($id)
     $canv delete tag.$id
     set xt [eval drawtags $id $idpos($id)]
-    $canv coords $linehtag($idline($id)) $xt [lindex $idpos($id) 2]
-    if {[info exists selectedline] && $selectedline == $idline($id)} {
+    $canv coords $linehtag($commitrow($id)) $xt [lindex $idpos($id) 2]
+    if {[info exists selectedline] && $selectedline == $commitrow($id)} {
 	selectline $selectedline 0
     }
 }
@@ -3697,6 +3743,9 @@ set maxgraphpct 50
 set maxwidth 16
 set revlistorder 0
 set fastdate 0
+set uparrowlen 7
+set downarrowlen 7
+set mingaplen 30
 
 set colors {green red blue magenta darkgrey brown orange}
 
@@ -3711,18 +3760,25 @@ foreach arg $argv {
     switch -regexp -- $arg {
 	"^$" { }
 	"^-d" { set datemode 1 }
-	"^-r" { set revlistorder 1 }
 	default {
 	    lappend revtreeargs $arg
 	}
     }
 }
 
+# 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 optim_delay 16
+
 set stopped 0
-set redisplaying 0
 set stuffsaved 0
 set patchnum 0
 setcoords