Commit | Line | Data |
---|---|---|
1db95b00 PM |
1 | #!/bin/sh |
2 | # Tcl ignores the next line -*- tcl -*- \ | |
9e026d39 | 3 | exec 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 |
10 | proc 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. | |
24 | proc 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 | ||
36 | proc filerun {fd script} { | |
37 | fileevent $fd readable [list filereadable $fd $script] | |
38 | } | |
39 | ||
40 | proc 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 | ||
50 | proc 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 | 82 | proc 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 | 122 | proc 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 | 135 | proc 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 | |
146 | proc 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 | 157 | proc 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 | 357 | proc 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 | ||
387 | proc 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 | 392 | proc 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 | 421 | proc 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 | 478 | proc 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 | 492 | proc 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 |
546 | proc 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 |
559 | proc 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 | |
568 | proc 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 | 582 | proc 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 |
592 | proc 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 |
599 | proc 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 | 616 | proc 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 | |
1061 | proc 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 | |
1078 | proc 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 |
1089 | proc 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. | |
1098 | proc 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 | 1112 | proc 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 |
1121 | proc 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 | ||
1143 | proc 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 | 1153 | proc 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 |
1206 | proc 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 | ||
1237 | proc 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 |
1258 | proc allcanvs args { |
1259 | global canv canv2 canv3 | |
1260 | eval $canv $args | |
1261 | eval $canv2 $args | |
1262 | eval $canv3 $args | |
1263 | } | |
1264 | ||
1265 | proc 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 | 1272 | proc 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 | 1282 | Gitk - a commit viewer for git |
9a40c50c | 1283 | |
9f1afe05 | 1284 |