]> git.ipfire.org Git - thirdparty/git.git/blame - gitk
[PATCH] gitk i18n: Import msgcat for message string translation; load translation...
[thirdparty/git.git] / gitk
CommitLineData
1db95b00
PM
1#!/bin/sh
2# Tcl ignores the next line -*- tcl -*- \
9e026d39 3exec wish "$0" -- "$@"
1db95b00 4
e1a7c81f 5# Copyright (C) 2005-2006 Paul Mackerras. All rights reserved.
1db95b00
PM
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 {
5024baa4 15 return [exec git rev-parse --git-dir]
73b6a6cb
JH
16 }
17}
18
7eb3cb9c
PM
19# A simple scheduler for compute-intensive stuff.
20# The aim is to make sure that event handlers for GUI actions can
21# run at least every 50-100 ms. Unfortunately fileevent handlers are
22# run before X event handlers, so reading from a fast source can
23# make the GUI completely unresponsive.
24proc run args {
25 global isonrunq runq
26
27 set script $args
28 if {[info exists isonrunq($script)]} return
29 if {$runq eq {}} {
30 after idle dorunq
31 }
32 lappend runq [list {} $script]
33 set isonrunq($script) 1
34}
35
36proc filerun {fd script} {
37 fileevent $fd readable [list filereadable $fd $script]
38}
39
40proc filereadable {fd script} {
41 global runq
42
43 fileevent $fd readable {}
44 if {$runq eq {}} {
45 after idle dorunq
46 }
47 lappend runq [list $fd $script]
48}
49
50proc dorunq {} {
51 global isonrunq runq
52
53 set tstart [clock clicks -milliseconds]
54 set t0 $tstart
55 while {$runq ne {}} {
56 set fd [lindex $runq 0 0]
57 set script [lindex $runq 0 1]
58 set repeat [eval $script]
59 set t1 [clock clicks -milliseconds]
60 set t [expr {$t1 - $t0}]
61 set runq [lrange $runq 1 end]
62 if {$repeat ne {} && $repeat} {
63 if {$fd eq {} || $repeat == 2} {
64 # script returns 1 if it wants to be readded
65 # file readers return 2 if they could do more straight away
66 lappend runq [list $fd $script]
67 } else {
68 fileevent $fd readable [list filereadable $fd $script]
69 }
70 } elseif {$fd eq {}} {
71 unset isonrunq($script)
72 }
73 set t0 $t1
74 if {$t1 - $tstart >= 80} break
75 }
76 if {$runq ne {}} {
77 after idle dorunq
78 }
79}
80
81# Start off a git rev-list process and arrange to read its output
da7c24dd 82proc start_rev_list {view} {
7eb3cb9c 83 global startmsecs
9f1afe05 84 global commfd leftover tclencoding datemode
f5f3c2e2 85 global viewargs viewfiles commitidx viewcomplete vnextroot
3e6b893f 86 global showlocalchanges commitinterest mainheadid
bb3edc8b 87 global progressdirn progresscoords proglastnc curview
9ccbdfbf 88
9ccbdfbf 89 set startmsecs [clock clicks -milliseconds]
da7c24dd 90 set commitidx($view) 0
f5f3c2e2 91 set viewcomplete($view) 0
6e8c8707 92 set vnextroot($view) 0
9f1afe05
PM
93 set order "--topo-order"
94 if {$datemode} {
95 set order "--date-order"
96 }
418c4c7b 97 if {[catch {
0166419a 98 set fd [open [concat | git log --no-color -z --pretty=raw $order --parents \
cdaee5db 99 --boundary $viewargs($view) "--" $viewfiles($view)] r]
418c4c7b 100 } err]} {
cdaee5db 101 error_popup "Error executing git rev-list: $err"
1d10f36d
PM
102 exit 1
103 }
da7c24dd
PM
104 set commfd($view) $fd
105 set leftover($view) {}
3e6b893f
PM
106 if {$showlocalchanges} {
107 lappend commitinterest($mainheadid) {dodiffindex}
108 }
86da5b6c 109 fconfigure $fd -blocking 0 -translation lf -eofchar {}
fd8ccbec 110 if {$tclencoding != {}} {
da7c24dd 111 fconfigure $fd -encoding $tclencoding
fd8ccbec 112 }
7eb3cb9c 113 filerun $fd [list getcommitlines $fd $view]
4570b7e9 114 nowbusy $view "Reading"
bb3edc8b
PM
115 if {$view == $curview} {
116 set progressdirn 1
117 set progresscoords {0 0}
118 set proglastnc 0
119 }
38ad0910
PM
120}
121
22626ef4 122proc stop_rev_list {} {
da7c24dd 123 global commfd curview
22626ef4 124
da7c24dd
PM
125 if {![info exists commfd($curview)]} return
126 set fd $commfd($curview)
22626ef4 127 catch {
da7c24dd 128 set pid [pid $fd]
22626ef4
PM
129 exec kill $pid
130 }
da7c24dd
PM
131 catch {close $fd}
132 unset commfd($curview)
22626ef4
PM
133}
134
a8aaf19c 135proc getcommits {} {
9c311b32 136 global phase canv curview
38ad0910 137
38ad0910 138 set phase getcommits
da7c24dd
PM
139 initlayout
140 start_rev_list $curview
098dd8a3 141 show_status "Reading commits..."
1d10f36d
PM
142}
143
6e8c8707
PM
144# This makes a string representation of a positive integer which
145# sorts as a string in numerical order
146proc strrep {n} {
147 if {$n < 16} {
148 return [format "%x" $n]
149 } elseif {$n < 256} {
150 return [format "x%.2x" $n]
151 } elseif {$n < 65536} {
152 return [format "y%.4x" $n]
153 }
154 return [format "z%.8x" $n]
155}
156
da7c24dd 157proc getcommitlines {fd view} {
3e6b893f 158 global commitlisted commitinterest
da7c24dd 159 global leftover commfd
f5f3c2e2 160 global displayorder commitidx viewcomplete commitrow commitdata
6a90bff1
PM
161 global parentlist children curview hlview
162 global vparentlist vdisporder vcmitlisted
b0cdca99 163 global ordertok vnextroot idpending
9ccbdfbf 164
d1e46756 165 set stuff [read $fd 500000]
005a2f4e
PM
166 # git log doesn't terminate the last commit with a null...
167 if {$stuff == {} && $leftover($view) ne {} && [eof $fd]} {
168 set stuff "\0"
169 }
b490a991 170 if {$stuff == {}} {
7eb3cb9c
PM
171 if {![eof $fd]} {
172 return 1
173 }
b0cdca99
PM
174 # Check if we have seen any ids listed as parents that haven't
175 # appeared in the list
176 foreach vid [array names idpending "$view,*"] {
177 # should only get here if git log is buggy
178 set id [lindex [split $vid ","] 1]
179 set commitrow($vid) $commitidx($view)
180 incr commitidx($view)
181 if {$view == $curview} {
182 lappend parentlist {}
183 lappend displayorder $id
184 lappend commitlisted 0
185 } else {
186 lappend vparentlist($view) {}
187 lappend vdisporder($view) $id
188 lappend vcmitlisted($view) 0
189 }
190 }
f5f3c2e2 191 set viewcomplete($view) 1
bb3edc8b 192 global viewname progresscoords
da7c24dd 193 unset commfd($view)
098dd8a3 194 notbusy $view
bb3edc8b
PM
195 set progresscoords {0 0}
196 adjustprogress
f0654861 197 # set it blocking so we wait for the process to terminate
da7c24dd 198 fconfigure $fd -blocking 1
098dd8a3
PM
199 if {[catch {close $fd} err]} {
200 set fv {}
201 if {$view != $curview} {
202 set fv " for the \"$viewname($view)\" view"
da7c24dd 203 }
098dd8a3
PM
204 if {[string range $err 0 4] == "usage"} {
205 set err "Gitk: error reading commits$fv:\
8974c6f9 206 bad arguments to git rev-list."
098dd8a3
PM
207 if {$viewname($view) eq "Command line"} {
208 append err \
8974c6f9 209 " (Note: arguments to gitk are passed to git rev-list\
098dd8a3
PM
210 to allow selection of commits to be displayed.)"
211 }
212 } else {
213 set err "Error reading commits$fv: $err"
214 }
215 error_popup $err
1d10f36d 216 }
098dd8a3 217 if {$view == $curview} {
7eb3cb9c 218 run chewcommits $view
9a40c50c 219 }
7eb3cb9c 220 return 0
9a40c50c 221 }
b490a991 222 set start 0
8f7d0cec 223 set gotsome 0
b490a991
PM
224 while 1 {
225 set i [string first "\0" $stuff $start]
226 if {$i < 0} {
da7c24dd 227 append leftover($view) [string range $stuff $start end]
9f1afe05 228 break
9ccbdfbf 229 }
b490a991 230 if {$start == 0} {
da7c24dd 231 set cmit $leftover($view)
8f7d0cec 232 append cmit [string range $stuff 0 [expr {$i - 1}]]
da7c24dd 233 set leftover($view) {}
8f7d0cec
PM
234 } else {
235 set cmit [string range $stuff $start [expr {$i - 1}]]
b490a991
PM
236 }
237 set start [expr {$i + 1}]
e5ea701b
PM
238 set j [string first "\n" $cmit]
239 set ok 0
16c1ff96 240 set listed 1
c961b228
PM
241 if {$j >= 0 && [string match "commit *" $cmit]} {
242 set ids [string range $cmit 7 [expr {$j - 1}]]
243 if {[string match {[-<>]*} $ids]} {
244 switch -- [string index $ids 0] {
245 "-" {set listed 0}
246 "<" {set listed 2}
247 ">" {set listed 3}
248 }
16c1ff96
PM
249 set ids [string range $ids 1 end]
250 }
e5ea701b
PM
251 set ok 1
252 foreach id $ids {
8f7d0cec 253 if {[string length $id] != 40} {
e5ea701b
PM
254 set ok 0
255 break
256 }
257 }
258 }
259 if {!$ok} {
7e952e79
PM
260 set shortcmit $cmit
261 if {[string length $shortcmit] > 80} {
262 set shortcmit "[string range $shortcmit 0 80]..."
263 }
c961b228 264 error_popup "Can't parse git log output: {$shortcmit}"
b490a991
PM
265 exit 1
266 }
e5ea701b 267 set id [lindex $ids 0]
6e8c8707
PM
268 if {![info exists ordertok($view,$id)]} {
269 set otok "o[strrep $vnextroot($view)]"
270 incr vnextroot($view)
271 set ordertok($view,$id) $otok
272 } else {
273 set otok $ordertok($view,$id)
b0cdca99 274 unset idpending($view,$id)
6e8c8707 275 }
16c1ff96
PM
276 if {$listed} {
277 set olds [lrange $ids 1 end]
6e8c8707
PM
278 if {[llength $olds] == 1} {
279 set p [lindex $olds 0]
280 lappend children($view,$p) $id
281 if {![info exists ordertok($view,$p)]} {
282 set ordertok($view,$p) $ordertok($view,$id)
b0cdca99 283 set idpending($view,$p) 1
6e8c8707
PM
284 }
285 } else {
286 set i 0
287 foreach p $olds {
288 if {$i == 0 || [lsearch -exact $olds $p] >= $i} {
289 lappend children($view,$p) $id
290 }
291 if {![info exists ordertok($view,$p)]} {
292 set ordertok($view,$p) "$otok[strrep $i]]"
b0cdca99 293 set idpending($view,$p) 1
6e8c8707
PM
294 }
295 incr i
50b44ece 296 }
79b2c75e 297 }
16c1ff96
PM
298 } else {
299 set olds {}
300 }
da7c24dd
PM
301 if {![info exists children($view,$id)]} {
302 set children($view,$id) {}
79b2c75e 303 }
f7a3e8d2 304 set commitdata($id) [string range $cmit [expr {$j + 1}] end]
da7c24dd
PM
305 set commitrow($view,$id) $commitidx($view)
306 incr commitidx($view)
307 if {$view == $curview} {
308 lappend parentlist $olds
da7c24dd
PM
309 lappend displayorder $id
310 lappend commitlisted $listed
311 } else {
312 lappend vparentlist($view) $olds
da7c24dd
PM
313 lappend vdisporder($view) $id
314 lappend vcmitlisted($view) $listed
315 }
3e6b893f
PM
316 if {[info exists commitinterest($id)]} {
317 foreach script $commitinterest($id) {
318 eval [string map [list "%I" $id] $script]
319 }
320 unset commitinterest($id)
321 }
8f7d0cec
PM
322 set gotsome 1
323 }
324 if {$gotsome} {
7eb3cb9c 325 run chewcommits $view
bb3edc8b
PM
326 if {$view == $curview} {
327 # update progress bar
328 global progressdirn progresscoords proglastnc
329 set inc [expr {($commitidx($view) - $proglastnc) * 0.0002}]
330 set proglastnc $commitidx($view)
331 set l [lindex $progresscoords 0]
332 set r [lindex $progresscoords 1]
333 if {$progressdirn} {
334 set r [expr {$r + $inc}]
335 if {$r >= 1.0} {
336 set r 1.0
337 set progressdirn 0
338 }
339 if {$r > 0.2} {
340 set l [expr {$r - 0.2}]
341 }
342 } else {
343 set l [expr {$l - $inc}]
344 if {$l <= 0.0} {
345 set l 0.0
346 set progressdirn 1
347 }
348 set r [expr {$l + 0.2}]
349 }
350 set progresscoords [list $l $r]
351 adjustprogress
352 }
9ccbdfbf 353 }
7eb3cb9c 354 return 2
9ccbdfbf
PM
355}
356
7eb3cb9c 357proc chewcommits {view} {
f5f3c2e2 358 global curview hlview viewcomplete
7eb3cb9c
PM
359 global selectedline pending_select
360
7eb3cb9c 361 if {$view == $curview} {
f5f3c2e2
PM
362 layoutmore
363 if {$viewcomplete($view)} {
8f489363 364 global displayorder commitidx phase
7eb3cb9c 365 global numcommits startmsecs
9ccbdfbf 366
7eb3cb9c 367 if {[info exists pending_select]} {
8f489363 368 set row [first_real_row]
7eb3cb9c
PM
369 selectline $row 1
370 }
371 if {$commitidx($curview) > 0} {
372 #set ms [expr {[clock clicks -milliseconds] - $startmsecs}]
373 #puts "overall $ms ms for $numcommits commits"
374 } else {
375 show_status "No commits selected"
376 }
377 notbusy layout
378 set phase {}
379 }
b664550c 380 }
7eb3cb9c
PM
381 if {[info exists hlview] && $view == $hlview} {
382 vhighlightmore
b664550c 383 }
f5f3c2e2 384 return 0
1db95b00
PM
385}
386
387proc readcommit {id} {
8974c6f9 388 if {[catch {set contents [exec git cat-file commit $id]}]} return
8f7d0cec 389 parsecommit $id $contents 0
b490a991
PM
390}
391
50b44ece 392proc updatecommits {} {
b0cdca99 393 global viewdata curview phase displayorder ordertok idpending
a69b2d1a 394 global children commitrow selectedline thickerline showneartags
50b44ece 395
22626ef4
PM
396 if {$phase ne {}} {
397 stop_rev_list
398 set phase {}
fd8ccbec 399 }
d94f8cd6 400 set n $curview
da7c24dd
PM
401 foreach id $displayorder {
402 catch {unset children($n,$id)}
403 catch {unset commitrow($n,$id)}
b0cdca99
PM
404 catch {unset ordertok($n,$id)}
405 }
406 foreach vid [array names idpending "$n,*"] {
407 unset idpending($vid)
da7c24dd 408 }
d94f8cd6 409 set curview -1
908c3585
PM
410 catch {unset selectedline}
411 catch {unset thickerline}
d94f8cd6 412 catch {unset viewdata($n)}
fd8ccbec 413 readrefs
e11f1233 414 changedrefs
a69b2d1a
PM
415 if {$showneartags} {
416 getallcommits
417 }
d94f8cd6 418 showview $n
fd8ccbec
PM
419}
420
8f7d0cec 421proc parsecommit {id contents listed} {
b5c2f306
SV
422 global commitinfo cdate
423
424 set inhdr 1
425 set comment {}
426 set headline {}
427 set auname {}
428 set audate {}
429 set comname {}
430 set comdate {}
232475d3
PM
431 set hdrend [string first "\n\n" $contents]
432 if {$hdrend < 0} {
433 # should never happen...
434 set hdrend [string length $contents]
435 }
436 set header [string range $contents 0 [expr {$hdrend - 1}]]
437 set comment [string range $contents [expr {$hdrend + 2}] end]
438 foreach line [split $header "\n"] {
439 set tag [lindex $line 0]
440 if {$tag == "author"} {
441 set audate [lindex $line end-1]
442 set auname [lrange $line 1 end-2]
443 } elseif {$tag == "committer"} {
444 set comdate [lindex $line end-1]
445 set comname [lrange $line 1 end-2]
1db95b00
PM
446 }
447 }
232475d3 448 set headline {}
43c25074
PM
449 # take the first non-blank line of the comment as the headline
450 set headline [string trimleft $comment]
451 set i [string first "\n" $headline]
232475d3 452 if {$i >= 0} {
43c25074
PM
453 set headline [string range $headline 0 $i]
454 }
455 set headline [string trimright $headline]
456 set i [string first "\r" $headline]
457 if {$i >= 0} {
458 set headline [string trimright [string range $headline 0 $i]]
232475d3
PM
459 }
460 if {!$listed} {
8974c6f9
TH
461 # git rev-list indents the comment by 4 spaces;
462 # if we got this via git cat-file, add the indentation
232475d3
PM
463 set newcomment {}
464 foreach line [split $comment "\n"] {
465 append newcomment " "
466 append newcomment $line
f6e2869f 467 append newcomment "\n"
232475d3
PM
468 }
469 set comment $newcomment
1db95b00
PM
470 }
471 if {$comdate != {}} {
cfb4563c 472 set cdate($id) $comdate
1db95b00 473 }
e5c2d856
PM
474 set commitinfo($id) [list $headline $auname $audate \
475 $comname $comdate $comment]
1db95b00
PM
476}
477
f7a3e8d2 478proc getcommit {id} {
79b2c75e 479 global commitdata commitinfo
8ed16484 480
f7a3e8d2
PM
481 if {[info exists commitdata($id)]} {
482 parsecommit $id $commitdata($id) 1
8ed16484
PM
483 } else {
484 readcommit $id
485 if {![info exists commitinfo($id)]} {
486 set commitinfo($id) {"No commit information available"}
8ed16484
PM
487 }
488 }
489 return 1
490}
491
887fe3c4 492proc readrefs {} {
62d3ea65 493 global tagids idtags headids idheads tagobjid
219ea3a9 494 global otherrefids idotherrefs mainhead mainheadid
106288cb 495
b5c2f306
SV
496 foreach v {tagids idtags headids idheads otherrefids idotherrefs} {
497 catch {unset $v}
498 }
62d3ea65
PM
499 set refd [open [list | git show-ref -d] r]
500 while {[gets $refd line] >= 0} {
501 if {[string index $line 40] ne " "} continue
502 set id [string range $line 0 39]
503 set ref [string range $line 41 end]
504 if {![string match "refs/*" $ref]} continue
505 set name [string range $ref 5 end]
506 if {[string match "remotes/*" $name]} {
507 if {![string match "*/HEAD" $name]} {
508 set headids($name) $id
509 lappend idheads($id) $name
f1d83ba3 510 }
62d3ea65
PM
511 } elseif {[string match "heads/*" $name]} {
512 set name [string range $name 6 end]
36a7cad6
JH
513 set headids($name) $id
514 lappend idheads($id) $name
62d3ea65
PM
515 } elseif {[string match "tags/*" $name]} {
516 # this lets refs/tags/foo^{} overwrite refs/tags/foo,
517 # which is what we want since the former is the commit ID
518 set name [string range $name 5 end]
519 if {[string match "*^{}" $name]} {
520 set name [string range $name 0 end-3]
521 } else {
522 set tagobjid($name) $id
523 }
524 set tagids($name) $id
525 lappend idtags($id) $name
36a7cad6
JH
526 } else {
527 set otherrefids($name) $id
528 lappend idotherrefs($id) $name
f1d83ba3
PM
529 }
530 }
062d671f 531 catch {close $refd}
8a48571c 532 set mainhead {}
219ea3a9 533 set mainheadid {}
8a48571c
PM
534 catch {
535 set thehead [exec git symbolic-ref HEAD]
536 if {[string match "refs/heads/*" $thehead]} {
537 set mainhead [string range $thehead 11 end]
219ea3a9
PM
538 if {[info exists headids($mainhead)]} {
539 set mainheadid $headids($mainhead)
540 }
8a48571c
PM
541 }
542 }
887fe3c4
PM
543}
544
8f489363
PM
545# skip over fake commits
546proc first_real_row {} {
547 global nullid nullid2 displayorder numcommits
548
549 for {set row 0} {$row < $numcommits} {incr row} {
550 set id [lindex $displayorder $row]
551 if {$id ne $nullid && $id ne $nullid2} {
552 break
553 }
554 }
555 return $row
556}
557
e11f1233
PM
558# update things for a head moved to a child of its previous location
559proc movehead {id name} {
560 global headids idheads
561
562 removehead $headids($name) $name
563 set headids($name) $id
564 lappend idheads($id) $name
565}
566
567# update things when a head has been removed
568proc removehead {id name} {
569 global headids idheads
570
571 if {$idheads($id) eq $name} {
572 unset idheads($id)
573 } else {
574 set i [lsearch -exact $idheads($id) $name]
575 if {$i >= 0} {
576 set idheads($id) [lreplace $idheads($id) $i $i]
577 }
578 }
579 unset headids($name)
580}
581
e54be9e3 582proc show_error {w top msg} {
df3d83b1
PM
583 message $w.m -text $msg -justify center -aspect 400
584 pack $w.m -side top -fill x -padx 20 -pady 20
e54be9e3 585 button $w.ok -text OK -command "destroy $top"
df3d83b1 586 pack $w.ok -side bottom -fill x
e54be9e3
PM
587 bind $top <Visibility> "grab $top; focus $top"
588 bind $top <Key-Return> "destroy $top"
589 tkwait window $top
df3d83b1
PM
590}
591
098dd8a3
PM
592proc error_popup msg {
593 set w .error
594 toplevel $w
595 wm transient $w .
e54be9e3 596 show_error $w $w $msg
098dd8a3
PM
597}
598
10299152
PM
599proc confirm_popup msg {
600 global confirm_ok
601 set confirm_ok 0
602 set w .confirm
603 toplevel $w
604 wm transient $w .
605 message $w.m -text $msg -justify center -aspect 400
606 pack $w.m -side top -fill x -padx 20 -pady 20
607 button $w.ok -text OK -command "set confirm_ok 1; destroy $w"
608 pack $w.ok -side left -fill x
609 button $w.cancel -text Cancel -command "destroy $w"
610 pack $w.cancel -side right -fill x
611 bind $w <Visibility> "grab $w; focus $w"
612 tkwait window $w
613 return $confirm_ok
614}
615
d94f8cd6 616proc makewindow {} {
fdedbcfb 617 global canv canv2 canv3 linespc charspc ctext cflist
9c311b32 618 global tabstop
b74fd579 619 global findtype findtypemenu findloc findstring fstring geometry
887fe3c4 620 global entries sha1entry sha1string sha1but
890fae70 621 global diffcontextstring diffcontext
94a2eede 622 global maincursor textcursor curtextcursor
219ea3a9 623 global rowctxmenu fakerowmenu mergemax wrapcomment
60f7a7dc 624 global highlight_files gdttype
3ea06f9f 625 global searchstring sstring
60378c0c 626 global bgcolor fgcolor bglist fglist diffcolors selectbgcolor
bb3edc8b
PM
627 global headctxmenu progresscanv progressitem progresscoords statusw
628 global fprogitem fprogcoord lastprogupdate progupdatepending
a137a90f 629 global rprogitem rprogcoord
32f1b3e4 630 global have_tk85
9a40c50c
PM
631
632 menu .bar
633 .bar add cascade -label "File" -menu .bar.file
9c311b32 634 .bar configure -font uifont
9a40c50c 635 menu .bar.file
50b44ece 636 .bar.file add command -label "Update" -command updatecommits
f1d83ba3 637 .bar.file add command -label "Reread references" -command rereadrefs
887c996e 638 .bar.file add command -label "List references" -command showrefs
1d10f36d 639 .bar.file add command -label "Quit" -command doquit
9c311b32 640 .bar.file configure -font uifont
712fcc08
PM
641 menu .bar.edit
642 .bar add cascade -label "Edit" -menu .bar.edit
643 .bar.edit add command -label "Preferences" -command doprefs
9c311b32 644 .bar.edit configure -font uifont
da7c24dd 645
9c311b32 646 menu .bar.view -font uifont
50b44ece 647 .bar add cascade -label "View" -menu .bar.view
da7c24dd
PM
648 .bar.view add command -label "New view..." -command {newview 0}
649 .bar.view add command -label "Edit view..." -command editview \
650 -state disabled
50b44ece
PM
651 .bar.view add command -label "Delete view" -command delview -state disabled
652 .bar.view add separator
a90a6d24
PM
653 .bar.view add radiobutton -label "All files" -command {showview 0} \
654 -variable selectedview -value 0
40b87ff8 655
9a40c50c
PM
656 menu .bar.help
657 .bar add cascade -label "Help" -menu .bar.help
658 .bar.help add command -label "About gitk" -command about
4e95e1f7 659 .bar.help add command -label "Key bindings" -command keys
9c311b32 660 .bar.help configure -font uifont
9a40c50c
PM
661 . configure -menu .bar
662
e9937d2a 663 # the gui has upper and lower half, parts of a paned window.
0327d27a 664 panedwindow .ctop -orient vertical
e9937d2a
JH
665
666 # possibly use assumed geometry
9ca72f4f 667 if {![info exists geometry(pwsash0)]} {
e9937d2a
JH
668 set geometry(topheight) [expr {15 * $linespc}]
669 set geometry(topwidth) [expr {80 * $charspc}]
670 set geometry(botheight) [expr {15 * $linespc}]
671 set geometry(botwidth) [expr {50 * $charspc}]
9ca72f4f
ML
672 set geometry(pwsash0) "[expr {40 * $charspc}] 2"
673 set geometry(pwsash1) "[expr {60 * $charspc}] 2"
e9937d2a
JH
674 }
675
676 # the upper half will have a paned window, a scroll bar to the right, and some stuff below
677 frame .tf -height $geometry(topheight) -width $geometry(topwidth)
678 frame .tf.histframe
679 panedwindow .tf.histframe.pwclist -orient horizontal -sashpad 0 -handlesize 4
680
681 # create three canvases
682 set cscroll .tf.histframe.csb
683 set canv .tf.histframe.pwclist.canv
9ca72f4f 684 canvas $canv \
60378c0c 685 -selectbackground $selectbgcolor \
f8a2c0d1 686 -background $bgcolor -bd 0 \
9f1afe05 687 -yscrollincr $linespc -yscrollcommand "scrollcanv $cscroll"
e9937d2a
JH
688 .tf.histframe.pwclist add $canv
689 set canv2 .tf.histframe.pwclist.canv2
9ca72f4f 690 canvas $canv2 \
60378c0c 691 -selectbackground $selectbgcolor \
f8a2c0d1 692 -background $bgcolor -bd 0 -yscrollincr $linespc
e9937d2a
JH
693 .tf.histframe.pwclist add $canv2
694 set canv3 .tf.histframe.pwclist.canv3
9ca72f4f 695 canvas $canv3 \
60378c0c 696 -selectbackground $selectbgcolor \
f8a2c0d1 697 -background $bgcolor -bd 0 -yscrollincr $linespc
e9937d2a 698 .tf.histframe.pwclist add $canv3
9ca72f4f
ML
699 eval .tf.histframe.pwclist sash place 0 $geometry(pwsash0)
700 eval .tf.histframe.pwclist sash place 1 $geometry(pwsash1)
e9937d2a
JH
701
702 # a scroll bar to rule them
703 scrollbar $cscroll -command {allcanvs yview} -highlightthickness 0
704 pack $cscroll -side right -fill y
705 bind .tf.histframe.pwclist <Configure> {resizeclistpanes %W %w}
f8a2c0d1 706 lappend bglist $canv $canv2 $canv3
e9937d2a 707 pack .tf.histframe.pwclist -fill both -expand 1 -side left
98f350e5 708
e9937d2a
JH
709 # we have two button bars at bottom of top frame. Bar 1
710 frame .tf.bar
711 frame .tf.lbar -height 15
712
713 set sha1entry .tf.bar.sha1
887fe3c4 714 set entries $sha1entry
e9937d2a 715 set sha1but .tf.bar.sha1label
887fe3c4 716 button $sha1but -text "SHA1 ID: " -state disabled -relief flat \
9c311b32 717 -command gotocommit -width 8 -font uifont
887fe3c4 718 $sha1but conf -disabledforeground [$sha1but cget -foreground]
e9937d2a 719 pack .tf.bar.sha1label -side left
9c311b32 720 entry $sha1entry -width 40 -font textfont -textvariable sha1string
887fe3c4 721 trace add variable sha1string write sha1change
98f350e5 722 pack $sha1entry -side left -pady 2
d698206c
PM
723
724 image create bitmap bm-left -data {
725 #define left_width 16
726 #define left_height 16
727 static unsigned char left_bits[] = {
728 0x00, 0x00, 0xc0, 0x01, 0xe0, 0x00, 0x70, 0x00, 0x38, 0x00, 0x1c, 0x00,
729 0x0e, 0x00, 0xff, 0x7f, 0xff, 0x7f, 0xff, 0x7f, 0x0e, 0x00, 0x1c, 0x00,
730 0x38, 0x00, 0x70, 0x00, 0xe0, 0x00, 0xc0, 0x01};
731 }
732 image create bitmap bm-right -data {
733 #define right_width 16
734 #define right_height 16
735 static unsigned char right_bits[] = {
736 0x00, 0x00, 0xc0, 0x01, 0x80, 0x03, 0x00, 0x07, 0x00, 0x0e, 0x00, 0x1c,
737 0x00, 0x38, 0xff, 0x7f, 0xff, 0x7f, 0xff, 0x7f, 0x00, 0x38, 0x00, 0x1c,
738 0x00, 0x0e, 0x00, 0x07, 0x80, 0x03, 0xc0, 0x01};
739 }
e9937d2a 740 button .tf.bar.leftbut -image bm-left -command goback \
d698206c 741 -state disabled -width 26
e9937d2a
JH
742 pack .tf.bar.leftbut -side left -fill y
743 button .tf.bar.rightbut -image bm-right -command goforw \
d698206c 744 -state disabled -width 26
e9937d2a 745 pack .tf.bar.rightbut -side left -fill y
d698206c 746
bb3edc8b
PM
747 # Status label and progress bar
748 set statusw .tf.bar.status
9c311b32 749 label $statusw -width 15 -relief sunken -font uifont
bb3edc8b 750 pack $statusw -side left -padx 5
9c311b32 751 set h [expr {[font metrics uifont -linespace] + 2}]
bb3edc8b
PM
752 set progresscanv .tf.bar.progress
753 canvas $progresscanv -relief sunken -height $h -borderwidth 2
754 set progressitem [$progresscanv create rect -1 0 0 $h -fill green]
755 set fprogitem [$progresscanv create rect -1 0 0 $h -fill yellow]
a137a90f 756 set rprogitem [$progresscanv create rect -1 0 0 $h -fill red]
bb3edc8b
PM
757 pack $progresscanv -side right -expand 1 -fill x
758 set progresscoords {0 0}
759 set fprogcoord 0
a137a90f 760 set rprogcoord 0
bb3edc8b
PM
761 bind $progresscanv <Configure> adjustprogress
762 set lastprogupdate [clock clicks -milliseconds]
763 set progupdatepending 0
764
687c8765 765 # build up the bottom bar of upper window
9c311b32 766 label .tf.lbar.flabel -text "Find " -font uifont
cca5d946
PM
767 button .tf.lbar.fnext -text "next" -command {dofind 1 1} -font uifont
768 button .tf.lbar.fprev -text "prev" -command {dofind -1 1} -font uifont
9c311b32 769 label .tf.lbar.flab2 -text " commit " -font uifont
687c8765
PM
770 pack .tf.lbar.flabel .tf.lbar.fnext .tf.lbar.fprev .tf.lbar.flab2 \
771 -side left -fill y
772 set gdttype "containing:"
773 set gm [tk_optionMenu .tf.lbar.gdttype gdttype \
774 "containing:" \
775 "touching paths:" \
776 "adding/removing string:"]
777 trace add variable gdttype write gdttype_change
9c311b32
PM
778 $gm conf -font uifont
779 .tf.lbar.gdttype conf -font uifont
687c8765
PM
780 pack .tf.lbar.gdttype -side left -fill y
781
98f350e5 782 set findstring {}
687c8765 783 set fstring .tf.lbar.findstring
887fe3c4 784 lappend entries $fstring
9c311b32 785 entry $fstring -width 30 -font textfont -textvariable findstring
60f7a7dc 786 trace add variable findstring write find_change
98f350e5 787 set findtype Exact
687c8765 788 set findtypemenu [tk_optionMenu .tf.lbar.findtype \
e9937d2a 789 findtype Exact IgnCase Regexp]
687c8765 790 trace add variable findtype write findcom_change
9c311b32
PM
791 .tf.lbar.findtype configure -font uifont
792 .tf.lbar.findtype.menu configure -font uifont
98f350e5 793 set findloc "All fields"
687c8765 794 tk_optionMenu .tf.lbar.findloc findloc "All fields" Headline \
60f7a7dc
PM
795 Comments Author Committer
796 trace add variable findloc write find_change
9c311b32
PM
797 .tf.lbar.findloc configure -font uifont
798 .tf.lbar.findloc.menu configure -font uifont
687c8765
PM
799 pack .tf.lbar.findloc -side right
800 pack .tf.lbar.findtype -side right
801 pack $fstring -side left -expand 1 -fill x
e9937d2a
JH
802
803 # Finish putting the upper half of the viewer together
804 pack .tf.lbar -in .tf -side bottom -fill x
805 pack .tf.bar -in .tf -side bottom -fill x
806 pack .tf.histframe -fill both -side top -expand 1
807 .ctop add .tf
9ca72f4f
ML
808 .ctop paneconfigure .tf -height $geometry(topheight)
809 .ctop paneconfigure .tf -width $geometry(topwidth)
e9937d2a
JH
810
811 # now build up the bottom
812 panedwindow .pwbottom -orient horizontal
813
814 # lower left, a text box over search bar, scroll bar to the right
815 # if we know window height, then that will set the lower text height, otherwise
816 # we set lower text height which will drive window height
817 if {[info exists geometry(main)]} {
818 frame .bleft -width $geometry(botwidth)
819 } else {
820 frame .bleft -width $geometry(botwidth) -height $geometry(botheight)
821 }
822 frame .bleft.top
a8d610a2 823 frame .bleft.mid
e9937d2a
JH
824
825 button .bleft.top.search -text "Search" -command dosearch \
9c311b32 826 -font uifont
e9937d2a
JH
827 pack .bleft.top.search -side left -padx 5
828 set sstring .bleft.top.sstring
9c311b32 829 entry $sstring -width 20 -font textfont -textvariable searchstring
3ea06f9f
PM
830 lappend entries $sstring
831 trace add variable searchstring write incrsearch
832 pack $sstring -side left -expand 1 -fill x
7388bcbc 833 radiobutton .bleft.mid.diff -text "Diff" -font uifont \
a8d610a2 834 -command changediffdisp -variable diffelide -value {0 0}
7388bcbc 835 radiobutton .bleft.mid.old -text "Old version" -font uifont \
a8d610a2 836 -command changediffdisp -variable diffelide -value {0 1}
7388bcbc 837 radiobutton .bleft.mid.new -text "New version" -font uifont \
a8d610a2 838 -command changediffdisp -variable diffelide -value {1 0}
890fae70 839 label .bleft.mid.labeldiffcontext -text " Lines of context: " \
9c311b32 840 -font uifont
a8d610a2 841 pack .bleft.mid.diff .bleft.mid.old .bleft.mid.new -side left
9c311b32 842 spinbox .bleft.mid.diffcontext -width 5 -font textfont \
890fae70
SP
843 -from 1 -increment 1 -to 10000000 \
844 -validate all -validatecommand "diffcontextvalidate %P" \
845 -textvariable diffcontextstring
846 .bleft.mid.diffcontext set $diffcontext
847 trace add variable diffcontextstring write diffcontextchange
848 lappend entries .bleft.mid.diffcontext
849 pack .bleft.mid.labeldiffcontext .bleft.mid.diffcontext -side left
e9937d2a 850 set ctext .bleft.ctext
f8a2c0d1 851 text $ctext -background $bgcolor -foreground $fgcolor \
9c311b32 852 -state disabled -font textfont \
3ea06f9f 853 -yscrollcommand scrolltext -wrap none
32f1b3e4
PM
854 if {$have_tk85} {
855 $ctext conf -tabstyle wordprocessor
856 }
e9937d2a
JH
857 scrollbar .bleft.sb -command "$ctext yview"
858 pack .bleft.top -side top -fill x
a8d610a2 859 pack .bleft.mid -side top -fill x
e9937d2a 860 pack .bleft.sb -side right -fill y
d2610d11 861 pack $ctext -side left -fill both -expand 1
f8a2c0d1
PM
862 lappend bglist $ctext
863 lappend fglist $ctext
d2610d11 864
f1b86294 865 $ctext tag conf comment -wrap $wrapcomment
9c311b32 866 $ctext tag conf filesep -font textfontbold -back "#aaaaaa"
f8a2c0d1
PM
867 $ctext tag conf hunksep -fore [lindex $diffcolors 2]
868 $ctext tag conf d0 -fore [lindex $diffcolors 0]
869 $ctext tag conf d1 -fore [lindex $diffcolors 1]
712fcc08
PM
870 $ctext tag conf m0 -fore red
871 $ctext tag conf m1 -fore blue
872 $ctext tag conf m2 -fore green
873 $ctext tag conf m3 -fore purple
874 $ctext tag conf m4 -fore brown
b77b0278
PM
875 $ctext tag conf m5 -fore "#009090"
876 $ctext tag conf m6 -fore magenta
877 $ctext tag conf m7 -fore "#808000"
878 $ctext tag conf m8 -fore "#009000"
879 $ctext tag conf m9 -fore "#ff0080"
880 $ctext tag conf m10 -fore cyan
881 $ctext tag conf m11 -fore "#b07070"
882 $ctext tag conf m12 -fore "#70b0f0"
883 $ctext tag conf m13 -fore "#70f0b0"
884 $ctext tag conf m14 -fore "#f0b070"
885 $ctext tag conf m15 -fore "#ff70b0"
712fcc08 886 $ctext tag conf mmax -fore darkgrey
b77b0278 887 set mergemax 16
9c311b32
PM
888 $ctext tag conf mresult -font textfontbold
889 $ctext tag conf msep -font textfontbold
712fcc08 890 $ctext tag conf found -back yellow
e5c2d856 891
e9937d2a 892 .pwbottom add .bleft
9ca72f4f 893 .pwbottom paneconfigure .bleft -width $geometry(botwidth)
e9937d2a
JH
894
895 # lower right
896 frame .bright
897 frame .bright.mode
898 radiobutton .bright.mode.patch -text "Patch" \
f8b28a40 899 -command reselectline -variable cmitmode -value "patch"
9c311b32 900 .bright.mode.patch configure -font uifont
e9937d2a 901 radiobutton .bright.mode.tree -text "Tree" \
f8b28a40 902 -command reselectline -variable cmitmode -value "tree"
9c311b32 903 .bright.mode.tree configure -font uifont
e9937d2a
JH
904 grid .bright.mode.patch .bright.mode.tree -sticky ew
905 pack .bright.mode -side top -fill x
906 set cflist .bright.cfiles
9c311b32 907 set indent [font measure mainfont "nn"]
e9937d2a 908 text $cflist \
60378c0c 909 -selectbackground $selectbgcolor \
f8a2c0d1 910 -background $bgcolor -foreground $fgcolor \
9c311b32 911 -font mainfont \
7fcceed7 912 -tabs [list $indent [expr {2 * $indent}]] \
e9937d2a 913 -yscrollcommand ".bright.sb set" \
7fcceed7
PM
914 -cursor [. cget -cursor] \
915 -spacing1 1 -spacing3 1
f8a2c0d1
PM
916 lappend bglist $cflist
917 lappend fglist $cflist
e9937d2a
JH
918 scrollbar .bright.sb -command "$cflist yview"
919 pack .bright.sb -side right -fill y
d2610d11 920 pack $cflist -side left -fill both -expand 1
89b11d3b
PM
921 $cflist tag configure highlight \
922 -background [$cflist cget -selectbackground]
9c311b32 923 $cflist tag configure bold -font mainfontbold
d2610d11 924
e9937d2a
JH
925 .pwbottom add .bright
926 .ctop add .pwbottom
1db95b00 927
e9937d2a
JH
928 # restore window position if known
929 if {[info exists geometry(main)]} {
930 wm geometry . "$geometry(main)"
931 }
932
d23d98d3
SP
933 if {[tk windowingsystem] eq {aqua}} {
934 set M1B M1
935 } else {
936 set M1B Control
937 }
938
e9937d2a
JH
939 bind .pwbottom <Configure> {resizecdetpanes %W %w}
940 pack .ctop -fill both -expand 1
c8dfbcf9
PM
941 bindall <1> {selcanvline %W %x %y}
942 #bindall <B1-Motion> {selcanvline %W %x %y}
314c3093
ML
943 if {[tk windowingsystem] == "win32"} {
944 bind . <MouseWheel> { windows_mousewheel_redirector %W %X %Y %D }
945 bind $ctext <MouseWheel> { windows_mousewheel_redirector %W %X %Y %D ; break }
946 } else {
947 bindall <ButtonRelease-4> "allcanvs yview scroll -5 units"
948 bindall <ButtonRelease-5> "allcanvs yview scroll 5 units"
5dd57d51
JS
949 if {[tk windowingsystem] eq "aqua"} {
950 bindall <MouseWheel> {
951 set delta [expr {- (%D)}]
952 allcanvs yview scroll $delta units
953 }
954 }
314c3093 955 }
be0cd098
PM
956 bindall <2> "canvscan mark %W %x %y"
957 bindall <B2-Motion> "canvscan dragto %W %x %y"
6e5f7203
RN
958 bindkey <Home> selfirstline
959 bindkey <End> sellastline
17386066
PM
960 bind . <Key-Up> "selnextline -1"
961 bind . <Key-Down> "selnextline 1"
cca5d946
PM
962 bind . <Shift-Key-Up> "dofind -1 0"
963 bind . <Shift-Key-Down> "dofind 1 0"
6e5f7203
RN
964 bindkey <Key-Right> "goforw"
965 bindkey <Key-Left> "goback"
966 bind . <Key-Prior> "selnextpage -1"
967 bind . <Key-Next> "selnextpage 1"
d23d98d3
SP
968 bind . <$M1B-Home> "allcanvs yview moveto 0.0"
969 bind . <$M1B-End> "allcanvs yview moveto 1.0"
970 bind . <$M1B-Key-Up> "allcanvs yview scroll -1 units"
971 bind . <$M1B-Key-Down> "allcanvs yview scroll 1 units"
972 bind . <$M1B-Key-Prior> "allcanvs yview scroll -1 pages"
973 bind . <$M1B-Key-Next> "allcanvs yview scroll 1 pages"
cfb4563c
PM
974 bindkey <Key-Delete> "$ctext yview scroll -1 pages"
975 bindkey <Key-BackSpace> "$ctext yview scroll -1 pages"
976 bindkey <Key-space> "$ctext yview scroll 1 pages"
df3d83b1
PM
977 bindkey p "selnextline -1"
978 bindkey n "selnextline 1"
6e2dda35
RS
979 bindkey z "goback"
980 bindkey x "goforw"
981 bindkey i "selnextline -1"
982 bindkey k "selnextline 1"
983 bindkey j "goback"
984 bindkey l "goforw"
cfb4563c
PM
985 bindkey b "$ctext yview scroll -1 pages"
986 bindkey d "$ctext yview scroll 18 units"
987 bindkey u "$ctext yview scroll -18 units"
cca5d946
PM
988 bindkey / {dofind 1 1}
989 bindkey <Key-Return> {dofind 1 1}
990 bindkey ? {dofind -1 1}
39ad8570 991 bindkey f nextfile
e7a09191 992 bindkey <F5> updatecommits
d23d98d3 993 bind . <$M1B-q> doquit
cca5d946
PM
994 bind . <$M1B-f> {dofind 1 1}
995 bind . <$M1B-g> {dofind 1 0}
d23d98d3
SP
996 bind . <$M1B-r> dosearchback
997 bind . <$M1B-s> dosearch
998 bind . <$M1B-equal> {incrfont 1}
999 bind . <$M1B-KP_Add> {incrfont 1}
1000 bind . <$M1B-minus> {incrfont -1}
1001 bind . <$M1B-KP_Subtract> {incrfont -1}
b6047c5a 1002 wm protocol . WM_DELETE_WINDOW doquit
df3d83b1 1003 bind . <Button-1> "click %W"
cca5d946 1004 bind $fstring <Key-Return> {dofind 1 1}
887fe3c4 1005 bind $sha1entry <Key-Return> gotocommit
ee3dc72e 1006 bind $sha1entry <<PasteSelection>> clearsha1
7fcceed7
PM
1007 bind $cflist <1> {sel_flist %W %x %y; break}
1008 bind $cflist <B1-Motion> {sel_flist %W %x %y; break}
f8b28a40 1009 bind $cflist <ButtonRelease-1> {treeclick %W %x %y}
3244729a 1010 bind $cflist <Button-3> {pop_flist_menu %W %X %Y %x %y}
ea13cba1
PM
1011
1012 set maincursor [. cget -cursor]
1013 set textcursor [$ctext cget -cursor]
94a2eede 1014 set curtextcursor $textcursor
84ba7345 1015
c8dfbcf9
PM
1016 set rowctxmenu .rowctxmenu
1017 menu $rowctxmenu -tearoff 0
1018 $rowctxmenu add command -label "Diff this -> selected" \
1019 -command {diffvssel 0}
1020 $rowctxmenu add command -label "Diff selected -> this" \
1021 -command {diffvssel 1}
74daedb6 1022 $rowctxmenu add command -label "Make patch" -command mkpatch
bdbfbe3d 1023 $rowctxmenu add command -label "Create tag" -command mktag
4a2139f5 1024 $rowctxmenu add command -label "Write commit to file" -command writecommit
d6ac1a86 1025 $rowctxmenu add command -label "Create new branch" -command mkbranch
ca6d8f58
PM
1026 $rowctxmenu add command -label "Cherry-pick this commit" \
1027 -command cherrypick
6fb735ae
PM
1028 $rowctxmenu add command -label "Reset HEAD branch to here" \
1029 -command resethead
10299152 1030
219ea3a9
PM
1031 set fakerowmenu .fakerowmenu
1032 menu $fakerowmenu -tearoff 0
1033 $fakerowmenu add command -label "Diff this -> selected" \
1034 -command {diffvssel 0}
1035 $fakerowmenu add command -label "Diff selected -> this" \
1036 -command {diffvssel 1}
1037 $fakerowmenu add command -label "Make patch" -command mkpatch
1038# $fakerowmenu add command -label "Commit" -command {mkcommit 0}
1039# $fakerowmenu add command -label "Commit all" -command {mkcommit 1}
1040# $fakerowmenu add command -label "Revert local changes" -command revertlocal
1041
10299152
PM
1042 set headctxmenu .headctxmenu
1043 menu $headctxmenu -tearoff 0
1044 $headctxmenu add command -label "Check out this branch" \
1045 -command cobranch
1046 $headctxmenu add command -label "Remove this branch" \
1047 -command rmbranch
3244729a
PM
1048
1049 global flist_menu
1050 set flist_menu .flistctxmenu
1051 menu $flist_menu -tearoff 0
1052 $flist_menu add command -label "Highlight this too" \
1053 -command {flist_hl 0}
1054 $flist_menu add command -label "Highlight this only" \
1055 -command {flist_hl 1}
df3d83b1
PM
1056}
1057
314c3093
ML
1058# Windows sends all mouse wheel events to the current focused window, not
1059# the one where the mouse hovers, so bind those events here and redirect
1060# to the correct window
1061proc windows_mousewheel_redirector {W X Y D} {
1062 global canv canv2 canv3
1063 set w [winfo containing -displayof $W $X $Y]
1064 if {$w ne ""} {
1065 set u [expr {$D < 0 ? 5 : -5}]
1066 if {$w == $canv || $w == $canv2 || $w == $canv3} {
1067 allcanvs yview scroll $u units
1068 } else {
1069 catch {
1070 $w yview scroll $u units
1071 }
1072 }
1073 }
1074}
1075
be0cd098
PM
1076# mouse-2 makes all windows scan vertically, but only the one
1077# the cursor is in scans horizontally
1078proc canvscan {op w x y} {
1079 global canv canv2 canv3
1080 foreach c [list $canv $canv2 $canv3] {
1081 if {$c == $w} {
1082 $c scan $op $x $y
1083 } else {
1084 $c scan $op 0 $y
1085 }
1086 }
1087}
1088
9f1afe05
PM
1089proc scrollcanv {cscroll f0 f1} {
1090 $cscroll set $f0 $f1
1091 drawfrac $f0 $f1
908c3585 1092 flushhighlights
9f1afe05
PM
1093}
1094
df3d83b1
PM
1095# when we make a key binding for the toplevel, make sure
1096# it doesn't get triggered when that key is pressed in the
1097# find string entry widget.
1098proc bindkey {ev script} {
887fe3c4 1099 global entries
df3d83b1
PM
1100 bind . $ev $script
1101 set escript [bind Entry $ev]
1102 if {$escript == {}} {
1103 set escript [bind Entry <Key>]
1104 }
887fe3c4
PM
1105 foreach e $entries {
1106 bind $e $ev "$escript; break"
1107 }
df3d83b1
PM
1108}
1109
1110# set the focus back to the toplevel for any click outside
887fe3c4 1111# the entry widgets
df3d83b1 1112proc click {w} {
bd441de4
ML
1113 global ctext entries
1114 foreach e [concat $entries $ctext] {
887fe3c4 1115 if {$w == $e} return
df3d83b1 1116 }
887fe3c4 1117 focus .
0fba86b3
PM
1118}
1119
bb3edc8b
PM
1120# Adjust the progress bar for a change in requested extent or canvas size
1121proc adjustprogress {} {
1122 global progresscanv progressitem progresscoords
1123 global fprogitem fprogcoord lastprogupdate progupdatepending
a137a90f 1124 global rprogitem rprogcoord
bb3edc8b
PM
1125
1126 set w [expr {[winfo width $progresscanv] - 4}]
1127 set x0 [expr {$w * [lindex $progresscoords 0]}]
1128 set x1 [expr {$w * [lindex $progresscoords 1]}]
1129 set h [winfo height $progresscanv]
1130 $progresscanv coords $progressitem $x0 0 $x1 $h
1131 $progresscanv coords $fprogitem 0 0 [expr {$w * $fprogcoord}] $h
a137a90f 1132 $progresscanv coords $rprogitem 0 0 [expr {$w * $rprogcoord}] $h
bb3edc8b
PM
1133 set now [clock clicks -milliseconds]
1134 if {$now >= $lastprogupdate + 100} {
1135 set progupdatepending 0
1136 update
1137 } elseif {!$progupdatepending} {
1138 set progupdatepending 1
1139 after [expr {$lastprogupdate + 100 - $now}] doprogupdate
1140 }
1141}
1142
1143proc doprogupdate {} {
1144 global lastprogupdate progupdatepending
1145
1146 if {$progupdatepending} {
1147 set progupdatepending 0
1148 set lastprogupdate [clock clicks -milliseconds]
1149 update
1150 }
1151}
1152
0fba86b3 1153proc savestuff {w} {
32f1b3e4 1154 global canv canv2 canv3 mainfont textfont uifont tabstop
712fcc08 1155 global stuffsaved findmergefiles maxgraphpct
219ea3a9 1156 global maxwidth showneartags showlocalchanges
098dd8a3 1157 global viewname viewfiles viewargs viewperm nextviewnum
7a39a17a 1158 global cmitmode wrapcomment datetimeformat limitdiffs
890fae70 1159 global colors bgcolor fgcolor diffcolors diffcontext selectbgcolor
4ef17537 1160
0fba86b3 1161 if {$stuffsaved} return
df3d83b1 1162 if {![winfo viewable .]} return
0fba86b3
PM
1163 catch {
1164 set f [open "~/.gitk-new" w]
f0654861
PM
1165 puts $f [list set mainfont $mainfont]
1166 puts $f [list set textfont $textfont]
4840be66 1167 puts $f [list set uifont $uifont]
7e12f1a6 1168 puts $f [list set tabstop $tabstop]
f0654861 1169 puts $f [list set findmergefiles $findmergefiles]
8d858d1a 1170 puts $f [list set maxgraphpct $maxgraphpct]
04c13d38 1171 puts $f [list set maxwidth $maxwidth]
f8b28a40 1172 puts $f [list set cmitmode $cmitmode]
f1b86294 1173 puts $f [list set wrapcomment $wrapcomment]
b8ab2e17 1174 puts $f [list set showneartags $showneartags]
219ea3a9 1175 puts $f [list set showlocalchanges $showlocalchanges]
e8b5f4be 1176 puts $f [list set datetimeformat $datetimeformat]
7a39a17a 1177 puts $f [list set limitdiffs $limitdiffs]
f8a2c0d1
PM
1178 puts $f [list set bgcolor $bgcolor]
1179 puts $f [list set fgcolor $fgcolor]
1180 puts $f [list set colors $colors]
1181 puts $f [list set diffcolors $diffcolors]
890fae70 1182 puts $f [list set diffcontext $diffcontext]
60378c0c 1183 puts $f [list set selectbgcolor $selectbgcolor]
e9937d2a 1184
b6047c5a 1185 puts $f "set geometry(main) [wm geometry .]"
e9937d2a
JH
1186 puts $f "set geometry(topwidth) [winfo width .tf]"
1187 puts $f "set geometry(topheight) [winfo height .tf]"
9ca72f4f
ML
1188 puts $f "set geometry(pwsash0) \"[.tf.histframe.pwclist sash coord 0]\""
1189 puts $f "set geometry(pwsash1) \"[.tf.histframe.pwclist sash coord 1]\""
e9937d2a
JH
1190 puts $f "set geometry(botwidth) [winfo width .bleft]"
1191 puts $f "set geometry(botheight) [winfo height .bleft]"
1192
a90a6d24
PM
1193 puts -nonewline $f "set permviews {"
1194 for {set v 0} {$v < $nextviewnum} {incr v} {
1195 if {$viewperm($v)} {
098dd8a3 1196 puts $f "{[list $viewname($v) $viewfiles($v) $viewargs($v)]}"
a90a6d24
PM
1197 }
1198 }
1199 puts $f "}"
0fba86b3
PM
1200 close $f
1201 file rename -force "~/.gitk-new" "~/.gitk"
1202 }
1203 set stuffsaved 1
1db95b00
PM
1204}
1205
43bddeb4
PM
1206proc resizeclistpanes {win w} {
1207 global oldwidth
418c4c7b 1208 if {[info exists oldwidth($win)]} {
43bddeb4
PM
1209 set s0 [$win sash coord 0]
1210 set s1 [$win sash coord 1]
1211 if {$w < 60} {
1212 set sash0 [expr {int($w/2 - 2)}]
1213 set sash1 [expr {int($w*5/6 - 2)}]
1214 } else {
1215 set factor [expr {1.0 * $w / $oldwidth($win)}]
1216 set sash0 [expr {int($factor * [lindex $s0 0])}]
1217 set sash1 [expr {int($factor * [lindex $s1 0])}]
1218 if {$sash0 < 30} {
1219 set sash0 30
1220 }
1221 if {$sash1 < $sash0 + 20} {
2ed49d54 1222 set sash1 [expr {$sash0 + 20}]
43bddeb4
PM
1223 }
1224 if {$sash1 > $w - 10} {
2ed49d54 1225 set sash1 [expr {$w - 10}]
43bddeb4 1226 if {$sash0 > $sash1 - 20} {
2ed49d54 1227 set sash0 [expr {$sash1 - 20}]
43bddeb4
PM
1228 }
1229 }
1230 }
1231 $win sash place 0 $sash0 [lindex $s0 1]
1232 $win sash place 1 $sash1 [lindex $s1 1]
1233 }
1234 set oldwidth($win) $w
1235}
1236
1237proc resizecdetpanes {win w} {
1238 global oldwidth
418c4c7b 1239 if {[info exists oldwidth($win)]} {
43bddeb4
PM
1240 set s0 [$win sash coord 0]
1241 if {$w < 60} {
1242 set sash0 [expr {int($w*3/4 - 2)}]
1243 } else {
1244 set factor [expr {1.0 * $w / $oldwidth($win)}]
1245 set sash0 [expr {int($factor * [lindex $s0 0])}]
1246 if {$sash0 < 45} {
1247 set sash0 45
1248 }
1249 if {$sash0 > $w - 15} {
2ed49d54 1250 set sash0 [expr {$w - 15}]
43bddeb4
PM
1251 }
1252 }
1253 $win sash place 0 $sash0 [lindex $s0 1]
1254 }
1255 set oldwidth($win) $w
1256}
1257
b5721c72
PM
1258proc allcanvs args {
1259 global canv canv2 canv3
1260 eval $canv $args
1261 eval $canv2 $args
1262 eval $canv3 $args
1263}
1264
1265proc bindall {event action} {
1266 global canv canv2 canv3
1267 bind $canv $event $action
1268 bind $canv2 $event $action
1269 bind $canv3 $event $action
1270}
1271
9a40c50c 1272proc about {} {
d59c4b6f 1273 global uifont
9a40c50c
PM
1274 set w .about
1275 if {[winfo exists $w]} {
1276 raise $w
1277 return
1278 }
1279 toplevel $w
1280 wm title $w "About gitk"
1281 message $w.m -text {
9f1afe05 1282Gitk - a commit viewer for git
9a40c50c 1283
9f1afe05 1284