Code

Update Maintainer field of debian/control
[git.git] / gitk
diff --git a/gitk b/gitk
index 2aa970d5cffea4bea0e3f8f1a100f68b53e5a7af..edf94bf4c46570245feaf87fa64f94eab72aec1c 100755 (executable)
--- a/gitk
+++ b/gitk
@@ -48,13 +48,13 @@ proc getcommits {rargs} {
        exit 1
     }
     set leftover {}
        exit 1
     }
     set leftover {}
-    fconfigure $commfd -blocking 0 -translation binary
+    fconfigure $commfd -blocking 0 -translation lf
     fileevent $commfd readable "getcommitlines $commfd"
     $canv delete all
     $canv create text 3 3 -anchor nw -text "Reading commits..." \
        -font $mainfont -tags textitems
     . config -cursor watch
     fileevent $commfd readable "getcommitlines $commfd"
     $canv delete all
     $canv create text 3 3 -anchor nw -text "Reading commits..." \
        -font $mainfont -tags textitems
     . config -cursor watch
-    $ctext config -cursor watch
+    settextcursor watch
 }
 
 proc getcommitlines {commfd}  {
 }
 
 proc getcommitlines {commfd}  {
@@ -277,7 +277,7 @@ proc makewindow {} {
     global canv canv2 canv3 linespc charspc ctext cflist textfont
     global findtype findtypemenu findloc findstring fstring geometry
     global entries sha1entry sha1string sha1but
     global canv canv2 canv3 linespc charspc ctext cflist textfont
     global findtype findtypemenu findloc findstring fstring geometry
     global entries sha1entry sha1string sha1but
-    global maincursor textcursor
+    global maincursor textcursor curtextcursor
     global rowctxmenu gaudydiff mergemax
 
     menu .bar
     global rowctxmenu gaudydiff mergemax
 
     menu .bar
@@ -339,6 +339,30 @@ proc makewindow {} {
     entry $sha1entry -width 40 -font $textfont -textvariable sha1string
     trace add variable sha1string write sha1change
     pack $sha1entry -side left -pady 2
     entry $sha1entry -width 40 -font $textfont -textvariable sha1string
     trace add variable sha1string write sha1change
     pack $sha1entry -side left -pady 2
+
+    image create bitmap bm-left -data {
+       #define left_width 16
+       #define left_height 16
+       static unsigned char left_bits[] = {
+       0x00, 0x00, 0xc0, 0x01, 0xe0, 0x00, 0x70, 0x00, 0x38, 0x00, 0x1c, 0x00,
+       0x0e, 0x00, 0xff, 0x7f, 0xff, 0x7f, 0xff, 0x7f, 0x0e, 0x00, 0x1c, 0x00,
+       0x38, 0x00, 0x70, 0x00, 0xe0, 0x00, 0xc0, 0x01};
+    }
+    image create bitmap bm-right -data {
+       #define right_width 16
+       #define right_height 16
+       static unsigned char right_bits[] = {
+       0x00, 0x00, 0xc0, 0x01, 0x80, 0x03, 0x00, 0x07, 0x00, 0x0e, 0x00, 0x1c,
+       0x00, 0x38, 0xff, 0x7f, 0xff, 0x7f, 0xff, 0x7f, 0x00, 0x38, 0x00, 0x1c,
+       0x00, 0x0e, 0x00, 0x07, 0x80, 0x03, 0xc0, 0x01};
+    }
+    button .ctop.top.bar.leftbut -image bm-left -command goback \
+       -state disabled -width 26
+    pack .ctop.top.bar.leftbut -side left -fill y
+    button .ctop.top.bar.rightbut -image bm-right -command goforw \
+       -state disabled -width 26
+    pack .ctop.top.bar.rightbut -side left -fill y
+
     button .ctop.top.bar.findbut -text "Find" -command dofind
     pack .ctop.top.bar.findbut -side left
     set findstring {}
     button .ctop.top.bar.findbut -text "Find" -command dofind
     pack .ctop.top.bar.findbut -side left
     set findstring {}
@@ -441,6 +465,7 @@ proc makewindow {} {
 
     set maincursor [. cget -cursor]
     set textcursor [$ctext cget -cursor]
 
     set maincursor [. cget -cursor]
     set textcursor [$ctext cget -cursor]
+    set curtextcursor $textcursor
 
     set rowctxmenu .rowctxmenu
     menu $rowctxmenu -tearoff 0
 
     set rowctxmenu .rowctxmenu
     menu $rowctxmenu -tearoff 0
@@ -480,7 +505,7 @@ proc click {w} {
 
 proc savestuff {w} {
     global canv canv2 canv3 ctext cflist mainfont textfont
 
 proc savestuff {w} {
     global canv canv2 canv3 ctext cflist mainfont textfont
-    global stuffsaved findmergefiles gaudydiff
+    global stuffsaved findmergefiles gaudydiff maxgraphpct
 
     if {$stuffsaved} return
     if {![winfo viewable .]} return
 
     if {$stuffsaved} return
     if {![winfo viewable .]} return
@@ -490,6 +515,7 @@ proc savestuff {w} {
        puts $f [list set textfont $textfont]
        puts $f [list set findmergefiles $findmergefiles]
        puts $f [list set gaudydiff $gaudydiff]
        puts $f [list set textfont $textfont]
        puts $f [list set findmergefiles $findmergefiles]
        puts $f [list set gaudydiff $gaudydiff]
+       puts $f [list set maxgraphpct $maxgraphpct]
        puts $f "set geometry(width) [winfo width .ctop]"
        puts $f "set geometry(height) [winfo height .ctop]"
        puts $f "set geometry(canv1) [expr [winfo width $canv]-2]"
        puts $f "set geometry(width) [winfo width .ctop]"
        puts $f "set geometry(height) [winfo height .ctop]"
        puts $f "set geometry(canv1) [expr [winfo width $canv]-2]"
@@ -689,12 +715,12 @@ proc bindline {t id} {
     $canv bind $t <Enter> "lineenter %x %y $id"
     $canv bind $t <Motion> "linemotion %x %y $id"
     $canv bind $t <Leave> "lineleave $id"
     $canv bind $t <Enter> "lineenter %x %y $id"
     $canv bind $t <Motion> "linemotion %x %y $id"
     $canv bind $t <Leave> "lineleave $id"
-    $canv bind $t <Button-1> "lineclick %x %y $id"
+    $canv bind $t <Button-1> "lineclick %x %y $id 1"
 }
 
 proc drawcommitline {level} {
     global parents children nparents nchildren todo
 }
 
 proc drawcommitline {level} {
     global parents children nparents nchildren todo
-    global canv canv2 canv3 mainfont namefont canvx0 canvy linespc
+    global canv canv2 canv3 mainfont namefont canvy linespc
     global lineid linehtag linentag linedtag commitinfo
     global colormap numcommits currentparents dupparents
     global oldlevel oldnlines oldtodo
     global lineid linehtag linentag linedtag commitinfo
     global colormap numcommits currentparents dupparents
     global oldlevel oldnlines oldtodo
@@ -728,7 +754,7 @@ proc drawcommitline {level} {
            }
        }
     }
            }
        }
     }
-    set x [expr $canvx0 + $level * $linespc]
+    set x [xcoord $level $level $lineno]
     set y1 $canvy
     set canvy [expr $canvy + $linespc]
     allcanvs conf -scrollregion \
     set y1 $canvy
     set canvy [expr $canvy + $linespc]
     allcanvs conf -scrollregion \
@@ -756,7 +782,7 @@ proc drawcommitline {level} {
               -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 [expr $canvx0 + [llength $todo] * $linespc]
+    set xt [xcoord [llength $todo] $level $lineno]
     if {[llength $currentparents] > 2} {
        set xt [expr {$xt + ([llength $currentparents] - 2) * $linespc}]
     }
     if {[llength $currentparents] > 2} {
        set xt [expr {$xt + ([llength $currentparents] - 2) * $linespc}]
     }
@@ -832,8 +858,8 @@ proc drawtags {id x xt y1} {
 proc updatetodo {level noshortcut} {
     global currentparents ncleft todo
     global mainline oldlevel oldtodo oldnlines
 proc updatetodo {level noshortcut} {
     global currentparents ncleft todo
     global mainline oldlevel oldtodo oldnlines
-    global canvx0 canvy linespc mainline
-    global commitinfo
+    global canvy linespc mainline
+    global commitinfo lineno xspc1
 
     set oldlevel $level
     set oldtodo $todo
 
     set oldlevel $level
     set oldtodo $todo
@@ -842,10 +868,11 @@ proc updatetodo {level noshortcut} {
        set p [lindex $currentparents 0]
        if {$ncleft($p) == 1 && [lsearch -exact $todo $p] < 0} {
            set ncleft($p) 0
        set p [lindex $currentparents 0]
        if {$ncleft($p) == 1 && [lsearch -exact $todo $p] < 0} {
            set ncleft($p) 0
-           set x [expr $canvx0 + $level * $linespc]
+           set x [xcoord $level $level $lineno]
            set y [expr $canvy - $linespc]
            set mainline($p) [list $x $y]
            set todo [lreplace $todo $level $level $p]
            set y [expr $canvy - $linespc]
            set mainline($p) [list $x $y]
            set todo [lreplace $todo $level $level $p]
+           set xspc1([expr {$lineno + 1}]) $xspc1($lineno)
            return 0
        }
     }
            return 0
        }
     }
@@ -891,28 +918,54 @@ proc notecrossings {id lo hi corner} {
     }
 }
 
     }
 }
 
-proc drawslants {} {
-    global canv mainline sidelines canvx0 canvy linespc
-    global oldlevel oldtodo todo currentparents dupparents
-    global lthickness linespc canvy colormap
+proc xcoord {i level ln} {
+    global canvx0 xspc1 xspc2
+
+    set x [expr {$canvx0 + $i * $xspc1($ln)}]
+    if {$i > 0 && $i == $level} {
+       set x [expr {$x + 0.5 * ($xspc2 - $xspc1($ln))}]
+    } elseif {$i > $level} {
+       set x [expr {$x + $xspc2 - $xspc1($ln)}]
+    }
+    return $x
+}
 
 
+proc drawslants {level} {
+    global canv mainline sidelines canvx0 canvy xspc1 xspc2 lthickness
+    global oldlevel oldtodo todo currentparents dupparents
+    global lthickness linespc canvy colormap lineno geometry
+    global maxgraphpct
+
+    # decide on the line spacing for the next line
+    set lj [expr {$lineno + 1}]
+    set maxw [expr {$maxgraphpct * $geometry(canv1) / 100}]
+    set n [llength $todo]
+    if {$n <= 1 || $canvx0 + $n * $xspc2 <= $maxw} {
+       set xspc1($lj) $xspc2
+    } else {
+       set xspc1($lj) [expr {($maxw - $canvx0 - $xspc2) / ($n - 1)}]
+       if {$xspc1($lj) < $lthickness} {
+           set xspc1($lj) $lthickness
+       }
+    }
+    
     set y1 [expr $canvy - $linespc]
     set y2 $canvy
     set i -1
     foreach id $oldtodo {
        incr i
        if {$id == {}} continue
     set y1 [expr $canvy - $linespc]
     set y2 $canvy
     set i -1
     foreach id $oldtodo {
        incr i
        if {$id == {}} continue
-       set xi [expr {$canvx0 + $i * $linespc}]
+       set xi [xcoord $i $oldlevel $lineno]
        if {$i == $oldlevel} {
            foreach p $currentparents {
                set j [lsearch -exact $todo $p]
                set coords [list $xi $y1]
        if {$i == $oldlevel} {
            foreach p $currentparents {
                set j [lsearch -exact $todo $p]
                set coords [list $xi $y1]
-               set xj [expr {$canvx0 + $j * $linespc}]
-               if {$j < $i - 1} {
-                   lappend coords [expr $xj + $linespc] $y1
+               set xj [xcoord $j $level $lj]
+               if {$xj < $xi - $linespc} {
+                   lappend coords [expr {$xj + $linespc}] $y1
                    notecrossings $p $j $i [expr {$j + 1}]
                    notecrossings $p $j $i [expr {$j + 1}]
-               } elseif {$j > $i + 1} {
-                   lappend coords [expr $xj - $linespc] $y1
+               } elseif {$xj > $xi + $linespc} {
+                   lappend coords [expr {$xj - $linespc}] $y1
                    notecrossings $p $i $j [expr {$j - 1}]
                }
                if {[lsearch -exact $dupparents $p] >= 0} {
                    notecrossings $p $i $j [expr {$j - 1}]
                }
                if {[lsearch -exact $dupparents $p] >= 0} {
@@ -924,28 +977,48 @@ proc drawslants {} {
                    }
                } else {
                    # normal case, no parent duplicated
                    }
                } 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 {![info exists mainline($p)]} {
-                       if {$i != $j} {
-                           lappend coords $xj $y2
+                       if {$xi != $xj} {
+                           lappend coords $xj $yb
                        }
                        set mainline($p) $coords
                    } else {
                        }
                        set mainline($p) $coords
                    } else {
-                       lappend coords $xj $y2
+                       lappend coords $xj $yb
+                       if {$yb < $y2} {
+                           lappend coords $xj $y2
+                       }
                        lappend sidelines($p) [list $coords 1]
                    }
                }
            }
                        lappend sidelines($p) [list $coords 1]
                    }
                }
            }
-       } elseif {[lindex $todo $i] != $id} {
-           set j [lsearch -exact $todo $id]
-           set xj [expr {$canvx0 + $j * $linespc}]
-           lappend mainline($id) $xi $y1 $xj $y2
+       } else {
+           set j $i
+           if {[lindex $todo $i] != $id} {
+               set j [lsearch -exact $todo $id]
+           }
+           if {$j != $i || $xspc1($lineno) != $xspc1($lj)
+               || ($oldlevel <= $i && $i <= $level)
+               || ($level <= $i && $i <= $oldlevel)} {
+               set xj [xcoord $j $level $lj]
+               set dx [expr {abs($xi - $xj)}]
+               set yb $y2
+               if {0 && $dx < $linespc} {
+                   set yb [expr {$y1 + $dx}]
+               }
+               lappend mainline($id) $xi $y1 $xj $yb
+           }
        }
     }
 }
 
 proc decidenext {{noread 0}} {
     global parents children nchildren ncleft todo
        }
     }
 }
 
 proc decidenext {{noread 0}} {
     global parents children nchildren ncleft todo
-    global canv canv2 canv3 mainfont namefont canvx0 canvy linespc
+    global canv canv2 canv3 mainfont namefont canvy linespc
     global datemode cdate
     global commitinfo
     global currentparents oldlevel oldnlines oldtodo
     global datemode cdate
     global commitinfo
     global currentparents oldlevel oldnlines oldtodo
@@ -1036,7 +1109,7 @@ proc drawcommit {id} {
            return
        }
        while 1 {
            return
        }
        while 1 {
-           drawslants
+           drawslants $level
            drawcommitline $level
            if {[updatetodo $level $datemode]} {
                set level [decidenext 1]
            drawcommitline $level
            if {[updatetodo $level $datemode]} {
                set level [decidenext 1]
@@ -1065,12 +1138,23 @@ proc finishcommits {} {
            -font $mainfont -tags textitems
        set phase {}
     } else {
            -font $mainfont -tags textitems
        set phase {}
     } else {
-       drawslants
        set level [decidenext]
        set level [decidenext]
+       drawslants $level
        drawrest $level [llength $startcommits]
     }
     . config -cursor $maincursor
        drawrest $level [llength $startcommits]
     }
     . config -cursor $maincursor
-    $ctext config -cursor $textcursor
+    settextcursor $textcursor
+}
+
+# Don't change the text pane cursor if it is currently the hand cursor,
+# showing that we are over a sha1 ID link.
+proc settextcursor {c} {
+    global ctext curtextcursor
+
+    if {[$ctext cget -cursor] == $curtextcursor} {
+       $ctext config -cursor $c
+    }
+    set curtextcursor $c
 }
 
 proc drawgraph {} {
 }
 
 proc drawgraph {} {
@@ -1114,7 +1198,7 @@ proc drawrest {level startix} {
            if {$hard} {
                set level [decidenext]
                if {$level < 0} break
            if {$hard} {
                set level [decidenext]
                if {$level < 0} break
-               drawslants
+               drawslants $level
            }
            if {[clock clicks -milliseconds] >= $nextupdate} {
                update
            }
            if {[clock clicks -milliseconds] >= $nextupdate} {
                update
@@ -1127,7 +1211,7 @@ proc drawrest {level startix} {
     #puts "overall $drawmsecs ms for $numcommits commits"
     if {$redisplaying} {
        if {$stopped == 0 && [info exists selectedline]} {
     #puts "overall $drawmsecs ms for $numcommits commits"
     if {$redisplaying} {
        if {$stopped == 0 && [info exists selectedline]} {
-           selectline $selectedline
+           selectline $selectedline 0
        }
        if {$stopped == 1} {
            set stopped 0
        }
        if {$stopped == 1} {
            set stopped 0
@@ -1226,7 +1310,7 @@ proc dofind {} {
 
 proc findselectline {l} {
     global findloc commentend ctext
 
 proc findselectline {l} {
     global findloc commentend ctext
-    selectline $l
+    selectline $l 1
     if {$findloc == "All fields" || $findloc == "Comments"} {
        # highlight the matches in the comments
        set f [$ctext get 1.0 $commentend]
     if {$findloc == "All fields" || $findloc == "Comments"} {
        # highlight the matches in the comments
        set f [$ctext get 1.0 $commentend]
@@ -1305,7 +1389,7 @@ proc stopfindproc {{done 0}} {
        unset findinprogress
        if {$phase != "incrdraw"} {
            . config -cursor $maincursor
        unset findinprogress
        if {$phase != "incrdraw"} {
            . config -cursor $maincursor
-           $ctext config -cursor $textcursor
+           settextcursor $textcursor
        }
     }
 }
        }
     }
 }
@@ -1348,7 +1432,7 @@ proc findpatches {} {
     fileevent $f readable readfindproc
     set finddidsel 0
     . config -cursor watch
     fileevent $f readable readfindproc
     set finddidsel 0
     . config -cursor watch
-    $ctext config -cursor watch
+    settextcursor watch
     set findinprogress 1
 }
 
     set findinprogress 1
 }
 
@@ -1453,7 +1537,7 @@ proc findfiles {} {
     set id $lineid($l)
     set p [lindex $parents($id) 0]
     . config -cursor watch
     set id $lineid($l)
     set p [lindex $parents($id) 0]
     . config -cursor watch
-    $ctext config -cursor watch
+    settextcursor watch
     set findinprogress 1
     findcont [list $id $p]
     update
     set findinprogress 1
     findcont [list $id $p]
     update
@@ -1603,7 +1687,7 @@ proc unmarkmatches {} {
 }
 
 proc selcanvline {w x y} {
 }
 
 proc selcanvline {w x y} {
-    global canv canvy0 ctext linespc selectedline
+    global canv canvy0 ctext linespc
     global lineid linehtag linentag linedtag rowtextx
     set ymax [lindex [$canv cget -scrollregion] 3]
     if {$ymax == {}} return
     global lineid linehtag linentag linedtag rowtextx
     set ymax [lindex [$canv cget -scrollregion] 3]
     if {$ymax == {}} return
@@ -1617,15 +1701,16 @@ proc selcanvline {w x y} {
        if {![info exists rowtextx($l)] || $x < $rowtextx($l)} return
     }
     unmarkmatches
        if {![info exists rowtextx($l)] || $x < $rowtextx($l)} return
     }
     unmarkmatches
-    selectline $l
+    selectline $l 1
 }
 
 }
 
-proc selectline {l} {
+proc selectline {l isnew} {
     global canv canv2 canv3 ctext commitinfo selectedline
     global lineid linehtag linentag linedtag
     global canvy0 linespc parents nparents
     global cflist currentid sha1entry
     global canv canv2 canv3 ctext commitinfo selectedline
     global lineid linehtag linentag linedtag
     global canvy0 linespc parents nparents
     global cflist currentid sha1entry
-    global commentend idtags
+    global commentend idtags idline
+
     $canv delete hover
     if {![info exists lineid($l)] || ![info exists linehtag($l)]} return
     $canv delete secsel
     $canv delete hover
     if {![info exists lineid($l)] || ![info exists linehtag($l)]} return
     $canv delete secsel
@@ -1674,6 +1759,11 @@ proc selectline {l} {
        }
        allcanvs yview moveto [expr $newtop * 1.0 / $ymax]
     }
        }
        allcanvs yview moveto [expr $newtop * 1.0 / $ymax]
     }
+
+    if {$isnew} {
+       addtohistory [list selectline $l 0]
+    }
+
     set selectedline $l
 
     set id $lineid($l)
     set selectedline $l
 
     set id $lineid($l)
@@ -1697,9 +1787,42 @@ proc selectline {l} {
        }
        $ctext insert end "\n"
     }
        }
        $ctext insert end "\n"
     }
+    set commentstart [$ctext index "end - 1c"]
+    set comment {}
+    foreach p $parents($id) {
+       set l "..."
+       if {[info exists commitinfo($p)]} {
+           set l [lindex $commitinfo($p) 0]
+           if {[string length $l] > 32} {
+               set l "[string range $l 0 28] ..."
+           }
+       }
+       append comment "Parent: $p  ($l)\n"
+    }
+    append comment "\n"
+    append comment [lindex $info 5]
+    $ctext insert end $comment
     $ctext insert end "\n"
     $ctext insert end "\n"
-    $ctext insert end [lindex $info 5]
-    $ctext insert end "\n"
+
+    # make anything that looks like a SHA1 ID be a clickable link
+    set links [regexp -indices -all -inline {[0-9a-f]{40}} $comment]
+    set i 0
+    foreach l $links {
+       set s [lindex $l 0]
+       set e [lindex $l 1]
+       set linkid [string range $comment $s $e]
+       if {![info exists idline($linkid)]} continue
+       incr e
+       $ctext tag add link "$commentstart + $s c" "$commentstart + $e c"
+       $ctext tag add link$i "$commentstart + $s c" "$commentstart + $e c"
+       $ctext tag bind link$i <1> [list selectline $idline($linkid) 1]
+       incr i
+    }
+    $ctext tag conf link -foreground blue -underline 1
+    $ctext tag bind link <Enter> { %W configure -cursor hand2 }
+    $ctext tag bind link <Leave> { %W configure -cursor $curtextcursor }
+
     $ctext tag delete Comments
     $ctext tag remove found 1.0 end
     $ctext conf -state disabled
     $ctext tag delete Comments
     $ctext tag remove found 1.0 end
     $ctext conf -state disabled
@@ -1719,7 +1842,64 @@ proc selnextline {dir} {
     if {![info exists selectedline]} return
     set l [expr $selectedline + $dir]
     unmarkmatches
     if {![info exists selectedline]} return
     set l [expr $selectedline + $dir]
     unmarkmatches
-    selectline $l
+    selectline $l 1
+}
+
+proc unselectline {} {
+    global selectedline
+
+    catch {unset selectedline}
+    allcanvs delete secsel
+}
+
+proc addtohistory {cmd} {
+    global history historyindex
+
+    if {$historyindex > 0
+       && [lindex $history [expr {$historyindex - 1}]] == $cmd} {
+       return
+    }
+
+    if {$historyindex < [llength $history]} {
+       set history [lreplace $history $historyindex end $cmd]
+    } else {
+       lappend history $cmd
+    }
+    incr historyindex
+    if {$historyindex > 1} {
+       .ctop.top.bar.leftbut conf -state normal
+    } else {
+       .ctop.top.bar.leftbut conf -state disabled
+    }
+    .ctop.top.bar.rightbut conf -state disabled
+}
+
+proc goback {} {
+    global history historyindex
+
+    if {$historyindex > 1} {
+       incr historyindex -1
+       set cmd [lindex $history [expr {$historyindex - 1}]]
+       eval $cmd
+       .ctop.top.bar.rightbut conf -state normal
+    }
+    if {$historyindex <= 1} {
+       .ctop.top.bar.leftbut conf -state disabled
+    }
+}
+
+proc goforw {} {
+    global history historyindex
+
+    if {$historyindex < [llength $history]} {
+       set cmd [lindex $history $historyindex]
+       incr historyindex
+       eval $cmd
+       .ctop.top.bar.leftbut conf -state normal
+    }
+    if {$historyindex >= [llength $history]} {
+       .ctop.top.bar.rightbut conf -state disabled
+    }
 }
 
 proc mergediff {id} {
 }
 
 proc mergediff {id} {
@@ -1729,7 +1909,9 @@ proc mergediff {id} {
     set diffpindex -1
     set diffmergegca [findgca $parents($id)]
     if {[info exists mergefilelist($id)]} {
     set diffpindex -1
     set diffmergegca [findgca $parents($id)]
     if {[info exists mergefilelist($id)]} {
-       showmergediff
+       if {$mergefilelist($id) ne {}} {
+           showmergediff
+       }
     } else {
        contmergediff {}
     }
     } else {
        contmergediff {}
     }
@@ -1753,7 +1935,7 @@ proc findgca {ids} {
 
 proc contmergediff {ids} {
     global diffmergeid diffpindex parents nparents diffmergegca
 
 proc contmergediff {ids} {
     global diffmergeid diffpindex parents nparents diffmergegca
-    global treediffs mergefilelist diffids
+    global treediffs mergefilelist diffids treepending
 
     # diff the child against each of the parents, and diff
     # each of the parents against the GCA.
 
     # diff the child against each of the parents, and diff
     # each of the parents against the GCA.
@@ -1814,8 +1996,8 @@ proc contmergediff {ids} {
 
 proc showmergediff {} {
     global cflist diffmergeid mergefilelist parents
 
 proc showmergediff {} {
     global cflist diffmergeid mergefilelist parents
-    global diffopts diffinhunk currentfile diffblocked
-    global groupfilelast mergefds
+    global diffopts diffinhunk currentfile currenthunk filelines
+    global diffblocked groupfilelast mergefds groupfilenum grouphunks
 
     set files $mergefilelist($diffmergeid)
     foreach f $files {
 
     set files $mergefilelist($diffmergeid)
     foreach f $files {
@@ -1826,6 +2008,8 @@ proc showmergediff {} {
     catch {unset currentfile}
     catch {unset currenthunk}
     catch {unset filelines}
     catch {unset currentfile}
     catch {unset currenthunk}
     catch {unset filelines}
+    catch {unset groupfilenum}
+    catch {unset grouphunks}
     set groupfilelast -1
     foreach p $parents($diffmergeid) {
        set cmd [list | git-diff-tree -p $p $diffmergeid]
     set groupfilelast -1
     foreach p $parents($diffmergeid) {
        set cmd [list | git-diff-tree -p $p $diffmergeid]
@@ -2447,14 +2631,18 @@ proc listboxsel {} {
 
 proc setcoords {} {
     global linespc charspc canvx0 canvy0 mainfont
 
 proc setcoords {} {
     global linespc charspc canvx0 canvy0 mainfont
+    global xspc1 xspc2
+
     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 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 xspc1(0) $linespc
+    set xspc2 $linespc
 }
 
 proc redisplay {} {
 }
 
 proc redisplay {} {
-    global selectedline stopped redisplaying phase
+    global stopped redisplaying phase
     if {$stopped > 1} return
     if {$phase == "getcommits"} return
     set redisplaying 1
     if {$stopped > 1} return
     if {$phase == "getcommits"} return
     set redisplaying 1
@@ -2466,7 +2654,7 @@ proc redisplay {} {
 }
 
 proc incrfont {inc} {
 }
 
 proc incrfont {inc} {
-    global mainfont namefont textfont selectedline ctext canv phase
+    global mainfont namefont textfont ctext canv phase
     global stopped entries
     unmarkmatches
     set mainfont [lreplace $mainfont 1 1 [expr {[lindex $mainfont 1] + $inc}]]
     global stopped entries
     unmarkmatches
     set mainfont [lreplace $mainfont 1 1 [expr {[lindex $mainfont 1] + $inc}]]
@@ -2534,7 +2722,7 @@ proc gotocommit {} {
        }
     }
     if {[info exists idline($id)]} {
        }
     }
     if {[info exists idline($id)]} {
-       selectline $idline($id)
+       selectline $idline($id) 1
        return
     }
     if {[regexp {^[0-9a-fA-F]{4,}$} $sha1string]} {
        return
     }
     if {[regexp {^[0-9a-fA-F]{4,}$} $sha1string]} {
@@ -2608,34 +2796,40 @@ proc linehover {} {
     $canv raise $t
 }
 
     $canv raise $t
 }
 
-proc lineclick {x y id} {
+proc lineclick {x y id isnew} {
     global ctext commitinfo children cflist canv
 
     unmarkmatches
     global ctext commitinfo children cflist canv
 
     unmarkmatches
+    unselectline
+    if {$isnew} {
+       addtohistory [list lineclick $x $x $id 0]
+    }
     $canv delete hover
     # fill the details pane with info about this line
     $ctext conf -state normal
     $ctext delete 0.0 end
     $canv delete hover
     # fill the details pane with info about this line
     $ctext conf -state normal
     $ctext delete 0.0 end
-    $ctext insert end "Parent:\n "
-    catch {destroy $ctext.$id}
-    button $ctext.$id -text "Go:" -command "selbyid $id" \
-       -padx 4 -pady 0
-    $ctext window create end -window $ctext.$id -align center
+    $ctext tag conf link -foreground blue -underline 1
+    $ctext tag bind link <Enter> { %W configure -cursor hand2 }
+    $ctext tag bind link <Leave> { %W configure -cursor $curtextcursor }
+    $ctext insert end "Parent:\t"
+    $ctext insert end $id [list link link0]
+    $ctext tag bind link0 <1> [list selbyid $id]
     set info $commitinfo($id)
     set info $commitinfo($id)
-    $ctext insert end "\t[lindex $info 0]\n"
+    $ctext insert end "\n\t[lindex $info 0]\n"
     $ctext insert end "\tAuthor:\t[lindex $info 1]\n"
     $ctext insert end "\tDate:\t[lindex $info 2]\n"
     $ctext insert end "\tAuthor:\t[lindex $info 1]\n"
     $ctext insert end "\tDate:\t[lindex $info 2]\n"
-    $ctext insert end "\tID:\t$id\n"
     if {[info exists children($id)]} {
        $ctext insert end "\nChildren:"
     if {[info exists children($id)]} {
        $ctext insert end "\nChildren:"
+       set i 0
        foreach child $children($id) {
        foreach child $children($id) {
-           $ctext insert end "\n "
-           catch {destroy $ctext.$child}
-           button $ctext.$child -text "Go:" -command "selbyid $child" \
-               -padx 4 -pady 0
-           $ctext window create end -window $ctext.$child -align center
+           incr i
            set info $commitinfo($child)
            set info $commitinfo($child)
-           $ctext insert end "\t[lindex $info 0]"
+           $ctext insert end "\n\t"
+           $ctext insert end $child [list link link$i]
+           $ctext tag bind link$i <1> [list selbyid $child]
+           $ctext insert end "\n\t[lindex $info 0]"
+           $ctext insert end "\n\tAuthor:\t[lindex $info 1]"
+           $ctext insert end "\n\tDate:\t[lindex $info 2]\n"
        }
     }
     $ctext conf -state disabled
        }
     }
     $ctext conf -state disabled
@@ -2646,7 +2840,7 @@ proc lineclick {x y id} {
 proc selbyid {id} {
     global idline
     if {[info exists idline($id)]} {
 proc selbyid {id} {
     global idline
     if {[info exists idline($id)]} {
-       selectline $idline($id)
+       selectline $idline($id) 1
     }
 }
 
     }
 }
 
@@ -2675,8 +2869,6 @@ proc rowmenu {x y id} {
 
 proc diffvssel {dirn} {
     global rowmenuid selectedline lineid
 
 proc diffvssel {dirn} {
     global rowmenuid selectedline lineid
-    global ctext cflist
-    global commitinfo
 
     if {![info exists selectedline]} return
     if {$dirn} {
 
     if {![info exists selectedline]} return
     if {$dirn} {
@@ -2686,21 +2878,38 @@ proc diffvssel {dirn} {
        set oldid $rowmenuid
        set newid $lineid($selectedline)
     }
        set oldid $rowmenuid
        set newid $lineid($selectedline)
     }
+    addtohistory [list doseldiff $oldid $newid]
+    doseldiff $oldid $newid
+}
+
+proc doseldiff {oldid newid} {
+    global ctext cflist
+    global commitinfo
+
     $ctext conf -state normal
     $ctext delete 0.0 end
     $ctext mark set fmark.0 0.0
     $ctext mark gravity fmark.0 left
     $cflist delete 0 end
     $cflist insert end "Top"
     $ctext conf -state normal
     $ctext delete 0.0 end
     $ctext mark set fmark.0 0.0
     $ctext mark gravity fmark.0 left
     $cflist delete 0 end
     $cflist insert end "Top"
-    $ctext insert end "From $oldid\n     "
+    $ctext insert end "From "
+    $ctext tag conf link -foreground blue -underline 1
+    $ctext tag bind link <Enter> { %W configure -cursor hand2 }
+    $ctext tag bind link <Leave> { %W configure -cursor $curtextcursor }
+    $ctext tag bind link0 <1> [list selbyid $oldid]
+    $ctext insert end $oldid [list link link0]
+    $ctext insert end "\n     "
     $ctext insert end [lindex $commitinfo($oldid) 0]
     $ctext insert end [lindex $commitinfo($oldid) 0]
-    $ctext insert end "\n\nTo   $newid\n     "
+    $ctext insert end "\n\nTo   "
+    $ctext tag bind link1 <1> [list selbyid $newid]
+    $ctext insert end $newid [list link link1]
+    $ctext insert end "\n     "
     $ctext insert end [lindex $commitinfo($newid) 0]
     $ctext insert end "\n"
     $ctext conf -state disabled
     $ctext tag delete Comments
     $ctext tag remove found 1.0 end
     $ctext insert end [lindex $commitinfo($newid) 0]
     $ctext insert end "\n"
     $ctext conf -state disabled
     $ctext tag delete Comments
     $ctext tag remove found 1.0 end
-    startdiff $newid [list $oldid]
+    startdiff [list $newid $oldid]
 }
 
 proc mkpatch {} {
 }
 
 proc mkpatch {} {
@@ -2850,7 +3059,7 @@ proc domktag {} {
     set xt [eval drawtags $id $idpos($id)]
     $canv coords $linehtag($idline($id)) $xt [lindex $idpos($id) 2]
     if {[info exists selectedline] && $selectedline == $idline($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)} {
-       selectline $selectedline
+       selectline $selectedline 0
     }
 }
 
     }
 }
 
@@ -2937,6 +3146,7 @@ set mainfont {Helvetica 9}
 set textfont {Courier 9}
 set findmergefiles 0
 set gaudydiff 0
 set textfont {Courier 9}
 set findmergefiles 0
 set gaudydiff 0
+set maxgraphpct 50
 
 set colors {green red blue magenta darkgrey brown orange}
 
 
 set colors {green red blue magenta darkgrey brown orange}
 
@@ -2959,6 +3169,9 @@ foreach arg $argv {
     }
 }
 
     }
 }
 
+set history {}
+set historyindex 0
+
 set stopped 0
 set redisplaying 0
 set stuffsaved 0
 set stopped 0
 set redisplaying 0
 set stuffsaved 0