[PATCH] Plug memory leak in write_sha1_to_fd()
[git.git] / gitk
diff --git a/gitk b/gitk
index 59cdd85..edf94bf 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
@@ -465,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
@@ -714,7 +715,7 @@ 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} {
 }
 
 proc drawcommitline {level} {
@@ -1142,7 +1143,18 @@ proc finishcommits {} {
        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 {} {
@@ -1377,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
        }
     }
 }
        }
     }
 }
@@ -1420,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
 }
 
@@ -1525,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
@@ -1675,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
@@ -1698,7 +1710,6 @@ proc selectline {l isnew} {
     global canvy0 linespc parents nparents
     global cflist currentid sha1entry
     global commentend idtags idline
     global canvy0 linespc parents nparents
     global cflist currentid sha1entry
     global commentend idtags idline
-    global history historyindex
 
     $canv delete hover
     if {![info exists lineid($l)] || ![info exists linehtag($l)]} return
 
     $canv delete hover
     if {![info exists lineid($l)] || ![info exists linehtag($l)]} return
@@ -1749,19 +1760,8 @@ proc selectline {l isnew} {
        allcanvs yview moveto [expr $newtop * 1.0 / $ymax]
     }
 
        allcanvs yview moveto [expr $newtop * 1.0 / $ymax]
     }
 
-    if {$isnew && (![info exists selectedline] || $selectedline != $l)} {
-       if {$historyindex < [llength $history]} {
-           set history [lreplace $history $historyindex end $l]
-       } else {
-           lappend history $l
-       }
-       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
+    if {$isnew} {
+       addtohistory [list selectline $l 0]
     }
 
     set selectedline $l
     }
 
     set selectedline $l
@@ -1787,9 +1787,21 @@ proc selectline {l isnew} {
        }
        $ctext insert end "\n"
     }
        }
        $ctext insert end "\n"
     }
-    $ctext insert end "\n"
     set commentstart [$ctext index "end - 1c"]
     set commentstart [$ctext index "end - 1c"]
-    set comment [lindex $info 5]
+    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 $comment
     $ctext insert end "\n"
 
@@ -1802,10 +1814,14 @@ proc selectline {l isnew} {
        set linkid [string range $comment $s $e]
        if {![info exists idline($linkid)]} continue
        incr e
        set linkid [string range $comment $s $e]
        if {![info exists idline($linkid)]} continue
        incr e
-       $ctext tag conf link$i -foreground blue -underline 1
+       $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]
        $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 tag delete Comments
     $ctext tag remove found 1.0 end
@@ -1829,12 +1845,42 @@ proc selnextline {dir} {
     selectline $l 1
 }
 
     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
 proc goback {} {
     global history historyindex
 
     if {$historyindex > 1} {
        incr historyindex -1
-       selectline [lindex $history [expr {$historyindex - 1}]] 0
+       set cmd [lindex $history [expr {$historyindex - 1}]]
+       eval $cmd
        .ctop.top.bar.rightbut conf -state normal
     }
     if {$historyindex <= 1} {
        .ctop.top.bar.rightbut conf -state normal
     }
     if {$historyindex <= 1} {
@@ -1846,9 +1892,9 @@ proc goforw {} {
     global history historyindex
 
     if {$historyindex < [llength $history]} {
     global history historyindex
 
     if {$historyindex < [llength $history]} {
-       set l [lindex $history $historyindex]
+       set cmd [lindex $history $historyindex]
        incr historyindex
        incr historyindex
-       selectline $l 0
+       eval $cmd
        .ctop.top.bar.leftbut conf -state normal
     }
     if {$historyindex >= [llength $history]} {
        .ctop.top.bar.leftbut conf -state normal
     }
     if {$historyindex >= [llength $history]} {
@@ -2596,7 +2642,7 @@ proc setcoords {} {
 }
 
 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
@@ -2608,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}]]
@@ -2750,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
@@ -2817,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} {
@@ -2828,15 +2878,32 @@ 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 insert end [lindex $commitinfo($newid) 0]
     $ctext insert end "\n"
     $ctext conf -state disabled