+ 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
+ }
+ }
+ }