2 # Tcl ignores the next line -*- tcl -*- \
3 exec wish "$0" -- "${1+$@}"
5 # Copyright (C) 2005 Paul Mackerras. All rights reserved.
6 # This program is free software; it may be used, copied, modified
7 # and distributed under the terms of the GNU General Public Licence,
8 # either version 2, or (at your option) any later version.
10 proc getcommits {rargs} {
11 global commits commfd phase canv mainfont env
12 global startmsecs nextupdate
13 global ctext maincursor textcursor leftover
15 # check that we can find a .git directory somewhere...
16 if {[info exists env(GIT_DIR)]} {
17 set gitdir $env(GIT_DIR)
21 if {![file isdirectory $gitdir]} {
22 error_popup "Cannot find the git directory \"$gitdir\"."
27 set startmsecs [clock clicks -milliseconds]
28 set nextupdate [expr $startmsecs + 100]
30 set parse_args [concat --default HEAD $rargs]
31 set parsed_args [split [eval exec git-rev-parse $parse_args] "\n"]
33 # if git-rev-parse failed for some reason...
37 set parsed_args $rargs
40 set commfd [open "|git-rev-list --header --merge-order $parsed_args" r]
42 puts stderr "Error executing git-rev-list: $err"
46 fconfigure $commfd -blocking 0 -translation binary
47 fileevent $commfd readable "getcommitlines $commfd"
49 $canv create text 3 3 -anchor nw -text "Reading commits..." \
50 -font $mainfont -tags textitems
51 . config -cursor watch
52 $ctext config -cursor watch
55 proc getcommitlines {commfd} {
56 global commits parents cdate children nchildren
57 global commitlisted phase commitinfo nextupdate
58 global stopped redisplaying leftover
60 set stuff [read $commfd]
62 if {![eof $commfd]} return
63 # this works around what is apparently a bug in Tcl...
64 fconfigure $commfd -blocking 1
65 if {![catch {close $commfd} err]} {
66 after idle finishcommits
69 if {[string range $err 0 4] == "usage"} {
71 {Gitk: error reading commits: bad arguments to git-rev-list.
72 (Note: arguments to gitk are passed to git-rev-list
73 to allow selection of commits to be displayed.)}
75 set err "Error reading commits: $err"
82 set i [string first "\0" $stuff $start]
84 set leftover [string range $stuff $start end]
87 set cmit [string range $stuff $start [expr {$i - 1}]]
89 set cmit "$leftover$cmit"
91 set start [expr {$i + 1}]
92 if {![regexp {^([0-9a-f]{40})\n} $cmit match id]} {
93 error_popup "Can't parse git-rev-list output: {$cmit}"
96 set cmit [string range $cmit 41 end]
98 set commitlisted($id) 1
99 parsecommit $id $cmit 1
101 if {[clock clicks -milliseconds] >= $nextupdate} {
104 while {$redisplaying} {
108 set phase "getcommits"
109 foreach id $commits {
112 if {[clock clicks -milliseconds] >= $nextupdate} {
122 global commfd nextupdate
125 fileevent $commfd readable {}
127 fileevent $commfd readable "getcommitlines $commfd"
130 proc readcommit {id} {
131 if [catch {set contents [exec git-cat-file commit $id]}] return
132 parsecommit $id $contents 0
135 proc parsecommit {id contents listed} {
136 global commitinfo children nchildren parents nparents cdate ncleft
145 if {![info exists nchildren($id)]} {
152 foreach line [split $contents "\n"] {
157 set tag [lindex $line 0]
158 if {$tag == "parent"} {
159 set p [lindex $line 1]
160 if {![info exists nchildren($p)]} {
165 lappend parents($id) $p
167 # sometimes we get a commit that lists a parent twice...
168 if {$listed && [lsearch -exact $children($p) $id] < 0} {
169 lappend children($p) $id
173 } elseif {$tag == "author"} {
174 set x [expr {[llength $line] - 2}]
175 set audate [lindex $line $x]
176 set auname [lrange $line 1 [expr {$x - 1}]]
177 } elseif {$tag == "committer"} {
178 set x [expr {[llength $line] - 2}]
179 set comdate [lindex $line $x]
180 set comname [lrange $line 1 [expr {$x - 1}]]
184 if {$comment == {}} {
185 set headline [string trim $line]
190 # git-rev-list indents the comment by 4 spaces;
191 # if we got this via git-cat-file, add the indentation
198 set audate [clock format $audate -format "%Y-%m-%d %H:%M:%S"]
200 if {$comdate != {}} {
201 set cdate($id) $comdate
202 set comdate [clock format $comdate -format "%Y-%m-%d %H:%M:%S"]
204 set commitinfo($id) [list $headline $auname $audate \
205 $comname $comdate $comment]
209 global tagids idtags headids idheads
210 set tags [glob -nocomplain -types f .git/refs/tags/*]
215 if {[regexp {^[0-9a-f]{40}} $line id]} {
216 set direct [file tail $f]
217 set tagids($direct) $id
218 lappend idtags($id) $direct
219 set contents [split [exec git-cat-file tag $id] "\n"]
223 foreach l $contents {
225 switch -- [lindex $l 0] {
226 "object" {set obj [lindex $l 1]}
227 "type" {set type [lindex $l 1]}
228 "tag" {set tag [string range $l 4 end]}
231 if {$obj != {} && $type == "commit" && $tag != {}} {
232 set tagids($tag) $obj
233 lappend idtags($obj) $tag
239 set heads [glob -nocomplain -types f .git/refs/heads/*]
243 set line [read $fd 40]
244 if {[regexp {^[0-9a-f]{40}} $line id]} {
245 set head [file tail $f]
246 set headids($head) $line
247 lappend idheads($line) $head
254 proc error_popup msg {
258 message $w.m -text $msg -justify center -aspect 400
259 pack $w.m -side top -fill x -padx 20 -pady 20
260 button $w.ok -text OK -command "destroy $w"
261 pack $w.ok -side bottom -fill x
262 bind $w <Visibility> "grab $w; focus $w"
267 global canv canv2 canv3 linespc charspc ctext cflist textfont
268 global findtype findloc findstring fstring geometry
269 global entries sha1entry sha1string sha1but
270 global maincursor textcursor
274 .bar add cascade -label "File" -menu .bar.file
276 .bar.file add command -label "Quit" -command doquit
278 .bar add cascade -label "Help" -menu .bar.help
279 .bar.help add command -label "About gitk" -command about
280 . configure -menu .bar
282 if {![info exists geometry(canv1)]} {
283 set geometry(canv1) [expr 45 * $charspc]
284 set geometry(canv2) [expr 30 * $charspc]
285 set geometry(canv3) [expr 15 * $charspc]
286 set geometry(canvh) [expr 25 * $linespc + 4]
287 set geometry(ctextw) 80
288 set geometry(ctexth) 30
289 set geometry(cflistw) 30
291 panedwindow .ctop -orient vertical
292 if {[info exists geometry(width)]} {
293 .ctop conf -width $geometry(width) -height $geometry(height)
294 set texth [expr {$geometry(height) - $geometry(canvh) - 56}]
295 set geometry(ctexth) [expr {($texth - 8) /
296 [font metrics $textfont -linespace]}]
300 pack .ctop.top.bar -side bottom -fill x
301 set cscroll .ctop.top.csb
302 scrollbar $cscroll -command {allcanvs yview} -highlightthickness 0
303 pack $cscroll -side right -fill y
304 panedwindow .ctop.top.clist -orient horizontal -sashpad 0 -handlesize 4
305 pack .ctop.top.clist -side top -fill both -expand 1
307 set canv .ctop.top.clist.canv
308 canvas $canv -height $geometry(canvh) -width $geometry(canv1) \
310 -yscrollincr $linespc -yscrollcommand "$cscroll set"
311 .ctop.top.clist add $canv
312 set canv2 .ctop.top.clist.canv2
313 canvas $canv2 -height $geometry(canvh) -width $geometry(canv2) \
314 -bg white -bd 0 -yscrollincr $linespc
315 .ctop.top.clist add $canv2
316 set canv3 .ctop.top.clist.canv3
317 canvas $canv3 -height $geometry(canvh) -width $geometry(canv3) \
318 -bg white -bd 0 -yscrollincr $linespc
319 .ctop.top.clist add $canv3
320 bind .ctop.top.clist <Configure> {resizeclistpanes %W %w}
322 set sha1entry .ctop.top.bar.sha1
323 set entries $sha1entry
324 set sha1but .ctop.top.bar.sha1label
325 button $sha1but -text "SHA1 ID: " -state disabled -relief flat \
326 -command gotocommit -width 8
327 $sha1but conf -disabledforeground [$sha1but cget -foreground]
328 pack .ctop.top.bar.sha1label -side left
329 entry $sha1entry -width 40 -font $textfont -textvariable sha1string
330 trace add variable sha1string write sha1change
331 pack $sha1entry -side left -pady 2
332 button .ctop.top.bar.findbut -text "Find" -command dofind
333 pack .ctop.top.bar.findbut -side left
335 set fstring .ctop.top.bar.findstring
336 lappend entries $fstring
337 entry $fstring -width 30 -font $textfont -textvariable findstring
338 pack $fstring -side left -expand 1 -fill x
340 tk_optionMenu .ctop.top.bar.findtype findtype Exact IgnCase Regexp
341 set findloc "All fields"
342 tk_optionMenu .ctop.top.bar.findloc findloc "All fields" Headline \
343 Comments Author Committer
344 pack .ctop.top.bar.findloc -side right
345 pack .ctop.top.bar.findtype -side right
347 panedwindow .ctop.cdet -orient horizontal
349 frame .ctop.cdet.left
350 set ctext .ctop.cdet.left.ctext
351 text $ctext -bg white -state disabled -font $textfont \
352 -width $geometry(ctextw) -height $geometry(ctexth) \
353 -yscrollcommand ".ctop.cdet.left.sb set"
354 scrollbar .ctop.cdet.left.sb -command "$ctext yview"
355 pack .ctop.cdet.left.sb -side right -fill y
356 pack $ctext -side left -fill both -expand 1
357 .ctop.cdet add .ctop.cdet.left
359 $ctext tag conf filesep -font [concat $textfont bold]
360 $ctext tag conf hunksep -back blue -fore white
361 $ctext tag conf d0 -back "#ff8080"
362 $ctext tag conf d1 -back green
363 $ctext tag conf found -back yellow
365 frame .ctop.cdet.right
366 set cflist .ctop.cdet.right.cfiles
367 listbox $cflist -bg white -selectmode extended -width $geometry(cflistw) \
368 -yscrollcommand ".ctop.cdet.right.sb set"
369 scrollbar .ctop.cdet.right.sb -command "$cflist yview"
370 pack .ctop.cdet.right.sb -side right -fill y
371 pack $cflist -side left -fill both -expand 1
372 .ctop.cdet add .ctop.cdet.right
373 bind .ctop.cdet <Configure> {resizecdetpanes %W %w}
375 pack .ctop -side top -fill both -expand 1
377 bindall <1> {selcanvline %W %x %y}
378 #bindall <B1-Motion> {selcanvline %W %x %y}
379 bindall <ButtonRelease-4> "allcanvs yview scroll -5 units"
380 bindall <ButtonRelease-5> "allcanvs yview scroll 5 units"
381 bindall <2> "allcanvs scan mark 0 %y"
382 bindall <B2-Motion> "allcanvs scan dragto 0 %y"
383 bind . <Key-Up> "selnextline -1"
384 bind . <Key-Down> "selnextline 1"
385 bind . <Key-Prior> "allcanvs yview scroll -1 pages"
386 bind . <Key-Next> "allcanvs yview scroll 1 pages"
387 bindkey <Key-Delete> "$ctext yview scroll -1 pages"
388 bindkey <Key-BackSpace> "$ctext yview scroll -1 pages"
389 bindkey <Key-space> "$ctext yview scroll 1 pages"
390 bindkey p "selnextline -1"
391 bindkey n "selnextline 1"
392 bindkey b "$ctext yview scroll -1 pages"
393 bindkey d "$ctext yview scroll 18 units"
394 bindkey u "$ctext yview scroll -18 units"
398 bind . <Control-q> doquit
399 bind . <Control-f> dofind
400 bind . <Control-g> findnext
401 bind . <Control-r> findprev
402 bind . <Control-equal> {incrfont 1}
403 bind . <Control-KP_Add> {incrfont 1}
404 bind . <Control-minus> {incrfont -1}
405 bind . <Control-KP_Subtract> {incrfont -1}
406 bind $cflist <<ListboxSelect>> listboxsel
407 bind . <Destroy> {savestuff %W}
408 bind . <Button-1> "click %W"
409 bind $fstring <Key-Return> dofind
410 bind $sha1entry <Key-Return> gotocommit
411 bind $sha1entry <<PasteSelection>> clearsha1
413 set maincursor [. cget -cursor]
414 set textcursor [$ctext cget -cursor]
416 set rowctxmenu .rowctxmenu
417 menu $rowctxmenu -tearoff 0
418 $rowctxmenu add command -label "Diff this -> selected" \
419 -command {diffvssel 0}
420 $rowctxmenu add command -label "Diff selected -> this" \
421 -command {diffvssel 1}
424 # when we make a key binding for the toplevel, make sure
425 # it doesn't get triggered when that key is pressed in the
426 # find string entry widget.
427 proc bindkey {ev script} {
430 set escript [bind Entry $ev]
431 if {$escript == {}} {
432 set escript [bind Entry <Key>]
435 bind $e $ev "$escript; break"
439 # set the focus back to the toplevel for any click outside
450 global canv canv2 canv3 ctext cflist mainfont textfont
452 if {$stuffsaved} return
453 if {![winfo viewable .]} return
455 set f [open "~/.gitk-new" w]
456 puts $f "set mainfont {$mainfont}"
457 puts $f "set textfont {$textfont}"
458 puts $f "set geometry(width) [winfo width .ctop]"
459 puts $f "set geometry(height) [winfo height .ctop]"
460 puts $f "set geometry(canv1) [expr [winfo width $canv]-2]"
461 puts $f "set geometry(canv2) [expr [winfo width $canv2]-2]"
462 puts $f "set geometry(canv3) [expr [winfo width $canv3]-2]"
463 puts $f "set geometry(canvh) [expr [winfo height $canv]-2]"
464 set wid [expr {([winfo width $ctext] - 8) \
465 / [font measure $textfont "0"]}]
466 puts $f "set geometry(ctextw) $wid"
467 set wid [expr {([winfo width $cflist] - 11) \
468 / [font measure [$cflist cget -font] "0"]}]
469 puts $f "set geometry(cflistw) $wid"
471 file rename -force "~/.gitk-new" "~/.gitk"
476 proc resizeclistpanes {win w} {
478 if [info exists oldwidth($win)] {
479 set s0 [$win sash coord 0]
480 set s1 [$win sash coord 1]
482 set sash0 [expr {int($w/2 - 2)}]
483 set sash1 [expr {int($w*5/6 - 2)}]
485 set factor [expr {1.0 * $w / $oldwidth($win)}]
486 set sash0 [expr {int($factor * [lindex $s0 0])}]
487 set sash1 [expr {int($factor * [lindex $s1 0])}]
491 if {$sash1 < $sash0 + 20} {
492 set sash1 [expr $sash0 + 20]
494 if {$sash1 > $w - 10} {
495 set sash1 [expr $w - 10]
496 if {$sash0 > $sash1 - 20} {
497 set sash0 [expr $sash1 - 20]
501 $win sash place 0 $sash0 [lindex $s0 1]
502 $win sash place 1 $sash1 [lindex $s1 1]
504 set oldwidth($win) $w
507 proc resizecdetpanes {win w} {
509 if [info exists oldwidth($win)] {
510 set s0 [$win sash coord 0]
512 set sash0 [expr {int($w*3/4 - 2)}]
514 set factor [expr {1.0 * $w / $oldwidth($win)}]
515 set sash0 [expr {int($factor * [lindex $s0 0])}]
519 if {$sash0 > $w - 15} {
520 set sash0 [expr $w - 15]
523 $win sash place 0 $sash0 [lindex $s0 1]
525 set oldwidth($win) $w
529 global canv canv2 canv3
535 proc bindall {event action} {
536 global canv canv2 canv3
537 bind $canv $event $action
538 bind $canv2 $event $action
539 bind $canv3 $event $action
544 if {[winfo exists $w]} {
549 wm title $w "About gitk"
553 Copyright © 2005 Paul Mackerras
555 Use and redistribute under the terms of the GNU General Public License} \
556 -justify center -aspect 400
557 pack $w.m -side top -fill x -padx 20 -pady 20
558 button $w.ok -text Close -command "destroy $w"
559 pack $w.ok -side bottom
562 proc assigncolor {id} {
563 global commitinfo colormap commcolors colors nextcolor
564 global parents nparents children nchildren
565 global cornercrossings crossings
567 if [info exists colormap($id)] return
568 set ncolors [llength $colors]
569 if {$nparents($id) <= 1 && $nchildren($id) == 1} {
570 set child [lindex $children($id) 0]
571 if {[info exists colormap($child)]
572 && $nparents($child) == 1} {
573 set colormap($id) $colormap($child)
578 if {[info exists cornercrossings($id)]} {
579 foreach x $cornercrossings($id) {
580 if {[info exists colormap($x)]
581 && [lsearch -exact $badcolors $colormap($x)] < 0} {
582 lappend badcolors $colormap($x)
585 if {[llength $badcolors] >= $ncolors} {
589 set origbad $badcolors
590 if {[llength $badcolors] < $ncolors - 1} {
591 if {[info exists crossings($id)]} {
592 foreach x $crossings($id) {
593 if {[info exists colormap($x)]
594 && [lsearch -exact $badcolors $colormap($x)] < 0} {
595 lappend badcolors $colormap($x)
598 if {[llength $badcolors] >= $ncolors} {
599 set badcolors $origbad
602 set origbad $badcolors
604 if {[llength $badcolors] < $ncolors - 1} {
605 foreach child $children($id) {
606 if {[info exists colormap($child)]
607 && [lsearch -exact $badcolors $colormap($child)] < 0} {
608 lappend badcolors $colormap($child)
610 if {[info exists parents($child)]} {
611 foreach p $parents($child) {
612 if {[info exists colormap($p)]
613 && [lsearch -exact $badcolors $colormap($p)] < 0} {
614 lappend badcolors $colormap($p)
619 if {[llength $badcolors] >= $ncolors} {
620 set badcolors $origbad
623 for {set i 0} {$i <= $ncolors} {incr i} {
624 set c [lindex $colors $nextcolor]
625 if {[incr nextcolor] >= $ncolors} {
628 if {[lsearch -exact $badcolors $c]} break
634 global canvy canvy0 lineno numcommits lthickness nextcolor linespc
635 global mainline sidelines
636 global nchildren ncleft
643 set lthickness [expr {int($linespc / 9) + 1}]
644 catch {unset mainline}
645 catch {unset sidelines}
646 foreach id [array names nchildren] {
647 set ncleft($id) $nchildren($id)
651 proc bindline {t id} {
654 $canv bind $t <Enter> "lineenter %x %y $id"
655 $canv bind $t <Motion> "linemotion %x %y $id"
656 $canv bind $t <Leave> "lineleave $id"
657 $canv bind $t <Button-1> "lineclick %x %y $id"
660 proc drawcommitline {level} {
661 global parents children nparents nchildren todo
662 global canv canv2 canv3 mainfont namefont canvx0 canvy linespc
663 global lineid linehtag linentag linedtag commitinfo
664 global colormap numcommits currentparents dupparents
665 global oldlevel oldnlines oldtodo
666 global idtags idline idheads
667 global lineno lthickness mainline sidelines
668 global commitlisted rowtextx
672 set id [lindex $todo $level]
673 set lineid($lineno) $id
674 set idline($id) $lineno
675 set ofill [expr {[info exists commitlisted($id)]? "blue": "white"}]
676 if {![info exists commitinfo($id)]} {
678 if {![info exists commitinfo($id)]} {
679 set commitinfo($id) {"No commit information available"}
684 set currentparents {}
686 if {[info exists commitlisted($id)] && [info exists parents($id)]} {
687 foreach p $parents($id) {
688 if {[lsearch -exact $currentparents $p] < 0} {
689 lappend currentparents $p
691 # remember that this parent was listed twice
692 lappend dupparents $p
696 set x [expr $canvx0 + $level * $linespc]
698 set canvy [expr $canvy + $linespc]
699 allcanvs conf -scrollregion \
700 [list 0 0 0 [expr $y1 + 0.5 * $linespc + 2]]
701 if {[info exists mainline($id)]} {
702 lappend mainline($id) $x $y1
703 set t [$canv create line $mainline($id) \
704 -width $lthickness -fill $colormap($id)]
708 if {[info exists sidelines($id)]} {
709 foreach ls $sidelines($id) {
710 set coords [lindex $ls 0]
711 set thick [lindex $ls 1]
712 set t [$canv create line $coords -fill $colormap($id) \
713 -width [expr {$thick * $lthickness}]]
718 set orad [expr {$linespc / 3}]
719 set t [$canv create oval [expr $x - $orad] [expr $y1 - $orad] \
720 [expr $x + $orad - 1] [expr $y1 + $orad - 1] \
721 -fill $ofill -outline black -width 1]
723 $canv bind $t <1> {selcanvline {} %x %y}
724 set xt [expr $canvx0 + [llength $todo] * $linespc]
725 if {[llength $currentparents] > 2} {
726 set xt [expr {$xt + ([llength $currentparents] - 2) * $linespc}]
728 set rowtextx($lineno) $xt
731 if {[info exists idtags($id)]} {
732 set marks $idtags($id)
733 set ntags [llength $marks]
735 if {[info exists idheads($id)]} {
736 set marks [concat $marks $idheads($id)]
739 set delta [expr {int(0.5 * ($linespc - $lthickness))}]
740 set yt [expr $y1 - 0.5 * $linespc]
741 set yb [expr $yt + $linespc - 1]
745 set wid [font measure $mainfont $tag]
748 set xt [expr {$xt + $delta + $wid + $lthickness + $linespc}]
750 set t [$canv create line $x $y1 [lindex $xvals end] $y1 \
751 -width $lthickness -fill black]
753 foreach tag $marks x $xvals wid $wvals {
754 set xl [expr $x + $delta]
755 set xr [expr $x + $delta + $wid + $lthickness]
756 if {[incr ntags -1] >= 0} {
758 $canv create polygon $x [expr $yt + $delta] $xl $yt\
759 $xr $yt $xr $yb $xl $yb $x [expr $yb - $delta] \
760 -width 1 -outline black -fill yellow
763 set xl [expr $xl - $delta/2]
764 $canv create polygon $x $yt $xr $yt $xr $yb $x $yb \
765 -width 1 -outline black -fill green
767 $canv create text $xl $y1 -anchor w -text $tag \
771 set headline [lindex $commitinfo($id) 0]
772 set name [lindex $commitinfo($id) 1]
773 set date [lindex $commitinfo($id) 2]
774 set linehtag($lineno) [$canv create text $xt $y1 -anchor w \
775 -text $headline -font $mainfont ]
776 $canv bind $linehtag($lineno) <Button-3> "rowmenu %X %Y $id"
777 set linentag($lineno) [$canv2 create text 3 $y1 -anchor w \
778 -text $name -font $namefont]
779 set linedtag($lineno) [$canv3 create text 3 $y1 -anchor w \
780 -text $date -font $mainfont]
783 proc updatetodo {level noshortcut} {
784 global currentparents ncleft todo
785 global mainline oldlevel oldtodo oldnlines
786 global canvx0 canvy linespc mainline
791 set oldnlines [llength $todo]
792 if {!$noshortcut && [llength $currentparents] == 1} {
793 set p [lindex $currentparents 0]
794 if {$ncleft($p) == 1 && [lsearch -exact $todo $p] < 0} {
796 set x [expr $canvx0 + $level * $linespc]
797 set y [expr $canvy - $linespc]
798 set mainline($p) [list $x $y]
799 set todo [lreplace $todo $level $level $p]
804 set todo [lreplace $todo $level $level]
806 foreach p $currentparents {
808 set k [lsearch -exact $todo $p]
810 set todo [linsert $todo $i $p]
817 proc notecrossings {id lo hi corner} {
818 global oldtodo crossings cornercrossings
820 for {set i $lo} {[incr i] < $hi} {} {
821 set p [lindex $oldtodo $i]
822 if {$p == {}} continue
824 if {![info exists cornercrossings($id)]
825 || [lsearch -exact $cornercrossings($id) $p] < 0} {
826 lappend cornercrossings($id) $p
828 if {![info exists cornercrossings($p)]
829 || [lsearch -exact $cornercrossings($p) $id] < 0} {
830 lappend cornercrossings($p) $id
833 if {![info exists crossings($id)]
834 || [lsearch -exact $crossings($id) $p] < 0} {
835 lappend crossings($id) $p
837 if {![info exists crossings($p)]
838 || [lsearch -exact $crossings($p) $id] < 0} {
839 lappend crossings($p) $id
846 global canv mainline sidelines canvx0 canvy linespc
847 global oldlevel oldtodo todo currentparents dupparents
848 global lthickness linespc canvy colormap
850 set y1 [expr $canvy - $linespc]
853 foreach id $oldtodo {
855 if {$id == {}} continue
856 set xi [expr {$canvx0 + $i * $linespc}]
857 if {$i == $oldlevel} {
858 foreach p $currentparents {
859 set j [lsearch -exact $todo $p]
860 set coords [list $xi $y1]
861 set xj [expr {$canvx0 + $j * $linespc}]
863 lappend coords [expr $xj + $linespc] $y1
864 notecrossings $p $j $i [expr {$j + 1}]
865 } elseif {$j > $i + 1} {
866 lappend coords [expr $xj - $linespc] $y1
867 notecrossings $p $i $j [expr {$j - 1}]
869 if {[lsearch -exact $dupparents $p] >= 0} {
870 # draw a double-width line to indicate the doubled parent
871 lappend coords $xj $y2
872 lappend sidelines($p) [list $coords 2]
873 if {![info exists mainline($p)]} {
874 set mainline($p) [list $xj $y2]
877 # normal case, no parent duplicated
878 if {![info exists mainline($p)]} {
880 lappend coords $xj $y2
882 set mainline($p) $coords
884 lappend coords $xj $y2
885 lappend sidelines($p) [list $coords 1]
889 } elseif {[lindex $todo $i] != $id} {
890 set j [lsearch -exact $todo $id]
891 set xj [expr {$canvx0 + $j * $linespc}]
892 lappend mainline($id) $xi $y1 $xj $y2
897 proc decidenext {{noread 0}} {
898 global parents children nchildren ncleft todo
899 global canv canv2 canv3 mainfont namefont canvx0 canvy linespc
900 global datemode cdate
902 global currentparents oldlevel oldnlines oldtodo
903 global lineno lthickness
905 # remove the null entry if present
906 set nullentry [lsearch -exact $todo {}]
907 if {$nullentry >= 0} {
908 set todo [lreplace $todo $nullentry $nullentry]
911 # choose which one to do next time around
912 set todol [llength $todo]
915 for {set k $todol} {[incr k -1] >= 0} {} {
916 set p [lindex $todo $k]
917 if {$ncleft($p) == 0} {
919 if {![info exists commitinfo($p)]} {
925 if {$latest == {} || $cdate($p) > $latest} {
927 set latest $cdate($p)
937 puts "ERROR: none of the pending commits can be done yet:"
939 puts " $p ($ncleft($p))"
945 # If we are reducing, put in a null entry
946 if {$todol < $oldnlines} {
947 if {$nullentry >= 0} {
950 && [lindex $oldtodo $i] == [lindex $todo $i]} {
960 set todo [linsert $todo $i {}]
969 proc drawcommit {id} {
970 global phase todo nchildren datemode nextupdate
973 if {$phase != "incrdraw"} {
979 updatetodo 0 $datemode
981 if {$nchildren($id) == 0} {
983 lappend startcommits $id
985 set level [decidenext 1]
986 if {$level == {} || $id != [lindex $todo $level]} {
991 drawcommitline $level
992 if {[updatetodo $level $datemode]} {
993 set level [decidenext 1]
994 if {$level == {}} break
996 set id [lindex $todo $level]
997 if {![info exists commitlisted($id)]} {
1000 if {[clock clicks -milliseconds] >= $nextupdate} {
1008 proc finishcommits {} {
1011 global canv mainfont ctext maincursor textcursor
1013 if {$phase != "incrdraw"} {
1015 $canv create text 3 3 -anchor nw -text "No commits selected" \
1016 -font $mainfont -tags textitems
1020 set level [decidenext]
1021 drawrest $level [llength $startcommits]
1023 . config -cursor $maincursor
1024 $ctext config -cursor $textcursor
1028 global nextupdate startmsecs startcommits todo
1030 if {$startcommits == {}} return
1031 set startmsecs [clock clicks -milliseconds]
1032 set nextupdate [expr $startmsecs + 100]
1034 set todo [lindex $startcommits 0]
1038 proc drawrest {level startix} {
1039 global phase stopped redisplaying selectedline
1040 global datemode currentparents todo
1042 global nextupdate startmsecs startcommits idline
1046 set startid [lindex $startcommits $startix]
1048 if {$startid != {}} {
1049 set startline $idline($startid)
1053 drawcommitline $level
1054 set hard [updatetodo $level $datemode]
1055 if {$numcommits == $startline} {
1056 lappend todo $startid
1059 set startid [lindex $startcommits $startix]
1061 if {$startid != {}} {
1062 set startline $idline($startid)
1066 set level [decidenext]
1067 if {$level < 0} break
1070 if {[clock clicks -milliseconds] >= $nextupdate} {
1077 set drawmsecs [expr [clock clicks -milliseconds] - $startmsecs]
1078 #puts "overall $drawmsecs ms for $numcommits commits"
1079 if {$redisplaying} {
1080 if {$stopped == 0 && [info exists selectedline]} {
1081 selectline $selectedline
1083 if {$stopped == 1} {
1085 after idle drawgraph
1092 proc findmatches {f} {
1093 global findtype foundstring foundstrlen
1094 if {$findtype == "Regexp"} {
1095 set matches [regexp -indices -all -inline $foundstring $f]
1097 if {$findtype == "IgnCase"} {
1098 set str [string tolower $f]
1104 while {[set j [string first $foundstring $str $i]] >= 0} {
1105 lappend matches [list $j [expr $j+$foundstrlen-1]]
1106 set i [expr $j + $foundstrlen]
1113 global findtype findloc findstring markedmatches commitinfo
1114 global numcommits lineid linehtag linentag linedtag
1115 global mainfont namefont canv canv2 canv3 selectedline
1116 global matchinglines foundstring foundstrlen
1119 set matchinglines {}
1120 set fldtypes {Headline Author Date Committer CDate Comment}
1121 if {$findtype == "IgnCase"} {
1122 set foundstring [string tolower $findstring]
1124 set foundstring $findstring
1126 set foundstrlen [string length $findstring]
1127 if {$foundstrlen == 0} return
1128 if {![info exists selectedline]} {
1131 set oldsel $selectedline
1134 for {set l 0} {$l < $numcommits} {incr l} {
1136 set info $commitinfo($id)
1138 foreach f $info ty $fldtypes {
1139 if {$findloc != "All fields" && $findloc != $ty} {
1142 set matches [findmatches $f]
1143 if {$matches == {}} continue
1145 if {$ty == "Headline"} {
1146 markmatches $canv $l $f $linehtag($l) $matches $mainfont
1147 } elseif {$ty == "Author"} {
1148 markmatches $canv2 $l $f $linentag($l) $matches $namefont
1149 } elseif {$ty == "Date"} {
1150 markmatches $canv3 $l $f $linedtag($l) $matches $mainfont
1154 lappend matchinglines $l
1155 if {!$didsel && $l > $oldsel} {
1161 if {$matchinglines == {}} {
1163 } elseif {!$didsel} {
1164 findselectline [lindex $matchinglines 0]
1168 proc findselectline {l} {
1169 global findloc commentend ctext
1171 if {$findloc == "All fields" || $findloc == "Comments"} {
1172 # highlight the matches in the comments
1173 set f [$ctext get 1.0 $commentend]
1174 set matches [findmatches $f]
1175 foreach match $matches {
1176 set start [lindex $match 0]
1177 set end [expr [lindex $match 1] + 1]
1178 $ctext tag add found "1.0 + $start c" "1.0 + $end c"
1184 global matchinglines selectedline
1185 if {![info exists matchinglines]} {
1189 if {![info exists selectedline]} return
1190 foreach l $matchinglines {
1191 if {$l > $selectedline} {
1200 global matchinglines selectedline
1201 if {![info exists matchinglines]} {
1205 if {![info exists selectedline]} return
1207 foreach l $matchinglines {
1208 if {$l >= $selectedline} break
1212 findselectline $prev
1218 proc markmatches {canv l str tag matches font} {
1219 set bbox [$canv bbox $tag]
1220 set x0 [lindex $bbox 0]
1221 set y0 [lindex $bbox 1]
1222 set y1 [lindex $bbox 3]
1223 foreach match $matches {
1224 set start [lindex $match 0]
1225 set end [lindex $match 1]
1226 if {$start > $end} continue
1227 set xoff [font measure $font [string range $str 0 [expr $start-1]]]
1228 set xlen [font measure $font [string range $str 0 [expr $end]]]
1229 set t [$canv create rect [expr $x0+$xoff] $y0 [expr $x0+$xlen+2] $y1 \
1230 -outline {} -tags matches -fill yellow]
1235 proc unmarkmatches {} {
1236 global matchinglines
1237 allcanvs delete matches
1238 catch {unset matchinglines}
1241 proc selcanvline {w x y} {
1242 global canv canvy0 ctext linespc selectedline
1243 global lineid linehtag linentag linedtag rowtextx
1244 set ymax [lindex [$canv cget -scrollregion] 3]
1245 if {$ymax == {}} return
1246 set yfrac [lindex [$canv yview] 0]
1247 set y [expr {$y + $yfrac * $ymax}]
1248 set l [expr {int(($y - $canvy0) / $linespc + 0.5)}]
1253 if {![info exists rowtextx($l)] || $x < $rowtextx($l)} return
1259 proc selectline {l} {
1260 global canv canv2 canv3 ctext commitinfo selectedline
1261 global lineid linehtag linentag linedtag
1262 global canvy0 linespc parents nparents
1263 global cflist currentid sha1entry diffids
1264 global commentend seenfile idtags
1266 if {![info exists lineid($l)] || ![info exists linehtag($l)]} return
1268 set t [eval $canv create rect [$canv bbox $linehtag($l)] -outline {{}} \
1269 -tags secsel -fill [$canv cget -selectbackground]]
1271 $canv2 delete secsel
1272 set t [eval $canv2 create rect [$canv2 bbox $linentag($l)] -outline {{}} \
1273 -tags secsel -fill [$canv2 cget -selectbackground]]
1275 $canv3 delete secsel
1276 set t [eval $canv3 create rect [$canv3 bbox $linedtag($l)] -outline {{}} \
1277 -tags secsel -fill [$canv3 cget -selectbackground]]
1279 set y [expr {$canvy0 + $l * $linespc}]
1280 set ymax [lindex [$canv cget -scrollregion] 3]
1281 set ytop [expr {$y - $linespc - 1}]
1282 set ybot [expr {$y + $linespc + 1}]
1283 set wnow [$canv yview]
1284 set wtop [expr [lindex $wnow 0] * $ymax]
1285 set wbot [expr [lindex $wnow 1] * $ymax]
1286 set wh [expr {$wbot - $wtop}]
1288 if {$ytop < $wtop} {
1289 if {$ybot < $wtop} {
1290 set newtop [expr {$y - $wh / 2.0}]
1293 if {$newtop > $wtop - $linespc} {
1294 set newtop [expr {$wtop - $linespc}]
1297 } elseif {$ybot > $wbot} {
1298 if {$ytop > $wbot} {
1299 set newtop [expr {$y - $wh / 2.0}]
1301 set newtop [expr {$ybot - $wh}]
1302 if {$newtop < $wtop + $linespc} {
1303 set newtop [expr {$wtop + $linespc}]
1307 if {$newtop != $wtop} {
1311 allcanvs yview moveto [expr $newtop * 1.0 / $ymax]
1317 set diffids [concat $id $parents($id)]
1318 $sha1entry delete 0 end
1319 $sha1entry insert 0 $id
1320 $sha1entry selection from 0
1321 $sha1entry selection to end
1323 $ctext conf -state normal
1324 $ctext delete 0.0 end
1325 $ctext mark set fmark.0 0.0
1326 $ctext mark gravity fmark.0 left
1327 set info $commitinfo($id)
1328 $ctext insert end "Author: [lindex $info 1] [lindex $info 2]\n"
1329 $ctext insert end "Committer: [lindex $info 3] [lindex $info 4]\n"
1330 if {[info exists idtags($id)]} {
1331 $ctext insert end "Tags:"
1332 foreach tag $idtags($id) {
1333 $ctext insert end " $tag"
1335 $ctext insert end "\n"
1337 $ctext insert end "\n"
1338 $ctext insert end [lindex $info 5]
1339 $ctext insert end "\n"
1340 $ctext tag delete Comments
1341 $ctext tag remove found 1.0 end
1342 $ctext conf -state disabled
1343 set commentend [$ctext index "end - 1c"]
1345 $cflist delete 0 end
1346 $cflist insert end "Comments"
1347 if {$nparents($id) == 1} {
1350 catch {unset seenfile}
1354 global treediffs diffids treepending
1356 if {![info exists treediffs($diffids)]} {
1357 if {![info exists treepending]} {
1358 gettreediffs $diffids
1361 addtocflist $diffids
1365 proc selnextline {dir} {
1367 if {![info exists selectedline]} return
1368 set l [expr $selectedline + $dir]
1373 proc addtocflist {ids} {
1374 global diffids treediffs cflist
1375 if {$ids != $diffids} {
1376 gettreediffs $diffids
1379 foreach f $treediffs($ids) {
1380 $cflist insert end $f
1385 proc gettreediffs {ids} {
1386 global treediffs parents treepending
1387 set treepending $ids
1388 set treediffs($ids) {}
1389 set id [lindex $ids 0]
1390 set p [lindex $ids 1]
1391 if [catch {set gdtf [open "|git-diff-tree -r $p $id" r]}] return
1392 fconfigure $gdtf -blocking 0
1393 fileevent $gdtf readable "gettreediffline $gdtf {$ids}"
1396 proc gettreediffline {gdtf ids} {
1397 global treediffs treepending
1398 set n [gets $gdtf line]
1400 if {![eof $gdtf]} return
1406 set file [lindex $line 5]
1407 lappend treediffs($ids) $file
1410 proc getblobdiffs {ids} {
1411 global diffopts blobdifffd env curdifftag curtagstart
1412 global diffindex difffilestart nextupdate
1414 set id [lindex $ids 0]
1415 set p [lindex $ids 1]
1416 set env(GIT_DIFF_OPTS) $diffopts
1417 if [catch {set bdf [open "|git-diff-tree -r -p $p $id" r]} err] {
1418 puts "error getting diffs: $err"
1421 fconfigure $bdf -blocking 0
1422 set blobdifffd($ids) $bdf
1423 set curdifftag Comments
1426 catch {unset difffilestart}
1427 fileevent $bdf readable "getblobdiffline $bdf {$ids}"
1428 set nextupdate [expr {[clock clicks -milliseconds] + 100}]
1431 proc getblobdiffline {bdf ids} {
1432 global diffids blobdifffd ctext curdifftag curtagstart seenfile
1433 global diffnexthead diffnextnote diffindex difffilestart
1436 set n [gets $bdf line]
1440 if {$ids == $diffids && $bdf == $blobdifffd($ids)} {
1441 $ctext tag add $curdifftag $curtagstart end
1442 set seenfile($curdifftag) 1
1447 if {$ids != $diffids || $bdf != $blobdifffd($ids)} {
1450 $ctext conf -state normal
1451 if {[regexp {^---[ \t]+([^/])*/(.*)} $line match s1 fname]} {
1452 # start of a new file
1453 $ctext insert end "\n"
1454 $ctext tag add $curdifftag $curtagstart end
1455 set seenfile($curdifftag) 1
1456 set curtagstart [$ctext index "end - 1c"]
1458 if {[info exists diffnexthead]} {
1459 set fname $diffnexthead
1460 set header "$diffnexthead ($diffnextnote)"
1463 set here [$ctext index "end - 1c"]
1464 set difffilestart($diffindex) $here
1466 # start mark names at fmark.1 for first file
1467 $ctext mark set fmark.$diffindex $here
1468 $ctext mark gravity fmark.$diffindex left
1469 set curdifftag "f:$fname"
1470 $ctext tag delete $curdifftag
1471 set l [expr {(78 - [string length $header]) / 2}]
1472 set pad [string range "----------------------------------------" 1 $l]
1473 $ctext insert end "$pad $header $pad\n" filesep
1474 } elseif {[string range $line 0 2] == "+++"} {
1475 # no need to do anything with this
1476 } elseif {[regexp {^Created: (.*) \((mode: *[0-7]*)\)} $line match fn m]} {
1477 set diffnexthead $fn
1478 set diffnextnote "created, mode $m"
1479 } elseif {[string range $line 0 8] == "Deleted: "} {
1480 set diffnexthead [string range $line 9 end]
1481 set diffnextnote "deleted"
1482 } elseif {[regexp {^diff --git a/(.*) b/} $line match fn]} {
1483 # save the filename in case the next thing is "new file mode ..."
1484 set diffnexthead $fn
1485 set diffnextnote "modified"
1486 } elseif {[regexp {^new file mode ([0-7]+)} $line match m]} {
1487 set diffnextnote "new file, mode $m"
1488 } elseif {[string range $line 0 11] == "deleted file"} {
1489 set diffnextnote "deleted"
1490 } elseif {[regexp {^@@ -([0-9]+),([0-9]+) \+([0-9]+),([0-9]+) @@(.*)} \
1491 $line match f1l f1c f2l f2c rest]} {
1492 $ctext insert end "\t" hunksep
1493 $ctext insert end " $f1l " d0 " $f2l " d1
1494 $ctext insert end " $rest \n" hunksep
1496 set x [string range $line 0 0]
1497 if {$x == "-" || $x == "+"} {
1498 set tag [expr {$x == "+"}]
1499 set line [string range $line 1 end]
1500 $ctext insert end "$line\n" d$tag
1501 } elseif {$x == " "} {
1502 set line [string range $line 1 end]
1503 $ctext insert end "$line\n"
1504 } elseif {$x == "\\"} {
1505 # e.g. "\ No newline at end of file"
1506 $ctext insert end "$line\n" filesep
1508 # Something else we don't recognize
1509 if {$curdifftag != "Comments"} {
1510 $ctext insert end "\n"
1511 $ctext tag add $curdifftag $curtagstart end
1512 set seenfile($curdifftag) 1
1513 set curtagstart [$ctext index "end - 1c"]
1514 set curdifftag Comments
1516 $ctext insert end "$line\n" filesep
1519 $ctext conf -state disabled
1520 if {[clock clicks -milliseconds] >= $nextupdate} {
1522 fileevent $bdf readable {}
1524 fileevent $bdf readable "getblobdiffline $bdf {$ids}"
1529 global difffilestart ctext
1530 set here [$ctext index @0,0]
1531 for {set i 0} {[info exists difffilestart($i)]} {incr i} {
1532 if {[$ctext compare $difffilestart($i) > $here]} {
1533 $ctext yview $difffilestart($i)
1539 proc listboxsel {} {
1540 global ctext cflist currentid treediffs seenfile
1541 if {![info exists currentid]} return
1542 set sel [lsort [$cflist curselection]]
1543 if {$sel eq {}} return
1544 set first [lindex $sel 0]
1545 catch {$ctext yview fmark.$first}
1549 global linespc charspc canvx0 canvy0 mainfont
1550 set linespc [font metrics $mainfont -linespace]
1551 set charspc [font measure $mainfont "m"]
1552 set canvy0 [expr 3 + 0.5 * $linespc]
1553 set canvx0 [expr 3 + 0.5 * $linespc]
1557 global selectedline stopped redisplaying phase
1558 if {$stopped > 1} return
1559 if {$phase == "getcommits"} return
1561 if {$phase == "drawgraph" || $phase == "incrdraw"} {
1568 proc incrfont {inc} {
1569 global mainfont namefont textfont selectedline ctext canv phase
1570 global stopped entries
1572 set mainfont [lreplace $mainfont 1 1 [expr {[lindex $mainfont 1] + $inc}]]
1573 set namefont [lreplace $namefont 1 1 [expr {[lindex $namefont 1] + $inc}]]
1574 set textfont [lreplace $textfont 1 1 [expr {[lindex $textfont 1] + $inc}]]
1576 $ctext conf -font $textfont
1577 $ctext tag conf filesep -font [concat $textfont bold]
1578 foreach e $entries {
1579 $e conf -font $mainfont
1581 if {$phase == "getcommits"} {
1582 $canv itemconf textitems -font $mainfont
1588 global sha1entry sha1string
1589 if {[string length $sha1string] == 40} {
1590 $sha1entry delete 0 end
1594 proc sha1change {n1 n2 op} {
1595 global sha1string currentid sha1but
1596 if {$sha1string == {}
1597 || ([info exists currentid] && $sha1string == $currentid)} {
1602 if {[$sha1but cget -state] == $state} return
1603 if {$state == "normal"} {
1604 $sha1but conf -state normal -relief raised -text "Goto: "
1606 $sha1but conf -state disabled -relief flat -text "SHA1 ID: "
1610 proc gotocommit {} {
1611 global sha1string currentid idline tagids
1612 if {$sha1string == {}
1613 || ([info exists currentid] && $sha1string == $currentid)} return
1614 if {[info exists tagids($sha1string)]} {
1615 set id $tagids($sha1string)
1617 set id [string tolower $sha1string]
1619 if {[info exists idline($id)]} {
1620 selectline $idline($id)
1623 if {[regexp {^[0-9a-fA-F]{40}$} $sha1string]} {
1628 error_popup "$type $sha1string is not known"
1631 proc lineenter {x y id} {
1632 global hoverx hovery hoverid hovertimer
1633 global commitinfo canv
1635 if {![info exists commitinfo($id)]} return
1639 if {[info exists hovertimer]} {
1640 after cancel $hovertimer
1642 set hovertimer [after 500 linehover]
1646 proc linemotion {x y id} {
1647 global hoverx hovery hoverid hovertimer
1649 if {[info exists hoverid] && $id == $hoverid} {
1652 if {[info exists hovertimer]} {
1653 after cancel $hovertimer
1655 set hovertimer [after 500 linehover]
1659 proc lineleave {id} {
1660 global hoverid hovertimer canv
1662 if {[info exists hoverid] && $id == $hoverid} {
1664 if {[info exists hovertimer]} {
1665 after cancel $hovertimer
1673 global hoverx hovery hoverid hovertimer
1674 global canv linespc lthickness
1675 global commitinfo mainfont
1677 set text [lindex $commitinfo($hoverid) 0]
1678 set ymax [lindex [$canv cget -scrollregion] 3]
1679 if {$ymax == {}} return
1680 set yfrac [lindex [$canv yview] 0]
1681 set x [expr {$hoverx + 2 * $linespc}]
1682 set y [expr {$hovery + $yfrac * $ymax - $linespc / 2}]
1683 set x0 [expr {$x - 2 * $lthickness}]
1684 set y0 [expr {$y - 2 * $lthickness}]
1685 set x1 [expr {$x + [font measure $mainfont $text] + 2 * $lthickness}]
1686 set y1 [expr {$y + $linespc + 2 * $lthickness}]
1687 set t [$canv create rectangle $x0 $y0 $x1 $y1 \
1688 -fill \#ffff80 -outline black -width 1 -tags hover]
1690 set t [$canv create text $x $y -anchor nw -text $text -tags hover]
1694 proc lineclick {x y id} {
1695 global ctext commitinfo children cflist canv
1699 # fill the details pane with info about this line
1700 $ctext conf -state normal
1701 $ctext delete 0.0 end
1702 $ctext insert end "Parent:\n "
1703 catch {destroy $ctext.$id}
1704 button $ctext.$id -text "Go:" -command "selbyid $id" \
1706 $ctext window create end -window $ctext.$id -align center
1707 set info $commitinfo($id)
1708 $ctext insert end "\t[lindex $info 0]\n"
1709 $ctext insert end "\tAuthor:\t[lindex $info 1]\n"
1710 $ctext insert end "\tDate:\t[lindex $info 2]\n"
1711 $ctext insert end "\tID:\t$id\n"
1712 if {[info exists children($id)]} {
1713 $ctext insert end "\nChildren:"
1714 foreach child $children($id) {
1715 $ctext insert end "\n "
1716 catch {destroy $ctext.$child}
1717 button $ctext.$child -text "Go:" -command "selbyid $child" \
1719 $ctext window create end -window $ctext.$child -align center
1720 set info $commitinfo($child)
1721 $ctext insert end "\t[lindex $info 0]"
1724 $ctext conf -state disabled
1726 $cflist delete 0 end
1731 if {[info exists idline($id)]} {
1732 selectline $idline($id)
1738 if {![info exists startmstime]} {
1739 set startmstime [clock clicks -milliseconds]
1741 return [format "%.3f" [expr {([clock click -milliseconds] - $startmstime) / 1000.0}]]
1744 proc rowmenu {x y id} {
1745 global rowctxmenu idline selectedline rowmenuid
1747 if {![info exists selectedline] || $idline($id) eq $selectedline} {
1752 $rowctxmenu entryconfigure 0 -state $state
1753 $rowctxmenu entryconfigure 1 -state $state
1755 tk_popup $rowctxmenu $x $y
1758 proc diffvssel {dirn} {
1759 global rowmenuid selectedline lineid
1761 global diffids commitinfo
1763 if {![info exists selectedline]} return
1765 set oldid $lineid($selectedline)
1766 set newid $rowmenuid
1768 set oldid $rowmenuid
1769 set newid $lineid($selectedline)
1771 $ctext conf -state normal
1772 $ctext delete 0.0 end
1773 $ctext mark set fmark.0 0.0
1774 $ctext mark gravity fmark.0 left
1775 $cflist delete 0 end
1776 $cflist insert end "Top"
1777 $ctext insert end "From $oldid\n "
1778 $ctext insert end [lindex $commitinfo($oldid) 0]
1779 $ctext insert end "\n\nTo $newid\n "
1780 $ctext insert end [lindex $commitinfo($newid) 0]
1781 $ctext insert end "\n"
1782 $ctext conf -state disabled
1783 $ctext tag delete Comments
1784 $ctext tag remove found 1.0 end
1785 set diffids [list $newid $oldid]
1798 set diffopts "-U 5 -p"
1800 set mainfont {Helvetica 9}
1801 set textfont {Courier 9}
1803 set colors {green red blue magenta darkgrey brown orange}
1805 catch {source ~/.gitk}
1807 set namefont $mainfont
1809 lappend namefont bold
1814 switch -regexp -- $arg {
1816 "^-b" { set boldnames 1 }
1817 "^-d" { set datemode 1 }
1819 lappend revtreeargs $arg
1830 getcommits $revtreeargs