[PATCH] gitk: Use git wrapper to run git-ls-remote.
[git/git.git] / gitk
CommitLineData
1db95b00
PM
1#!/bin/sh
2# Tcl ignores the next line -*- tcl -*- \
9e026d39 3exec wish "$0" -- "$@"
1db95b00
PM
4
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.
9
73b6a6cb
JH
10proc gitdir {} {
11 global env
12 if {[info exists env(GIT_DIR)]} {
13 return $env(GIT_DIR)
14 } else {
15 return ".git"
16 }
17}
18
b5c2f306
SV
19proc parse_args {rargs} {
20 global parsed_args
21
418c4c7b 22 if {[catch {
b5c2f306
SV
23 set parse_args [concat --default HEAD $rargs]
24 set parsed_args [split [eval exec git-rev-parse $parse_args] "\n"]
418c4c7b 25 }]} {
b5c2f306
SV
26 # if git-rev-parse failed for some reason...
27 if {$rargs == {}} {
28 set rargs HEAD
29 }
30 set parsed_args $rargs
31 }
32 return $parsed_args
33}
34
38ad0910 35proc start_rev_list {rlargs} {
466e4fdd 36 global startmsecs nextupdate ncmupdate
9f1afe05 37 global commfd leftover tclencoding datemode
9ccbdfbf 38
9ccbdfbf 39 set startmsecs [clock clicks -milliseconds]
2ed49d54 40 set nextupdate [expr {$startmsecs + 100}]
b664550c 41 set ncmupdate 1
8f7d0cec 42 initlayout
9f1afe05
PM
43 set order "--topo-order"
44 if {$datemode} {
45 set order "--date-order"
46 }
418c4c7b 47 if {[catch {
9f1afe05 48 set commfd [open [concat | git-rev-list --header $order \
16c1ff96 49 --parents --boundary $rlargs] r]
418c4c7b 50 } err]} {
cfb4563c 51 puts stderr "Error executing git-rev-list: $err"
1d10f36d
PM
52 exit 1
53 }
b490a991 54 set leftover {}
fd8ccbec
PM
55 fconfigure $commfd -blocking 0 -translation lf
56 if {$tclencoding != {}} {
57 fconfigure $commfd -encoding $tclencoding
58 }
466e4fdd 59 fileevent $commfd readable [list getcommitlines $commfd]
38ad0910
PM
60 . config -cursor watch
61 settextcursor watch
62}
63
64proc getcommits {rargs} {
aa81d974 65 global phase canv mainfont
38ad0910 66
38ad0910
PM
67 set phase getcommits
68 start_rev_list [parse_args $rargs]
1d10f36d
PM
69 $canv delete all
70 $canv create text 3 3 -anchor nw -text "Reading commits..." \
71 -font $mainfont -tags textitems
72}
73
b490a991 74proc getcommitlines {commfd} {
8ed16484
PM
75 global commitlisted nextupdate
76 global leftover
77 global displayorder commitidx commitrow commitdata
79b2c75e 78 global parentlist childlist children
9ccbdfbf 79
b490a991
PM
80 set stuff [read $commfd]
81 if {$stuff == {}} {
1d10f36d 82 if {![eof $commfd]} return
f0654861 83 # set it blocking so we wait for the process to terminate
df3d83b1 84 fconfigure $commfd -blocking 1
1d10f36d 85 if {![catch {close $commfd} err]} {
9ccbdfbf 86 after idle finishcommits
1d10f36d
PM
87 return
88 }
9a40c50c 89 if {[string range $err 0 4] == "usage"} {
9ccbdfbf 90 set err \
2ed49d54
JH
91 "Gitk: error reading commits: bad arguments to git-rev-list.\
92 (Note: arguments to gitk are passed to git-rev-list\
93 to allow selection of commits to be displayed.)"
9a40c50c 94 } else {
df3d83b1 95 set err "Error reading commits: $err"
9a40c50c 96 }
df3d83b1 97 error_popup $err
1d10f36d 98 exit 1
9a40c50c 99 }
b490a991 100 set start 0
8f7d0cec 101 set gotsome 0
b490a991
PM
102 while 1 {
103 set i [string first "\0" $stuff $start]
104 if {$i < 0} {
7e952e79 105 append leftover [string range $stuff $start end]
9f1afe05 106 break
9ccbdfbf 107 }
b490a991 108 if {$start == 0} {
8f7d0cec
PM
109 set cmit $leftover
110 append cmit [string range $stuff 0 [expr {$i - 1}]]
7e952e79 111 set leftover {}
8f7d0cec
PM
112 } else {
113 set cmit [string range $stuff $start [expr {$i - 1}]]
b490a991
PM
114 }
115 set start [expr {$i + 1}]
e5ea701b
PM
116 set j [string first "\n" $cmit]
117 set ok 0
16c1ff96 118 set listed 1
e5ea701b
PM
119 if {$j >= 0} {
120 set ids [string range $cmit 0 [expr {$j - 1}]]
16c1ff96
PM
121 if {[string range $ids 0 0] == "-"} {
122 set listed 0
123 set ids [string range $ids 1 end]
124 }
e5ea701b
PM
125 set ok 1
126 foreach id $ids {
8f7d0cec 127 if {[string length $id] != 40} {
e5ea701b
PM
128 set ok 0
129 break
130 }
131 }
132 }
133 if {!$ok} {
7e952e79
PM
134 set shortcmit $cmit
135 if {[string length $shortcmit] > 80} {
136 set shortcmit "[string range $shortcmit 0 80]..."
137 }
138 error_popup "Can't parse git-rev-list output: {$shortcmit}"
b490a991
PM
139 exit 1
140 }
e5ea701b 141 set id [lindex $ids 0]
16c1ff96
PM
142 if {$listed} {
143 set olds [lrange $ids 1 end]
79b2c75e
PM
144 if {[llength $olds] > 1} {
145 set olds [lsort -unique $olds]
146 }
147 foreach p $olds {
148 lappend children($p) $id
149 }
16c1ff96
PM
150 } else {
151 set olds {}
152 }
79b2c75e
PM
153 lappend parentlist $olds
154 if {[info exists children($id)]} {
155 lappend childlist $children($id)
156 } else {
157 lappend childlist {}
158 }
f7a3e8d2 159 set commitdata($id) [string range $cmit [expr {$j + 1}] end]
8f7d0cec
PM
160 set commitrow($id) $commitidx
161 incr commitidx
162 lappend displayorder $id
79b2c75e 163 lappend commitlisted $listed
8f7d0cec
PM
164 set gotsome 1
165 }
166 if {$gotsome} {
167 layoutmore
9f1afe05 168 }
9f1afe05
PM
169 if {[clock clicks -milliseconds] >= $nextupdate} {
170 doupdate 1
9ccbdfbf
PM
171 }
172}
173
b664550c
PM
174proc doupdate {reading} {
175 global commfd nextupdate numcommits ncmupdate
9ccbdfbf 176
b664550c
PM
177 if {$reading} {
178 fileevent $commfd readable {}
179 }
9ccbdfbf 180 update
b664550c
PM
181 set nextupdate [expr {[clock clicks -milliseconds] + 100}]
182 if {$numcommits < 100} {
183 set ncmupdate [expr {$numcommits + 1}]
184 } elseif {$numcommits < 10000} {
185 set ncmupdate [expr {$numcommits + 10}]
186 } else {
187 set ncmupdate [expr {$numcommits + 100}]
188 }
189 if {$reading} {
190 fileevent $commfd readable [list getcommitlines $commfd]
191 }
1db95b00
PM
192}
193
194proc readcommit {id} {
418c4c7b 195 if {[catch {set contents [exec git-cat-file commit $id]}]} return
8f7d0cec 196 parsecommit $id $contents 0
b490a991
PM
197}
198
fd8ccbec 199proc updatecommits {rargs} {
aa81d974 200 stopfindproc
79b2c75e 201 foreach v {colormap selectedline matchinglines treediffs
8f7d0cec 202 mergefilelist currentid rowtextx commitrow
aa81d974
PM
203 rowidlist rowoffsets idrowranges idrangedrawn iddrawn
204 linesegends crossings cornercrossings} {
205 global $v
206 catch {unset $v}
fd8ccbec 207 }
aa81d974 208 allcanvs delete all
fd8ccbec 209 readrefs
aa81d974 210 getcommits $rargs
fd8ccbec
PM
211}
212
8f7d0cec 213proc parsecommit {id contents listed} {
b5c2f306
SV
214 global commitinfo cdate
215
216 set inhdr 1
217 set comment {}
218 set headline {}
219 set auname {}
220 set audate {}
221 set comname {}
222 set comdate {}
232475d3
PM
223 set hdrend [string first "\n\n" $contents]
224 if {$hdrend < 0} {
225 # should never happen...
226 set hdrend [string length $contents]
227 }
228 set header [string range $contents 0 [expr {$hdrend - 1}]]
229 set comment [string range $contents [expr {$hdrend + 2}] end]
230 foreach line [split $header "\n"] {
231 set tag [lindex $line 0]
232 if {$tag == "author"} {
233 set audate [lindex $line end-1]
234 set auname [lrange $line 1 end-2]
235 } elseif {$tag == "committer"} {
236 set comdate [lindex $line end-1]
237 set comname [lrange $line 1 end-2]
1db95b00
PM
238 }
239 }
232475d3
PM
240 set headline {}
241 # take the first line of the comment as the headline
242 set i [string first "\n" $comment]
243 if {$i >= 0} {
244 set headline [string trim [string range $comment 0 $i]]
f6e2869f
PM
245 } else {
246 set headline $comment
232475d3
PM
247 }
248 if {!$listed} {
249 # git-rev-list indents the comment by 4 spaces;
250 # if we got this via git-cat-file, add the indentation
251 set newcomment {}
252 foreach line [split $comment "\n"] {
253 append newcomment " "
254 append newcomment $line
f6e2869f 255 append newcomment "\n"
232475d3
PM
256 }
257 set comment $newcomment
1db95b00
PM
258 }
259 if {$comdate != {}} {
cfb4563c 260 set cdate($id) $comdate
1db95b00 261 }
e5c2d856
PM
262 set commitinfo($id) [list $headline $auname $audate \
263 $comname $comdate $comment]
1db95b00
PM
264}
265
f7a3e8d2 266proc getcommit {id} {
79b2c75e 267 global commitdata commitinfo
8ed16484 268
f7a3e8d2
PM
269 if {[info exists commitdata($id)]} {
270 parsecommit $id $commitdata($id) 1
8ed16484
PM
271 } else {
272 readcommit $id
273 if {![info exists commitinfo($id)]} {
274 set commitinfo($id) {"No commit information available"}
8ed16484
PM
275 }
276 }
277 return 1
278}
279
887fe3c4 280proc readrefs {} {
106288cb 281 global tagids idtags headids idheads tagcontents
36a7cad6 282 global otherrefids idotherrefs
106288cb 283
b5c2f306
SV
284 foreach v {tagids idtags headids idheads otherrefids idotherrefs} {
285 catch {unset $v}
286 }
ce088722 287 set refd [open [list | git ls-remote [gitdir]] r]
36a7cad6
JH
288 while {0 <= [set n [gets $refd line]]} {
289 if {![regexp {^([0-9a-f]{40}) refs/([^^]*)$} $line \
290 match id path]} {
291 continue
c2f6a022 292 }
36a7cad6
JH
293 if {![regexp {^(tags|heads)/(.*)$} $path match type name]} {
294 set type others
295 set name $path
887fe3c4 296 }
36a7cad6
JH
297 if {$type == "tags"} {
298 set tagids($name) $id
299 lappend idtags($id) $name
300 set obj {}
301 set type {}
302 set tag {}
303 catch {
304 set commit [exec git-rev-parse "$id^0"]
305 if {"$commit" != "$id"} {
306 set tagids($name) $commit
307 lappend idtags($commit) $name
308 }
309 }
310 catch {
311 set tagcontents($name) [exec git-cat-file tag "$id"]
f1d83ba3 312 }
36a7cad6
JH
313 } elseif { $type == "heads" } {
314 set headids($name) $id
315 lappend idheads($id) $name
316 } else {
317 set otherrefids($name) $id
318 lappend idotherrefs($id) $name
f1d83ba3
PM
319 }
320 }
36a7cad6 321 close $refd
887fe3c4
PM
322}
323
df3d83b1
PM
324proc error_popup msg {
325 set w .error
326 toplevel $w
327 wm transient $w .
328 message $w.m -text $msg -justify center -aspect 400
329 pack $w.m -side top -fill x -padx 20 -pady 20
330 button $w.ok -text OK -command "destroy $w"
331 pack $w.ok -side bottom -fill x
332 bind $w <Visibility> "grab $w; focus $w"
9f841cf1 333 bind $w <Key-Return> "destroy $w"
df3d83b1
PM
334 tkwait window $w
335}
336
b5c2f306 337proc makewindow {rargs} {
e5c2d856 338 global canv canv2 canv3 linespc charspc ctext cflist textfont
b74fd579 339 global findtype findtypemenu findloc findstring fstring geometry
887fe3c4 340 global entries sha1entry sha1string sha1but
94a2eede 341 global maincursor textcursor curtextcursor
712fcc08 342 global rowctxmenu mergemax
9a40c50c
PM
343
344 menu .bar
345 .bar add cascade -label "File" -menu .bar.file
346 menu .bar.file
b5c2f306 347 .bar.file add command -label "Update" -command [list updatecommits $rargs]
f1d83ba3 348 .bar.file add command -label "Reread references" -command rereadrefs
1d10f36d 349 .bar.file add command -label "Quit" -command doquit
712fcc08
PM
350 menu .bar.edit
351 .bar add cascade -label "Edit" -menu .bar.edit
352 .bar.edit add command -label "Preferences" -command doprefs
9a40c50c
PM
353 menu .bar.help
354 .bar add cascade -label "Help" -menu .bar.help
355 .bar.help add command -label "About gitk" -command about
4e95e1f7 356 .bar.help add command -label "Key bindings" -command keys
9a40c50c
PM
357 . configure -menu .bar
358
0fba86b3 359 if {![info exists geometry(canv1)]} {
2ed49d54
JH
360 set geometry(canv1) [expr {45 * $charspc}]
361 set geometry(canv2) [expr {30 * $charspc}]
362 set geometry(canv3) [expr {15 * $charspc}]
363 set geometry(canvh) [expr {25 * $linespc + 4}]
0fba86b3
PM
364 set geometry(ctextw) 80
365 set geometry(ctexth) 30
366 set geometry(cflistw) 30
367 }
0327d27a 368 panedwindow .ctop -orient vertical
0fba86b3
PM
369 if {[info exists geometry(width)]} {
370 .ctop conf -width $geometry(width) -height $geometry(height)
17386066
PM
371 set texth [expr {$geometry(height) - $geometry(canvh) - 56}]
372 set geometry(ctexth) [expr {($texth - 8) /
373 [font metrics $textfont -linespace]}]
0fba86b3 374 }
98f350e5
PM
375 frame .ctop.top
376 frame .ctop.top.bar
377 pack .ctop.top.bar -side bottom -fill x
378 set cscroll .ctop.top.csb
379 scrollbar $cscroll -command {allcanvs yview} -highlightthickness 0
380 pack $cscroll -side right -fill y
381 panedwindow .ctop.top.clist -orient horizontal -sashpad 0 -handlesize 4
382 pack .ctop.top.clist -side top -fill both -expand 1
383 .ctop add .ctop.top
384 set canv .ctop.top.clist.canv
0fba86b3 385 canvas $canv -height $geometry(canvh) -width $geometry(canv1) \
b5721c72 386 -bg white -bd 0 \
9f1afe05 387 -yscrollincr $linespc -yscrollcommand "scrollcanv $cscroll"
98f350e5
PM
388 .ctop.top.clist add $canv
389 set canv2 .ctop.top.clist.canv2
0fba86b3 390 canvas $canv2 -height $geometry(canvh) -width $geometry(canv2) \
b5721c72 391 -bg white -bd 0 -yscrollincr $linespc
98f350e5
PM
392 .ctop.top.clist add $canv2
393 set canv3 .ctop.top.clist.canv3
0fba86b3 394 canvas $canv3 -height $geometry(canvh) -width $geometry(canv3) \
b5721c72 395 -bg white -bd 0 -yscrollincr $linespc
98f350e5 396 .ctop.top.clist add $canv3
43bddeb4 397 bind .ctop.top.clist <Configure> {resizeclistpanes %W %w}
98f350e5
PM
398
399 set sha1entry .ctop.top.bar.sha1
887fe3c4
PM
400 set entries $sha1entry
401 set sha1but .ctop.top.bar.sha1label
402 button $sha1but -text "SHA1 ID: " -state disabled -relief flat \
403 -command gotocommit -width 8
404 $sha1but conf -disabledforeground [$sha1but cget -foreground]
98f350e5 405 pack .ctop.top.bar.sha1label -side left
887fe3c4
PM
406 entry $sha1entry -width 40 -font $textfont -textvariable sha1string
407 trace add variable sha1string write sha1change
98f350e5 408 pack $sha1entry -side left -pady 2
d698206c
PM
409
410 image create bitmap bm-left -data {
411 #define left_width 16
412 #define left_height 16
413 static unsigned char left_bits[] = {
414 0x00, 0x00, 0xc0, 0x01, 0xe0, 0x00, 0x70, 0x00, 0x38, 0x00, 0x1c, 0x00,
415 0x0e, 0x00, 0xff, 0x7f, 0xff, 0x7f, 0xff, 0x7f, 0x0e, 0x00, 0x1c, 0x00,
416 0x38, 0x00, 0x70, 0x00, 0xe0, 0x00, 0xc0, 0x01};
417 }
418 image create bitmap bm-right -data {
419 #define right_width 16
420 #define right_height 16
421 static unsigned char right_bits[] = {
422 0x00, 0x00, 0xc0, 0x01, 0x80, 0x03, 0x00, 0x07, 0x00, 0x0e, 0x00, 0x1c,
423 0x00, 0x38, 0xff, 0x7f, 0xff, 0x7f, 0xff, 0x7f, 0x00, 0x38, 0x00, 0x1c,
424 0x00, 0x0e, 0x00, 0x07, 0x80, 0x03, 0xc0, 0x01};
425 }
426 button .ctop.top.bar.leftbut -image bm-left -command goback \
427 -state disabled -width 26
428 pack .ctop.top.bar.leftbut -side left -fill y
429 button .ctop.top.bar.rightbut -image bm-right -command goforw \
430 -state disabled -width 26
431 pack .ctop.top.bar.rightbut -side left -fill y
432
98f350e5
PM
433 button .ctop.top.bar.findbut -text "Find" -command dofind
434 pack .ctop.top.bar.findbut -side left
435 set findstring {}
df3d83b1 436 set fstring .ctop.top.bar.findstring
887fe3c4 437 lappend entries $fstring
df3d83b1 438 entry $fstring -width 30 -font $textfont -textvariable findstring
df3d83b1 439 pack $fstring -side left -expand 1 -fill x
98f350e5 440 set findtype Exact
b74fd579
PM
441 set findtypemenu [tk_optionMenu .ctop.top.bar.findtype \
442 findtype Exact IgnCase Regexp]
98f350e5
PM
443 set findloc "All fields"
444 tk_optionMenu .ctop.top.bar.findloc findloc "All fields" Headline \
b74fd579 445 Comments Author Committer Files Pickaxe
98f350e5
PM
446 pack .ctop.top.bar.findloc -side right
447 pack .ctop.top.bar.findtype -side right
b74fd579
PM
448 # for making sure type==Exact whenever loc==Pickaxe
449 trace add variable findloc write findlocchange
b5721c72 450
5ad588de
PM
451 panedwindow .ctop.cdet -orient horizontal
452 .ctop add .ctop.cdet
d2610d11
PM
453 frame .ctop.cdet.left
454 set ctext .ctop.cdet.left.ctext
0fba86b3
PM
455 text $ctext -bg white -state disabled -font $textfont \
456 -width $geometry(ctextw) -height $geometry(ctexth) \
b1ba39e7 457 -yscrollcommand ".ctop.cdet.left.sb set" -wrap none
d2610d11
PM
458 scrollbar .ctop.cdet.left.sb -command "$ctext yview"
459 pack .ctop.cdet.left.sb -side right -fill y
460 pack $ctext -side left -fill both -expand 1
461 .ctop.cdet add .ctop.cdet.left
462
f0654861 463 $ctext tag conf filesep -font [concat $textfont bold] -back "#aaaaaa"
712fcc08
PM
464 $ctext tag conf hunksep -fore blue
465 $ctext tag conf d0 -fore red
466 $ctext tag conf d1 -fore "#00a000"
467 $ctext tag conf m0 -fore red
468 $ctext tag conf m1 -fore blue
469 $ctext tag conf m2 -fore green
470 $ctext tag conf m3 -fore purple
471 $ctext tag conf m4 -fore brown
b77b0278
PM
472 $ctext tag conf m5 -fore "#009090"
473 $ctext tag conf m6 -fore magenta
474 $ctext tag conf m7 -fore "#808000"
475 $ctext tag conf m8 -fore "#009000"
476 $ctext tag conf m9 -fore "#ff0080"
477 $ctext tag conf m10 -fore cyan
478 $ctext tag conf m11 -fore "#b07070"
479 $ctext tag conf m12 -fore "#70b0f0"
480 $ctext tag conf m13 -fore "#70f0b0"
481 $ctext tag conf m14 -fore "#f0b070"
482 $ctext tag conf m15 -fore "#ff70b0"
712fcc08 483 $ctext tag conf mmax -fore darkgrey
b77b0278 484 set mergemax 16
712fcc08
PM
485 $ctext tag conf mresult -font [concat $textfont bold]
486 $ctext tag conf msep -font [concat $textfont bold]
487 $ctext tag conf found -back yellow
e5c2d856 488
d2610d11
PM
489 frame .ctop.cdet.right
490 set cflist .ctop.cdet.right.cfiles
17386066 491 listbox $cflist -bg white -selectmode extended -width $geometry(cflistw) \
d2610d11
PM
492 -yscrollcommand ".ctop.cdet.right.sb set"
493 scrollbar .ctop.cdet.right.sb -command "$cflist yview"
494 pack .ctop.cdet.right.sb -side right -fill y
495 pack $cflist -side left -fill both -expand 1
496 .ctop.cdet add .ctop.cdet.right
0fba86b3 497 bind .ctop.cdet <Configure> {resizecdetpanes %W %w}
d2610d11 498
0327d27a 499 pack .ctop -side top -fill both -expand 1
1db95b00 500
c8dfbcf9
PM
501 bindall <1> {selcanvline %W %x %y}
502 #bindall <B1-Motion> {selcanvline %W %x %y}
cfb4563c
PM
503 bindall <ButtonRelease-4> "allcanvs yview scroll -5 units"
504 bindall <ButtonRelease-5> "allcanvs yview scroll 5 units"
be0cd098
PM
505 bindall <2> "canvscan mark %W %x %y"
506 bindall <B2-Motion> "canvscan dragto %W %x %y"
6e5f7203
RN
507 bindkey <Home> selfirstline
508 bindkey <End> sellastline
17386066
PM
509 bind . <Key-Up> "selnextline -1"
510 bind . <Key-Down> "selnextline 1"
6e5f7203
RN
511 bindkey <Key-Right> "goforw"
512 bindkey <Key-Left> "goback"
513 bind . <Key-Prior> "selnextpage -1"
514 bind . <Key-Next> "selnextpage 1"
515 bind . <Control-Home> "allcanvs yview moveto 0.0"
516 bind . <Control-End> "allcanvs yview moveto 1.0"
517 bind . <Control-Key-Up> "allcanvs yview scroll -1 units"
518 bind . <Control-Key-Down> "allcanvs yview scroll 1 units"
519 bind . <Control-Key-Prior> "allcanvs yview scroll -1 pages"
520 bind . <Control-Key-Next> "allcanvs yview scroll 1 pages"
cfb4563c
PM
521 bindkey <Key-Delete> "$ctext yview scroll -1 pages"
522 bindkey <Key-BackSpace> "$ctext yview scroll -1 pages"
523 bindkey <Key-space> "$ctext yview scroll 1 pages"
df3d83b1
PM
524 bindkey p "selnextline -1"
525 bindkey n "selnextline 1"
6e2dda35
RS
526 bindkey z "goback"
527 bindkey x "goforw"
528 bindkey i "selnextline -1"
529 bindkey k "selnextline 1"
530 bindkey j "goback"
531 bindkey l "goforw"
cfb4563c
PM
532 bindkey b "$ctext yview scroll -1 pages"
533 bindkey d "$ctext yview scroll 18 units"
534 bindkey u "$ctext yview scroll -18 units"
b74fd579
PM
535 bindkey / {findnext 1}
536 bindkey <Key-Return> {findnext 0}
df3d83b1 537 bindkey ? findprev
39ad8570 538 bindkey f nextfile
1d10f36d 539 bind . <Control-q> doquit
98f350e5 540 bind . <Control-f> dofind
b74fd579 541 bind . <Control-g> {findnext 0}
98f350e5 542 bind . <Control-r> findprev
1d10f36d
PM
543 bind . <Control-equal> {incrfont 1}
544 bind . <Control-KP_Add> {incrfont 1}
545 bind . <Control-minus> {incrfont -1}
546 bind . <Control-KP_Subtract> {incrfont -1}
e5c2d856 547 bind $cflist <<ListboxSelect>> listboxsel
0fba86b3 548 bind . <Destroy> {savestuff %W}
df3d83b1 549 bind . <Button-1> "click %W"
17386066 550 bind $fstring <Key-Return> dofind
887fe3c4 551 bind $sha1entry <Key-Return> gotocommit
ee3dc72e 552 bind $sha1entry <<PasteSelection>> clearsha1
ea13cba1
PM
553
554 set maincursor [. cget -cursor]
555 set textcursor [$ctext cget -cursor]
94a2eede 556 set curtextcursor $textcursor
84ba7345 557
c8dfbcf9
PM
558 set rowctxmenu .rowctxmenu
559 menu $rowctxmenu -tearoff 0
560 $rowctxmenu add command -label "Diff this -> selected" \
561 -command {diffvssel 0}
562 $rowctxmenu add command -label "Diff selected -> this" \
563 -command {diffvssel 1}
74daedb6 564 $rowctxmenu add command -label "Make patch" -command mkpatch
bdbfbe3d 565 $rowctxmenu add command -label "Create tag" -command mktag
4a2139f5 566 $rowctxmenu add command -label "Write commit to file" -command writecommit
df3d83b1
PM
567}
568
be0cd098
PM
569# mouse-2 makes all windows scan vertically, but only the one
570# the cursor is in scans horizontally
571proc canvscan {op w x y} {
572 global canv canv2 canv3
573 foreach c [list $canv $canv2 $canv3] {
574 if {$c == $w} {
575 $c scan $op $x $y
576 } else {
577 $c scan $op 0 $y
578 }
579 }
580}
581
9f1afe05
PM
582proc scrollcanv {cscroll f0 f1} {
583 $cscroll set $f0 $f1
584 drawfrac $f0 $f1
585}
586
df3d83b1
PM
587# when we make a key binding for the toplevel, make sure
588# it doesn't get triggered when that key is pressed in the
589# find string entry widget.
590proc bindkey {ev script} {
887fe3c4 591 global entries
df3d83b1
PM
592 bind . $ev $script
593 set escript [bind Entry $ev]
594 if {$escript == {}} {
595 set escript [bind Entry <Key>]
596 }
887fe3c4
PM
597 foreach e $entries {
598 bind $e $ev "$escript; break"
599 }
df3d83b1
PM
600}
601
602# set the focus back to the toplevel for any click outside
887fe3c4 603# the entry widgets
df3d83b1 604proc click {w} {
887fe3c4
PM
605 global entries
606 foreach e $entries {
607 if {$w == $e} return
df3d83b1 608 }
887fe3c4 609 focus .
0fba86b3
PM
610}
611
612proc savestuff {w} {
613 global canv canv2 canv3 ctext cflist mainfont textfont
712fcc08 614 global stuffsaved findmergefiles maxgraphpct
04c13d38 615 global maxwidth
4ef17537 616
0fba86b3 617 if {$stuffsaved} return
df3d83b1 618 if {![winfo viewable .]} return
0fba86b3
PM
619 catch {
620 set f [open "~/.gitk-new" w]
f0654861
PM
621 puts $f [list set mainfont $mainfont]
622 puts $f [list set textfont $textfont]
623 puts $f [list set findmergefiles $findmergefiles]
8d858d1a 624 puts $f [list set maxgraphpct $maxgraphpct]
04c13d38 625 puts $f [list set maxwidth $maxwidth]
0fba86b3
PM
626 puts $f "set geometry(width) [winfo width .ctop]"
627 puts $f "set geometry(height) [winfo height .ctop]"
2ed49d54
JH
628 puts $f "set geometry(canv1) [expr {[winfo width $canv]-2}]"
629 puts $f "set geometry(canv2) [expr {[winfo width $canv2]-2}]"
630 puts $f "set geometry(canv3) [expr {[winfo width $canv3]-2}]"
631 puts $f "set geometry(canvh) [expr {[winfo height $canv]-2}]"
0fba86b3
PM
632 set wid [expr {([winfo width $ctext] - 8) \
633 / [font measure $textfont "0"]}]
0fba86b3 634 puts $f "set geometry(ctextw) $wid"
0fba86b3
PM
635 set wid [expr {([winfo width $cflist] - 11) \
636 / [font measure [$cflist cget -font] "0"]}]
637 puts $f "set geometry(cflistw) $wid"
638 close $f
639 file rename -force "~/.gitk-new" "~/.gitk"
640 }
641 set stuffsaved 1
1db95b00
PM
642}
643
43bddeb4
PM
644proc resizeclistpanes {win w} {
645 global oldwidth
418c4c7b 646 if {[info exists oldwidth($win)]} {
43bddeb4
PM
647 set s0 [$win sash coord 0]
648 set s1 [$win sash coord 1]
649 if {$w < 60} {
650 set sash0 [expr {int($w/2 - 2)}]
651 set sash1 [expr {int($w*5/6 - 2)}]
652 } else {
653 set factor [expr {1.0 * $w / $oldwidth($win)}]
654 set sash0 [expr {int($factor * [lindex $s0 0])}]
655 set sash1 [expr {int($factor * [lindex $s1 0])}]
656 if {$sash0 < 30} {
657 set sash0 30
658 }
659 if {$sash1 < $sash0 + 20} {
2ed49d54 660 set sash1 [expr {$sash0 + 20}]
43bddeb4
PM
661 }
662 if {$sash1 > $w - 10} {
2ed49d54 663 set sash1 [expr {$w - 10}]
43bddeb4 664 if {$sash0 > $sash1 - 20} {
2ed49d54 665 set sash0 [expr {$sash1 - 20}]
43bddeb4
PM
666 }
667 }
668 }
669 $win sash place 0 $sash0 [lindex $s0 1]
670 $win sash place 1 $sash1 [lindex $s1 1]
671 }
672 set oldwidth($win) $w
673}
674
675proc resizecdetpanes {win w} {
676 global oldwidth
418c4c7b 677 if {[info exists oldwidth($win)]} {
43bddeb4
PM
678 set s0 [$win sash coord 0]
679 if {$w < 60} {
680 set sash0 [expr {int($w*3/4 - 2)}]
681 } else {
682 set factor [expr {1.0 * $w / $oldwidth($win)}]
683 set sash0 [expr {int($factor * [lindex $s0 0])}]
684 if {$sash0 < 45} {
685 set sash0 45
686 }
687 if {$sash0 > $w - 15} {
2ed49d54 688 set sash0 [expr {$w - 15}]
43bddeb4
PM
689 }
690 }
691 $win sash place 0 $sash0 [lindex $s0 1]
692 }
693 set oldwidth($win) $w
694}
695
b5721c72
PM
696proc allcanvs args {
697 global canv canv2 canv3
698 eval $canv $args
699 eval $canv2 $args
700 eval $canv3 $args
701}
702
703proc bindall {event action} {
704 global canv canv2 canv3
705 bind $canv $event $action
706 bind $canv2 $event $action
707 bind $canv3 $event $action
708}
709
9a40c50c
PM
710proc about {} {
711 set w .about
712 if {[winfo exists $w]} {
713 raise $w
714 return
715 }
716 toplevel $w
717 wm title $w "About gitk"
718 message $w.m -text {
9f1afe05 719Gitk - a commit viewer for git
9a40c50c 720
9f1afe05 721