blob: 087c4ac733be4b788751d0bae5b7aad22ce0dd99 [file] [log] [blame]
Paul Mackerras1db95b02005-05-09 04:08:39 +00001#!/bin/sh
2# Tcl ignores the next line -*- tcl -*- \
Paul Mackerras9e026d32005-09-27 10:29:41 +10003exec wish "$0" -- "$@"
Paul Mackerras1db95b02005-05-09 04:08:39 +00004
Paul Mackerrasee66e082008-05-09 10:14:07 +10005# Copyright © 2005-2008 Paul Mackerras. All rights reserved.
Paul Mackerras1db95b02005-05-09 04:08:39 +00006# 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
Junio C Hamano73b6a6c2005-07-28 00:28:44 -070010proc gitdir {} {
11 global env
12 if {[info exists env(GIT_DIR)]} {
13 return $env(GIT_DIR)
14 } else {
Peter Baumann5024baa2007-01-09 15:30:19 +010015 return [exec git rev-parse --git-dir]
Junio C Hamano73b6a6c2005-07-28 00:28:44 -070016 }
17}
18
Paul Mackerras7eb3cb92007-06-17 14:45:00 +100019# 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 {
Alexander Gavrilovdf75e862008-08-09 14:41:50 +040025 global isonrunq runq currunq
Paul Mackerras7eb3cb92007-06-17 14:45:00 +100026
27 set script $args
28 if {[info exists isonrunq($script)]} return
Alexander Gavrilovdf75e862008-08-09 14:41:50 +040029 if {$runq eq {} && ![info exists currunq]} {
Paul Mackerras7eb3cb92007-06-17 14:45:00 +100030 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} {
Alexander Gavrilovdf75e862008-08-09 14:41:50 +040041 global runq currunq
Paul Mackerras7eb3cb92007-06-17 14:45:00 +100042
43 fileevent $fd readable {}
Alexander Gavrilovdf75e862008-08-09 14:41:50 +040044 if {$runq eq {} && ![info exists currunq]} {
Paul Mackerras7eb3cb92007-06-17 14:45:00 +100045 after idle dorunq
46 }
47 lappend runq [list $fd $script]
48}
49
Paul Mackerras7fcc92b2007-12-03 10:33:01 +110050proc nukefile {fd} {
51 global runq
52
53 for {set i 0} {$i < [llength $runq]} {} {
54 if {[lindex $runq $i 0] eq $fd} {
55 set runq [lreplace $runq $i $i]
56 } else {
57 incr i
58 }
59 }
60}
61
Paul Mackerras7eb3cb92007-06-17 14:45:00 +100062proc dorunq {} {
Alexander Gavrilovdf75e862008-08-09 14:41:50 +040063 global isonrunq runq currunq
Paul Mackerras7eb3cb92007-06-17 14:45:00 +100064
65 set tstart [clock clicks -milliseconds]
66 set t0 $tstart
Paul Mackerras7fcc92b2007-12-03 10:33:01 +110067 while {[llength $runq] > 0} {
Paul Mackerras7eb3cb92007-06-17 14:45:00 +100068 set fd [lindex $runq 0 0]
69 set script [lindex $runq 0 1]
Alexander Gavrilovdf75e862008-08-09 14:41:50 +040070 set currunq [lindex $runq 0]
71 set runq [lrange $runq 1 end]
Paul Mackerras7eb3cb92007-06-17 14:45:00 +100072 set repeat [eval $script]
Alexander Gavrilovdf75e862008-08-09 14:41:50 +040073 unset currunq
Paul Mackerras7eb3cb92007-06-17 14:45:00 +100074 set t1 [clock clicks -milliseconds]
75 set t [expr {$t1 - $t0}]
Paul Mackerras7eb3cb92007-06-17 14:45:00 +100076 if {$repeat ne {} && $repeat} {
77 if {$fd eq {} || $repeat == 2} {
78 # script returns 1 if it wants to be readded
79 # file readers return 2 if they could do more straight away
80 lappend runq [list $fd $script]
81 } else {
82 fileevent $fd readable [list filereadable $fd $script]
83 }
84 } elseif {$fd eq {}} {
85 unset isonrunq($script)
86 }
87 set t0 $t1
88 if {$t1 - $tstart >= 80} break
89 }
90 if {$runq ne {}} {
91 after idle dorunq
92 }
93}
94
Alexander Gavrilove439e092008-07-13 16:40:47 +040095proc reg_instance {fd} {
96 global commfd leftover loginstance
97
98 set i [incr loginstance]
99 set commfd($i) $fd
100 set leftover($i) {}
101 return $i
102}
103
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000104proc unmerged_files {files} {
105 global nr_unmerged
106
107 # find the list of unmerged files
108 set mlist {}
109 set nr_unmerged 0
110 if {[catch {
111 set fd [open "| git ls-files -u" r]
112 } err]} {
113 show_error {} . "[mc "Couldn't get list of unmerged files:"] $err"
114 exit 1
115 }
116 while {[gets $fd line] >= 0} {
117 set i [string first "\t" $line]
118 if {$i < 0} continue
119 set fname [string range $line [expr {$i+1}] end]
120 if {[lsearch -exact $mlist $fname] >= 0} continue
121 incr nr_unmerged
122 if {$files eq {} || [path_filter $files $fname]} {
123 lappend mlist $fname
124 }
125 }
126 catch {close $fd}
127 return $mlist
128}
129
130proc parseviewargs {n arglist} {
Paul Mackerrasee66e082008-05-09 10:14:07 +1000131 global vdatemode vmergeonly vflags vdflags vrevs vfiltered vorigargs
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000132
133 set vdatemode($n) 0
134 set vmergeonly($n) 0
Paul Mackerrasee66e082008-05-09 10:14:07 +1000135 set glflags {}
136 set diffargs {}
137 set nextisval 0
138 set revargs {}
139 set origargs $arglist
140 set allknown 1
141 set filtered 0
142 set i -1
143 foreach arg $arglist {
144 incr i
145 if {$nextisval} {
146 lappend glflags $arg
147 set nextisval 0
148 continue
149 }
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000150 switch -glob -- $arg {
151 "-d" -
152 "--date-order" {
153 set vdatemode($n) 1
Paul Mackerrasee66e082008-05-09 10:14:07 +1000154 # remove from origargs in case we hit an unknown option
155 set origargs [lreplace $origargs $i $i]
156 incr i -1
157 }
158 # These request or affect diff output, which we don't want.
159 # Some could be used to set our defaults for diff display.
160 "-[puabwcrRBMC]" -
161 "--no-renames" - "--full-index" - "--binary" - "--abbrev=*" -
162 "--find-copies-harder" - "-l*" - "--ext-diff" - "--no-ext-diff" -
163 "--src-prefix=*" - "--dst-prefix=*" - "--no-prefix" -
164 "-O*" - "--text" - "--full-diff" - "--ignore-space-at-eol" -
165 "--ignore-space-change" - "-U*" - "--unified=*" {
166 lappend diffargs $arg
167 }
168 # These cause our parsing of git log's output to fail, or else
169 # they're options we want to set ourselves, so ignore them.
170 "--raw" - "--patch-with-raw" - "--patch-with-stat" -
171 "--name-only" - "--name-status" - "--color" - "--color-words" -
172 "--log-size" - "--pretty=*" - "--decorate" - "--abbrev-commit" -
173 "--cc" - "-z" - "--header" - "--parents" - "--boundary" -
174 "--no-color" - "-g" - "--walk-reflogs" - "--no-walk" -
175 "--timestamp" - "relative-date" - "--date=*" - "--stdin" -
176 "--objects" - "--objects-edge" - "--reverse" {
177 }
178 # These are harmless, and some are even useful
179 "--stat=*" - "--numstat" - "--shortstat" - "--summary" -
180 "--check" - "--exit-code" - "--quiet" - "--topo-order" -
181 "--full-history" - "--dense" - "--sparse" -
182 "--follow" - "--left-right" - "--encoding=*" {
183 lappend glflags $arg
184 }
185 # These mean that we get a subset of the commits
186 "--diff-filter=*" - "--no-merges" - "--unpacked" -
187 "--max-count=*" - "--skip=*" - "--since=*" - "--after=*" -
188 "--until=*" - "--before=*" - "--max-age=*" - "--min-age=*" -
189 "--author=*" - "--committer=*" - "--grep=*" - "-[iE]" -
190 "--remove-empty" - "--first-parent" - "--cherry-pick" -
191 "-S*" - "--pickaxe-all" - "--pickaxe-regex" - {
192 set filtered 1
193 lappend glflags $arg
194 }
195 # This appears to be the only one that has a value as a
196 # separate word following it
197 "-n" {
198 set filtered 1
199 set nextisval 1
200 lappend glflags $arg
201 }
202 "--not" {
203 set notflag [expr {!$notflag}]
204 lappend revargs $arg
205 }
206 "--all" {
207 lappend revargs $arg
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000208 }
209 "--merge" {
210 set vmergeonly($n) 1
Paul Mackerrasee66e082008-05-09 10:14:07 +1000211 # git rev-parse doesn't understand --merge
212 lappend revargs --gitk-symmetric-diff-marker MERGE_HEAD...HEAD
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000213 }
Paul Mackerrasee66e082008-05-09 10:14:07 +1000214 # Other flag arguments including -<n>
215 "-*" {
216 if {[string is digit -strict [string range $arg 1 end]]} {
217 set filtered 1
218 } else {
219 # a flag argument that we don't recognize;
220 # that means we can't optimize
221 set allknown 0
222 }
223 lappend glflags $arg
224 }
225 # Non-flag arguments specify commits or ranges of commits
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000226 default {
Paul Mackerrasee66e082008-05-09 10:14:07 +1000227 if {[string match "*...*" $arg]} {
228 lappend revargs --gitk-symmetric-diff-marker
229 }
230 lappend revargs $arg
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000231 }
232 }
233 }
Paul Mackerrasee66e082008-05-09 10:14:07 +1000234 set vdflags($n) $diffargs
235 set vflags($n) $glflags
236 set vrevs($n) $revargs
237 set vfiltered($n) $filtered
238 set vorigargs($n) $origargs
239 return $allknown
240}
241
242proc parseviewrevs {view revs} {
243 global vposids vnegids
244
245 if {$revs eq {}} {
246 set revs HEAD
247 }
248 if {[catch {set ids [eval exec git rev-parse $revs]} err]} {
249 # we get stdout followed by stderr in $err
250 # for an unknown rev, git rev-parse echoes it and then errors out
251 set errlines [split $err "\n"]
252 set badrev {}
253 for {set l 0} {$l < [llength $errlines]} {incr l} {
254 set line [lindex $errlines $l]
255 if {!([string length $line] == 40 && [string is xdigit $line])} {
256 if {[string match "fatal:*" $line]} {
257 if {[string match "fatal: ambiguous argument*" $line]
258 && $badrev ne {}} {
259 if {[llength $badrev] == 1} {
260 set err "unknown revision $badrev"
261 } else {
262 set err "unknown revisions: [join $badrev ", "]"
263 }
264 } else {
265 set err [join [lrange $errlines $l end] "\n"]
266 }
267 break
268 }
269 lappend badrev $line
270 }
271 }
272 error_popup "Error parsing revisions: $err"
273 return {}
274 }
275 set ret {}
276 set pos {}
277 set neg {}
278 set sdm 0
279 foreach id [split $ids "\n"] {
280 if {$id eq "--gitk-symmetric-diff-marker"} {
281 set sdm 4
282 } elseif {[string match "^*" $id]} {
283 if {$sdm != 1} {
284 lappend ret $id
285 if {$sdm == 3} {
286 set sdm 0
287 }
288 }
289 lappend neg [string range $id 1 end]
290 } else {
291 if {$sdm != 2} {
292 lappend ret $id
293 } else {
294 lset ret end [lindex $ret end]...$id
295 }
296 lappend pos $id
297 }
298 incr sdm -1
299 }
300 set vposids($view) $pos
301 set vnegids($view) $neg
302 return $ret
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000303}
304
Paul Mackerrasf9e0b6f2008-03-04 21:14:17 +1100305# Start off a git log process and arrange to read its output
Paul Mackerrasda7c24d2006-05-02 11:15:29 +1000306proc start_rev_list {view} {
Paul Mackerras6df74032008-05-11 22:13:02 +1000307 global startmsecs commitidx viewcomplete curview
Alexander Gavrilove439e092008-07-13 16:40:47 +0400308 global tclencoding
Paul Mackerrasee66e082008-05-09 10:14:07 +1000309 global viewargs viewargscmd viewfiles vfilelimit
Paul Mackerrasc11ff122008-05-26 10:11:33 +1000310 global showlocalchanges commitinterest
Alexander Gavrilove439e092008-07-13 16:40:47 +0400311 global viewactive viewinstances vmergeonly
Alexander Gavrilov567c34e2008-07-26 20:13:45 +0400312 global mainheadid
Paul Mackerrasee66e082008-05-09 10:14:07 +1000313 global vcanopt vflags vrevs vorigargs
Paul Mackerras38ad0912005-12-01 22:42:46 +1100314
315 set startmsecs [clock clicks -milliseconds]
Paul Mackerrasda7c24d2006-05-02 11:15:29 +1000316 set commitidx($view) 0
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000317 # these are set this way for the error exits
318 set viewcomplete($view) 1
319 set viewactive($view) 0
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100320 varcinit $view
321
Yann Dirson2d480852008-02-21 21:23:31 +0100322 set args $viewargs($view)
323 if {$viewargscmd($view) ne {}} {
324 if {[catch {
325 set str [exec sh -c $viewargscmd($view)]
326 } err]} {
327 error_popup "Error executing --argscmd command: $err"
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000328 return 0
Yann Dirson2d480852008-02-21 21:23:31 +0100329 }
330 set args [concat $args [split $str "\n"]]
331 }
Paul Mackerrasee66e082008-05-09 10:14:07 +1000332 set vcanopt($view) [parseviewargs $view $args]
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000333
334 set files $viewfiles($view)
335 if {$vmergeonly($view)} {
336 set files [unmerged_files $files]
337 if {$files eq {}} {
338 global nr_unmerged
339 if {$nr_unmerged == 0} {
340 error_popup [mc "No files selected: --merge specified but\
341 no files are unmerged."]
342 } else {
343 error_popup [mc "No files selected: --merge specified but\
344 no unmerged files are within file limit."]
345 }
346 return 0
347 }
348 }
349 set vfilelimit($view) $files
350
Paul Mackerrasee66e082008-05-09 10:14:07 +1000351 if {$vcanopt($view)} {
352 set revs [parseviewrevs $view $vrevs($view)]
353 if {$revs eq {}} {
354 return 0
355 }
356 set args [concat $vflags($view) $revs]
357 } else {
358 set args $vorigargs($view)
359 }
360
Paul Mackerras418c4c72006-02-07 09:10:18 +1100361 if {[catch {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100362 set fd [open [concat | git log --no-color -z --pretty=raw --parents \
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000363 --boundary $args "--" $files] r]
Paul Mackerras418c4c72006-02-07 09:10:18 +1100364 } err]} {
Paul Mackerras00abadb2007-12-20 10:25:50 +1100365 error_popup "[mc "Error executing git log:"] $err"
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000366 return 0
Paul Mackerras38ad0912005-12-01 22:42:46 +1100367 }
Alexander Gavrilove439e092008-07-13 16:40:47 +0400368 set i [reg_instance $fd]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100369 set viewinstances($view) [list $i]
Paul Mackerrasc11ff122008-05-26 10:11:33 +1000370 if {$showlocalchanges && $mainheadid ne {}} {
Paul Mackerras3e6b8932007-09-15 09:33:39 +1000371 lappend commitinterest($mainheadid) {dodiffindex}
372 }
Mark Levedahl86da5b62007-07-17 18:42:04 -0400373 fconfigure $fd -blocking 0 -translation lf -eofchar {}
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +1100374 if {$tclencoding != {}} {
Paul Mackerrasda7c24d2006-05-02 11:15:29 +1000375 fconfigure $fd -encoding $tclencoding
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +1100376 }
Paul Mackerrasf806f0f2008-02-24 12:16:56 +1100377 filerun $fd [list getcommitlines $fd $i $view 0]
Christian Stimmingd990ced2007-11-07 18:42:55 +0100378 nowbusy $view [mc "Reading"]
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000379 set viewcomplete($view) 0
380 set viewactive($view) 1
381 return 1
Paul Mackerras38ad0912005-12-01 22:42:46 +1100382}
383
Alexander Gavrilove2f90ee2008-07-12 16:09:28 +0400384proc stop_instance {inst} {
385 global commfd leftover
386
387 set fd $commfd($inst)
388 catch {
389 set pid [pid $fd]
Alexander Gavrilovb6326e92008-07-15 00:35:42 +0400390
391 if {$::tcl_platform(platform) eq {windows}} {
392 exec kill -f $pid
393 } else {
394 exec kill $pid
395 }
Alexander Gavrilove2f90ee2008-07-12 16:09:28 +0400396 }
397 catch {close $fd}
398 nukefile $fd
399 unset commfd($inst)
400 unset leftover($inst)
401}
402
403proc stop_backends {} {
404 global commfd
405
406 foreach inst [array names commfd] {
407 stop_instance $inst
408 }
409}
410
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100411proc stop_rev_list {view} {
Alexander Gavrilove2f90ee2008-07-12 16:09:28 +0400412 global viewinstances
Paul Mackerras22626ef2006-04-17 09:56:02 +1000413
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100414 foreach inst $viewinstances($view) {
Alexander Gavrilove2f90ee2008-07-12 16:09:28 +0400415 stop_instance $inst
Paul Mackerras22626ef2006-04-17 09:56:02 +1000416 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100417 set viewinstances($view) {}
Paul Mackerras22626ef2006-04-17 09:56:02 +1000418}
419
Alexander Gavrilov567c34e2008-07-26 20:13:45 +0400420proc reset_pending_select {selid} {
421 global pending_select mainheadid
422
423 if {$selid ne {}} {
424 set pending_select $selid
425 } else {
426 set pending_select $mainheadid
427 }
428}
429
430proc getcommits {selid} {
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000431 global canv curview need_redisplay viewactive
Sven Verdoolaegeb5c2f302005-11-29 22:15:51 +0100432
Paul Mackerrasda7c24d2006-05-02 11:15:29 +1000433 initlayout
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000434 if {[start_rev_list $curview]} {
Alexander Gavrilov567c34e2008-07-26 20:13:45 +0400435 reset_pending_select $selid
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000436 show_status [mc "Reading commits..."]
437 set need_redisplay 1
438 } else {
439 show_status [mc "No commits selected"]
440 }
Paul Mackerras1d10f362005-05-15 12:55:47 +0000441}
442
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100443proc updatecommits {} {
Paul Mackerrasee66e082008-05-09 10:14:07 +1000444 global curview vcanopt vorigargs vfilelimit viewinstances
Alexander Gavrilove439e092008-07-13 16:40:47 +0400445 global viewactive viewcomplete tclencoding
446 global startmsecs showneartags showlocalchanges
Paul Mackerras3e766082008-01-13 17:26:30 +1100447 global mainheadid pending_select
Paul Mackerras92e22ca2008-03-11 22:21:39 +1100448 global isworktree
Paul Mackerrasee66e082008-05-09 10:14:07 +1000449 global varcid vposids vnegids vflags vrevs
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100450
Paul Mackerras92e22ca2008-03-11 22:21:39 +1100451 set isworktree [expr {[exec git rev-parse --is-inside-work-tree] == "true"}]
Paul Mackerraseb5f8c92007-12-29 21:13:34 +1100452 set oldmainid $mainheadid
Paul Mackerrasfc2a2562007-12-26 23:03:43 +1100453 rereadrefs
Paul Mackerraseb5f8c92007-12-29 21:13:34 +1100454 if {$showlocalchanges} {
455 if {$mainheadid ne $oldmainid} {
456 dohidelocalchanges
457 }
458 if {[commitinview $mainheadid $curview]} {
459 dodiffindex
460 }
461 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100462 set view $curview
Paul Mackerrasee66e082008-05-09 10:14:07 +1000463 if {$vcanopt($view)} {
464 set oldpos $vposids($view)
465 set oldneg $vnegids($view)
466 set revs [parseviewrevs $view $vrevs($view)]
467 if {$revs eq {}} {
468 return
469 }
470 # note: getting the delta when negative refs change is hard,
471 # and could require multiple git log invocations, so in that
472 # case we ask git log for all the commits (not just the delta)
473 if {$oldneg eq $vnegids($view)} {
474 set newrevs {}
475 set npos 0
476 # take out positive refs that we asked for before or
477 # that we have already seen
478 foreach rev $revs {
479 if {[string length $rev] == 40} {
480 if {[lsearch -exact $oldpos $rev] < 0
481 && ![info exists varcid($view,$rev)]} {
482 lappend newrevs $rev
483 incr npos
484 }
485 } else {
486 lappend $newrevs $rev
487 }
488 }
489 if {$npos == 0} return
490 set revs $newrevs
491 set vposids($view) [lsort -unique [concat $oldpos $vposids($view)]]
492 }
493 set args [concat $vflags($view) $revs --not $oldpos]
494 } else {
495 set args $vorigargs($view)
496 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100497 if {[catch {
498 set fd [open [concat | git log --no-color -z --pretty=raw --parents \
Paul Mackerrasee66e082008-05-09 10:14:07 +1000499 --boundary $args "--" $vfilelimit($view)] r]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100500 } err]} {
501 error_popup "Error executing git log: $err"
Paul Mackerrasee66e082008-05-09 10:14:07 +1000502 return
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100503 }
504 if {$viewactive($view) == 0} {
505 set startmsecs [clock clicks -milliseconds]
506 }
Alexander Gavrilove439e092008-07-13 16:40:47 +0400507 set i [reg_instance $fd]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100508 lappend viewinstances($view) $i
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100509 fconfigure $fd -blocking 0 -translation lf -eofchar {}
510 if {$tclencoding != {}} {
511 fconfigure $fd -encoding $tclencoding
512 }
Paul Mackerrasf806f0f2008-02-24 12:16:56 +1100513 filerun $fd [list getcommitlines $fd $i $view 1]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100514 incr viewactive($view)
515 set viewcomplete($view) 0
Alexander Gavrilov567c34e2008-07-26 20:13:45 +0400516 reset_pending_select {}
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100517 nowbusy $view "Reading"
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100518 if {$showneartags} {
519 getallcommits
520 }
521}
522
523proc reloadcommits {} {
524 global curview viewcomplete selectedline currentid thickerline
525 global showneartags treediffs commitinterest cached_commitrow
Paul Mackerras6df74032008-05-11 22:13:02 +1000526 global targetid
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100527
Alexander Gavrilov567c34e2008-07-26 20:13:45 +0400528 set selid {}
529 if {$selectedline ne {}} {
530 set selid $currentid
531 }
532
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100533 if {!$viewcomplete($curview)} {
534 stop_rev_list $curview
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100535 }
536 resetvarcs $curview
Paul Mackerras94b4a692008-05-20 20:51:06 +1000537 set selectedline {}
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100538 catch {unset currentid}
539 catch {unset thickerline}
540 catch {unset treediffs}
541 readrefs
542 changedrefs
543 if {$showneartags} {
544 getallcommits
545 }
546 clear_display
547 catch {unset commitinterest}
548 catch {unset cached_commitrow}
Paul Mackerras42a671f2008-01-02 09:59:39 +1100549 catch {unset targetid}
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100550 setcanvscroll
Alexander Gavrilov567c34e2008-07-26 20:13:45 +0400551 getcommits $selid
Paul Mackerrase7297a12008-01-15 22:30:40 +1100552 return 0
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100553}
554
Paul Mackerras6e8c8702007-07-31 21:03:06 +1000555# This makes a string representation of a positive integer which
556# sorts as a string in numerical order
557proc strrep {n} {
558 if {$n < 16} {
559 return [format "%x" $n]
560 } elseif {$n < 256} {
561 return [format "x%.2x" $n]
562 } elseif {$n < 65536} {
563 return [format "y%.4x" $n]
564 }
565 return [format "z%.8x" $n]
566}
567
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100568# Procedures used in reordering commits from git log (without
569# --topo-order) into the order for display.
570
571proc varcinit {view} {
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100572 global varcstart vupptr vdownptr vleftptr vbackptr varctok varcrow
573 global vtokmod varcmod vrowmod varcix vlastins
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100574
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100575 set varcstart($view) {{}}
576 set vupptr($view) {0}
577 set vdownptr($view) {0}
578 set vleftptr($view) {0}
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100579 set vbackptr($view) {0}
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100580 set varctok($view) {{}}
581 set varcrow($view) {{}}
582 set vtokmod($view) {}
583 set varcmod($view) 0
Paul Mackerrase5b37ac2007-12-12 18:13:51 +1100584 set vrowmod($view) 0
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100585 set varcix($view) {{}}
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100586 set vlastins($view) {0}
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100587}
588
589proc resetvarcs {view} {
590 global varcid varccommits parents children vseedcount ordertok
591
592 foreach vid [array names varcid $view,*] {
593 unset varcid($vid)
594 unset children($vid)
595 unset parents($vid)
596 }
597 # some commits might have children but haven't been seen yet
598 foreach vid [array names children $view,*] {
599 unset children($vid)
600 }
601 foreach va [array names varccommits $view,*] {
602 unset varccommits($va)
603 }
604 foreach vd [array names vseedcount $view,*] {
605 unset vseedcount($vd)
606 }
Paul Mackerras9257d8f2007-12-11 10:45:38 +1100607 catch {unset ordertok}
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100608}
609
Paul Mackerras468bcae2008-03-03 10:19:35 +1100610# returns a list of the commits with no children
611proc seeds {v} {
612 global vdownptr vleftptr varcstart
613
614 set ret {}
615 set a [lindex $vdownptr($v) 0]
616 while {$a != 0} {
617 lappend ret [lindex $varcstart($v) $a]
618 set a [lindex $vleftptr($v) $a]
619 }
620 return $ret
621}
622
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100623proc newvarc {view id} {
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000624 global varcid varctok parents children vdatemode
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100625 global vupptr vdownptr vleftptr vbackptr varcrow varcix varcstart
626 global commitdata commitinfo vseedcount varccommits vlastins
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100627
628 set a [llength $varctok($view)]
629 set vid $view,$id
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000630 if {[llength $children($vid)] == 0 || $vdatemode($view)} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100631 if {![info exists commitinfo($id)]} {
632 parsecommit $id $commitdata($id) 1
633 }
634 set cdate [lindex $commitinfo($id) 4]
635 if {![string is integer -strict $cdate]} {
636 set cdate 0
637 }
638 if {![info exists vseedcount($view,$cdate)]} {
639 set vseedcount($view,$cdate) -1
640 }
641 set c [incr vseedcount($view,$cdate)]
642 set cdate [expr {$cdate ^ 0xffffffff}]
643 set tok "s[strrep $cdate][strrep $c]"
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100644 } else {
645 set tok {}
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100646 }
647 set ka 0
648 if {[llength $children($vid)] > 0} {
649 set kid [lindex $children($vid) end]
650 set k $varcid($view,$kid)
651 if {[string compare [lindex $varctok($view) $k] $tok] > 0} {
652 set ki $kid
653 set ka $k
654 set tok [lindex $varctok($view) $k]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100655 }
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100656 }
657 if {$ka != 0} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100658 set i [lsearch -exact $parents($view,$ki) $id]
659 set j [expr {[llength $parents($view,$ki)] - 1 - $i}]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100660 append tok [strrep $j]
661 }
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100662 set c [lindex $vlastins($view) $ka]
663 if {$c == 0 || [string compare $tok [lindex $varctok($view) $c]] < 0} {
664 set c $ka
665 set b [lindex $vdownptr($view) $ka]
666 } else {
667 set b [lindex $vleftptr($view) $c]
668 }
669 while {$b != 0 && [string compare $tok [lindex $varctok($view) $b]] >= 0} {
670 set c $b
671 set b [lindex $vleftptr($view) $c]
672 }
673 if {$c == $ka} {
674 lset vdownptr($view) $ka $a
675 lappend vbackptr($view) 0
676 } else {
677 lset vleftptr($view) $c $a
678 lappend vbackptr($view) $c
679 }
680 lset vlastins($view) $ka $a
681 lappend vupptr($view) $ka
682 lappend vleftptr($view) $b
683 if {$b != 0} {
684 lset vbackptr($view) $b $a
685 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100686 lappend varctok($view) $tok
687 lappend varcstart($view) $id
688 lappend vdownptr($view) 0
689 lappend varcrow($view) {}
690 lappend varcix($view) {}
Paul Mackerrase5b37ac2007-12-12 18:13:51 +1100691 set varccommits($view,$a) {}
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100692 lappend vlastins($view) 0
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100693 return $a
694}
695
696proc splitvarc {p v} {
697 global varcid varcstart varccommits varctok
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100698 global vupptr vdownptr vleftptr vbackptr varcix varcrow vlastins
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100699
700 set oa $varcid($v,$p)
701 set ac $varccommits($v,$oa)
702 set i [lsearch -exact $varccommits($v,$oa) $p]
703 if {$i <= 0} return
704 set na [llength $varctok($v)]
705 # "%" sorts before "0"...
706 set tok "[lindex $varctok($v) $oa]%[strrep $i]"
707 lappend varctok($v) $tok
708 lappend varcrow($v) {}
709 lappend varcix($v) {}
710 set varccommits($v,$oa) [lrange $ac 0 [expr {$i - 1}]]
711 set varccommits($v,$na) [lrange $ac $i end]
712 lappend varcstart($v) $p
713 foreach id $varccommits($v,$na) {
714 set varcid($v,$id) $na
715 }
716 lappend vdownptr($v) [lindex $vdownptr($v) $oa]
Paul Mackerras841ea822008-02-18 10:44:33 +1100717 lappend vlastins($v) [lindex $vlastins($v) $oa]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100718 lset vdownptr($v) $oa $na
Paul Mackerras841ea822008-02-18 10:44:33 +1100719 lset vlastins($v) $oa 0
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100720 lappend vupptr($v) $oa
721 lappend vleftptr($v) 0
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100722 lappend vbackptr($v) 0
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100723 for {set b [lindex $vdownptr($v) $na]} {$b != 0} {set b [lindex $vleftptr($v) $b]} {
724 lset vupptr($v) $b $na
725 }
726}
727
728proc renumbervarc {a v} {
729 global parents children varctok varcstart varccommits
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000730 global vupptr vdownptr vleftptr vbackptr vlastins varcid vtokmod vdatemode
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100731
732 set t1 [clock clicks -milliseconds]
733 set todo {}
734 set isrelated($a) 1
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100735 set kidchanged($a) 1
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100736 set ntot 0
737 while {$a != 0} {
738 if {[info exists isrelated($a)]} {
739 lappend todo $a
740 set id [lindex $varccommits($v,$a) end]
741 foreach p $parents($v,$id) {
742 if {[info exists varcid($v,$p)]} {
743 set isrelated($varcid($v,$p)) 1
744 }
745 }
746 }
747 incr ntot
748 set b [lindex $vdownptr($v) $a]
749 if {$b == 0} {
750 while {$a != 0} {
751 set b [lindex $vleftptr($v) $a]
752 if {$b != 0} break
753 set a [lindex $vupptr($v) $a]
754 }
755 }
756 set a $b
757 }
758 foreach a $todo {
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100759 if {![info exists kidchanged($a)]} continue
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100760 set id [lindex $varcstart($v) $a]
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100761 if {[llength $children($v,$id)] > 1} {
762 set children($v,$id) [lsort -command [list vtokcmp $v] \
763 $children($v,$id)]
764 }
765 set oldtok [lindex $varctok($v) $a]
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000766 if {!$vdatemode($v)} {
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100767 set tok {}
768 } else {
769 set tok $oldtok
770 }
771 set ka 0
Paul Mackerrasc8c9f3d2008-01-06 13:54:58 +1100772 set kid [last_real_child $v,$id]
773 if {$kid ne {}} {
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100774 set k $varcid($v,$kid)
775 if {[string compare [lindex $varctok($v) $k] $tok] > 0} {
776 set ki $kid
777 set ka $k
778 set tok [lindex $varctok($v) $k]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100779 }
780 }
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100781 if {$ka != 0} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100782 set i [lsearch -exact $parents($v,$ki) $id]
783 set j [expr {[llength $parents($v,$ki)] - 1 - $i}]
784 append tok [strrep $j]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100785 }
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100786 if {$tok eq $oldtok} {
787 continue
788 }
789 set id [lindex $varccommits($v,$a) end]
790 foreach p $parents($v,$id) {
791 if {[info exists varcid($v,$p)]} {
792 set kidchanged($varcid($v,$p)) 1
793 } else {
794 set sortkids($p) 1
795 }
796 }
797 lset varctok($v) $a $tok
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100798 set b [lindex $vupptr($v) $a]
799 if {$b != $ka} {
Paul Mackerras9257d8f2007-12-11 10:45:38 +1100800 if {[string compare [lindex $varctok($v) $ka] $vtokmod($v)] < 0} {
801 modify_arc $v $ka
Paul Mackerras38dfe932007-12-06 20:50:31 +1100802 }
Paul Mackerras9257d8f2007-12-11 10:45:38 +1100803 if {[string compare [lindex $varctok($v) $b] $vtokmod($v)] < 0} {
804 modify_arc $v $b
Paul Mackerras38dfe932007-12-06 20:50:31 +1100805 }
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100806 set c [lindex $vbackptr($v) $a]
807 set d [lindex $vleftptr($v) $a]
808 if {$c == 0} {
809 lset vdownptr($v) $b $d
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100810 } else {
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100811 lset vleftptr($v) $c $d
812 }
813 if {$d != 0} {
814 lset vbackptr($v) $d $c
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100815 }
Paul Mackerras841ea822008-02-18 10:44:33 +1100816 if {[lindex $vlastins($v) $b] == $a} {
817 lset vlastins($v) $b $c
818 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100819 lset vupptr($v) $a $ka
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100820 set c [lindex $vlastins($v) $ka]
821 if {$c == 0 || \
822 [string compare $tok [lindex $varctok($v) $c]] < 0} {
823 set c $ka
824 set b [lindex $vdownptr($v) $ka]
825 } else {
826 set b [lindex $vleftptr($v) $c]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100827 }
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100828 while {$b != 0 && \
829 [string compare $tok [lindex $varctok($v) $b]] >= 0} {
830 set c $b
831 set b [lindex $vleftptr($v) $c]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100832 }
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100833 if {$c == $ka} {
834 lset vdownptr($v) $ka $a
835 lset vbackptr($v) $a 0
836 } else {
837 lset vleftptr($v) $c $a
838 lset vbackptr($v) $a $c
839 }
840 lset vleftptr($v) $a $b
841 if {$b != 0} {
842 lset vbackptr($v) $b $a
843 }
844 lset vlastins($v) $ka $a
845 }
846 }
847 foreach id [array names sortkids] {
848 if {[llength $children($v,$id)] > 1} {
849 set children($v,$id) [lsort -command [list vtokcmp $v] \
850 $children($v,$id)]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100851 }
852 }
853 set t2 [clock clicks -milliseconds]
854 #puts "renumbervarc did [llength $todo] of $ntot arcs in [expr {$t2-$t1}]ms"
855}
856
Paul Mackerrasf806f0f2008-02-24 12:16:56 +1100857# Fix up the graph after we have found out that in view $v,
858# $p (a commit that we have already seen) is actually the parent
859# of the last commit in arc $a.
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100860proc fix_reversal {p a v} {
Paul Mackerras24f7a662007-12-19 09:35:33 +1100861 global varcid varcstart varctok vupptr
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100862
863 set pa $varcid($v,$p)
864 if {$p ne [lindex $varcstart($v) $pa]} {
865 splitvarc $p $v
866 set pa $varcid($v,$p)
867 }
Paul Mackerras24f7a662007-12-19 09:35:33 +1100868 # seeds always need to be renumbered
869 if {[lindex $vupptr($v) $pa] == 0 ||
870 [string compare [lindex $varctok($v) $a] \
871 [lindex $varctok($v) $pa]] > 0} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100872 renumbervarc $pa $v
873 }
874}
875
876proc insertrow {id p v} {
Paul Mackerrasb8a938c2008-02-13 22:12:31 +1100877 global cmitlisted children parents varcid varctok vtokmod
878 global varccommits ordertok commitidx numcommits curview
879 global targetid targetrow
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100880
Paul Mackerrasb8a938c2008-02-13 22:12:31 +1100881 readcommit $id
882 set vid $v,$id
883 set cmitlisted($vid) 1
884 set children($vid) {}
885 set parents($vid) [list $p]
886 set a [newvarc $v $id]
887 set varcid($vid) $a
888 if {[string compare [lindex $varctok($v) $a] $vtokmod($v)] < 0} {
889 modify_arc $v $a
890 }
891 lappend varccommits($v,$a) $id
892 set vp $v,$p
893 if {[llength [lappend children($vp) $id]] > 1} {
894 set children($vp) [lsort -command [list vtokcmp $v] $children($vp)]
895 catch {unset ordertok}
896 }
897 fix_reversal $p $a $v
898 incr commitidx($v)
899 if {$v == $curview} {
900 set numcommits $commitidx($v)
901 setcanvscroll
902 if {[info exists targetid]} {
903 if {![comes_before $targetid $p]} {
904 incr targetrow
905 }
906 }
907 }
908}
909
910proc insertfakerow {id p} {
911 global varcid varccommits parents children cmitlisted
912 global commitidx varctok vtokmod targetid targetrow curview numcommits
913
914 set v $curview
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100915 set a $varcid($v,$p)
916 set i [lsearch -exact $varccommits($v,$a) $p]
917 if {$i < 0} {
Paul Mackerrasb8a938c2008-02-13 22:12:31 +1100918 puts "oops: insertfakerow can't find [shortids $p] on arc $a"
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100919 return
920 }
921 set children($v,$id) {}
922 set parents($v,$id) [list $p]
923 set varcid($v,$id) $a
Paul Mackerras9257d8f2007-12-11 10:45:38 +1100924 lappend children($v,$p) $id
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100925 set cmitlisted($v,$id) 1
Paul Mackerrasb8a938c2008-02-13 22:12:31 +1100926 set numcommits [incr commitidx($v)]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100927 # note we deliberately don't update varcstart($v) even if $i == 0
928 set varccommits($v,$a) [linsert $varccommits($v,$a) $i $id]
Paul Mackerrasc9cfdc92008-03-04 21:32:38 +1100929 modify_arc $v $a $i
Paul Mackerras42a671f2008-01-02 09:59:39 +1100930 if {[info exists targetid]} {
931 if {![comes_before $targetid $p]} {
932 incr targetrow
933 }
934 }
Paul Mackerrasb8a938c2008-02-13 22:12:31 +1100935 setcanvscroll
Paul Mackerras9257d8f2007-12-11 10:45:38 +1100936 drawvisible
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100937}
938
Paul Mackerrasb8a938c2008-02-13 22:12:31 +1100939proc removefakerow {id} {
Paul Mackerras9257d8f2007-12-11 10:45:38 +1100940 global varcid varccommits parents children commitidx
Paul Mackerrasfc2a2562007-12-26 23:03:43 +1100941 global varctok vtokmod cmitlisted currentid selectedline
Paul Mackerrasb8a938c2008-02-13 22:12:31 +1100942 global targetid curview numcommits
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100943
Paul Mackerrasb8a938c2008-02-13 22:12:31 +1100944 set v $curview
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100945 if {[llength $parents($v,$id)] != 1} {
Paul Mackerrasb8a938c2008-02-13 22:12:31 +1100946 puts "oops: removefakerow [shortids $id] has [llength $parents($v,$id)] parents"
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100947 return
948 }
949 set p [lindex $parents($v,$id) 0]
950 set a $varcid($v,$id)
951 set i [lsearch -exact $varccommits($v,$a) $id]
952 if {$i < 0} {
Paul Mackerrasb8a938c2008-02-13 22:12:31 +1100953 puts "oops: removefakerow can't find [shortids $id] on arc $a"
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100954 return
955 }
956 unset varcid($v,$id)
957 set varccommits($v,$a) [lreplace $varccommits($v,$a) $i $i]
958 unset parents($v,$id)
959 unset children($v,$id)
960 unset cmitlisted($v,$id)
Paul Mackerrasb8a938c2008-02-13 22:12:31 +1100961 set numcommits [incr commitidx($v) -1]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100962 set j [lsearch -exact $children($v,$p) $id]
963 if {$j >= 0} {
964 set children($v,$p) [lreplace $children($v,$p) $j $j]
965 }
Paul Mackerrasc9cfdc92008-03-04 21:32:38 +1100966 modify_arc $v $a $i
Paul Mackerrasfc2a2562007-12-26 23:03:43 +1100967 if {[info exist currentid] && $id eq $currentid} {
968 unset currentid
Paul Mackerras94b4a692008-05-20 20:51:06 +1000969 set selectedline {}
Paul Mackerrasfc2a2562007-12-26 23:03:43 +1100970 }
Paul Mackerras42a671f2008-01-02 09:59:39 +1100971 if {[info exists targetid] && $targetid eq $id} {
972 set targetid $p
973 }
Paul Mackerrasb8a938c2008-02-13 22:12:31 +1100974 setcanvscroll
Paul Mackerras9257d8f2007-12-11 10:45:38 +1100975 drawvisible
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100976}
977
Paul Mackerrasc8c9f3d2008-01-06 13:54:58 +1100978proc first_real_child {vp} {
979 global children nullid nullid2
980
981 foreach id $children($vp) {
982 if {$id ne $nullid && $id ne $nullid2} {
983 return $id
984 }
985 }
986 return {}
987}
988
989proc last_real_child {vp} {
990 global children nullid nullid2
991
992 set kids $children($vp)
993 for {set i [llength $kids]} {[incr i -1] >= 0} {} {
994 set id [lindex $kids $i]
995 if {$id ne $nullid && $id ne $nullid2} {
996 return $id
997 }
998 }
999 return {}
1000}
1001
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001002proc vtokcmp {v a b} {
1003 global varctok varcid
1004
1005 return [string compare [lindex $varctok($v) $varcid($v,$a)] \
1006 [lindex $varctok($v) $varcid($v,$b)]]
1007}
1008
Paul Mackerrasc9cfdc92008-03-04 21:32:38 +11001009# This assumes that if lim is not given, the caller has checked that
1010# arc a's token is less than $vtokmod($v)
Paul Mackerrase5b37ac2007-12-12 18:13:51 +11001011proc modify_arc {v a {lim {}}} {
1012 global varctok vtokmod varcmod varcrow vupptr curview vrowmod varccommits
Paul Mackerras9257d8f2007-12-11 10:45:38 +11001013
Paul Mackerrasc9cfdc92008-03-04 21:32:38 +11001014 if {$lim ne {}} {
1015 set c [string compare [lindex $varctok($v) $a] $vtokmod($v)]
1016 if {$c > 0} return
1017 if {$c == 0} {
1018 set r [lindex $varcrow($v) $a]
1019 if {$r ne {} && $vrowmod($v) <= $r + $lim} return
1020 }
1021 }
Paul Mackerras9257d8f2007-12-11 10:45:38 +11001022 set vtokmod($v) [lindex $varctok($v) $a]
1023 set varcmod($v) $a
1024 if {$v == $curview} {
1025 while {$a != 0 && [lindex $varcrow($v) $a] eq {}} {
1026 set a [lindex $vupptr($v) $a]
Paul Mackerrase5b37ac2007-12-12 18:13:51 +11001027 set lim {}
Paul Mackerras9257d8f2007-12-11 10:45:38 +11001028 }
Paul Mackerrase5b37ac2007-12-12 18:13:51 +11001029 set r 0
1030 if {$a != 0} {
1031 if {$lim eq {}} {
1032 set lim [llength $varccommits($v,$a)]
1033 }
1034 set r [expr {[lindex $varcrow($v) $a] + $lim}]
1035 }
1036 set vrowmod($v) $r
Paul Mackerras0c278862007-12-11 20:09:53 +11001037 undolayout $r
Paul Mackerras9257d8f2007-12-11 10:45:38 +11001038 }
1039}
1040
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001041proc update_arcrows {v} {
Paul Mackerrase5b37ac2007-12-12 18:13:51 +11001042 global vtokmod varcmod vrowmod varcrow commitidx currentid selectedline
Paul Mackerras24f7a662007-12-19 09:35:33 +11001043 global varcid vrownum varcorder varcix varccommits
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001044 global vupptr vdownptr vleftptr varctok
Paul Mackerras24f7a662007-12-19 09:35:33 +11001045 global displayorder parentlist curview cached_commitrow
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001046
Paul Mackerrasc9cfdc92008-03-04 21:32:38 +11001047 if {$vrowmod($v) == $commitidx($v)} return
1048 if {$v == $curview} {
1049 if {[llength $displayorder] > $vrowmod($v)} {
1050 set displayorder [lrange $displayorder 0 [expr {$vrowmod($v) - 1}]]
1051 set parentlist [lrange $parentlist 0 [expr {$vrowmod($v) - 1}]]
1052 }
1053 catch {unset cached_commitrow}
1054 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001055 set narctot [expr {[llength $varctok($v)] - 1}]
1056 set a $varcmod($v)
1057 while {$a != 0 && [lindex $varcix($v) $a] eq {}} {
1058 # go up the tree until we find something that has a row number,
1059 # or we get to a seed
1060 set a [lindex $vupptr($v) $a]
1061 }
1062 if {$a == 0} {
1063 set a [lindex $vdownptr($v) 0]
1064 if {$a == 0} return
1065 set vrownum($v) {0}
1066 set varcorder($v) [list $a]
1067 lset varcix($v) $a 0
1068 lset varcrow($v) $a 0
1069 set arcn 0
1070 set row 0
1071 } else {
1072 set arcn [lindex $varcix($v) $a]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001073 if {[llength $vrownum($v)] > $arcn + 1} {
1074 set vrownum($v) [lrange $vrownum($v) 0 $arcn]
1075 set varcorder($v) [lrange $varcorder($v) 0 $arcn]
1076 }
1077 set row [lindex $varcrow($v) $a]
1078 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001079 while {1} {
1080 set p $a
1081 incr row [llength $varccommits($v,$a)]
1082 # go down if possible
1083 set b [lindex $vdownptr($v) $a]
1084 if {$b == 0} {
1085 # if not, go left, or go up until we can go left
1086 while {$a != 0} {
1087 set b [lindex $vleftptr($v) $a]
1088 if {$b != 0} break
1089 set a [lindex $vupptr($v) $a]
1090 }
1091 if {$a == 0} break
1092 }
1093 set a $b
1094 incr arcn
1095 lappend vrownum($v) $row
1096 lappend varcorder($v) $a
1097 lset varcix($v) $a $arcn
1098 lset varcrow($v) $a $row
1099 }
Paul Mackerrase5b37ac2007-12-12 18:13:51 +11001100 set vtokmod($v) [lindex $varctok($v) $p]
1101 set varcmod($v) $p
1102 set vrowmod($v) $row
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001103 if {[info exists currentid]} {
1104 set selectedline [rowofcommit $currentid]
1105 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001106}
1107
1108# Test whether view $v contains commit $id
1109proc commitinview {id v} {
1110 global varcid
1111
1112 return [info exists varcid($v,$id)]
1113}
1114
1115# Return the row number for commit $id in the current view
1116proc rowofcommit {id} {
1117 global varcid varccommits varcrow curview cached_commitrow
Paul Mackerras9257d8f2007-12-11 10:45:38 +11001118 global varctok vtokmod
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001119
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001120 set v $curview
1121 if {![info exists varcid($v,$id)]} {
1122 puts "oops rowofcommit no arc for [shortids $id]"
1123 return {}
1124 }
1125 set a $varcid($v,$id)
Paul Mackerrasfc2a2562007-12-26 23:03:43 +11001126 if {[string compare [lindex $varctok($v) $a] $vtokmod($v)] >= 0} {
Paul Mackerras9257d8f2007-12-11 10:45:38 +11001127 update_arcrows $v
1128 }
Paul Mackerras31c0eaa2007-12-30 22:41:14 +11001129 if {[info exists cached_commitrow($id)]} {
1130 return $cached_commitrow($id)
1131 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001132 set i [lsearch -exact $varccommits($v,$a) $id]
1133 if {$i < 0} {
1134 puts "oops didn't find commit [shortids $id] in arc $a"
1135 return {}
1136 }
1137 incr i [lindex $varcrow($v) $a]
1138 set cached_commitrow($id) $i
1139 return $i
1140}
1141
Paul Mackerras42a671f2008-01-02 09:59:39 +11001142# Returns 1 if a is on an earlier row than b, otherwise 0
1143proc comes_before {a b} {
1144 global varcid varctok curview
1145
1146 set v $curview
1147 if {$a eq $b || ![info exists varcid($v,$a)] || \
1148 ![info exists varcid($v,$b)]} {
1149 return 0
1150 }
1151 if {$varcid($v,$a) != $varcid($v,$b)} {
1152 return [expr {[string compare [lindex $varctok($v) $varcid($v,$a)] \
1153 [lindex $varctok($v) $varcid($v,$b)]] < 0}]
1154 }
1155 return [expr {[rowofcommit $a] < [rowofcommit $b]}]
1156}
1157
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001158proc bsearch {l elt} {
1159 if {[llength $l] == 0 || $elt <= [lindex $l 0]} {
1160 return 0
1161 }
1162 set lo 0
1163 set hi [llength $l]
1164 while {$hi - $lo > 1} {
1165 set mid [expr {int(($lo + $hi) / 2)}]
1166 set t [lindex $l $mid]
1167 if {$elt < $t} {
1168 set hi $mid
1169 } elseif {$elt > $t} {
1170 set lo $mid
1171 } else {
1172 return $mid
1173 }
1174 }
1175 return $lo
1176}
1177
1178# Make sure rows $start..$end-1 are valid in displayorder and parentlist
1179proc make_disporder {start end} {
1180 global vrownum curview commitidx displayorder parentlist
Paul Mackerrase5b37ac2007-12-12 18:13:51 +11001181 global varccommits varcorder parents vrowmod varcrow
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001182 global d_valid_start d_valid_end
1183
Paul Mackerrase5b37ac2007-12-12 18:13:51 +11001184 if {$end > $vrowmod($curview)} {
Paul Mackerras9257d8f2007-12-11 10:45:38 +11001185 update_arcrows $curview
1186 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001187 set ai [bsearch $vrownum($curview) $start]
1188 set start [lindex $vrownum($curview) $ai]
1189 set narc [llength $vrownum($curview)]
1190 for {set r $start} {$ai < $narc && $r < $end} {incr ai} {
1191 set a [lindex $varcorder($curview) $ai]
1192 set l [llength $displayorder]
1193 set al [llength $varccommits($curview,$a)]
1194 if {$l < $r + $al} {
1195 if {$l < $r} {
1196 set pad [ntimes [expr {$r - $l}] {}]
1197 set displayorder [concat $displayorder $pad]
1198 set parentlist [concat $parentlist $pad]
1199 } elseif {$l > $r} {
1200 set displayorder [lrange $displayorder 0 [expr {$r - 1}]]
1201 set parentlist [lrange $parentlist 0 [expr {$r - 1}]]
1202 }
1203 foreach id $varccommits($curview,$a) {
1204 lappend displayorder $id
1205 lappend parentlist $parents($curview,$id)
1206 }
Paul Mackerras17529cf92008-01-12 21:46:31 +11001207 } elseif {[lindex $displayorder [expr {$r + $al - 1}]] eq {}} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001208 set i $r
1209 foreach id $varccommits($curview,$a) {
1210 lset displayorder $i $id
1211 lset parentlist $i $parents($curview,$id)
1212 incr i
1213 }
1214 }
1215 incr r $al
1216 }
1217}
1218
1219proc commitonrow {row} {
1220 global displayorder
1221
1222 set id [lindex $displayorder $row]
1223 if {$id eq {}} {
1224 make_disporder $row [expr {$row + 1}]
1225 set id [lindex $displayorder $row]
1226 }
1227 return $id
1228}
1229
1230proc closevarcs {v} {
1231 global varctok varccommits varcid parents children
Paul Mackerras9257d8f2007-12-11 10:45:38 +11001232 global cmitlisted commitidx commitinterest vtokmod
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001233
1234 set missing_parents 0
1235 set scripts {}
1236 set narcs [llength $varctok($v)]
1237 for {set a 1} {$a < $narcs} {incr a} {
1238 set id [lindex $varccommits($v,$a) end]
1239 foreach p $parents($v,$id) {
1240 if {[info exists varcid($v,$p)]} continue
1241 # add p as a new commit
1242 incr missing_parents
1243 set cmitlisted($v,$p) 0
1244 set parents($v,$p) {}
1245 if {[llength $children($v,$p)] == 1 &&
1246 [llength $parents($v,$id)] == 1} {
1247 set b $a
1248 } else {
1249 set b [newvarc $v $p]
1250 }
1251 set varcid($v,$p) $b
Paul Mackerras9257d8f2007-12-11 10:45:38 +11001252 if {[string compare [lindex $varctok($v) $b] $vtokmod($v)] < 0} {
1253 modify_arc $v $b
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001254 }
Paul Mackerrase5b37ac2007-12-12 18:13:51 +11001255 lappend varccommits($v,$b) $p
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001256 incr commitidx($v)
1257 if {[info exists commitinterest($p)]} {
1258 foreach script $commitinterest($p) {
1259 lappend scripts [string map [list "%I" $p] $script]
1260 }
1261 unset commitinterest($id)
1262 }
1263 }
1264 }
1265 if {$missing_parents > 0} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001266 foreach s $scripts {
1267 eval $s
1268 }
1269 }
1270}
1271
Paul Mackerrasf806f0f2008-02-24 12:16:56 +11001272# Use $rwid as a substitute for $id, i.e. reparent $id's children to $rwid
1273# Assumes we already have an arc for $rwid.
1274proc rewrite_commit {v id rwid} {
1275 global children parents varcid varctok vtokmod varccommits
1276
1277 foreach ch $children($v,$id) {
1278 # make $rwid be $ch's parent in place of $id
1279 set i [lsearch -exact $parents($v,$ch) $id]
1280 if {$i < 0} {
1281 puts "oops rewrite_commit didn't find $id in parent list for $ch"
1282 }
1283 set parents($v,$ch) [lreplace $parents($v,$ch) $i $i $rwid]
1284 # add $ch to $rwid's children and sort the list if necessary
1285 if {[llength [lappend children($v,$rwid) $ch]] > 1} {
1286 set children($v,$rwid) [lsort -command [list vtokcmp $v] \
1287 $children($v,$rwid)]
1288 }
1289 # fix the graph after joining $id to $rwid
1290 set a $varcid($v,$ch)
1291 fix_reversal $rwid $a $v
Paul Mackerrasc9cfdc92008-03-04 21:32:38 +11001292 # parentlist is wrong for the last element of arc $a
1293 # even if displayorder is right, hence the 3rd arg here
1294 modify_arc $v $a [expr {[llength $varccommits($v,$a)] - 1}]
Paul Mackerrasf806f0f2008-02-24 12:16:56 +11001295 }
1296}
1297
1298proc getcommitlines {fd inst view updating} {
Paul Mackerras24f7a662007-12-19 09:35:33 +11001299 global cmitlisted commitinterest leftover
Paul Mackerras3ed31a82008-04-26 16:00:00 +10001300 global commitidx commitdata vdatemode
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001301 global parents children curview hlview
Paul Mackerras468bcae2008-03-03 10:19:35 +11001302 global idpending ordertok
Paul Mackerras3ed31a82008-04-26 16:00:00 +10001303 global varccommits varcid varctok vtokmod vfilelimit
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +00001304
Paul Mackerrasd1e46752006-08-16 20:02:32 +10001305 set stuff [read $fd 500000]
Paul Mackerras005a2f42007-07-26 22:36:39 +10001306 # git log doesn't terminate the last commit with a null...
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001307 if {$stuff == {} && $leftover($inst) ne {} && [eof $fd]} {
Paul Mackerras005a2f42007-07-26 22:36:39 +10001308 set stuff "\0"
1309 }
Paul Mackerrasb490a992005-06-22 10:25:38 +10001310 if {$stuff == {}} {
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10001311 if {![eof $fd]} {
1312 return 1
1313 }
Paul Mackerras6df74032008-05-11 22:13:02 +10001314 global commfd viewcomplete viewactive viewname
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001315 global viewinstances
1316 unset commfd($inst)
1317 set i [lsearch -exact $viewinstances($view) $inst]
1318 if {$i >= 0} {
1319 set viewinstances($view) [lreplace $viewinstances($view) $i $i]
Paul Mackerrasb0cdca92007-08-23 19:35:51 +10001320 }
Paul Mackerrasf0654862005-07-18 14:29:03 -04001321 # set it blocking so we wait for the process to terminate
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10001322 fconfigure $fd -blocking 1
Paul Mackerras098dd8a2006-05-03 09:32:53 +10001323 if {[catch {close $fd} err]} {
1324 set fv {}
1325 if {$view != $curview} {
1326 set fv " for the \"$viewname($view)\" view"
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10001327 }
Paul Mackerras098dd8a2006-05-03 09:32:53 +10001328 if {[string range $err 0 4] == "usage"} {
1329 set err "Gitk: error reading commits$fv:\
Paul Mackerrasf9e0b6f2008-03-04 21:14:17 +11001330 bad arguments to git log."
Paul Mackerras098dd8a2006-05-03 09:32:53 +10001331 if {$viewname($view) eq "Command line"} {
1332 append err \
Paul Mackerrasf9e0b6f2008-03-04 21:14:17 +11001333 " (Note: arguments to gitk are passed to git log\
Paul Mackerras098dd8a2006-05-03 09:32:53 +10001334 to allow selection of commits to be displayed.)"
1335 }
1336 } else {
1337 set err "Error reading commits$fv: $err"
1338 }
1339 error_popup $err
Paul Mackerras1d10f362005-05-15 12:55:47 +00001340 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001341 if {[incr viewactive($view) -1] <= 0} {
1342 set viewcomplete($view) 1
1343 # Check if we have seen any ids listed as parents that haven't
1344 # appeared in the list
1345 closevarcs $view
1346 notbusy $view
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001347 }
Paul Mackerras098dd8a2006-05-03 09:32:53 +10001348 if {$view == $curview} {
Paul Mackerrasac1276a2008-03-03 10:11:08 +11001349 run chewcommits
Paul Mackerras9a40c502005-05-12 23:46:16 +00001350 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10001351 return 0
Paul Mackerras9a40c502005-05-12 23:46:16 +00001352 }
Paul Mackerrasb490a992005-06-22 10:25:38 +10001353 set start 0
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11001354 set gotsome 0
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001355 set scripts {}
Paul Mackerrasb490a992005-06-22 10:25:38 +10001356 while 1 {
1357 set i [string first "\0" $stuff $start]
1358 if {$i < 0} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001359 append leftover($inst) [string range $stuff $start end]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11001360 break
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +00001361 }
Paul Mackerrasb490a992005-06-22 10:25:38 +10001362 if {$start == 0} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001363 set cmit $leftover($inst)
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11001364 append cmit [string range $stuff 0 [expr {$i - 1}]]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001365 set leftover($inst) {}
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11001366 } else {
1367 set cmit [string range $stuff $start [expr {$i - 1}]]
Paul Mackerrasb490a992005-06-22 10:25:38 +10001368 }
1369 set start [expr {$i + 1}]
Paul Mackerrase5ea7012005-08-18 20:40:39 +10001370 set j [string first "\n" $cmit]
1371 set ok 0
Paul Mackerras16c1ff92006-03-30 18:43:51 +11001372 set listed 1
Paul Mackerrasc961b222007-07-09 22:45:47 +10001373 if {$j >= 0 && [string match "commit *" $cmit]} {
1374 set ids [string range $cmit 7 [expr {$j - 1}]]
Linus Torvalds1407ade2008-02-09 14:02:07 -08001375 if {[string match {[-^<>]*} $ids]} {
Paul Mackerrasc961b222007-07-09 22:45:47 +10001376 switch -- [string index $ids 0] {
1377 "-" {set listed 0}
Linus Torvalds1407ade2008-02-09 14:02:07 -08001378 "^" {set listed 2}
1379 "<" {set listed 3}
1380 ">" {set listed 4}
Paul Mackerrasc961b222007-07-09 22:45:47 +10001381 }
Paul Mackerras16c1ff92006-03-30 18:43:51 +11001382 set ids [string range $ids 1 end]
1383 }
Paul Mackerrase5ea7012005-08-18 20:40:39 +10001384 set ok 1
1385 foreach id $ids {
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11001386 if {[string length $id] != 40} {
Paul Mackerrase5ea7012005-08-18 20:40:39 +10001387 set ok 0
1388 break
1389 }
1390 }
1391 }
1392 if {!$ok} {
Paul Mackerras7e952e72005-06-27 20:04:26 +10001393 set shortcmit $cmit
1394 if {[string length $shortcmit] > 80} {
1395 set shortcmit "[string range $shortcmit 0 80]..."
1396 }
Christian Stimmingd990ced2007-11-07 18:42:55 +01001397 error_popup "[mc "Can't parse git log output:"] {$shortcmit}"
Paul Mackerrasb490a992005-06-22 10:25:38 +10001398 exit 1
1399 }
Paul Mackerrase5ea7012005-08-18 20:40:39 +10001400 set id [lindex $ids 0]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001401 set vid $view,$id
Paul Mackerrasf806f0f2008-02-24 12:16:56 +11001402
1403 if {!$listed && $updating && ![info exists varcid($vid)] &&
Paul Mackerras3ed31a82008-04-26 16:00:00 +10001404 $vfilelimit($view) ne {}} {
Paul Mackerrasf806f0f2008-02-24 12:16:56 +11001405 # git log doesn't rewrite parents for unlisted commits
1406 # when doing path limiting, so work around that here
1407 # by working out the rewritten parent with git rev-list
1408 # and if we already know about it, using the rewritten
1409 # parent as a substitute parent for $id's children.
1410 if {![catch {
1411 set rwid [exec git rev-list --first-parent --max-count=1 \
Paul Mackerras3ed31a82008-04-26 16:00:00 +10001412 $id -- $vfilelimit($view)]
Paul Mackerrasf806f0f2008-02-24 12:16:56 +11001413 }]} {
1414 if {$rwid ne {} && [info exists varcid($view,$rwid)]} {
1415 # use $rwid in place of $id
1416 rewrite_commit $view $id $rwid
1417 continue
1418 }
1419 }
1420 }
1421
Paul Mackerrasf1bf4ee2008-02-16 17:47:31 +11001422 set a 0
1423 if {[info exists varcid($vid)]} {
1424 if {$cmitlisted($vid) || !$listed} continue
1425 set a $varcid($vid)
1426 }
Paul Mackerras16c1ff92006-03-30 18:43:51 +11001427 if {$listed} {
1428 set olds [lrange $ids 1 end]
Paul Mackerras16c1ff92006-03-30 18:43:51 +11001429 } else {
1430 set olds {}
1431 }
Paul Mackerrasf7a3e8d2006-03-18 10:04:48 +11001432 set commitdata($id) [string range $cmit [expr {$j + 1}] end]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001433 set cmitlisted($vid) $listed
1434 set parents($vid) $olds
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001435 if {![info exists children($vid)]} {
1436 set children($vid) {}
Paul Mackerrasf1bf4ee2008-02-16 17:47:31 +11001437 } elseif {$a == 0 && [llength $children($vid)] == 1} {
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +11001438 set k [lindex $children($vid) 0]
1439 if {[llength $parents($view,$k)] == 1 &&
Paul Mackerras3ed31a82008-04-26 16:00:00 +10001440 (!$vdatemode($view) ||
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +11001441 $varcid($view,$k) == [llength $varctok($view)] - 1)} {
1442 set a $varcid($view,$k)
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001443 }
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10001444 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001445 if {$a == 0} {
1446 # new arc
1447 set a [newvarc $view $id]
1448 }
Paul Mackerrase5b37ac2007-12-12 18:13:51 +11001449 if {[string compare [lindex $varctok($view) $a] $vtokmod($view)] < 0} {
1450 modify_arc $view $a
1451 }
Paul Mackerrasf1bf4ee2008-02-16 17:47:31 +11001452 if {![info exists varcid($vid)]} {
1453 set varcid($vid) $a
1454 lappend varccommits($view,$a) $id
1455 incr commitidx($view)
1456 }
Paul Mackerrase5b37ac2007-12-12 18:13:51 +11001457
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001458 set i 0
1459 foreach p $olds {
1460 if {$i == 0 || [lsearch -exact $olds $p] >= $i} {
1461 set vp $view,$p
1462 if {[llength [lappend children($vp) $id]] > 1 &&
1463 [vtokcmp $view [lindex $children($vp) end-1] $id] > 0} {
1464 set children($vp) [lsort -command [list vtokcmp $view] \
1465 $children($vp)]
Paul Mackerras9257d8f2007-12-11 10:45:38 +11001466 catch {unset ordertok}
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001467 }
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +11001468 if {[info exists varcid($view,$p)]} {
1469 fix_reversal $p $a $view
1470 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001471 }
1472 incr i
1473 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001474
Paul Mackerras3e6b8932007-09-15 09:33:39 +10001475 if {[info exists commitinterest($id)]} {
1476 foreach script $commitinterest($id) {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001477 lappend scripts [string map [list "%I" $id] $script]
Paul Mackerras3e6b8932007-09-15 09:33:39 +10001478 }
1479 unset commitinterest($id)
1480 }
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11001481 set gotsome 1
Paul Mackerras9f1afe02006-02-19 22:44:47 +11001482 }
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11001483 if {$gotsome} {
Paul Mackerrasac1276a2008-03-03 10:11:08 +11001484 global numcommits hlview
1485
1486 if {$view == $curview} {
1487 set numcommits $commitidx($view)
1488 run chewcommits
1489 }
1490 if {[info exists hlview] && $view == $hlview} {
1491 # we never actually get here...
1492 run vhighlightmore
1493 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001494 foreach s $scripts {
1495 eval $s
1496 }
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11001497 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10001498 return 2
Paul Mackerrascfb45632005-05-31 12:14:42 +00001499}
1500
Paul Mackerrasac1276a2008-03-03 10:11:08 +11001501proc chewcommits {} {
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10001502 global curview hlview viewcomplete
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001503 global pending_select
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +00001504
Paul Mackerrasac1276a2008-03-03 10:11:08 +11001505 layoutmore
1506 if {$viewcomplete($curview)} {
1507 global commitidx varctok
1508 global numcommits startmsecs
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10001509
Paul Mackerrasac1276a2008-03-03 10:11:08 +11001510 if {[info exists pending_select]} {
Alexander Gavrilov835e62a2008-07-26 20:15:54 +04001511 update
1512 reset_pending_select {}
1513
1514 if {[commitinview $pending_select $curview]} {
1515 selectline [rowofcommit $pending_select] 1
1516 } else {
1517 set row [first_real_row]
1518 selectline $row 1
1519 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10001520 }
Paul Mackerrasac1276a2008-03-03 10:11:08 +11001521 if {$commitidx($curview) > 0} {
1522 #set ms [expr {[clock clicks -milliseconds] - $startmsecs}]
1523 #puts "overall $ms ms for $numcommits commits"
1524 #puts "[llength $varctok($view)] arcs, $commitidx($view) commits"
1525 } else {
1526 show_status [mc "No commits selected"]
1527 }
1528 notbusy layout
Paul Mackerrasb6645502005-08-11 09:56:23 +10001529 }
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10001530 return 0
Paul Mackerras1db95b02005-05-09 04:08:39 +00001531}
1532
1533proc readcommit {id} {
Timo Hirvonen8974c6f2006-05-24 10:57:40 +03001534 if {[catch {set contents [exec git cat-file commit $id]}]} return
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11001535 parsecommit $id $contents 0
Paul Mackerrasb490a992005-06-22 10:25:38 +10001536}
1537
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11001538proc parsecommit {id contents listed} {
Sven Verdoolaegeb5c2f302005-11-29 22:15:51 +01001539 global commitinfo cdate
1540
1541 set inhdr 1
1542 set comment {}
1543 set headline {}
1544 set auname {}
1545 set audate {}
1546 set comname {}
1547 set comdate {}
Paul Mackerras232475d2005-11-15 10:34:03 +11001548 set hdrend [string first "\n\n" $contents]
1549 if {$hdrend < 0} {
1550 # should never happen...
1551 set hdrend [string length $contents]
1552 }
1553 set header [string range $contents 0 [expr {$hdrend - 1}]]
1554 set comment [string range $contents [expr {$hdrend + 2}] end]
1555 foreach line [split $header "\n"] {
1556 set tag [lindex $line 0]
1557 if {$tag == "author"} {
1558 set audate [lindex $line end-1]
1559 set auname [lrange $line 1 end-2]
1560 } elseif {$tag == "committer"} {
1561 set comdate [lindex $line end-1]
1562 set comname [lrange $line 1 end-2]
Paul Mackerras1db95b02005-05-09 04:08:39 +00001563 }
1564 }
Paul Mackerras232475d2005-11-15 10:34:03 +11001565 set headline {}
Paul Mackerras43c25072006-09-27 10:56:02 +10001566 # take the first non-blank line of the comment as the headline
1567 set headline [string trimleft $comment]
1568 set i [string first "\n" $headline]
Paul Mackerras232475d2005-11-15 10:34:03 +11001569 if {$i >= 0} {
Paul Mackerras43c25072006-09-27 10:56:02 +10001570 set headline [string range $headline 0 $i]
1571 }
1572 set headline [string trimright $headline]
1573 set i [string first "\r" $headline]
1574 if {$i >= 0} {
1575 set headline [string trimright [string range $headline 0 $i]]
Paul Mackerras232475d2005-11-15 10:34:03 +11001576 }
1577 if {!$listed} {
Paul Mackerrasf9e0b6f2008-03-04 21:14:17 +11001578 # git log indents the comment by 4 spaces;
Timo Hirvonen8974c6f2006-05-24 10:57:40 +03001579 # if we got this via git cat-file, add the indentation
Paul Mackerras232475d2005-11-15 10:34:03 +11001580 set newcomment {}
1581 foreach line [split $comment "\n"] {
1582 append newcomment " "
1583 append newcomment $line
Paul Mackerrasf6e28692005-11-20 23:08:22 +11001584 append newcomment "\n"
Paul Mackerras232475d2005-11-15 10:34:03 +11001585 }
1586 set comment $newcomment
Paul Mackerras1db95b02005-05-09 04:08:39 +00001587 }
1588 if {$comdate != {}} {
Paul Mackerrascfb45632005-05-31 12:14:42 +00001589 set cdate($id) $comdate
Paul Mackerras1db95b02005-05-09 04:08:39 +00001590 }
Paul Mackerrase5c2d852005-05-11 23:44:54 +00001591 set commitinfo($id) [list $headline $auname $audate \
1592 $comname $comdate $comment]
Paul Mackerras1db95b02005-05-09 04:08:39 +00001593}
1594
Paul Mackerrasf7a3e8d2006-03-18 10:04:48 +11001595proc getcommit {id} {
Paul Mackerras79b2c752006-04-02 20:47:40 +10001596 global commitdata commitinfo
Paul Mackerras8ed16482006-03-02 22:56:44 +11001597
Paul Mackerrasf7a3e8d2006-03-18 10:04:48 +11001598 if {[info exists commitdata($id)]} {
1599 parsecommit $id $commitdata($id) 1
Paul Mackerras8ed16482006-03-02 22:56:44 +11001600 } else {
1601 readcommit $id
1602 if {![info exists commitinfo($id)]} {
Christian Stimmingd990ced2007-11-07 18:42:55 +01001603 set commitinfo($id) [list [mc "No commit information available"]]
Paul Mackerras8ed16482006-03-02 22:56:44 +11001604 }
1605 }
1606 return 1
1607}
1608
Paul Mackerras887fe3c2005-05-21 07:35:37 +00001609proc readrefs {} {
Paul Mackerras62d3ea62006-09-11 10:36:53 +10001610 global tagids idtags headids idheads tagobjid
Paul Mackerras219ea3a2006-09-07 10:21:39 +10001611 global otherrefids idotherrefs mainhead mainheadid
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10001612
Sven Verdoolaegeb5c2f302005-11-29 22:15:51 +01001613 foreach v {tagids idtags headids idheads otherrefids idotherrefs} {
1614 catch {unset $v}
1615 }
Paul Mackerras62d3ea62006-09-11 10:36:53 +10001616 set refd [open [list | git show-ref -d] r]
1617 while {[gets $refd line] >= 0} {
1618 if {[string index $line 40] ne " "} continue
1619 set id [string range $line 0 39]
1620 set ref [string range $line 41 end]
1621 if {![string match "refs/*" $ref]} continue
1622 set name [string range $ref 5 end]
1623 if {[string match "remotes/*" $name]} {
1624 if {![string match "*/HEAD" $name]} {
1625 set headids($name) $id
1626 lappend idheads($id) $name
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10001627 }
Paul Mackerras62d3ea62006-09-11 10:36:53 +10001628 } elseif {[string match "heads/*" $name]} {
1629 set name [string range $name 6 end]
Junio C Hamano36a7cad2005-11-18 23:54:17 -08001630 set headids($name) $id
1631 lappend idheads($id) $name
Paul Mackerras62d3ea62006-09-11 10:36:53 +10001632 } elseif {[string match "tags/*" $name]} {
1633 # this lets refs/tags/foo^{} overwrite refs/tags/foo,
1634 # which is what we want since the former is the commit ID
1635 set name [string range $name 5 end]
1636 if {[string match "*^{}" $name]} {
1637 set name [string range $name 0 end-3]
1638 } else {
1639 set tagobjid($name) $id
1640 }
1641 set tagids($name) $id
1642 lappend idtags($id) $name
Junio C Hamano36a7cad2005-11-18 23:54:17 -08001643 } else {
1644 set otherrefids($name) $id
1645 lappend idotherrefs($id) $name
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10001646 }
1647 }
Alex Riesen062d6712007-07-29 22:28:40 +02001648 catch {close $refd}
Paul Mackerras8a485712006-07-06 10:21:23 +10001649 set mainhead {}
Paul Mackerras219ea3a2006-09-07 10:21:39 +10001650 set mainheadid {}
Paul Mackerras8a485712006-07-06 10:21:23 +10001651 catch {
Paul Mackerrasc11ff122008-05-26 10:11:33 +10001652 set mainheadid [exec git rev-parse HEAD]
Paul Mackerras8a485712006-07-06 10:21:23 +10001653 set thehead [exec git symbolic-ref HEAD]
1654 if {[string match "refs/heads/*" $thehead]} {
1655 set mainhead [string range $thehead 11 end]
1656 }
1657 }
Paul Mackerras887fe3c2005-05-21 07:35:37 +00001658}
1659
Paul Mackerras8f489362007-07-13 19:49:37 +10001660# skip over fake commits
1661proc first_real_row {} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001662 global nullid nullid2 numcommits
Paul Mackerras8f489362007-07-13 19:49:37 +10001663
1664 for {set row 0} {$row < $numcommits} {incr row} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001665 set id [commitonrow $row]
Paul Mackerras8f489362007-07-13 19:49:37 +10001666 if {$id ne $nullid && $id ne $nullid2} {
1667 break
1668 }
1669 }
1670 return $row
1671}
1672
Paul Mackerrase11f1232007-06-16 20:29:25 +10001673# update things for a head moved to a child of its previous location
1674proc movehead {id name} {
1675 global headids idheads
1676
1677 removehead $headids($name) $name
1678 set headids($name) $id
1679 lappend idheads($id) $name
1680}
1681
1682# update things when a head has been removed
1683proc removehead {id name} {
1684 global headids idheads
1685
1686 if {$idheads($id) eq $name} {
1687 unset idheads($id)
1688 } else {
1689 set i [lsearch -exact $idheads($id) $name]
1690 if {$i >= 0} {
1691 set idheads($id) [lreplace $idheads($id) $i $i]
1692 }
1693 }
1694 unset headids($name)
1695}
1696
Paul Mackerrase54be9e2006-05-26 22:34:30 +10001697proc show_error {w top msg} {
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00001698 message $w.m -text $msg -justify center -aspect 400
1699 pack $w.m -side top -fill x -padx 20 -pady 20
Christian Stimmingd990ced2007-11-07 18:42:55 +01001700 button $w.ok -text [mc OK] -command "destroy $top"
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00001701 pack $w.ok -side bottom -fill x
Paul Mackerrase54be9e2006-05-26 22:34:30 +10001702 bind $top <Visibility> "grab $top; focus $top"
1703 bind $top <Key-Return> "destroy $top"
1704 tkwait window $top
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00001705}
1706
Paul Mackerras098dd8a2006-05-03 09:32:53 +10001707proc error_popup msg {
1708 set w .error
1709 toplevel $w
1710 wm transient $w .
Paul Mackerrase54be9e2006-05-26 22:34:30 +10001711 show_error $w $w $msg
Paul Mackerras098dd8a2006-05-03 09:32:53 +10001712}
1713
Paul Mackerras10299152006-08-02 09:52:01 +10001714proc confirm_popup msg {
1715 global confirm_ok
1716 set confirm_ok 0
1717 set w .confirm
1718 toplevel $w
1719 wm transient $w .
1720 message $w.m -text $msg -justify center -aspect 400
1721 pack $w.m -side top -fill x -padx 20 -pady 20
Christian Stimmingd990ced2007-11-07 18:42:55 +01001722 button $w.ok -text [mc OK] -command "set confirm_ok 1; destroy $w"
Paul Mackerras10299152006-08-02 09:52:01 +10001723 pack $w.ok -side left -fill x
Christian Stimmingd990ced2007-11-07 18:42:55 +01001724 button $w.cancel -text [mc Cancel] -command "destroy $w"
Paul Mackerras10299152006-08-02 09:52:01 +10001725 pack $w.cancel -side right -fill x
1726 bind $w <Visibility> "grab $w; focus $w"
1727 tkwait window $w
1728 return $confirm_ok
1729}
1730
Paul Mackerrasb039f0a2008-01-06 15:54:46 +11001731proc setoptions {} {
1732 option add *Panedwindow.showHandle 1 startupFile
1733 option add *Panedwindow.sashRelief raised startupFile
1734 option add *Button.font uifont startupFile
1735 option add *Checkbutton.font uifont startupFile
1736 option add *Radiobutton.font uifont startupFile
1737 option add *Menu.font uifont startupFile
1738 option add *Menubutton.font uifont startupFile
1739 option add *Label.font uifont startupFile
1740 option add *Message.font uifont startupFile
1741 option add *Entry.font uifont startupFile
1742}
1743
Paul Mackerrasd94f8cd2006-04-06 10:18:23 +10001744proc makewindow {} {
Paul Mackerras31c0eaa2007-12-30 22:41:14 +11001745 global canv canv2 canv3 linespc charspc ctext cflist cscroll
Paul Mackerras9c311b32007-10-04 22:27:13 +10001746 global tabstop
Paul Mackerrasb74fd572005-07-16 07:46:13 -04001747 global findtype findtypemenu findloc findstring fstring geometry
Paul Mackerras887fe3c2005-05-21 07:35:37 +00001748 global entries sha1entry sha1string sha1but
Steffen Prohaska890fae72007-08-12 12:05:46 +02001749 global diffcontextstring diffcontext
Steffen Prohaskab9b86002008-01-17 23:42:55 +01001750 global ignorespace
Paul Mackerras94a2eed2005-08-07 15:27:57 +10001751 global maincursor textcursor curtextcursor
Paul Mackerras219ea3a2006-09-07 10:21:39 +10001752 global rowctxmenu fakerowmenu mergemax wrapcomment
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10001753 global highlight_files gdttype
Paul Mackerras3ea06f92006-05-24 10:16:03 +10001754 global searchstring sstring
Mark Levedahl60378c02007-05-20 12:12:48 -04001755 global bgcolor fgcolor bglist fglist diffcolors selectbgcolor
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10001756 global headctxmenu progresscanv progressitem progresscoords statusw
1757 global fprogitem fprogcoord lastprogupdate progupdatepending
Paul Mackerras6df74032008-05-11 22:13:02 +10001758 global rprogitem rprogcoord rownumsel numcommits
Paul Mackerras32f1b3e2007-09-28 21:27:39 +10001759 global have_tk85
Paul Mackerras9a40c502005-05-12 23:46:16 +00001760
1761 menu .bar
Christian Stimmingd990ced2007-11-07 18:42:55 +01001762 .bar add cascade -label [mc "File"] -menu .bar.file
Paul Mackerras9a40c502005-05-12 23:46:16 +00001763 menu .bar.file
Christian Stimmingd990ced2007-11-07 18:42:55 +01001764 .bar.file add command -label [mc "Update"] -command updatecommits
Paul Mackerras00abadb2007-12-20 10:25:50 +11001765 .bar.file add command -label [mc "Reload"] -command reloadcommits
Christian Stimmingd990ced2007-11-07 18:42:55 +01001766 .bar.file add command -label [mc "Reread references"] -command rereadrefs
1767 .bar.file add command -label [mc "List references"] -command showrefs
1768 .bar.file add command -label [mc "Quit"] -command doquit
Paul Mackerras712fcc02005-11-30 09:28:16 +11001769 menu .bar.edit
Christian Stimmingd990ced2007-11-07 18:42:55 +01001770 .bar add cascade -label [mc "Edit"] -menu .bar.edit
1771 .bar.edit add command -label [mc "Preferences"] -command doprefs
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10001772
Paul Mackerrasb039f0a2008-01-06 15:54:46 +11001773 menu .bar.view
Christian Stimmingd990ced2007-11-07 18:42:55 +01001774 .bar add cascade -label [mc "View"] -menu .bar.view
1775 .bar.view add command -label [mc "New view..."] -command {newview 0}
1776 .bar.view add command -label [mc "Edit view..."] -command editview \
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10001777 -state disabled
Christian Stimmingd990ced2007-11-07 18:42:55 +01001778 .bar.view add command -label [mc "Delete view"] -command delview -state disabled
Paul Mackerras50b44ec2006-04-04 10:16:22 +10001779 .bar.view add separator
Christian Stimmingd990ced2007-11-07 18:42:55 +01001780 .bar.view add radiobutton -label [mc "All files"] -command {showview 0} \
Paul Mackerrasa90a6d22006-04-25 17:12:46 +10001781 -variable selectedview -value 0
Mark Levedahl40b87ff2007-02-01 08:44:46 -05001782
Paul Mackerras9a40c502005-05-12 23:46:16 +00001783 menu .bar.help
Christian Stimmingd990ced2007-11-07 18:42:55 +01001784 .bar add cascade -label [mc "Help"] -menu .bar.help
1785 .bar.help add command -label [mc "About gitk"] -command about
1786 .bar.help add command -label [mc "Key bindings"] -command keys
Paul Mackerrasb039f0a2008-01-06 15:54:46 +11001787 .bar.help configure
Paul Mackerras9a40c502005-05-12 23:46:16 +00001788 . configure -menu .bar
1789
Junio C Hamanoe9937d22007-02-01 08:46:38 -05001790 # the gui has upper and lower half, parts of a paned window.
Paul Mackerras0327d272005-05-10 00:23:42 +00001791 panedwindow .ctop -orient vertical
Junio C Hamanoe9937d22007-02-01 08:46:38 -05001792
1793 # possibly use assumed geometry
Mark Levedahl9ca72f42007-02-12 19:19:34 -05001794 if {![info exists geometry(pwsash0)]} {
Junio C Hamanoe9937d22007-02-01 08:46:38 -05001795 set geometry(topheight) [expr {15 * $linespc}]
1796 set geometry(topwidth) [expr {80 * $charspc}]
1797 set geometry(botheight) [expr {15 * $linespc}]
1798 set geometry(botwidth) [expr {50 * $charspc}]
Mark Levedahl9ca72f42007-02-12 19:19:34 -05001799 set geometry(pwsash0) "[expr {40 * $charspc}] 2"
1800 set geometry(pwsash1) "[expr {60 * $charspc}] 2"
Paul Mackerras0fba86b2005-05-16 23:54:58 +00001801 }
Junio C Hamanoe9937d22007-02-01 08:46:38 -05001802
1803 # the upper half will have a paned window, a scroll bar to the right, and some stuff below
1804 frame .tf -height $geometry(topheight) -width $geometry(topwidth)
1805 frame .tf.histframe
1806 panedwindow .tf.histframe.pwclist -orient horizontal -sashpad 0 -handlesize 4
1807
1808 # create three canvases
1809 set cscroll .tf.histframe.csb
1810 set canv .tf.histframe.pwclist.canv
Mark Levedahl9ca72f42007-02-12 19:19:34 -05001811 canvas $canv \
Mark Levedahl60378c02007-05-20 12:12:48 -04001812 -selectbackground $selectbgcolor \
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10001813 -background $bgcolor -bd 0 \
Paul Mackerras9f1afe02006-02-19 22:44:47 +11001814 -yscrollincr $linespc -yscrollcommand "scrollcanv $cscroll"
Junio C Hamanoe9937d22007-02-01 08:46:38 -05001815 .tf.histframe.pwclist add $canv
1816 set canv2 .tf.histframe.pwclist.canv2
Mark Levedahl9ca72f42007-02-12 19:19:34 -05001817 canvas $canv2 \
Mark Levedahl60378c02007-05-20 12:12:48 -04001818 -selectbackground $selectbgcolor \
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10001819 -background $bgcolor -bd 0 -yscrollincr $linespc
Junio C Hamanoe9937d22007-02-01 08:46:38 -05001820 .tf.histframe.pwclist add $canv2
1821 set canv3 .tf.histframe.pwclist.canv3
Mark Levedahl9ca72f42007-02-12 19:19:34 -05001822 canvas $canv3 \
Mark Levedahl60378c02007-05-20 12:12:48 -04001823 -selectbackground $selectbgcolor \
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10001824 -background $bgcolor -bd 0 -yscrollincr $linespc
Junio C Hamanoe9937d22007-02-01 08:46:38 -05001825 .tf.histframe.pwclist add $canv3
Mark Levedahl9ca72f42007-02-12 19:19:34 -05001826 eval .tf.histframe.pwclist sash place 0 $geometry(pwsash0)
1827 eval .tf.histframe.pwclist sash place 1 $geometry(pwsash1)
Paul Mackerras98f350e2005-05-15 05:56:51 +00001828
Junio C Hamanoe9937d22007-02-01 08:46:38 -05001829 # a scroll bar to rule them
1830 scrollbar $cscroll -command {allcanvs yview} -highlightthickness 0
1831 pack $cscroll -side right -fill y
1832 bind .tf.histframe.pwclist <Configure> {resizeclistpanes %W %w}
1833 lappend bglist $canv $canv2 $canv3
1834 pack .tf.histframe.pwclist -fill both -expand 1 -side left
1835
1836 # we have two button bars at bottom of top frame. Bar 1
1837 frame .tf.bar
1838 frame .tf.lbar -height 15
1839
1840 set sha1entry .tf.bar.sha1
Paul Mackerras887fe3c2005-05-21 07:35:37 +00001841 set entries $sha1entry
Junio C Hamanoe9937d22007-02-01 08:46:38 -05001842 set sha1but .tf.bar.sha1label
Christian Stimmingd990ced2007-11-07 18:42:55 +01001843 button $sha1but -text [mc "SHA1 ID: "] -state disabled -relief flat \
Paul Mackerrasb039f0a2008-01-06 15:54:46 +11001844 -command gotocommit -width 8
Paul Mackerras887fe3c2005-05-21 07:35:37 +00001845 $sha1but conf -disabledforeground [$sha1but cget -foreground]
Junio C Hamanoe9937d22007-02-01 08:46:38 -05001846 pack .tf.bar.sha1label -side left
Paul Mackerras9c311b32007-10-04 22:27:13 +10001847 entry $sha1entry -width 40 -font textfont -textvariable sha1string
Paul Mackerras887fe3c2005-05-21 07:35:37 +00001848 trace add variable sha1string write sha1change
Paul Mackerras98f350e2005-05-15 05:56:51 +00001849 pack $sha1entry -side left -pady 2
Paul Mackerrasd6982062005-08-06 22:06:06 +10001850
1851 image create bitmap bm-left -data {
1852 #define left_width 16
1853 #define left_height 16
1854 static unsigned char left_bits[] = {
1855 0x00, 0x00, 0xc0, 0x01, 0xe0, 0x00, 0x70, 0x00, 0x38, 0x00, 0x1c, 0x00,
1856 0x0e, 0x00, 0xff, 0x7f, 0xff, 0x7f, 0xff, 0x7f, 0x0e, 0x00, 0x1c, 0x00,
1857 0x38, 0x00, 0x70, 0x00, 0xe0, 0x00, 0xc0, 0x01};
1858 }
1859 image create bitmap bm-right -data {
1860 #define right_width 16
1861 #define right_height 16
1862 static unsigned char right_bits[] = {
1863 0x00, 0x00, 0xc0, 0x01, 0x80, 0x03, 0x00, 0x07, 0x00, 0x0e, 0x00, 0x1c,
1864 0x00, 0x38, 0xff, 0x7f, 0xff, 0x7f, 0xff, 0x7f, 0x00, 0x38, 0x00, 0x1c,
1865 0x00, 0x0e, 0x00, 0x07, 0x80, 0x03, 0xc0, 0x01};
1866 }
Junio C Hamanoe9937d22007-02-01 08:46:38 -05001867 button .tf.bar.leftbut -image bm-left -command goback \
Paul Mackerrasd6982062005-08-06 22:06:06 +10001868 -state disabled -width 26
Junio C Hamanoe9937d22007-02-01 08:46:38 -05001869 pack .tf.bar.leftbut -side left -fill y
1870 button .tf.bar.rightbut -image bm-right -command goforw \
Paul Mackerrasd6982062005-08-06 22:06:06 +10001871 -state disabled -width 26
Junio C Hamanoe9937d22007-02-01 08:46:38 -05001872 pack .tf.bar.rightbut -side left -fill y
Paul Mackerrasd6982062005-08-06 22:06:06 +10001873
Paul Mackerras6df74032008-05-11 22:13:02 +10001874 label .tf.bar.rowlabel -text [mc "Row"]
1875 set rownumsel {}
1876 label .tf.bar.rownum -width 7 -font textfont -textvariable rownumsel \
1877 -relief sunken -anchor e
1878 label .tf.bar.rowlabel2 -text "/"
1879 label .tf.bar.numcommits -width 7 -font textfont -textvariable numcommits \
1880 -relief sunken -anchor e
1881 pack .tf.bar.rowlabel .tf.bar.rownum .tf.bar.rowlabel2 .tf.bar.numcommits \
1882 -side left
1883 global selectedline
Paul Mackerras94b4a692008-05-20 20:51:06 +10001884 trace add variable selectedline write selectedline_change
Paul Mackerras6df74032008-05-11 22:13:02 +10001885
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10001886 # Status label and progress bar
1887 set statusw .tf.bar.status
Paul Mackerrasb039f0a2008-01-06 15:54:46 +11001888 label $statusw -width 15 -relief sunken
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10001889 pack $statusw -side left -padx 5
Paul Mackerras9c311b32007-10-04 22:27:13 +10001890 set h [expr {[font metrics uifont -linespace] + 2}]
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10001891 set progresscanv .tf.bar.progress
1892 canvas $progresscanv -relief sunken -height $h -borderwidth 2
1893 set progressitem [$progresscanv create rect -1 0 0 $h -fill green]
1894 set fprogitem [$progresscanv create rect -1 0 0 $h -fill yellow]
Paul Mackerrasa137a902007-10-23 21:12:49 +10001895 set rprogitem [$progresscanv create rect -1 0 0 $h -fill red]
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10001896 pack $progresscanv -side right -expand 1 -fill x
1897 set progresscoords {0 0}
1898 set fprogcoord 0
Paul Mackerrasa137a902007-10-23 21:12:49 +10001899 set rprogcoord 0
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10001900 bind $progresscanv <Configure> adjustprogress
1901 set lastprogupdate [clock clicks -milliseconds]
1902 set progupdatepending 0
Paul Mackerrasb5721c72005-05-10 12:08:22 +00001903
Junio C Hamanoe9937d22007-02-01 08:46:38 -05001904 # build up the bottom bar of upper window
Paul Mackerrasb039f0a2008-01-06 15:54:46 +11001905 label .tf.lbar.flabel -text "[mc "Find"] "
1906 button .tf.lbar.fnext -text [mc "next"] -command {dofind 1 1}
1907 button .tf.lbar.fprev -text [mc "prev"] -command {dofind -1 1}
1908 label .tf.lbar.flab2 -text " [mc "commit"] "
Paul Mackerras687c8762007-09-22 12:49:33 +10001909 pack .tf.lbar.flabel .tf.lbar.fnext .tf.lbar.fprev .tf.lbar.flab2 \
1910 -side left -fill y
Christian Stimmingb007ee22007-11-07 18:44:35 +01001911 set gdttype [mc "containing:"]
Paul Mackerras687c8762007-09-22 12:49:33 +10001912 set gm [tk_optionMenu .tf.lbar.gdttype gdttype \
Christian Stimmingb007ee22007-11-07 18:44:35 +01001913 [mc "containing:"] \
1914 [mc "touching paths:"] \
1915 [mc "adding/removing string:"]]
Paul Mackerras687c8762007-09-22 12:49:33 +10001916 trace add variable gdttype write gdttype_change
Junio C Hamanoe9937d22007-02-01 08:46:38 -05001917 pack .tf.lbar.gdttype -side left -fill y
Paul Mackerras687c8762007-09-22 12:49:33 +10001918
1919 set findstring {}
1920 set fstring .tf.lbar.findstring
1921 lappend entries $fstring
Paul Mackerras9c311b32007-10-04 22:27:13 +10001922 entry $fstring -width 30 -font textfont -textvariable findstring
Paul Mackerras687c8762007-09-22 12:49:33 +10001923 trace add variable findstring write find_change
Christian Stimmingb007ee22007-11-07 18:44:35 +01001924 set findtype [mc "Exact"]
Paul Mackerras687c8762007-09-22 12:49:33 +10001925 set findtypemenu [tk_optionMenu .tf.lbar.findtype \
Christian Stimmingb007ee22007-11-07 18:44:35 +01001926 findtype [mc "Exact"] [mc "IgnCase"] [mc "Regexp"]]
Paul Mackerras687c8762007-09-22 12:49:33 +10001927 trace add variable findtype write findcom_change
Christian Stimmingb007ee22007-11-07 18:44:35 +01001928 set findloc [mc "All fields"]
1929 tk_optionMenu .tf.lbar.findloc findloc [mc "All fields"] [mc "Headline"] \
1930 [mc "Comments"] [mc "Author"] [mc "Committer"]
Paul Mackerras687c8762007-09-22 12:49:33 +10001931 trace add variable findloc write find_change
Paul Mackerras687c8762007-09-22 12:49:33 +10001932 pack .tf.lbar.findloc -side right
1933 pack .tf.lbar.findtype -side right
1934 pack $fstring -side left -expand 1 -fill x
Paul Mackerras908c3582006-05-20 09:38:11 +10001935
Junio C Hamanoe9937d22007-02-01 08:46:38 -05001936 # Finish putting the upper half of the viewer together
1937 pack .tf.lbar -in .tf -side bottom -fill x
1938 pack .tf.bar -in .tf -side bottom -fill x
1939 pack .tf.histframe -fill both -side top -expand 1
1940 .ctop add .tf
Mark Levedahl9ca72f42007-02-12 19:19:34 -05001941 .ctop paneconfigure .tf -height $geometry(topheight)
1942 .ctop paneconfigure .tf -width $geometry(topwidth)
Junio C Hamanoe9937d22007-02-01 08:46:38 -05001943
1944 # now build up the bottom
1945 panedwindow .pwbottom -orient horizontal
1946
1947 # lower left, a text box over search bar, scroll bar to the right
1948 # if we know window height, then that will set the lower text height, otherwise
1949 # we set lower text height which will drive window height
1950 if {[info exists geometry(main)]} {
1951 frame .bleft -width $geometry(botwidth)
1952 } else {
1953 frame .bleft -width $geometry(botwidth) -height $geometry(botheight)
1954 }
1955 frame .bleft.top
Paul Mackerrasa8d610a2007-04-19 11:39:12 +10001956 frame .bleft.mid
Pekka Kaitaniemi8809d692008-03-08 14:27:23 +02001957 frame .bleft.bottom
Junio C Hamanoe9937d22007-02-01 08:46:38 -05001958
Paul Mackerrasb039f0a2008-01-06 15:54:46 +11001959 button .bleft.top.search -text [mc "Search"] -command dosearch
Junio C Hamanoe9937d22007-02-01 08:46:38 -05001960 pack .bleft.top.search -side left -padx 5
1961 set sstring .bleft.top.sstring
Paul Mackerras9c311b32007-10-04 22:27:13 +10001962 entry $sstring -width 20 -font textfont -textvariable searchstring
Paul Mackerras3ea06f92006-05-24 10:16:03 +10001963 lappend entries $sstring
1964 trace add variable searchstring write incrsearch
1965 pack $sstring -side left -expand 1 -fill x
Paul Mackerrasb039f0a2008-01-06 15:54:46 +11001966 radiobutton .bleft.mid.diff -text [mc "Diff"] \
Paul Mackerrasa8d610a2007-04-19 11:39:12 +10001967 -command changediffdisp -variable diffelide -value {0 0}
Paul Mackerrasb039f0a2008-01-06 15:54:46 +11001968 radiobutton .bleft.mid.old -text [mc "Old version"] \
Paul Mackerrasa8d610a2007-04-19 11:39:12 +10001969 -command changediffdisp -variable diffelide -value {0 1}
Paul Mackerrasb039f0a2008-01-06 15:54:46 +11001970 radiobutton .bleft.mid.new -text [mc "New version"] \
Paul Mackerrasa8d610a2007-04-19 11:39:12 +10001971 -command changediffdisp -variable diffelide -value {1 0}
Paul Mackerrasb039f0a2008-01-06 15:54:46 +11001972 label .bleft.mid.labeldiffcontext -text " [mc "Lines of context"]: "
Paul Mackerrasa8d610a2007-04-19 11:39:12 +10001973 pack .bleft.mid.diff .bleft.mid.old .bleft.mid.new -side left
Paul Mackerras9c311b32007-10-04 22:27:13 +10001974 spinbox .bleft.mid.diffcontext -width 5 -font textfont \
Steffen Prohaska890fae72007-08-12 12:05:46 +02001975 -from 1 -increment 1 -to 10000000 \
1976 -validate all -validatecommand "diffcontextvalidate %P" \
1977 -textvariable diffcontextstring
1978 .bleft.mid.diffcontext set $diffcontext
1979 trace add variable diffcontextstring write diffcontextchange
1980 lappend entries .bleft.mid.diffcontext
1981 pack .bleft.mid.labeldiffcontext .bleft.mid.diffcontext -side left
Steffen Prohaskab9b86002008-01-17 23:42:55 +01001982 checkbutton .bleft.mid.ignspace -text [mc "Ignore space change"] \
1983 -command changeignorespace -variable ignorespace
1984 pack .bleft.mid.ignspace -side left -padx 5
Pekka Kaitaniemi8809d692008-03-08 14:27:23 +02001985 set ctext .bleft.bottom.ctext
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10001986 text $ctext -background $bgcolor -foreground $fgcolor \
Paul Mackerras9c311b32007-10-04 22:27:13 +10001987 -state disabled -font textfont \
Pekka Kaitaniemi8809d692008-03-08 14:27:23 +02001988 -yscrollcommand scrolltext -wrap none \
1989 -xscrollcommand ".bleft.bottom.sbhorizontal set"
Paul Mackerras32f1b3e2007-09-28 21:27:39 +10001990 if {$have_tk85} {
1991 $ctext conf -tabstyle wordprocessor
1992 }
Pekka Kaitaniemi8809d692008-03-08 14:27:23 +02001993 scrollbar .bleft.bottom.sb -command "$ctext yview"
1994 scrollbar .bleft.bottom.sbhorizontal -command "$ctext xview" -orient h \
1995 -width 10
Junio C Hamanoe9937d22007-02-01 08:46:38 -05001996 pack .bleft.top -side top -fill x
Paul Mackerrasa8d610a2007-04-19 11:39:12 +10001997 pack .bleft.mid -side top -fill x
Pekka Kaitaniemi8809d692008-03-08 14:27:23 +02001998 grid $ctext .bleft.bottom.sb -sticky nsew
1999 grid .bleft.bottom.sbhorizontal -sticky ew
2000 grid columnconfigure .bleft.bottom 0 -weight 1
2001 grid rowconfigure .bleft.bottom 0 -weight 1
2002 grid rowconfigure .bleft.bottom 1 -weight 0
2003 pack .bleft.bottom -side top -fill both -expand 1
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10002004 lappend bglist $ctext
2005 lappend fglist $ctext
Paul Mackerrasd2610d12005-05-11 00:45:38 +00002006
Sergey Vlasovf1b86292006-05-15 19:13:14 +04002007 $ctext tag conf comment -wrap $wrapcomment
Paul Mackerras9c311b32007-10-04 22:27:13 +10002008 $ctext tag conf filesep -font textfontbold -back "#aaaaaa"
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10002009 $ctext tag conf hunksep -fore [lindex $diffcolors 2]
2010 $ctext tag conf d0 -fore [lindex $diffcolors 0]
2011 $ctext tag conf d1 -fore [lindex $diffcolors 1]
Paul Mackerras712fcc02005-11-30 09:28:16 +11002012 $ctext tag conf m0 -fore red
2013 $ctext tag conf m1 -fore blue
2014 $ctext tag conf m2 -fore green
2015 $ctext tag conf m3 -fore purple
2016 $ctext tag conf m4 -fore brown
Paul Mackerrasb77b0272006-02-07 09:13:52 +11002017 $ctext tag conf m5 -fore "#009090"
2018 $ctext tag conf m6 -fore magenta
2019 $ctext tag conf m7 -fore "#808000"
2020 $ctext tag conf m8 -fore "#009000"
2021 $ctext tag conf m9 -fore "#ff0080"
2022 $ctext tag conf m10 -fore cyan
2023 $ctext tag conf m11 -fore "#b07070"
2024 $ctext tag conf m12 -fore "#70b0f0"
2025 $ctext tag conf m13 -fore "#70f0b0"
2026 $ctext tag conf m14 -fore "#f0b070"
2027 $ctext tag conf m15 -fore "#ff70b0"
Paul Mackerras712fcc02005-11-30 09:28:16 +11002028 $ctext tag conf mmax -fore darkgrey
Paul Mackerrasb77b0272006-02-07 09:13:52 +11002029 set mergemax 16
Paul Mackerras9c311b32007-10-04 22:27:13 +10002030 $ctext tag conf mresult -font textfontbold
2031 $ctext tag conf msep -font textfontbold
Paul Mackerras712fcc02005-11-30 09:28:16 +11002032 $ctext tag conf found -back yellow
Paul Mackerrase5c2d852005-05-11 23:44:54 +00002033
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002034 .pwbottom add .bleft
Mark Levedahl9ca72f42007-02-12 19:19:34 -05002035 .pwbottom paneconfigure .bleft -width $geometry(botwidth)
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002036
2037 # lower right
2038 frame .bright
2039 frame .bright.mode
Christian Stimmingd990ced2007-11-07 18:42:55 +01002040 radiobutton .bright.mode.patch -text [mc "Patch"] \
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10002041 -command reselectline -variable cmitmode -value "patch"
Christian Stimmingd990ced2007-11-07 18:42:55 +01002042 radiobutton .bright.mode.tree -text [mc "Tree"] \
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10002043 -command reselectline -variable cmitmode -value "tree"
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002044 grid .bright.mode.patch .bright.mode.tree -sticky ew
2045 pack .bright.mode -side top -fill x
2046 set cflist .bright.cfiles
Paul Mackerras9c311b32007-10-04 22:27:13 +10002047 set indent [font measure mainfont "nn"]
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002048 text $cflist \
Mark Levedahl60378c02007-05-20 12:12:48 -04002049 -selectbackground $selectbgcolor \
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10002050 -background $bgcolor -foreground $fgcolor \
Paul Mackerras9c311b32007-10-04 22:27:13 +10002051 -font mainfont \
Paul Mackerras7fcceed2006-04-27 19:21:49 +10002052 -tabs [list $indent [expr {2 * $indent}]] \
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002053 -yscrollcommand ".bright.sb set" \
Paul Mackerras7fcceed2006-04-27 19:21:49 +10002054 -cursor [. cget -cursor] \
2055 -spacing1 1 -spacing3 1
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10002056 lappend bglist $cflist
2057 lappend fglist $cflist
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002058 scrollbar .bright.sb -command "$cflist yview"
2059 pack .bright.sb -side right -fill y
Paul Mackerrasd2610d12005-05-11 00:45:38 +00002060 pack $cflist -side left -fill both -expand 1
Paul Mackerras89b11d32006-05-02 19:55:31 +10002061 $cflist tag configure highlight \
2062 -background [$cflist cget -selectbackground]
Paul Mackerras9c311b32007-10-04 22:27:13 +10002063 $cflist tag configure bold -font mainfontbold
Paul Mackerrasd2610d12005-05-11 00:45:38 +00002064
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002065 .pwbottom add .bright
2066 .ctop add .pwbottom
Paul Mackerras1db95b02005-05-09 04:08:39 +00002067
Paul Mackerrasb9bee112008-03-10 16:50:34 +11002068 # restore window width & height if known
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002069 if {[info exists geometry(main)]} {
Paul Mackerrasb9bee112008-03-10 16:50:34 +11002070 if {[scan $geometry(main) "%dx%d" w h] >= 2} {
2071 if {$w > [winfo screenwidth .]} {
2072 set w [winfo screenwidth .]
2073 }
2074 if {$h > [winfo screenheight .]} {
2075 set h [winfo screenheight .]
2076 }
2077 wm geometry . "${w}x$h"
2078 }
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002079 }
2080
Shawn O. Pearced23d98d2007-07-19 00:37:58 -04002081 if {[tk windowingsystem] eq {aqua}} {
2082 set M1B M1
2083 } else {
2084 set M1B Control
2085 }
2086
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002087 bind .pwbottom <Configure> {resizecdetpanes %W %w}
2088 pack .ctop -fill both -expand 1
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10002089 bindall <1> {selcanvline %W %x %y}
2090 #bindall <B1-Motion> {selcanvline %W %x %y}
Mark Levedahl314c3092007-08-07 21:40:35 -04002091 if {[tk windowingsystem] == "win32"} {
2092 bind . <MouseWheel> { windows_mousewheel_redirector %W %X %Y %D }
2093 bind $ctext <MouseWheel> { windows_mousewheel_redirector %W %X %Y %D ; break }
2094 } else {
2095 bindall <ButtonRelease-4> "allcanvs yview scroll -5 units"
2096 bindall <ButtonRelease-5> "allcanvs yview scroll 5 units"
Jonathan del Strother5dd57d52007-10-15 10:33:07 +01002097 if {[tk windowingsystem] eq "aqua"} {
2098 bindall <MouseWheel> {
2099 set delta [expr {- (%D)}]
2100 allcanvs yview scroll $delta units
2101 }
2102 }
Mark Levedahl314c3092007-08-07 21:40:35 -04002103 }
Paul Mackerrasbe0cd092006-03-31 09:55:11 +11002104 bindall <2> "canvscan mark %W %x %y"
2105 bindall <B2-Motion> "canvscan dragto %W %x %y"
Rutger Nijlunsing6e5f7202006-04-05 10:24:03 +10002106 bindkey <Home> selfirstline
2107 bindkey <End> sellastline
Paul Mackerras17386062005-05-18 22:51:00 +00002108 bind . <Key-Up> "selnextline -1"
2109 bind . <Key-Down> "selnextline 1"
Paul Mackerrascca5d942007-10-27 21:16:56 +10002110 bind . <Shift-Key-Up> "dofind -1 0"
2111 bind . <Shift-Key-Down> "dofind 1 0"
Rutger Nijlunsing6e5f7202006-04-05 10:24:03 +10002112 bindkey <Key-Right> "goforw"
2113 bindkey <Key-Left> "goback"
2114 bind . <Key-Prior> "selnextpage -1"
2115 bind . <Key-Next> "selnextpage 1"
Shawn O. Pearced23d98d2007-07-19 00:37:58 -04002116 bind . <$M1B-Home> "allcanvs yview moveto 0.0"
2117 bind . <$M1B-End> "allcanvs yview moveto 1.0"
2118 bind . <$M1B-Key-Up> "allcanvs yview scroll -1 units"
2119 bind . <$M1B-Key-Down> "allcanvs yview scroll 1 units"
2120 bind . <$M1B-Key-Prior> "allcanvs yview scroll -1 pages"
2121 bind . <$M1B-Key-Next> "allcanvs yview scroll 1 pages"
Paul Mackerrascfb45632005-05-31 12:14:42 +00002122 bindkey <Key-Delete> "$ctext yview scroll -1 pages"
2123 bindkey <Key-BackSpace> "$ctext yview scroll -1 pages"
2124 bindkey <Key-space> "$ctext yview scroll 1 pages"
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00002125 bindkey p "selnextline -1"
2126 bindkey n "selnextline 1"
Robert Suetterlin6e2dda32005-09-22 10:07:36 +10002127 bindkey z "goback"
2128 bindkey x "goforw"
2129 bindkey i "selnextline -1"
2130 bindkey k "selnextline 1"
2131 bindkey j "goback"
2132 bindkey l "goforw"
Paul Mackerrasf4c54b32008-05-10 13:15:36 +10002133 bindkey b prevfile
Paul Mackerrascfb45632005-05-31 12:14:42 +00002134 bindkey d "$ctext yview scroll 18 units"
2135 bindkey u "$ctext yview scroll -18 units"
Paul Mackerrascca5d942007-10-27 21:16:56 +10002136 bindkey / {dofind 1 1}
2137 bindkey <Key-Return> {dofind 1 1}
2138 bindkey ? {dofind -1 1}
Paul Mackerras39ad8572005-05-19 12:35:53 +00002139 bindkey f nextfile
Eric Wonge7a09192007-02-23 12:36:34 -08002140 bindkey <F5> updatecommits
Shawn O. Pearced23d98d2007-07-19 00:37:58 -04002141 bind . <$M1B-q> doquit
Paul Mackerrascca5d942007-10-27 21:16:56 +10002142 bind . <$M1B-f> {dofind 1 1}
2143 bind . <$M1B-g> {dofind 1 0}
Shawn O. Pearced23d98d2007-07-19 00:37:58 -04002144 bind . <$M1B-r> dosearchback
2145 bind . <$M1B-s> dosearch
2146 bind . <$M1B-equal> {incrfont 1}
Johannes Schindelin646f3a12008-01-11 12:39:33 +00002147 bind . <$M1B-plus> {incrfont 1}
Shawn O. Pearced23d98d2007-07-19 00:37:58 -04002148 bind . <$M1B-KP_Add> {incrfont 1}
2149 bind . <$M1B-minus> {incrfont -1}
2150 bind . <$M1B-KP_Subtract> {incrfont -1}
Mark Levedahlb6047c52007-02-08 22:22:24 -05002151 wm protocol . WM_DELETE_WINDOW doquit
Alexander Gavrilove2f90ee2008-07-12 16:09:28 +04002152 bind . <Destroy> {stop_backends}
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00002153 bind . <Button-1> "click %W"
Paul Mackerrascca5d942007-10-27 21:16:56 +10002154 bind $fstring <Key-Return> {dofind 1 1}
Paul Mackerras887fe3c2005-05-21 07:35:37 +00002155 bind $sha1entry <Key-Return> gotocommit
Paul Mackerrasee3dc722005-06-25 16:37:13 +10002156 bind $sha1entry <<PasteSelection>> clearsha1
Paul Mackerras7fcceed2006-04-27 19:21:49 +10002157 bind $cflist <1> {sel_flist %W %x %y; break}
2158 bind $cflist <B1-Motion> {sel_flist %W %x %y; break}
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10002159 bind $cflist <ButtonRelease-1> {treeclick %W %x %y}
Paul Mackerras32447292007-07-27 22:30:15 +10002160 bind $cflist <Button-3> {pop_flist_menu %W %X %Y %x %y}
Paul Mackerrasea13cba2005-06-16 10:54:04 +00002161
2162 set maincursor [. cget -cursor]
2163 set textcursor [$ctext cget -cursor]
Paul Mackerras94a2eed2005-08-07 15:27:57 +10002164 set curtextcursor $textcursor
Paul Mackerras84ba7342005-06-17 00:12:26 +00002165
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10002166 set rowctxmenu .rowctxmenu
2167 menu $rowctxmenu -tearoff 0
Christian Stimmingd990ced2007-11-07 18:42:55 +01002168 $rowctxmenu add command -label [mc "Diff this -> selected"] \
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10002169 -command {diffvssel 0}
Christian Stimmingd990ced2007-11-07 18:42:55 +01002170 $rowctxmenu add command -label [mc "Diff selected -> this"] \
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10002171 -command {diffvssel 1}
Christian Stimmingd990ced2007-11-07 18:42:55 +01002172 $rowctxmenu add command -label [mc "Make patch"] -command mkpatch
2173 $rowctxmenu add command -label [mc "Create tag"] -command mktag
2174 $rowctxmenu add command -label [mc "Write commit to file"] -command writecommit
2175 $rowctxmenu add command -label [mc "Create new branch"] -command mkbranch
2176 $rowctxmenu add command -label [mc "Cherry-pick this commit"] \
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10002177 -command cherrypick
Christian Stimmingd990ced2007-11-07 18:42:55 +01002178 $rowctxmenu add command -label [mc "Reset HEAD branch to here"] \
Paul Mackerras6fb735a2006-10-19 10:09:06 +10002179 -command resethead
Paul Mackerras10299152006-08-02 09:52:01 +10002180
Paul Mackerras219ea3a2006-09-07 10:21:39 +10002181 set fakerowmenu .fakerowmenu
2182 menu $fakerowmenu -tearoff 0
Christian Stimmingd990ced2007-11-07 18:42:55 +01002183 $fakerowmenu add command -label [mc "Diff this -> selected"] \
Paul Mackerras219ea3a2006-09-07 10:21:39 +10002184 -command {diffvssel 0}
Christian Stimmingd990ced2007-11-07 18:42:55 +01002185 $fakerowmenu add command -label [mc "Diff selected -> this"] \
Paul Mackerras219ea3a2006-09-07 10:21:39 +10002186 -command {diffvssel 1}
Christian Stimmingd990ced2007-11-07 18:42:55 +01002187 $fakerowmenu add command -label [mc "Make patch"] -command mkpatch
2188# $fakerowmenu add command -label [mc "Commit"] -command {mkcommit 0}
2189# $fakerowmenu add command -label [mc "Commit all"] -command {mkcommit 1}
2190# $fakerowmenu add command -label [mc "Revert local changes"] -command revertlocal
Paul Mackerras219ea3a2006-09-07 10:21:39 +10002191
Paul Mackerras10299152006-08-02 09:52:01 +10002192 set headctxmenu .headctxmenu
2193 menu $headctxmenu -tearoff 0
Christian Stimmingd990ced2007-11-07 18:42:55 +01002194 $headctxmenu add command -label [mc "Check out this branch"] \
Paul Mackerras10299152006-08-02 09:52:01 +10002195 -command cobranch
Christian Stimmingd990ced2007-11-07 18:42:55 +01002196 $headctxmenu add command -label [mc "Remove this branch"] \
Paul Mackerras10299152006-08-02 09:52:01 +10002197 -command rmbranch
Paul Mackerras32447292007-07-27 22:30:15 +10002198
2199 global flist_menu
2200 set flist_menu .flistctxmenu
2201 menu $flist_menu -tearoff 0
Christian Stimmingd990ced2007-11-07 18:42:55 +01002202 $flist_menu add command -label [mc "Highlight this too"] \
Paul Mackerras32447292007-07-27 22:30:15 +10002203 -command {flist_hl 0}
Christian Stimmingd990ced2007-11-07 18:42:55 +01002204 $flist_menu add command -label [mc "Highlight this only"] \
Paul Mackerras32447292007-07-27 22:30:15 +10002205 -command {flist_hl 1}
Thomas Arcila314f5de2008-03-24 12:55:36 +01002206 $flist_menu add command -label [mc "External diff"] \
2207 -command {external_diff}
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00002208}
2209
Mark Levedahl314c3092007-08-07 21:40:35 -04002210# Windows sends all mouse wheel events to the current focused window, not
2211# the one where the mouse hovers, so bind those events here and redirect
2212# to the correct window
2213proc windows_mousewheel_redirector {W X Y D} {
2214 global canv canv2 canv3
2215 set w [winfo containing -displayof $W $X $Y]
2216 if {$w ne ""} {
2217 set u [expr {$D < 0 ? 5 : -5}]
2218 if {$w == $canv || $w == $canv2 || $w == $canv3} {
2219 allcanvs yview scroll $u units
2220 } else {
2221 catch {
2222 $w yview scroll $u units
2223 }
2224 }
2225 }
2226}
2227
Paul Mackerras6df74032008-05-11 22:13:02 +10002228# Update row number label when selectedline changes
2229proc selectedline_change {n1 n2 op} {
2230 global selectedline rownumsel
2231
Paul Mackerras94b4a692008-05-20 20:51:06 +10002232 if {$selectedline eq {}} {
Paul Mackerras6df74032008-05-11 22:13:02 +10002233 set rownumsel {}
2234 } else {
2235 set rownumsel [expr {$selectedline + 1}]
2236 }
2237}
2238
Paul Mackerrasbe0cd092006-03-31 09:55:11 +11002239# mouse-2 makes all windows scan vertically, but only the one
2240# the cursor is in scans horizontally
2241proc canvscan {op w x y} {
2242 global canv canv2 canv3
2243 foreach c [list $canv $canv2 $canv3] {
2244 if {$c == $w} {
2245 $c scan $op $x $y
2246 } else {
2247 $c scan $op 0 $y
2248 }
2249 }
2250}
2251
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002252proc scrollcanv {cscroll f0 f1} {
2253 $cscroll set $f0 $f1
Paul Mackerras31c0eaa2007-12-30 22:41:14 +11002254 drawvisible
Paul Mackerras908c3582006-05-20 09:38:11 +10002255 flushhighlights
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002256}
2257
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00002258# when we make a key binding for the toplevel, make sure
2259# it doesn't get triggered when that key is pressed in the
2260# find string entry widget.
2261proc bindkey {ev script} {
Paul Mackerras887fe3c2005-05-21 07:35:37 +00002262 global entries
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00002263 bind . $ev $script
2264 set escript [bind Entry $ev]
2265 if {$escript == {}} {
2266 set escript [bind Entry <Key>]
2267 }
Paul Mackerras887fe3c2005-05-21 07:35:37 +00002268 foreach e $entries {
2269 bind $e $ev "$escript; break"
2270 }
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00002271}
2272
2273# set the focus back to the toplevel for any click outside
Paul Mackerras887fe3c2005-05-21 07:35:37 +00002274# the entry widgets
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00002275proc click {w} {
Mark Levedahlbd441de2007-08-07 21:40:34 -04002276 global ctext entries
2277 foreach e [concat $entries $ctext] {
Paul Mackerras887fe3c2005-05-21 07:35:37 +00002278 if {$w == $e} return
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00002279 }
Paul Mackerras887fe3c2005-05-21 07:35:37 +00002280 focus .
Paul Mackerras0fba86b2005-05-16 23:54:58 +00002281}
2282
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10002283# Adjust the progress bar for a change in requested extent or canvas size
2284proc adjustprogress {} {
2285 global progresscanv progressitem progresscoords
2286 global fprogitem fprogcoord lastprogupdate progupdatepending
Paul Mackerrasa137a902007-10-23 21:12:49 +10002287 global rprogitem rprogcoord
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10002288
2289 set w [expr {[winfo width $progresscanv] - 4}]
2290 set x0 [expr {$w * [lindex $progresscoords 0]}]
2291 set x1 [expr {$w * [lindex $progresscoords 1]}]
2292 set h [winfo height $progresscanv]
2293 $progresscanv coords $progressitem $x0 0 $x1 $h
2294 $progresscanv coords $fprogitem 0 0 [expr {$w * $fprogcoord}] $h
Paul Mackerrasa137a902007-10-23 21:12:49 +10002295 $progresscanv coords $rprogitem 0 0 [expr {$w * $rprogcoord}] $h
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10002296 set now [clock clicks -milliseconds]
2297 if {$now >= $lastprogupdate + 100} {
2298 set progupdatepending 0
2299 update
2300 } elseif {!$progupdatepending} {
2301 set progupdatepending 1
2302 after [expr {$lastprogupdate + 100 - $now}] doprogupdate
2303 }
2304}
2305
2306proc doprogupdate {} {
2307 global lastprogupdate progupdatepending
2308
2309 if {$progupdatepending} {
2310 set progupdatepending 0
2311 set lastprogupdate [clock clicks -milliseconds]
2312 update
2313 }
2314}
2315
Paul Mackerras0fba86b2005-05-16 23:54:58 +00002316proc savestuff {w} {
Paul Mackerras32f1b3e2007-09-28 21:27:39 +10002317 global canv canv2 canv3 mainfont textfont uifont tabstop
Paul Mackerras712fcc02005-11-30 09:28:16 +11002318 global stuffsaved findmergefiles maxgraphpct
Paul Mackerras219ea3a2006-09-07 10:21:39 +10002319 global maxwidth showneartags showlocalchanges
Yann Dirson2d480852008-02-21 21:23:31 +01002320 global viewname viewfiles viewargs viewargscmd viewperm nextviewnum
Paul Mackerras7a39a172007-10-23 10:15:11 +10002321 global cmitmode wrapcomment datetimeformat limitdiffs
Steffen Prohaska890fae72007-08-12 12:05:46 +02002322 global colors bgcolor fgcolor diffcolors diffcontext selectbgcolor
Thomas Arcila314f5de2008-03-24 12:55:36 +01002323 global autoselect extdifftool
Paul Mackerras4ef17532005-07-27 22:16:51 -05002324
Paul Mackerras0fba86b2005-05-16 23:54:58 +00002325 if {$stuffsaved} return
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00002326 if {![winfo viewable .]} return
Paul Mackerras0fba86b2005-05-16 23:54:58 +00002327 catch {
2328 set f [open "~/.gitk-new" w]
Paul Mackerrasf0654862005-07-18 14:29:03 -04002329 puts $f [list set mainfont $mainfont]
2330 puts $f [list set textfont $textfont]
Keith Packard4840be62006-04-04 00:19:45 -07002331 puts $f [list set uifont $uifont]
Mark Levedahl7e12f1a2007-05-20 11:45:50 -04002332 puts $f [list set tabstop $tabstop]
Paul Mackerrasf0654862005-07-18 14:29:03 -04002333 puts $f [list set findmergefiles $findmergefiles]
Paul Mackerras8d858d12005-08-05 09:52:16 +10002334 puts $f [list set maxgraphpct $maxgraphpct]
Paul Mackerras04c13d32005-08-19 10:22:24 +10002335 puts $f [list set maxwidth $maxwidth]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10002336 puts $f [list set cmitmode $cmitmode]
Sergey Vlasovf1b86292006-05-15 19:13:14 +04002337 puts $f [list set wrapcomment $wrapcomment]
Jeff King95293b52008-03-06 06:49:25 -05002338 puts $f [list set autoselect $autoselect]
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10002339 puts $f [list set showneartags $showneartags]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10002340 puts $f [list set showlocalchanges $showlocalchanges]
Arjen Laarhovene8b5f4b2007-08-14 22:02:04 +02002341 puts $f [list set datetimeformat $datetimeformat]
Paul Mackerras7a39a172007-10-23 10:15:11 +10002342 puts $f [list set limitdiffs $limitdiffs]
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10002343 puts $f [list set bgcolor $bgcolor]
2344 puts $f [list set fgcolor $fgcolor]
2345 puts $f [list set colors $colors]
2346 puts $f [list set diffcolors $diffcolors]
Steffen Prohaska890fae72007-08-12 12:05:46 +02002347 puts $f [list set diffcontext $diffcontext]
Mark Levedahl60378c02007-05-20 12:12:48 -04002348 puts $f [list set selectbgcolor $selectbgcolor]
Thomas Arcila314f5de2008-03-24 12:55:36 +01002349 puts $f [list set extdifftool $extdifftool]
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002350
Mark Levedahlb6047c52007-02-08 22:22:24 -05002351 puts $f "set geometry(main) [wm geometry .]"
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002352 puts $f "set geometry(topwidth) [winfo width .tf]"
2353 puts $f "set geometry(topheight) [winfo height .tf]"
Mark Levedahl9ca72f42007-02-12 19:19:34 -05002354 puts $f "set geometry(pwsash0) \"[.tf.histframe.pwclist sash coord 0]\""
2355 puts $f "set geometry(pwsash1) \"[.tf.histframe.pwclist sash coord 1]\""
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002356 puts $f "set geometry(botwidth) [winfo width .bleft]"
2357 puts $f "set geometry(botheight) [winfo height .bleft]"
2358
Paul Mackerrasa90a6d22006-04-25 17:12:46 +10002359 puts -nonewline $f "set permviews {"
2360 for {set v 0} {$v < $nextviewnum} {incr v} {
2361 if {$viewperm($v)} {
Yann Dirson2d480852008-02-21 21:23:31 +01002362 puts $f "{[list $viewname($v) $viewfiles($v) $viewargs($v) $viewargscmd($v)]}"
Paul Mackerrasa90a6d22006-04-25 17:12:46 +10002363 }
2364 }
2365 puts $f "}"
Paul Mackerras0fba86b2005-05-16 23:54:58 +00002366 close $f
2367 file rename -force "~/.gitk-new" "~/.gitk"
2368 }
2369 set stuffsaved 1
Paul Mackerras1db95b02005-05-09 04:08:39 +00002370}
2371
Paul Mackerras43bddeb2005-05-15 23:19:18 +00002372proc resizeclistpanes {win w} {
2373 global oldwidth
Paul Mackerras418c4c72006-02-07 09:10:18 +11002374 if {[info exists oldwidth($win)]} {
Paul Mackerras43bddeb2005-05-15 23:19:18 +00002375 set s0 [$win sash coord 0]
2376 set s1 [$win sash coord 1]
2377 if {$w < 60} {
2378 set sash0 [expr {int($w/2 - 2)}]
2379 set sash1 [expr {int($w*5/6 - 2)}]
2380 } else {
2381 set factor [expr {1.0 * $w / $oldwidth($win)}]
2382 set sash0 [expr {int($factor * [lindex $s0 0])}]
2383 set sash1 [expr {int($factor * [lindex $s1 0])}]
2384 if {$sash0 < 30} {
2385 set sash0 30
2386 }
2387 if {$sash1 < $sash0 + 20} {
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08002388 set sash1 [expr {$sash0 + 20}]
Paul Mackerras43bddeb2005-05-15 23:19:18 +00002389 }
2390 if {$sash1 > $w - 10} {
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08002391 set sash1 [expr {$w - 10}]
Paul Mackerras43bddeb2005-05-15 23:19:18 +00002392 if {$sash0 > $sash1 - 20} {
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08002393 set sash0 [expr {$sash1 - 20}]
Paul Mackerras43bddeb2005-05-15 23:19:18 +00002394 }
2395 }
2396 }
2397 $win sash place 0 $sash0 [lindex $s0 1]
2398 $win sash place 1 $sash1 [lindex $s1 1]
2399 }
2400 set oldwidth($win) $w
2401}
2402
2403proc resizecdetpanes {win w} {
2404 global oldwidth
Paul Mackerras418c4c72006-02-07 09:10:18 +11002405 if {[info exists oldwidth($win)]} {
Paul Mackerras43bddeb2005-05-15 23:19:18 +00002406 set s0 [$win sash coord 0]
2407 if {$w < 60} {
2408 set sash0 [expr {int($w*3/4 - 2)}]
2409 } else {
2410 set factor [expr {1.0 * $w / $oldwidth($win)}]
2411 set sash0 [expr {int($factor * [lindex $s0 0])}]
2412 if {$sash0 < 45} {
2413 set sash0 45
2414 }
2415 if {$sash0 > $w - 15} {
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08002416 set sash0 [expr {$w - 15}]
Paul Mackerras43bddeb2005-05-15 23:19:18 +00002417 }
2418 }
2419 $win sash place 0 $sash0 [lindex $s0 1]
2420 }
2421 set oldwidth($win) $w
2422}
2423
Paul Mackerrasb5721c72005-05-10 12:08:22 +00002424proc allcanvs args {
2425 global canv canv2 canv3
2426 eval $canv $args
2427 eval $canv2 $args
2428 eval $canv3 $args
2429}
2430
2431proc bindall {event action} {
2432 global canv canv2 canv3
2433 bind $canv $event $action
2434 bind $canv2 $event $action
2435 bind $canv3 $event $action
2436}
2437
Paul Mackerras9a40c502005-05-12 23:46:16 +00002438proc about {} {
Eygene Ryabinkind59c4b62007-03-27 14:36:12 +04002439 global uifont
Paul Mackerras9a40c502005-05-12 23:46:16 +00002440 set w .about
2441 if {[winfo exists $w]} {
2442 raise $w
2443 return
2444 }
2445 toplevel $w
Christian Stimmingd990ced2007-11-07 18:42:55 +01002446 wm title $w [mc "About gitk"]
2447 message $w.m -text [mc "
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002448Gitk - a commit viewer for git
Paul Mackerras9a40c502005-05-12 23:46:16 +00002449
Paul Mackerrasee66e082008-05-09 10:14:07 +10002450Copyright © 2005-2008 Paul Mackerras
Paul Mackerras9a40c502005-05-12 23:46:16 +00002451
Christian Stimmingd990ced2007-11-07 18:42:55 +01002452Use and redistribute under the terms of the GNU General Public License"] \
Eygene Ryabinkin3a950e92007-03-27 14:36:59 +04002453 -justify center -aspect 400 -border 2 -bg white -relief groove
2454 pack $w.m -side top -fill x -padx 2 -pady 2
Christian Stimmingd990ced2007-11-07 18:42:55 +01002455 button $w.ok -text [mc "Close"] -command "destroy $w" -default active
Paul Mackerras9a40c502005-05-12 23:46:16 +00002456 pack $w.ok -side bottom
Eygene Ryabinkin3a950e92007-03-27 14:36:59 +04002457 bind $w <Visibility> "focus $w.ok"
2458 bind $w <Key-Escape> "destroy $w"
2459 bind $w <Key-Return> "destroy $w"
Paul Mackerras9a40c502005-05-12 23:46:16 +00002460}
2461
Paul Mackerras4e95e1f2006-04-05 09:39:51 +10002462proc keys {} {
2463 set w .keys
2464 if {[winfo exists $w]} {
2465 raise $w
2466 return
2467 }
Shawn O. Pearced23d98d2007-07-19 00:37:58 -04002468 if {[tk windowingsystem] eq {aqua}} {
2469 set M1T Cmd
2470 } else {
2471 set M1T Ctrl
2472 }
Paul Mackerras4e95e1f2006-04-05 09:39:51 +10002473 toplevel $w
Christian Stimmingd990ced2007-11-07 18:42:55 +01002474 wm title $w [mc "Gitk key bindings"]
Michele Ballabio3d2c9982008-01-15 23:31:49 +01002475 message $w.m -text "
2476[mc "Gitk key bindings:"]
Paul Mackerras4e95e1f2006-04-05 09:39:51 +10002477
Michele Ballabio3d2c9982008-01-15 23:31:49 +01002478[mc "<%s-Q> Quit" $M1T]
2479[mc "<Home> Move to first commit"]
2480[mc "<End> Move to last commit"]
2481[mc "<Up>, p, i Move up one commit"]
2482[mc "<Down>, n, k Move down one commit"]
2483[mc "<Left>, z, j Go back in history list"]
2484[mc "<Right>, x, l Go forward in history list"]
2485[mc "<PageUp> Move up one page in commit list"]
2486[mc "<PageDown> Move down one page in commit list"]
2487[mc "<%s-Home> Scroll to top of commit list" $M1T]
2488[mc "<%s-End> Scroll to bottom of commit list" $M1T]
2489[mc "<%s-Up> Scroll commit list up one line" $M1T]
2490[mc "<%s-Down> Scroll commit list down one line" $M1T]
2491[mc "<%s-PageUp> Scroll commit list up one page" $M1T]
2492[mc "<%s-PageDown> Scroll commit list down one page" $M1T]
2493[mc "<Shift-Up> Find backwards (upwards, later commits)"]
2494[mc "<Shift-Down> Find forwards (downwards, earlier commits)"]
2495[mc "<Delete>, b Scroll diff view up one page"]
2496[mc "<Backspace> Scroll diff view up one page"]
2497[mc "<Space> Scroll diff view down one page"]
2498[mc "u Scroll diff view up 18 lines"]
2499[mc "d Scroll diff view down 18 lines"]
2500[mc "<%s-F> Find" $M1T]
2501[mc "<%s-G> Move to next find hit" $M1T]
2502[mc "<Return> Move to next find hit"]
2503[mc "/ Move to next find hit, or redo find"]
2504[mc "? Move to previous find hit"]
2505[mc "f Scroll diff view to next file"]
2506[mc "<%s-S> Search for next hit in diff view" $M1T]
2507[mc "<%s-R> Search for previous hit in diff view" $M1T]
2508[mc "<%s-KP+> Increase font size" $M1T]
2509[mc "<%s-plus> Increase font size" $M1T]
2510[mc "<%s-KP-> Decrease font size" $M1T]
2511[mc "<%s-minus> Decrease font size" $M1T]
2512[mc "<F5> Update"]
2513" \
Eygene Ryabinkin3a950e92007-03-27 14:36:59 +04002514 -justify left -bg white -border 2 -relief groove
2515 pack $w.m -side top -fill both -padx 2 -pady 2
Christian Stimmingd990ced2007-11-07 18:42:55 +01002516 button $w.ok -text [mc "Close"] -command "destroy $w" -default active
Paul Mackerras4e95e1f2006-04-05 09:39:51 +10002517 pack $w.ok -side bottom
Eygene Ryabinkin3a950e92007-03-27 14:36:59 +04002518 bind $w <Visibility> "focus $w.ok"
2519 bind $w <Key-Escape> "destroy $w"
2520 bind $w <Key-Return> "destroy $w"
Paul Mackerras4e95e1f2006-04-05 09:39:51 +10002521}
2522
Paul Mackerras7fcceed2006-04-27 19:21:49 +10002523# Procedures for manipulating the file list window at the
2524# bottom right of the overall window.
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10002525
2526proc treeview {w l openlevs} {
2527 global treecontents treediropen treeheight treeparent treeindex
2528
2529 set ix 0
2530 set treeindex() 0
2531 set lev 0
2532 set prefix {}
2533 set prefixend -1
2534 set prefendstack {}
2535 set htstack {}
2536 set ht 0
2537 set treecontents() {}
2538 $w conf -state normal
2539 foreach f $l {
2540 while {[string range $f 0 $prefixend] ne $prefix} {
2541 if {$lev <= $openlevs} {
2542 $w mark set e:$treeindex($prefix) "end -1c"
2543 $w mark gravity e:$treeindex($prefix) left
2544 }
2545 set treeheight($prefix) $ht
2546 incr ht [lindex $htstack end]
2547 set htstack [lreplace $htstack end end]
2548 set prefixend [lindex $prefendstack end]
2549 set prefendstack [lreplace $prefendstack end end]
2550 set prefix [string range $prefix 0 $prefixend]
2551 incr lev -1
2552 }
2553 set tail [string range $f [expr {$prefixend+1}] end]
2554 while {[set slash [string first "/" $tail]] >= 0} {
2555 lappend htstack $ht
2556 set ht 0
2557 lappend prefendstack $prefixend
2558 incr prefixend [expr {$slash + 1}]
2559 set d [string range $tail 0 $slash]
2560 lappend treecontents($prefix) $d
2561 set oldprefix $prefix
2562 append prefix $d
2563 set treecontents($prefix) {}
2564 set treeindex($prefix) [incr ix]
2565 set treeparent($prefix) $oldprefix
2566 set tail [string range $tail [expr {$slash+1}] end]
2567 if {$lev <= $openlevs} {
2568 set ht 1
2569 set treediropen($prefix) [expr {$lev < $openlevs}]
2570 set bm [expr {$lev == $openlevs? "tri-rt": "tri-dn"}]
2571 $w mark set d:$ix "end -1c"
2572 $w mark gravity d:$ix left
2573 set str "\n"
2574 for {set i 0} {$i < $lev} {incr i} {append str "\t"}
2575 $w insert end $str
2576 $w image create end -align center -image $bm -padx 1 \
2577 -name a:$ix
Paul Mackerras45a9d502006-05-20 22:56:27 +10002578 $w insert end $d [highlight_tag $prefix]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10002579 $w mark set s:$ix "end -1c"
2580 $w mark gravity s:$ix left
2581 }
2582 incr lev
2583 }
2584 if {$tail ne {}} {
2585 if {$lev <= $openlevs} {
2586 incr ht
2587 set str "\n"
2588 for {set i 0} {$i < $lev} {incr i} {append str "\t"}
2589 $w insert end $str
Paul Mackerras45a9d502006-05-20 22:56:27 +10002590 $w insert end $tail [highlight_tag $f]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10002591 }
2592 lappend treecontents($prefix) $tail
2593 }
2594 }
2595 while {$htstack ne {}} {
2596 set treeheight($prefix) $ht
2597 incr ht [lindex $htstack end]
2598 set htstack [lreplace $htstack end end]
Brian Downing096e96b2007-07-05 06:33:02 -05002599 set prefixend [lindex $prefendstack end]
2600 set prefendstack [lreplace $prefendstack end end]
2601 set prefix [string range $prefix 0 $prefixend]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10002602 }
2603 $w conf -state disabled
2604}
2605
2606proc linetoelt {l} {
2607 global treeheight treecontents
2608
2609 set y 2
2610 set prefix {}
2611 while {1} {
2612 foreach e $treecontents($prefix) {
2613 if {$y == $l} {
2614 return "$prefix$e"
2615 }
2616 set n 1
2617 if {[string index $e end] eq "/"} {
2618 set n $treeheight($prefix$e)
2619 if {$y + $n > $l} {
2620 append prefix $e
2621 incr y
2622 break
2623 }
2624 }
2625 incr y $n
2626 }
2627 }
2628}
2629
Paul Mackerras45a9d502006-05-20 22:56:27 +10002630proc highlight_tree {y prefix} {
2631 global treeheight treecontents cflist
2632
2633 foreach e $treecontents($prefix) {
2634 set path $prefix$e
2635 if {[highlight_tag $path] ne {}} {
2636 $cflist tag add bold $y.0 "$y.0 lineend"
2637 }
2638 incr y
2639 if {[string index $e end] eq "/" && $treeheight($path) > 1} {
2640 set y [highlight_tree $y $path]
2641 }
2642 }
2643 return $y
2644}
2645
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10002646proc treeclosedir {w dir} {
2647 global treediropen treeheight treeparent treeindex
2648
2649 set ix $treeindex($dir)
2650 $w conf -state normal
2651 $w delete s:$ix e:$ix
2652 set treediropen($dir) 0
2653 $w image configure a:$ix -image tri-rt
2654 $w conf -state disabled
2655 set n [expr {1 - $treeheight($dir)}]
2656 while {$dir ne {}} {
2657 incr treeheight($dir) $n
2658 set dir $treeparent($dir)
2659 }
2660}
2661
2662proc treeopendir {w dir} {
2663 global treediropen treeheight treeparent treecontents treeindex
2664
2665 set ix $treeindex($dir)
2666 $w conf -state normal
2667 $w image configure a:$ix -image tri-dn
2668 $w mark set e:$ix s:$ix
2669 $w mark gravity e:$ix right
2670 set lev 0
2671 set str "\n"
2672 set n [llength $treecontents($dir)]
2673 for {set x $dir} {$x ne {}} {set x $treeparent($x)} {
2674 incr lev
2675 append str "\t"
2676 incr treeheight($x) $n
2677 }
2678 foreach e $treecontents($dir) {
Paul Mackerras45a9d502006-05-20 22:56:27 +10002679 set de $dir$e
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10002680 if {[string index $e end] eq "/"} {
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10002681 set iy $treeindex($de)
2682 $w mark set d:$iy e:$ix
2683 $w mark gravity d:$iy left
2684 $w insert e:$ix $str
2685 set treediropen($de) 0
2686 $w image create e:$ix -align center -image tri-rt -padx 1 \
2687 -name a:$iy
Paul Mackerras45a9d502006-05-20 22:56:27 +10002688 $w insert e:$ix $e [highlight_tag $de]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10002689 $w mark set s:$iy e:$ix
2690 $w mark gravity s:$iy left
2691 set treeheight($de) 1
2692 } else {
2693 $w insert e:$ix $str
Paul Mackerras45a9d502006-05-20 22:56:27 +10002694 $w insert e:$ix $e [highlight_tag $de]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10002695 }
2696 }
2697 $w mark gravity e:$ix left
2698 $w conf -state disabled
2699 set treediropen($dir) 1
2700 set top [lindex [split [$w index @0,0] .] 0]
2701 set ht [$w cget -height]
2702 set l [lindex [split [$w index s:$ix] .] 0]
2703 if {$l < $top} {
2704 $w yview $l.0
2705 } elseif {$l + $n + 1 > $top + $ht} {
2706 set top [expr {$l + $n + 2 - $ht}]
2707 if {$l < $top} {
2708 set top $l
2709 }
2710 $w yview $top.0
2711 }
2712}
2713
2714proc treeclick {w x y} {
2715 global treediropen cmitmode ctext cflist cflist_top
2716
2717 if {$cmitmode ne "tree"} return
2718 if {![info exists cflist_top]} return
2719 set l [lindex [split [$w index "@$x,$y"] "."] 0]
2720 $cflist tag remove highlight $cflist_top.0 "$cflist_top.0 lineend"
2721 $cflist tag add highlight $l.0 "$l.0 lineend"
2722 set cflist_top $l
2723 if {$l == 1} {
2724 $ctext yview 1.0
2725 return
2726 }
2727 set e [linetoelt $l]
2728 if {[string index $e end] ne "/"} {
2729 showfile $e
2730 } elseif {$treediropen($e)} {
2731 treeclosedir $w $e
2732 } else {
2733 treeopendir $w $e
2734 }
2735}
2736
2737proc setfilelist {id} {
2738 global treefilelist cflist
2739
2740 treeview $cflist $treefilelist($id) 0
2741}
2742
2743image create bitmap tri-rt -background black -foreground blue -data {
2744 #define tri-rt_width 13
2745 #define tri-rt_height 13
2746 static unsigned char tri-rt_bits[] = {
2747 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x30, 0x00, 0x70, 0x00, 0xf0, 0x00,
2748 0xf0, 0x01, 0xf0, 0x00, 0x70, 0x00, 0x30, 0x00, 0x10, 0x00, 0x00, 0x00,
2749 0x00, 0x00};
2750} -maskdata {
2751 #define tri-rt-mask_width 13
2752 #define tri-rt-mask_height 13
2753 static unsigned char tri-rt-mask_bits[] = {
2754 0x08, 0x00, 0x18, 0x00, 0x38, 0x00, 0x78, 0x00, 0xf8, 0x00, 0xf8, 0x01,
2755 0xf8, 0x03, 0xf8, 0x01, 0xf8, 0x00, 0x78, 0x00, 0x38, 0x00, 0x18, 0x00,
2756 0x08, 0x00};
2757}
2758image create bitmap tri-dn -background black -foreground blue -data {
2759 #define tri-dn_width 13
2760 #define tri-dn_height 13
2761 static unsigned char tri-dn_bits[] = {
2762 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x07, 0xf8, 0x03,
2763 0xf0, 0x01, 0xe0, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2764 0x00, 0x00};
2765} -maskdata {
2766 #define tri-dn-mask_width 13
2767 #define tri-dn-mask_height 13
2768 static unsigned char tri-dn-mask_bits[] = {
2769 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x1f, 0xfe, 0x0f, 0xfc, 0x07,
2770 0xf8, 0x03, 0xf0, 0x01, 0xe0, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00,
2771 0x00, 0x00};
2772}
2773
Paul Mackerras887c9962007-08-20 19:36:20 +10002774image create bitmap reficon-T -background black -foreground yellow -data {
2775 #define tagicon_width 13
2776 #define tagicon_height 9
2777 static unsigned char tagicon_bits[] = {
2778 0x00, 0x00, 0x00, 0x00, 0xf0, 0x07, 0xf8, 0x07,
2779 0xfc, 0x07, 0xf8, 0x07, 0xf0, 0x07, 0x00, 0x00, 0x00, 0x00};
2780} -maskdata {
2781 #define tagicon-mask_width 13
2782 #define tagicon-mask_height 9
2783 static unsigned char tagicon-mask_bits[] = {
2784 0x00, 0x00, 0xf0, 0x0f, 0xf8, 0x0f, 0xfc, 0x0f,
2785 0xfe, 0x0f, 0xfc, 0x0f, 0xf8, 0x0f, 0xf0, 0x0f, 0x00, 0x00};
2786}
2787set rectdata {
2788 #define headicon_width 13
2789 #define headicon_height 9
2790 static unsigned char headicon_bits[] = {
2791 0x00, 0x00, 0x00, 0x00, 0xf8, 0x07, 0xf8, 0x07,
2792 0xf8, 0x07, 0xf8, 0x07, 0xf8, 0x07, 0x00, 0x00, 0x00, 0x00};
2793}
2794set rectmask {
2795 #define headicon-mask_width 13
2796 #define headicon-mask_height 9
2797 static unsigned char headicon-mask_bits[] = {
2798 0x00, 0x00, 0xfc, 0x0f, 0xfc, 0x0f, 0xfc, 0x0f,
2799 0xfc, 0x0f, 0xfc, 0x0f, 0xfc, 0x0f, 0xfc, 0x0f, 0x00, 0x00};
2800}
2801image create bitmap reficon-H -background black -foreground green \
2802 -data $rectdata -maskdata $rectmask
2803image create bitmap reficon-o -background black -foreground "#ddddff" \
2804 -data $rectdata -maskdata $rectmask
2805
Paul Mackerras7fcceed2006-04-27 19:21:49 +10002806proc init_flist {first} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11002807 global cflist cflist_top difffilestart
Paul Mackerras7fcceed2006-04-27 19:21:49 +10002808
2809 $cflist conf -state normal
2810 $cflist delete 0.0 end
2811 if {$first ne {}} {
2812 $cflist insert end $first
2813 set cflist_top 1
Paul Mackerras7fcceed2006-04-27 19:21:49 +10002814 $cflist tag add highlight 1.0 "1.0 lineend"
2815 } else {
2816 catch {unset cflist_top}
2817 }
2818 $cflist conf -state disabled
2819 set difffilestart {}
2820}
2821
Paul Mackerras63b79192006-05-20 21:31:52 +10002822proc highlight_tag {f} {
2823 global highlight_paths
2824
2825 foreach p $highlight_paths {
2826 if {[string match $p $f]} {
2827 return "bold"
2828 }
2829 }
2830 return {}
2831}
2832
2833proc highlight_filelist {} {
Paul Mackerras45a9d502006-05-20 22:56:27 +10002834 global cmitmode cflist
Paul Mackerras63b79192006-05-20 21:31:52 +10002835
Paul Mackerras45a9d502006-05-20 22:56:27 +10002836 $cflist conf -state normal
2837 if {$cmitmode ne "tree"} {
Paul Mackerras63b79192006-05-20 21:31:52 +10002838 set end [lindex [split [$cflist index end] .] 0]
2839 for {set l 2} {$l < $end} {incr l} {
2840 set line [$cflist get $l.0 "$l.0 lineend"]
2841 if {[highlight_tag $line] ne {}} {
2842 $cflist tag add bold $l.0 "$l.0 lineend"
2843 }
2844 }
Paul Mackerras45a9d502006-05-20 22:56:27 +10002845 } else {
2846 highlight_tree 2 {}
Paul Mackerras63b79192006-05-20 21:31:52 +10002847 }
Paul Mackerras45a9d502006-05-20 22:56:27 +10002848 $cflist conf -state disabled
Paul Mackerras63b79192006-05-20 21:31:52 +10002849}
2850
2851proc unhighlight_filelist {} {
Paul Mackerras45a9d502006-05-20 22:56:27 +10002852 global cflist
Paul Mackerras63b79192006-05-20 21:31:52 +10002853
Paul Mackerras45a9d502006-05-20 22:56:27 +10002854 $cflist conf -state normal
2855 $cflist tag remove bold 1.0 end
2856 $cflist conf -state disabled
Paul Mackerras63b79192006-05-20 21:31:52 +10002857}
2858
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10002859proc add_flist {fl} {
Paul Mackerras45a9d502006-05-20 22:56:27 +10002860 global cflist
Paul Mackerras7fcceed2006-04-27 19:21:49 +10002861
Paul Mackerras45a9d502006-05-20 22:56:27 +10002862 $cflist conf -state normal
2863 foreach f $fl {
2864 $cflist insert end "\n"
2865 $cflist insert end $f [highlight_tag $f]
Paul Mackerras7fcceed2006-04-27 19:21:49 +10002866 }
Paul Mackerras45a9d502006-05-20 22:56:27 +10002867 $cflist conf -state disabled
Paul Mackerras7fcceed2006-04-27 19:21:49 +10002868}
2869
2870proc sel_flist {w x y} {
Paul Mackerras45a9d502006-05-20 22:56:27 +10002871 global ctext difffilestart cflist cflist_top cmitmode
Paul Mackerras7fcceed2006-04-27 19:21:49 +10002872
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10002873 if {$cmitmode eq "tree"} return
Paul Mackerras7fcceed2006-04-27 19:21:49 +10002874 if {![info exists cflist_top]} return
2875 set l [lindex [split [$w index "@$x,$y"] "."] 0]
Paul Mackerras89b11d32006-05-02 19:55:31 +10002876 $cflist tag remove highlight $cflist_top.0 "$cflist_top.0 lineend"
2877 $cflist tag add highlight $l.0 "$l.0 lineend"
2878 set cflist_top $l
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10002879 if {$l == 1} {
2880 $ctext yview 1.0
2881 } else {
2882 catch {$ctext yview [lindex $difffilestart [expr {$l - 2}]]}
Paul Mackerras7fcceed2006-04-27 19:21:49 +10002883 }
Paul Mackerras7fcceed2006-04-27 19:21:49 +10002884}
2885
Paul Mackerras32447292007-07-27 22:30:15 +10002886proc pop_flist_menu {w X Y x y} {
2887 global ctext cflist cmitmode flist_menu flist_menu_file
2888 global treediffs diffids
2889
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10002890 stopfinding
Paul Mackerras32447292007-07-27 22:30:15 +10002891 set l [lindex [split [$w index "@$x,$y"] "."] 0]
2892 if {$l <= 1} return
2893 if {$cmitmode eq "tree"} {
2894 set e [linetoelt $l]
2895 if {[string index $e end] eq "/"} return
2896 } else {
2897 set e [lindex $treediffs($diffids) [expr {$l-2}]]
2898 }
2899 set flist_menu_file $e
Thomas Arcila314f5de2008-03-24 12:55:36 +01002900 set xdiffstate "normal"
2901 if {$cmitmode eq "tree"} {
2902 set xdiffstate "disabled"
2903 }
2904 # Disable "External diff" item in tree mode
2905 $flist_menu entryconf 2 -state $xdiffstate
Paul Mackerras32447292007-07-27 22:30:15 +10002906 tk_popup $flist_menu $X $Y
2907}
2908
2909proc flist_hl {only} {
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10002910 global flist_menu_file findstring gdttype
Paul Mackerras32447292007-07-27 22:30:15 +10002911
2912 set x [shellquote $flist_menu_file]
Christian Stimmingb007ee22007-11-07 18:44:35 +01002913 if {$only || $findstring eq {} || $gdttype ne [mc "touching paths:"]} {
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10002914 set findstring $x
Paul Mackerras32447292007-07-27 22:30:15 +10002915 } else {
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10002916 append findstring " " $x
Paul Mackerras32447292007-07-27 22:30:15 +10002917 }
Christian Stimmingb007ee22007-11-07 18:44:35 +01002918 set gdttype [mc "touching paths:"]
Paul Mackerras32447292007-07-27 22:30:15 +10002919}
2920
Thomas Arcila314f5de2008-03-24 12:55:36 +01002921proc save_file_from_commit {filename output what} {
2922 global nullfile
2923
2924 if {[catch {exec git show $filename -- > $output} err]} {
2925 if {[string match "fatal: bad revision *" $err]} {
2926 return $nullfile
2927 }
2928 error_popup "Error getting \"$filename\" from $what: $err"
2929 return {}
2930 }
2931 return $output
2932}
2933
2934proc external_diff_get_one_file {diffid filename diffdir} {
2935 global nullid nullid2 nullfile
2936 global gitdir
2937
2938 if {$diffid == $nullid} {
2939 set difffile [file join [file dirname $gitdir] $filename]
2940 if {[file exists $difffile]} {
2941 return $difffile
2942 }
2943 return $nullfile
2944 }
2945 if {$diffid == $nullid2} {
2946 set difffile [file join $diffdir "\[index\] [file tail $filename]"]
2947 return [save_file_from_commit :$filename $difffile index]
2948 }
2949 set difffile [file join $diffdir "\[$diffid\] [file tail $filename]"]
2950 return [save_file_from_commit $diffid:$filename $difffile \
2951 "revision $diffid"]
2952}
2953
2954proc external_diff {} {
2955 global gitktmpdir nullid nullid2
2956 global flist_menu_file
2957 global diffids
2958 global diffnum
2959 global gitdir extdifftool
2960
2961 if {[llength $diffids] == 1} {
2962 # no reference commit given
2963 set diffidto [lindex $diffids 0]
2964 if {$diffidto eq $nullid} {
2965 # diffing working copy with index
2966 set diffidfrom $nullid2
2967 } elseif {$diffidto eq $nullid2} {
2968 # diffing index with HEAD
2969 set diffidfrom "HEAD"
2970 } else {
2971 # use first parent commit
2972 global parentlist selectedline
2973 set diffidfrom [lindex $parentlist $selectedline 0]
2974 }
2975 } else {
2976 set diffidfrom [lindex $diffids 0]
2977 set diffidto [lindex $diffids 1]
2978 }
2979
2980 # make sure that several diffs wont collide
2981 if {![info exists gitktmpdir]} {
2982 set gitktmpdir [file join [file dirname $gitdir] \
2983 [format ".gitk-tmp.%s" [pid]]]
2984 if {[catch {file mkdir $gitktmpdir} err]} {
2985 error_popup "Error creating temporary directory $gitktmpdir: $err"
2986 unset gitktmpdir
2987 return
2988 }
2989 set diffnum 0
2990 }
2991 incr diffnum
2992 set diffdir [file join $gitktmpdir $diffnum]
2993 if {[catch {file mkdir $diffdir} err]} {
2994 error_popup "Error creating temporary directory $diffdir: $err"
2995 return
2996 }
2997
2998 # gather files to diff
2999 set difffromfile [external_diff_get_one_file $diffidfrom $flist_menu_file $diffdir]
3000 set difftofile [external_diff_get_one_file $diffidto $flist_menu_file $diffdir]
3001
3002 if {$difffromfile ne {} && $difftofile ne {}} {
3003 set cmd [concat | [shellsplit $extdifftool] \
3004 [list $difffromfile $difftofile]]
3005 if {[catch {set fl [open $cmd r]} err]} {
3006 file delete -force $diffdir
3007 error_popup [mc "$extdifftool: command failed: $err"]
3008 } else {
3009 fconfigure $fl -blocking 0
3010 filerun $fl [list delete_at_eof $fl $diffdir]
3011 }
3012 }
3013}
3014
3015# delete $dir when we see eof on $f (presumably because the child has exited)
3016proc delete_at_eof {f dir} {
3017 while {[gets $f line] >= 0} {}
3018 if {[eof $f]} {
3019 if {[catch {close $f} err]} {
3020 error_popup "External diff viewer failed: $err"
3021 }
3022 file delete -force $dir
3023 return 0
3024 }
3025 return 1
3026}
3027
Paul Mackerras098dd8a2006-05-03 09:32:53 +10003028# Functions for adding and removing shell-type quoting
3029
3030proc shellquote {str} {
3031 if {![string match "*\['\"\\ \t]*" $str]} {
3032 return $str
3033 }
3034 if {![string match "*\['\"\\]*" $str]} {
3035 return "\"$str\""
3036 }
3037 if {![string match "*'*" $str]} {
3038 return "'$str'"
3039 }
3040 return "\"[string map {\" \\\" \\ \\\\} $str]\""
3041}
3042
3043proc shellarglist {l} {
3044 set str {}
3045 foreach a $l {
3046 if {$str ne {}} {
3047 append str " "
3048 }
3049 append str [shellquote $a]
3050 }
3051 return $str
3052}
3053
3054proc shelldequote {str} {
3055 set ret {}
3056 set used -1
3057 while {1} {
3058 incr used
3059 if {![regexp -start $used -indices "\['\"\\\\ \t]" $str first]} {
3060 append ret [string range $str $used end]
3061 set used [string length $str]
3062 break
3063 }
3064 set first [lindex $first 0]
3065 set ch [string index $str $first]
3066 if {$first > $used} {
3067 append ret [string range $str $used [expr {$first - 1}]]
3068 set used $first
3069 }
3070 if {$ch eq " " || $ch eq "\t"} break
3071 incr used
3072 if {$ch eq "'"} {
3073 set first [string first "'" $str $used]
3074 if {$first < 0} {
3075 error "unmatched single-quote"
3076 }
3077 append ret [string range $str $used [expr {$first - 1}]]
3078 set used $first
3079 continue
3080 }
3081 if {$ch eq "\\"} {
3082 if {$used >= [string length $str]} {
3083 error "trailing backslash"
3084 }
3085 append ret [string index $str $used]
3086 continue
3087 }
3088 # here ch == "\""
3089 while {1} {
3090 if {![regexp -start $used -indices "\[\"\\\\]" $str first]} {
3091 error "unmatched double-quote"
3092 }
3093 set first [lindex $first 0]
3094 set ch [string index $str $first]
3095 if {$first > $used} {
3096 append ret [string range $str $used [expr {$first - 1}]]
3097 set used $first
3098 }
3099 if {$ch eq "\""} break
3100 incr used
3101 append ret [string index $str $used]
3102 incr used
3103 }
3104 }
3105 return [list $used $ret]
3106}
3107
3108proc shellsplit {str} {
3109 set l {}
3110 while {1} {
3111 set str [string trimleft $str]
3112 if {$str eq {}} break
3113 set dq [shelldequote $str]
3114 set n [lindex $dq 0]
3115 set word [lindex $dq 1]
3116 set str [string range $str $n end]
3117 lappend l $word
3118 }
3119 return $l
3120}
3121
Paul Mackerras7fcceed2006-04-27 19:21:49 +10003122# Code to implement multiple views
3123
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10003124proc newview {ishighlight} {
Paul Mackerrasb039f0a2008-01-06 15:54:46 +11003125 global nextviewnum newviewname newviewperm newishighlight
Yann Dirson2d480852008-02-21 21:23:31 +01003126 global newviewargs revtreeargs viewargscmd newviewargscmd curview
Paul Mackerras50b44ec2006-04-04 10:16:22 +10003127
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10003128 set newishighlight $ishighlight
Paul Mackerras50b44ec2006-04-04 10:16:22 +10003129 set top .gitkview
3130 if {[winfo exists $top]} {
3131 raise $top
3132 return
3133 }
Michele Ballabioa3a1f572008-03-03 21:12:47 +01003134 set newviewname($nextviewnum) "[mc "View"] $nextviewnum"
Paul Mackerrasd16c0812006-04-25 21:21:10 +10003135 set newviewperm($nextviewnum) 0
Paul Mackerras098dd8a2006-05-03 09:32:53 +10003136 set newviewargs($nextviewnum) [shellarglist $revtreeargs]
Yann Dirson2d480852008-02-21 21:23:31 +01003137 set newviewargscmd($nextviewnum) $viewargscmd($curview)
Christian Stimmingd990ced2007-11-07 18:42:55 +01003138 vieweditor $top $nextviewnum [mc "Gitk view definition"]
Paul Mackerrasd16c0812006-04-25 21:21:10 +10003139}
3140
3141proc editview {} {
3142 global curview
3143 global viewname viewperm newviewname newviewperm
Yann Dirson2d480852008-02-21 21:23:31 +01003144 global viewargs newviewargs viewargscmd newviewargscmd
Paul Mackerrasd16c0812006-04-25 21:21:10 +10003145
3146 set top .gitkvedit-$curview
3147 if {[winfo exists $top]} {
3148 raise $top
3149 return
3150 }
3151 set newviewname($curview) $viewname($curview)
3152 set newviewperm($curview) $viewperm($curview)
Paul Mackerras098dd8a2006-05-03 09:32:53 +10003153 set newviewargs($curview) [shellarglist $viewargs($curview)]
Yann Dirson2d480852008-02-21 21:23:31 +01003154 set newviewargscmd($curview) $viewargscmd($curview)
Paul Mackerrasd16c0812006-04-25 21:21:10 +10003155 vieweditor $top $curview "Gitk: edit view $viewname($curview)"
3156}
3157
3158proc vieweditor {top n title} {
Gerrit Papef0c84262008-01-09 14:19:47 +11003159 global newviewname newviewperm viewfiles bgcolor
Paul Mackerrasd16c0812006-04-25 21:21:10 +10003160
Paul Mackerras50b44ec2006-04-04 10:16:22 +10003161 toplevel $top
Paul Mackerrasd16c0812006-04-25 21:21:10 +10003162 wm title $top $title
Paul Mackerrasb039f0a2008-01-06 15:54:46 +11003163 label $top.nl -text [mc "Name"]
3164 entry $top.name -width 20 -textvariable newviewname($n)
Paul Mackerrasa90a6d22006-04-25 17:12:46 +10003165 grid $top.nl $top.name -sticky w -pady 5
Paul Mackerrasb039f0a2008-01-06 15:54:46 +11003166 checkbutton $top.perm -text [mc "Remember this view"] \
3167 -variable newviewperm($n)
Paul Mackerrasa90a6d22006-04-25 17:12:46 +10003168 grid $top.perm - -pady 5 -sticky w
Paul Mackerrasb039f0a2008-01-06 15:54:46 +11003169 message $top.al -aspect 1000 \
Paul Mackerrasf9e0b6f2008-03-04 21:14:17 +11003170 -text [mc "Commits to include (arguments to git log):"]
Paul Mackerras098dd8a2006-05-03 09:32:53 +10003171 grid $top.al - -sticky w -pady 5
3172 entry $top.args -width 50 -textvariable newviewargs($n) \
Gerrit Papef0c84262008-01-09 14:19:47 +11003173 -background $bgcolor
Paul Mackerras098dd8a2006-05-03 09:32:53 +10003174 grid $top.args - -sticky ew -padx 5
Yann Dirson2d480852008-02-21 21:23:31 +01003175
3176 message $top.ac -aspect 1000 \
3177 -text [mc "Command to generate more commits to include:"]
3178 grid $top.ac - -sticky w -pady 5
3179 entry $top.argscmd -width 50 -textvariable newviewargscmd($n) \
3180 -background white
3181 grid $top.argscmd - -sticky ew -padx 5
3182
Paul Mackerrasb039f0a2008-01-06 15:54:46 +11003183 message $top.l -aspect 1000 \
Christian Stimmingd990ced2007-11-07 18:42:55 +01003184 -text [mc "Enter files and directories to include, one per line:"]
Paul Mackerrasa90a6d22006-04-25 17:12:46 +10003185 grid $top.l - -sticky w
Gerrit Papef0c84262008-01-09 14:19:47 +11003186 text $top.t -width 40 -height 10 -background $bgcolor -font uifont
Paul Mackerrasd16c0812006-04-25 21:21:10 +10003187 if {[info exists viewfiles($n)]} {
3188 foreach f $viewfiles($n) {
3189 $top.t insert end $f
3190 $top.t insert end "\n"
3191 }
3192 $top.t delete {end - 1c} end
3193 $top.t mark set insert 0.0
3194 }
Paul Mackerras098dd8a2006-05-03 09:32:53 +10003195 grid $top.t - -sticky ew -padx 5
Paul Mackerras50b44ec2006-04-04 10:16:22 +10003196 frame $top.buts
Paul Mackerrasb039f0a2008-01-06 15:54:46 +11003197 button $top.buts.ok -text [mc "OK"] -command [list newviewok $top $n]
3198 button $top.buts.can -text [mc "Cancel"] -command [list destroy $top]
Paul Mackerras50b44ec2006-04-04 10:16:22 +10003199 grid $top.buts.ok $top.buts.can
3200 grid columnconfigure $top.buts 0 -weight 1 -uniform a
3201 grid columnconfigure $top.buts 1 -weight 1 -uniform a
3202 grid $top.buts - -pady 10 -sticky ew
3203 focus $top.t
3204}
3205
Paul Mackerras908c3582006-05-20 09:38:11 +10003206proc doviewmenu {m first cmd op argv} {
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10003207 set nmenu [$m index end]
3208 for {set i $first} {$i <= $nmenu} {incr i} {
3209 if {[$m entrycget $i -command] eq $cmd} {
Paul Mackerras908c3582006-05-20 09:38:11 +10003210 eval $m $op $i $argv
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10003211 break
Paul Mackerrasd16c0812006-04-25 21:21:10 +10003212 }
3213 }
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10003214}
3215
3216proc allviewmenus {n op args} {
Paul Mackerras687c8762007-09-22 12:49:33 +10003217 # global viewhlmenu
Paul Mackerras908c3582006-05-20 09:38:11 +10003218
Paul Mackerras3cd204e2006-11-23 21:06:16 +11003219 doviewmenu .bar.view 5 [list showview $n] $op $args
Paul Mackerras687c8762007-09-22 12:49:33 +10003220 # doviewmenu $viewhlmenu 1 [list addvhighlight $n] $op $args
Paul Mackerrasd16c0812006-04-25 21:21:10 +10003221}
Paul Mackerras50b44ec2006-04-04 10:16:22 +10003222
Paul Mackerrasd16c0812006-04-25 21:21:10 +10003223proc newviewok {top n} {
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10003224 global nextviewnum newviewperm newviewname newishighlight
Paul Mackerrasd16c0812006-04-25 21:21:10 +10003225 global viewname viewfiles viewperm selectedview curview
Yann Dirson2d480852008-02-21 21:23:31 +01003226 global viewargs newviewargs viewargscmd newviewargscmd viewhlmenu
Paul Mackerrasd16c0812006-04-25 21:21:10 +10003227
Paul Mackerras098dd8a2006-05-03 09:32:53 +10003228 if {[catch {
3229 set newargs [shellsplit $newviewargs($n)]
3230 } err]} {
Christian Stimmingd990ced2007-11-07 18:42:55 +01003231 error_popup "[mc "Error in commit selection arguments:"] $err"
Paul Mackerras098dd8a2006-05-03 09:32:53 +10003232 wm raise $top
3233 focus $top
3234 return
3235 }
Paul Mackerras50b44ec2006-04-04 10:16:22 +10003236 set files {}
Paul Mackerrasd16c0812006-04-25 21:21:10 +10003237 foreach f [split [$top.t get 0.0 end] "\n"] {
Paul Mackerras50b44ec2006-04-04 10:16:22 +10003238 set ft [string trim $f]
3239 if {$ft ne {}} {
3240 lappend files $ft
3241 }
3242 }
Paul Mackerrasd16c0812006-04-25 21:21:10 +10003243 if {![info exists viewfiles($n)]} {
3244 # creating a new view
3245 incr nextviewnum
3246 set viewname($n) $newviewname($n)
3247 set viewperm($n) $newviewperm($n)
3248 set viewfiles($n) $files
Paul Mackerras098dd8a2006-05-03 09:32:53 +10003249 set viewargs($n) $newargs
Yann Dirson2d480852008-02-21 21:23:31 +01003250 set viewargscmd($n) $newviewargscmd($n)
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10003251 addviewmenu $n
3252 if {!$newishighlight} {
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10003253 run showview $n
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10003254 } else {
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10003255 run addvhighlight $n
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10003256 }
Paul Mackerrasd16c0812006-04-25 21:21:10 +10003257 } else {
3258 # editing an existing view
3259 set viewperm($n) $newviewperm($n)
3260 if {$newviewname($n) ne $viewname($n)} {
3261 set viewname($n) $newviewname($n)
Paul Mackerras3cd204e2006-11-23 21:06:16 +11003262 doviewmenu .bar.view 5 [list showview $n] \
Paul Mackerras908c3582006-05-20 09:38:11 +10003263 entryconf [list -label $viewname($n)]
Paul Mackerras687c8762007-09-22 12:49:33 +10003264 # doviewmenu $viewhlmenu 1 [list addvhighlight $n] \
3265 # entryconf [list -label $viewname($n) -value $viewname($n)]
Paul Mackerrasd16c0812006-04-25 21:21:10 +10003266 }
Yann Dirson2d480852008-02-21 21:23:31 +01003267 if {$files ne $viewfiles($n) || $newargs ne $viewargs($n) || \
3268 $newviewargscmd($n) ne $viewargscmd($n)} {
Paul Mackerrasd16c0812006-04-25 21:21:10 +10003269 set viewfiles($n) $files
Paul Mackerras098dd8a2006-05-03 09:32:53 +10003270 set viewargs($n) $newargs
Yann Dirson2d480852008-02-21 21:23:31 +01003271 set viewargscmd($n) $newviewargscmd($n)
Paul Mackerrasd16c0812006-04-25 21:21:10 +10003272 if {$curview == $n} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11003273 run reloadcommits
Paul Mackerrasd16c0812006-04-25 21:21:10 +10003274 }
3275 }
3276 }
3277 catch {destroy $top}
Paul Mackerras50b44ec2006-04-04 10:16:22 +10003278}
3279
3280proc delview {} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11003281 global curview viewperm hlview selectedhlview
Paul Mackerras50b44ec2006-04-04 10:16:22 +10003282
3283 if {$curview == 0} return
Paul Mackerras908c3582006-05-20 09:38:11 +10003284 if {[info exists hlview] && $hlview == $curview} {
Christian Stimmingb007ee22007-11-07 18:44:35 +01003285 set selectedhlview [mc "None"]
Paul Mackerras908c3582006-05-20 09:38:11 +10003286 unset hlview
3287 }
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10003288 allviewmenus $curview delete
Paul Mackerrasa90a6d22006-04-25 17:12:46 +10003289 set viewperm($curview) 0
Paul Mackerras50b44ec2006-04-04 10:16:22 +10003290 showview 0
3291}
3292
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10003293proc addviewmenu {n} {
Paul Mackerras908c3582006-05-20 09:38:11 +10003294 global viewname viewhlmenu
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10003295
3296 .bar.view add radiobutton -label $viewname($n) \
3297 -command [list showview $n] -variable selectedview -value $n
Paul Mackerras687c8762007-09-22 12:49:33 +10003298 #$viewhlmenu add radiobutton -label $viewname($n) \
3299 # -command [list addvhighlight $n] -variable selectedhlview
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10003300}
3301
Paul Mackerras50b44ec2006-04-04 10:16:22 +10003302proc showview {n} {
Paul Mackerras3ed31a82008-04-26 16:00:00 +10003303 global curview cached_commitrow ordertok
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10003304 global displayorder parentlist rowidlist rowisopt rowfinal
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11003305 global colormap rowtextx nextcolor canvxmax
3306 global numcommits viewcomplete
Paul Mackerras50b44ec2006-04-04 10:16:22 +10003307 global selectedline currentid canv canvy0
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10003308 global treediffs
Paul Mackerras3e766082008-01-13 17:26:30 +11003309 global pending_select mainheadid
Paul Mackerras03800812007-08-29 21:45:21 +10003310 global commitidx
Paul Mackerras3e766082008-01-13 17:26:30 +11003311 global selectedview
Paul Mackerras97645682007-08-23 22:24:38 +10003312 global hlview selectedhlview commitinterest
Paul Mackerras50b44ec2006-04-04 10:16:22 +10003313
3314 if {$n == $curview} return
3315 set selid {}
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11003316 set ymax [lindex [$canv cget -scrollregion] 3]
3317 set span [$canv yview]
3318 set ytop [expr {[lindex $span 0] * $ymax}]
3319 set ybot [expr {[lindex $span 1] * $ymax}]
3320 set yscreen [expr {($ybot - $ytop) / 2}]
Paul Mackerras94b4a692008-05-20 20:51:06 +10003321 if {$selectedline ne {}} {
Paul Mackerras50b44ec2006-04-04 10:16:22 +10003322 set selid $currentid
3323 set y [yc $selectedline]
Paul Mackerras50b44ec2006-04-04 10:16:22 +10003324 if {$ytop < $y && $y < $ybot} {
3325 set yscreen [expr {$y - $ytop}]
Paul Mackerras50b44ec2006-04-04 10:16:22 +10003326 }
Paul Mackerrase507fd42007-06-16 21:51:08 +10003327 } elseif {[info exists pending_select]} {
3328 set selid $pending_select
3329 unset pending_select
Paul Mackerras50b44ec2006-04-04 10:16:22 +10003330 }
3331 unselectline
Paul Mackerrasfdedbcf2006-04-06 21:22:52 +10003332 normalline
Paul Mackerras50b44ec2006-04-04 10:16:22 +10003333 catch {unset treediffs}
3334 clear_display
Paul Mackerras908c3582006-05-20 09:38:11 +10003335 if {[info exists hlview] && $hlview == $n} {
3336 unset hlview
Christian Stimmingb007ee22007-11-07 18:44:35 +01003337 set selectedhlview [mc "None"]
Paul Mackerras908c3582006-05-20 09:38:11 +10003338 }
Paul Mackerras97645682007-08-23 22:24:38 +10003339 catch {unset commitinterest}
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11003340 catch {unset cached_commitrow}
Paul Mackerras9257d8f2007-12-11 10:45:38 +11003341 catch {unset ordertok}
Paul Mackerras50b44ec2006-04-04 10:16:22 +10003342
3343 set curview $n
Paul Mackerrasa90a6d22006-04-25 17:12:46 +10003344 set selectedview $n
Christian Stimmingd990ced2007-11-07 18:42:55 +01003345 .bar.view entryconf [mc "Edit view..."] -state [expr {$n == 0? "disabled": "normal"}]
3346 .bar.view entryconf [mc "Delete view"] -state [expr {$n == 0? "disabled": "normal"}]
Paul Mackerras50b44ec2006-04-04 10:16:22 +10003347
Paul Mackerrasdf904492007-08-29 22:03:07 +10003348 run refill_reflist
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11003349 if {![info exists viewcomplete($n)]} {
Alexander Gavrilov567c34e2008-07-26 20:13:45 +04003350 getcommits $selid
Paul Mackerras50b44ec2006-04-04 10:16:22 +10003351 return
3352 }
3353
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11003354 set displayorder {}
3355 set parentlist {}
3356 set rowidlist {}
3357 set rowisopt {}
3358 set rowfinal {}
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10003359 set numcommits $commitidx($n)
Paul Mackerras22626ef2006-04-17 09:56:02 +10003360
Paul Mackerras50b44ec2006-04-04 10:16:22 +10003361 catch {unset colormap}
3362 catch {unset rowtextx}
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10003363 set nextcolor 0
3364 set canvxmax [$canv cget -width]
Paul Mackerras50b44ec2006-04-04 10:16:22 +10003365 set curview $n
3366 set row 0
Paul Mackerras50b44ec2006-04-04 10:16:22 +10003367 setcanvscroll
3368 set yf 0
Paul Mackerrase507fd42007-06-16 21:51:08 +10003369 set row {}
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11003370 if {$selid ne {} && [commitinview $selid $n]} {
3371 set row [rowofcommit $selid]
Paul Mackerras50b44ec2006-04-04 10:16:22 +10003372 # try to get the selected row in the same position on the screen
3373 set ymax [lindex [$canv cget -scrollregion] 3]
3374 set ytop [expr {[yc $row] - $yscreen}]
3375 if {$ytop < 0} {
3376 set ytop 0
3377 }
3378 set yf [expr {$ytop * 1.0 / $ymax}]
3379 }
3380 allcanvs yview moveto $yf
3381 drawvisible
Paul Mackerrase507fd42007-06-16 21:51:08 +10003382 if {$row ne {}} {
3383 selectline $row 0
Paul Mackerras3e766082008-01-13 17:26:30 +11003384 } elseif {!$viewcomplete($n)} {
Alexander Gavrilov567c34e2008-07-26 20:13:45 +04003385 reset_pending_select $selid
Paul Mackerrase507fd42007-06-16 21:51:08 +10003386 } else {
Alexander Gavrilov835e62a2008-07-26 20:15:54 +04003387 reset_pending_select {}
3388
3389 if {[commitinview $pending_select $curview]} {
3390 selectline [rowofcommit $pending_select] 1
3391 } else {
3392 set row [first_real_row]
3393 if {$row < $numcommits} {
3394 selectline $row 0
3395 }
Paul Mackerrase507fd42007-06-16 21:51:08 +10003396 }
3397 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11003398 if {!$viewcomplete($n)} {
3399 if {$numcommits == 0} {
Christian Stimmingd990ced2007-11-07 18:42:55 +01003400 show_status [mc "Reading commits..."]
Paul Mackerrasd16c0812006-04-25 21:21:10 +10003401 }
Paul Mackerras098dd8a2006-05-03 09:32:53 +10003402 } elseif {$numcommits == 0} {
Christian Stimmingd990ced2007-11-07 18:42:55 +01003403 show_status [mc "No commits selected"]
Paul Mackerras2516dae2006-04-21 10:35:31 +10003404 }
Paul Mackerras50b44ec2006-04-04 10:16:22 +10003405}
3406
Paul Mackerras908c3582006-05-20 09:38:11 +10003407# Stuff relating to the highlighting facility
3408
Paul Mackerras476ca632008-01-07 22:16:31 +11003409proc ishighlighted {id} {
Paul Mackerras164ff272006-05-29 19:50:02 +10003410 global vhighlights fhighlights nhighlights rhighlights
Paul Mackerras908c3582006-05-20 09:38:11 +10003411
Paul Mackerras476ca632008-01-07 22:16:31 +11003412 if {[info exists nhighlights($id)] && $nhighlights($id) > 0} {
3413 return $nhighlights($id)
Paul Mackerras908c3582006-05-20 09:38:11 +10003414 }
Paul Mackerras476ca632008-01-07 22:16:31 +11003415 if {[info exists vhighlights($id)] && $vhighlights($id) > 0} {
3416 return $vhighlights($id)
Paul Mackerras908c3582006-05-20 09:38:11 +10003417 }
Paul Mackerras476ca632008-01-07 22:16:31 +11003418 if {[info exists fhighlights($id)] && $fhighlights($id) > 0} {
3419 return $fhighlights($id)
Paul Mackerras908c3582006-05-20 09:38:11 +10003420 }
Paul Mackerras476ca632008-01-07 22:16:31 +11003421 if {[info exists rhighlights($id)] && $rhighlights($id) > 0} {
3422 return $rhighlights($id)
Paul Mackerras164ff272006-05-29 19:50:02 +10003423 }
Paul Mackerras908c3582006-05-20 09:38:11 +10003424 return 0
3425}
3426
3427proc bolden {row font} {
Paul Mackerras4e7d6772006-05-30 21:33:07 +10003428 global canv linehtag selectedline boldrows
Paul Mackerras908c3582006-05-20 09:38:11 +10003429
Paul Mackerras4e7d6772006-05-30 21:33:07 +10003430 lappend boldrows $row
Paul Mackerras908c3582006-05-20 09:38:11 +10003431 $canv itemconf $linehtag($row) -font $font
Paul Mackerras94b4a692008-05-20 20:51:06 +10003432 if {$row == $selectedline} {
Paul Mackerras908c3582006-05-20 09:38:11 +10003433 $canv delete secsel
3434 set t [eval $canv create rect [$canv bbox $linehtag($row)] \
3435 -outline {{}} -tags secsel \
3436 -fill [$canv cget -selectbackground]]
3437 $canv lower $t
3438 }
3439}
3440
3441proc bolden_name {row font} {
Paul Mackerras4e7d6772006-05-30 21:33:07 +10003442 global canv2 linentag selectedline boldnamerows
Paul Mackerras908c3582006-05-20 09:38:11 +10003443
Paul Mackerras4e7d6772006-05-30 21:33:07 +10003444 lappend boldnamerows $row
Paul Mackerras908c3582006-05-20 09:38:11 +10003445 $canv2 itemconf $linentag($row) -font $font
Paul Mackerras94b4a692008-05-20 20:51:06 +10003446 if {$row == $selectedline} {
Paul Mackerras908c3582006-05-20 09:38:11 +10003447 $canv2 delete secsel
3448 set t [eval $canv2 create rect [$canv2 bbox $linentag($row)] \
3449 -outline {{}} -tags secsel \
3450 -fill [$canv2 cget -selectbackground]]
3451 $canv2 lower $t
3452 }
3453}
3454
Paul Mackerras4e7d6772006-05-30 21:33:07 +10003455proc unbolden {} {
Paul Mackerras9c311b32007-10-04 22:27:13 +10003456 global boldrows
Paul Mackerras908c3582006-05-20 09:38:11 +10003457
Paul Mackerras4e7d6772006-05-30 21:33:07 +10003458 set stillbold {}
3459 foreach row $boldrows {
Paul Mackerras476ca632008-01-07 22:16:31 +11003460 if {![ishighlighted [commitonrow $row]]} {
Paul Mackerras9c311b32007-10-04 22:27:13 +10003461 bolden $row mainfont
Paul Mackerras4e7d6772006-05-30 21:33:07 +10003462 } else {
3463 lappend stillbold $row
Paul Mackerras908c3582006-05-20 09:38:11 +10003464 }
3465 }
Paul Mackerras4e7d6772006-05-30 21:33:07 +10003466 set boldrows $stillbold
Paul Mackerras908c3582006-05-20 09:38:11 +10003467}
3468
3469proc addvhighlight {n} {
Paul Mackerras476ca632008-01-07 22:16:31 +11003470 global hlview viewcomplete curview vhl_done commitidx
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10003471
3472 if {[info exists hlview]} {
Paul Mackerras908c3582006-05-20 09:38:11 +10003473 delvhighlight
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10003474 }
3475 set hlview $n
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11003476 if {$n != $curview && ![info exists viewcomplete($n)]} {
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10003477 start_rev_list $n
Paul Mackerras908c3582006-05-20 09:38:11 +10003478 }
3479 set vhl_done $commitidx($hlview)
3480 if {$vhl_done > 0} {
3481 drawvisible
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10003482 }
3483}
3484
Paul Mackerras908c3582006-05-20 09:38:11 +10003485proc delvhighlight {} {
3486 global hlview vhighlights
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10003487
3488 if {![info exists hlview]} return
3489 unset hlview
Paul Mackerras4e7d6772006-05-30 21:33:07 +10003490 catch {unset vhighlights}
3491 unbolden
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10003492}
3493
Paul Mackerras908c3582006-05-20 09:38:11 +10003494proc vhighlightmore {} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11003495 global hlview vhl_done commitidx vhighlights curview
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10003496
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10003497 set max $commitidx($hlview)
Paul Mackerras908c3582006-05-20 09:38:11 +10003498 set vr [visiblerows]
3499 set r0 [lindex $vr 0]
3500 set r1 [lindex $vr 1]
3501 for {set i $vhl_done} {$i < $max} {incr i} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11003502 set id [commitonrow $i $hlview]
3503 if {[commitinview $id $curview]} {
3504 set row [rowofcommit $id]
Paul Mackerras908c3582006-05-20 09:38:11 +10003505 if {$r0 <= $row && $row <= $r1} {
3506 if {![highlighted $row]} {
Paul Mackerras9c311b32007-10-04 22:27:13 +10003507 bolden $row mainfontbold
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10003508 }
Paul Mackerras476ca632008-01-07 22:16:31 +11003509 set vhighlights($id) 1
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10003510 }
3511 }
3512 }
Paul Mackerras908c3582006-05-20 09:38:11 +10003513 set vhl_done $max
Paul Mackerrasac1276a2008-03-03 10:11:08 +11003514 return 0
Paul Mackerras908c3582006-05-20 09:38:11 +10003515}
3516
3517proc askvhighlight {row id} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11003518 global hlview vhighlights iddrawn
Paul Mackerras908c3582006-05-20 09:38:11 +10003519
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11003520 if {[commitinview $id $hlview]} {
Paul Mackerras476ca632008-01-07 22:16:31 +11003521 if {[info exists iddrawn($id)] && ![ishighlighted $id]} {
Paul Mackerras9c311b32007-10-04 22:27:13 +10003522 bolden $row mainfontbold
Paul Mackerras908c3582006-05-20 09:38:11 +10003523 }
Paul Mackerras476ca632008-01-07 22:16:31 +11003524 set vhighlights($id) 1
Paul Mackerras908c3582006-05-20 09:38:11 +10003525 } else {
Paul Mackerras476ca632008-01-07 22:16:31 +11003526 set vhighlights($id) 0
Paul Mackerras908c3582006-05-20 09:38:11 +10003527 }
3528}
3529
Paul Mackerras687c8762007-09-22 12:49:33 +10003530proc hfiles_change {} {
Paul Mackerras908c3582006-05-20 09:38:11 +10003531 global highlight_files filehighlight fhighlights fh_serial
Paul Mackerras9c311b32007-10-04 22:27:13 +10003532 global highlight_paths gdttype
Paul Mackerras908c3582006-05-20 09:38:11 +10003533
3534 if {[info exists filehighlight]} {
3535 # delete previous highlights
3536 catch {close $filehighlight}
3537 unset filehighlight
Paul Mackerras4e7d6772006-05-30 21:33:07 +10003538 catch {unset fhighlights}
3539 unbolden
Paul Mackerras63b79192006-05-20 21:31:52 +10003540 unhighlight_filelist
Paul Mackerras908c3582006-05-20 09:38:11 +10003541 }
Paul Mackerras63b79192006-05-20 21:31:52 +10003542 set highlight_paths {}
Paul Mackerras908c3582006-05-20 09:38:11 +10003543 after cancel do_file_hl $fh_serial
3544 incr fh_serial
3545 if {$highlight_files ne {}} {
3546 after 300 do_file_hl $fh_serial
3547 }
3548}
3549
Paul Mackerras687c8762007-09-22 12:49:33 +10003550proc gdttype_change {name ix op} {
3551 global gdttype highlight_files findstring findpattern
3552
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10003553 stopfinding
Paul Mackerras687c8762007-09-22 12:49:33 +10003554 if {$findstring ne {}} {
Christian Stimmingb007ee22007-11-07 18:44:35 +01003555 if {$gdttype eq [mc "containing:"]} {
Paul Mackerras687c8762007-09-22 12:49:33 +10003556 if {$highlight_files ne {}} {
3557 set highlight_files {}
3558 hfiles_change
3559 }
3560 findcom_change
3561 } else {
3562 if {$findpattern ne {}} {
3563 set findpattern {}
3564 findcom_change
3565 }
3566 set highlight_files $findstring
3567 hfiles_change
3568 }
3569 drawvisible
3570 }
3571 # enable/disable findtype/findloc menus too
3572}
3573
3574proc find_change {name ix op} {
3575 global gdttype findstring highlight_files
3576
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10003577 stopfinding
Christian Stimmingb007ee22007-11-07 18:44:35 +01003578 if {$gdttype eq [mc "containing:"]} {
Paul Mackerras687c8762007-09-22 12:49:33 +10003579 findcom_change
3580 } else {
3581 if {$highlight_files ne $findstring} {
3582 set highlight_files $findstring
3583 hfiles_change
3584 }
3585 }
3586 drawvisible
3587}
3588
Paul Mackerras64b5f142007-10-04 22:19:24 +10003589proc findcom_change args {
Paul Mackerras9c311b32007-10-04 22:27:13 +10003590 global nhighlights boldnamerows
Paul Mackerras687c8762007-09-22 12:49:33 +10003591 global findpattern findtype findstring gdttype
3592
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10003593 stopfinding
Paul Mackerras687c8762007-09-22 12:49:33 +10003594 # delete previous highlights, if any
3595 foreach row $boldnamerows {
Paul Mackerras9c311b32007-10-04 22:27:13 +10003596 bolden_name $row mainfont
Paul Mackerras687c8762007-09-22 12:49:33 +10003597 }
3598 set boldnamerows {}
3599 catch {unset nhighlights}
3600 unbolden
3601 unmarkmatches
Christian Stimmingb007ee22007-11-07 18:44:35 +01003602 if {$gdttype ne [mc "containing:"] || $findstring eq {}} {
Paul Mackerras687c8762007-09-22 12:49:33 +10003603 set findpattern {}
Christian Stimmingb007ee22007-11-07 18:44:35 +01003604 } elseif {$findtype eq [mc "Regexp"]} {
Paul Mackerras687c8762007-09-22 12:49:33 +10003605 set findpattern $findstring
3606 } else {
3607 set e [string map {"*" "\\*" "?" "\\?" "\[" "\\\[" "\\" "\\\\"} \
3608 $findstring]
3609 set findpattern "*$e*"
3610 }
3611}
3612
Paul Mackerras63b79192006-05-20 21:31:52 +10003613proc makepatterns {l} {
3614 set ret {}
3615 foreach e $l {
3616 set ee [string map {"*" "\\*" "?" "\\?" "\[" "\\\[" "\\" "\\\\"} $e]
3617 if {[string index $ee end] eq "/"} {
3618 lappend ret "$ee*"
3619 } else {
3620 lappend ret $ee
3621 lappend ret "$ee/*"
3622 }
3623 }
3624 return $ret
3625}
3626
Paul Mackerras908c3582006-05-20 09:38:11 +10003627proc do_file_hl {serial} {
Paul Mackerras4e7d6772006-05-30 21:33:07 +10003628 global highlight_files filehighlight highlight_paths gdttype fhl_list
Paul Mackerras908c3582006-05-20 09:38:11 +10003629
Christian Stimmingb007ee22007-11-07 18:44:35 +01003630 if {$gdttype eq [mc "touching paths:"]} {
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10003631 if {[catch {set paths [shellsplit $highlight_files]}]} return
3632 set highlight_paths [makepatterns $paths]
3633 highlight_filelist
3634 set gdtargs [concat -- $paths]
Christian Stimmingb007ee22007-11-07 18:44:35 +01003635 } elseif {$gdttype eq [mc "adding/removing string:"]} {
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10003636 set gdtargs [list "-S$highlight_files"]
Paul Mackerras687c8762007-09-22 12:49:33 +10003637 } else {
3638 # must be "containing:", i.e. we're searching commit info
3639 return
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10003640 }
Brandon Casey1ce09dd2007-03-19 18:00:37 -05003641 set cmd [concat | git diff-tree -r -s --stdin $gdtargs]
Paul Mackerras908c3582006-05-20 09:38:11 +10003642 set filehighlight [open $cmd r+]
3643 fconfigure $filehighlight -blocking 0
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10003644 filerun $filehighlight readfhighlight
Paul Mackerras4e7d6772006-05-30 21:33:07 +10003645 set fhl_list {}
Paul Mackerras908c3582006-05-20 09:38:11 +10003646 drawvisible
3647 flushhighlights
3648}
3649
3650proc flushhighlights {} {
Paul Mackerras4e7d6772006-05-30 21:33:07 +10003651 global filehighlight fhl_list
Paul Mackerras908c3582006-05-20 09:38:11 +10003652
3653 if {[info exists filehighlight]} {
Paul Mackerras4e7d6772006-05-30 21:33:07 +10003654 lappend fhl_list {}
Paul Mackerras908c3582006-05-20 09:38:11 +10003655 puts $filehighlight ""
3656 flush $filehighlight
3657 }
3658}
3659
3660proc askfilehighlight {row id} {
Paul Mackerras4e7d6772006-05-30 21:33:07 +10003661 global filehighlight fhighlights fhl_list
Paul Mackerras908c3582006-05-20 09:38:11 +10003662
Paul Mackerras4e7d6772006-05-30 21:33:07 +10003663 lappend fhl_list $id
Paul Mackerras476ca632008-01-07 22:16:31 +11003664 set fhighlights($id) -1
Paul Mackerras908c3582006-05-20 09:38:11 +10003665 puts $filehighlight $id
3666}
3667
3668proc readfhighlight {} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11003669 global filehighlight fhighlights curview iddrawn
Paul Mackerras687c8762007-09-22 12:49:33 +10003670 global fhl_list find_dirn
Paul Mackerras908c3582006-05-20 09:38:11 +10003671
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10003672 if {![info exists filehighlight]} {
3673 return 0
3674 }
3675 set nr 0
3676 while {[incr nr] <= 100 && [gets $filehighlight line] >= 0} {
Paul Mackerras4e7d6772006-05-30 21:33:07 +10003677 set line [string trim $line]
3678 set i [lsearch -exact $fhl_list $line]
3679 if {$i < 0} continue
3680 for {set j 0} {$j < $i} {incr j} {
3681 set id [lindex $fhl_list $j]
Paul Mackerras476ca632008-01-07 22:16:31 +11003682 set fhighlights($id) 0
Paul Mackerras908c3582006-05-20 09:38:11 +10003683 }
Paul Mackerras4e7d6772006-05-30 21:33:07 +10003684 set fhl_list [lrange $fhl_list [expr {$i+1}] end]
3685 if {$line eq {}} continue
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11003686 if {![commitinview $line $curview]} continue
3687 set row [rowofcommit $line]
Paul Mackerras476ca632008-01-07 22:16:31 +11003688 if {[info exists iddrawn($line)] && ![ishighlighted $line]} {
Paul Mackerras9c311b32007-10-04 22:27:13 +10003689 bolden $row mainfontbold
Paul Mackerras4e7d6772006-05-30 21:33:07 +10003690 }
Paul Mackerras476ca632008-01-07 22:16:31 +11003691 set fhighlights($line) 1
Paul Mackerras908c3582006-05-20 09:38:11 +10003692 }
Paul Mackerras4e7d6772006-05-30 21:33:07 +10003693 if {[eof $filehighlight]} {
3694 # strange...
Brandon Casey1ce09dd2007-03-19 18:00:37 -05003695 puts "oops, git diff-tree died"
Paul Mackerras4e7d6772006-05-30 21:33:07 +10003696 catch {close $filehighlight}
3697 unset filehighlight
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10003698 return 0
Paul Mackerras908c3582006-05-20 09:38:11 +10003699 }
Paul Mackerras687c8762007-09-22 12:49:33 +10003700 if {[info exists find_dirn]} {
Paul Mackerrascca5d942007-10-27 21:16:56 +10003701 run findmore
Paul Mackerras687c8762007-09-22 12:49:33 +10003702 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10003703 return 1
Paul Mackerras908c3582006-05-20 09:38:11 +10003704}
3705
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10003706proc doesmatch {f} {
Paul Mackerras687c8762007-09-22 12:49:33 +10003707 global findtype findpattern
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10003708
Christian Stimmingb007ee22007-11-07 18:44:35 +01003709 if {$findtype eq [mc "Regexp"]} {
Paul Mackerras687c8762007-09-22 12:49:33 +10003710 return [regexp $findpattern $f]
Christian Stimmingb007ee22007-11-07 18:44:35 +01003711 } elseif {$findtype eq [mc "IgnCase"]} {
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10003712 return [string match -nocase $findpattern $f]
3713 } else {
3714 return [string match $findpattern $f]
3715 }
3716}
3717
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10003718proc askfindhighlight {row id} {
Paul Mackerras9c311b32007-10-04 22:27:13 +10003719 global nhighlights commitinfo iddrawn
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10003720 global findloc
3721 global markingmatches
Paul Mackerras908c3582006-05-20 09:38:11 +10003722
3723 if {![info exists commitinfo($id)]} {
3724 getcommit $id
3725 }
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10003726 set info $commitinfo($id)
Paul Mackerras908c3582006-05-20 09:38:11 +10003727 set isbold 0
Christian Stimmingb007ee22007-11-07 18:44:35 +01003728 set fldtypes [list [mc Headline] [mc Author] [mc Date] [mc Committer] [mc CDate] [mc Comments]]
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10003729 foreach f $info ty $fldtypes {
Christian Stimmingb007ee22007-11-07 18:44:35 +01003730 if {($findloc eq [mc "All fields"] || $findloc eq $ty) &&
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10003731 [doesmatch $f]} {
Christian Stimmingb007ee22007-11-07 18:44:35 +01003732 if {$ty eq [mc "Author"]} {
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10003733 set isbold 2
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10003734 break
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10003735 }
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10003736 set isbold 1
Paul Mackerras908c3582006-05-20 09:38:11 +10003737 }
3738 }
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10003739 if {$isbold && [info exists iddrawn($id)]} {
Paul Mackerras476ca632008-01-07 22:16:31 +11003740 if {![ishighlighted $id]} {
Paul Mackerras9c311b32007-10-04 22:27:13 +10003741 bolden $row mainfontbold
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10003742 if {$isbold > 1} {
Paul Mackerras9c311b32007-10-04 22:27:13 +10003743 bolden_name $row mainfontbold
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10003744 }
Paul Mackerras908c3582006-05-20 09:38:11 +10003745 }
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10003746 if {$markingmatches} {
Paul Mackerras005a2f42007-07-26 22:36:39 +10003747 markrowmatches $row $id
Paul Mackerras908c3582006-05-20 09:38:11 +10003748 }
3749 }
Paul Mackerras476ca632008-01-07 22:16:31 +11003750 set nhighlights($id) $isbold
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10003751}
3752
Paul Mackerras005a2f42007-07-26 22:36:39 +10003753proc markrowmatches {row id} {
3754 global canv canv2 linehtag linentag commitinfo findloc
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10003755
Paul Mackerras005a2f42007-07-26 22:36:39 +10003756 set headline [lindex $commitinfo($id) 0]
3757 set author [lindex $commitinfo($id) 1]
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10003758 $canv delete match$row
3759 $canv2 delete match$row
Christian Stimmingb007ee22007-11-07 18:44:35 +01003760 if {$findloc eq [mc "All fields"] || $findloc eq [mc "Headline"]} {
Paul Mackerras005a2f42007-07-26 22:36:39 +10003761 set m [findmatches $headline]
3762 if {$m ne {}} {
3763 markmatches $canv $row $headline $linehtag($row) $m \
3764 [$canv itemcget $linehtag($row) -font] $row
3765 }
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10003766 }
Christian Stimmingb007ee22007-11-07 18:44:35 +01003767 if {$findloc eq [mc "All fields"] || $findloc eq [mc "Author"]} {
Paul Mackerras005a2f42007-07-26 22:36:39 +10003768 set m [findmatches $author]
3769 if {$m ne {}} {
3770 markmatches $canv2 $row $author $linentag($row) $m \
3771 [$canv2 itemcget $linentag($row) -font] $row
3772 }
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10003773 }
3774}
3775
Paul Mackerras164ff272006-05-29 19:50:02 +10003776proc vrel_change {name ix op} {
3777 global highlight_related
3778
3779 rhighlight_none
Christian Stimmingb007ee22007-11-07 18:44:35 +01003780 if {$highlight_related ne [mc "None"]} {
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10003781 run drawvisible
Paul Mackerras164ff272006-05-29 19:50:02 +10003782 }
3783}
3784
3785# prepare for testing whether commits are descendents or ancestors of a
3786proc rhighlight_sel {a} {
3787 global descendent desc_todo ancestor anc_todo
Paul Mackerras476ca632008-01-07 22:16:31 +11003788 global highlight_related
Paul Mackerras164ff272006-05-29 19:50:02 +10003789
3790 catch {unset descendent}
3791 set desc_todo [list $a]
3792 catch {unset ancestor}
3793 set anc_todo [list $a]
Christian Stimmingb007ee22007-11-07 18:44:35 +01003794 if {$highlight_related ne [mc "None"]} {
Paul Mackerras164ff272006-05-29 19:50:02 +10003795 rhighlight_none
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10003796 run drawvisible
Paul Mackerras164ff272006-05-29 19:50:02 +10003797 }
3798}
3799
3800proc rhighlight_none {} {
3801 global rhighlights
3802
Paul Mackerras4e7d6772006-05-30 21:33:07 +10003803 catch {unset rhighlights}
3804 unbolden
Paul Mackerras164ff272006-05-29 19:50:02 +10003805}
3806
3807proc is_descendent {a} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11003808 global curview children descendent desc_todo
Paul Mackerras164ff272006-05-29 19:50:02 +10003809
3810 set v $curview
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11003811 set la [rowofcommit $a]
Paul Mackerras164ff272006-05-29 19:50:02 +10003812 set todo $desc_todo
3813 set leftover {}
3814 set done 0
3815 for {set i 0} {$i < [llength $todo]} {incr i} {
3816 set do [lindex $todo $i]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11003817 if {[rowofcommit $do] < $la} {
Paul Mackerras164ff272006-05-29 19:50:02 +10003818 lappend leftover $do
3819 continue
3820 }
3821 foreach nk $children($v,$do) {
3822 if {![info exists descendent($nk)]} {
3823 set descendent($nk) 1
3824 lappend todo $nk
3825 if {$nk eq $a} {
3826 set done 1
3827 }
3828 }
3829 }
3830 if {$done} {
3831 set desc_todo [concat $leftover [lrange $todo [expr {$i+1}] end]]
3832 return
3833 }
3834 }
3835 set descendent($a) 0
3836 set desc_todo $leftover
3837}
3838
3839proc is_ancestor {a} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11003840 global curview parents ancestor anc_todo
Paul Mackerras164ff272006-05-29 19:50:02 +10003841
3842 set v $curview
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11003843 set la [rowofcommit $a]
Paul Mackerras164ff272006-05-29 19:50:02 +10003844 set todo $anc_todo
3845 set leftover {}
3846 set done 0
3847 for {set i 0} {$i < [llength $todo]} {incr i} {
3848 set do [lindex $todo $i]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11003849 if {![commitinview $do $v] || [rowofcommit $do] > $la} {
Paul Mackerras164ff272006-05-29 19:50:02 +10003850 lappend leftover $do
3851 continue
3852 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11003853 foreach np $parents($v,$do) {
Paul Mackerras164ff272006-05-29 19:50:02 +10003854 if {![info exists ancestor($np)]} {
3855 set ancestor($np) 1
3856 lappend todo $np
3857 if {$np eq $a} {
3858 set done 1
3859 }
3860 }
3861 }
3862 if {$done} {
3863 set anc_todo [concat $leftover [lrange $todo [expr {$i+1}] end]]
3864 return
3865 }
3866 }
3867 set ancestor($a) 0
3868 set anc_todo $leftover
3869}
3870
3871proc askrelhighlight {row id} {
Paul Mackerras9c311b32007-10-04 22:27:13 +10003872 global descendent highlight_related iddrawn rhighlights
Paul Mackerras164ff272006-05-29 19:50:02 +10003873 global selectedline ancestor
3874
Paul Mackerras94b4a692008-05-20 20:51:06 +10003875 if {$selectedline eq {}} return
Paul Mackerras164ff272006-05-29 19:50:02 +10003876 set isbold 0
Christian Stimming55e34432008-01-09 22:23:18 +01003877 if {$highlight_related eq [mc "Descendant"] ||
3878 $highlight_related eq [mc "Not descendant"]} {
Paul Mackerras164ff272006-05-29 19:50:02 +10003879 if {![info exists descendent($id)]} {
3880 is_descendent $id
3881 }
Christian Stimming55e34432008-01-09 22:23:18 +01003882 if {$descendent($id) == ($highlight_related eq [mc "Descendant"])} {
Paul Mackerras164ff272006-05-29 19:50:02 +10003883 set isbold 1
3884 }
Christian Stimmingb007ee22007-11-07 18:44:35 +01003885 } elseif {$highlight_related eq [mc "Ancestor"] ||
3886 $highlight_related eq [mc "Not ancestor"]} {
Paul Mackerras164ff272006-05-29 19:50:02 +10003887 if {![info exists ancestor($id)]} {
3888 is_ancestor $id
3889 }
Christian Stimmingb007ee22007-11-07 18:44:35 +01003890 if {$ancestor($id) == ($highlight_related eq [mc "Ancestor"])} {
Paul Mackerras164ff272006-05-29 19:50:02 +10003891 set isbold 1
3892 }
3893 }
3894 if {[info exists iddrawn($id)]} {
Paul Mackerras476ca632008-01-07 22:16:31 +11003895 if {$isbold && ![ishighlighted $id]} {
Paul Mackerras9c311b32007-10-04 22:27:13 +10003896 bolden $row mainfontbold
Paul Mackerras164ff272006-05-29 19:50:02 +10003897 }
3898 }
Paul Mackerras476ca632008-01-07 22:16:31 +11003899 set rhighlights($id) $isbold
Paul Mackerras164ff272006-05-29 19:50:02 +10003900}
3901
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10003902# Graph layout functions
3903
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003904proc shortids {ids} {
3905 set res {}
3906 foreach id $ids {
3907 if {[llength $id] > 1} {
3908 lappend res [shortids $id]
3909 } elseif {[regexp {^[0-9a-f]{40}$} $id]} {
3910 lappend res [string range $id 0 7]
3911 } else {
3912 lappend res $id
3913 }
3914 }
3915 return $res
3916}
3917
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003918proc ntimes {n o} {
3919 set ret {}
Paul Mackerras03800812007-08-29 21:45:21 +10003920 set o [list $o]
3921 for {set mask 1} {$mask <= $n} {incr mask $mask} {
3922 if {($n & $mask) != 0} {
3923 set ret [concat $ret $o]
3924 }
3925 set o [concat $o $o]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003926 }
3927 return $ret
3928}
3929
Paul Mackerras9257d8f2007-12-11 10:45:38 +11003930proc ordertoken {id} {
3931 global ordertok curview varcid varcstart varctok curview parents children
3932 global nullid nullid2
3933
3934 if {[info exists ordertok($id)]} {
3935 return $ordertok($id)
3936 }
3937 set origid $id
3938 set todo {}
3939 while {1} {
3940 if {[info exists varcid($curview,$id)]} {
3941 set a $varcid($curview,$id)
3942 set p [lindex $varcstart($curview) $a]
3943 } else {
3944 set p [lindex $children($curview,$id) 0]
3945 }
3946 if {[info exists ordertok($p)]} {
3947 set tok $ordertok($p)
3948 break
3949 }
Paul Mackerrasc8c9f3d2008-01-06 13:54:58 +11003950 set id [first_real_child $curview,$p]
3951 if {$id eq {}} {
Paul Mackerras9257d8f2007-12-11 10:45:38 +11003952 # it's a root
Paul Mackerras46308ea2008-01-15 22:16:32 +11003953 set tok [lindex $varctok($curview) $varcid($curview,$p)]
Paul Mackerras9257d8f2007-12-11 10:45:38 +11003954 break
3955 }
Paul Mackerras9257d8f2007-12-11 10:45:38 +11003956 if {[llength $parents($curview,$id)] == 1} {
3957 lappend todo [list $p {}]
3958 } else {
3959 set j [lsearch -exact $parents($curview,$id) $p]
3960 if {$j < 0} {
3961 puts "oops didn't find [shortids $p] in parents of [shortids $id]"
3962 }
3963 lappend todo [list $p [strrep $j]]
3964 }
3965 }
3966 for {set i [llength $todo]} {[incr i -1] >= 0} {} {
3967 set p [lindex $todo $i 0]
3968 append tok [lindex $todo $i 1]
3969 set ordertok($p) $tok
3970 }
3971 set ordertok($origid) $tok
3972 return $tok
3973}
3974
Paul Mackerras6e8c8702007-07-31 21:03:06 +10003975# Work out where id should go in idlist so that order-token
3976# values increase from left to right
3977proc idcol {idlist id {i 0}} {
Paul Mackerras9257d8f2007-12-11 10:45:38 +11003978 set t [ordertoken $id]
Paul Mackerrase5b37ac2007-12-12 18:13:51 +11003979 if {$i < 0} {
3980 set i 0
3981 }
Paul Mackerras9257d8f2007-12-11 10:45:38 +11003982 if {$i >= [llength $idlist] || $t < [ordertoken [lindex $idlist $i]]} {
Paul Mackerras6e8c8702007-07-31 21:03:06 +10003983 if {$i > [llength $idlist]} {
3984 set i [llength $idlist]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003985 }
Paul Mackerras9257d8f2007-12-11 10:45:38 +11003986 while {[incr i -1] >= 0 && $t < [ordertoken [lindex $idlist $i]]} {}
Paul Mackerras6e8c8702007-07-31 21:03:06 +10003987 incr i
3988 } else {
Paul Mackerras9257d8f2007-12-11 10:45:38 +11003989 if {$t > [ordertoken [lindex $idlist $i]]} {
Paul Mackerras6e8c8702007-07-31 21:03:06 +10003990 while {[incr i] < [llength $idlist] &&
Paul Mackerras9257d8f2007-12-11 10:45:38 +11003991 $t >= [ordertoken [lindex $idlist $i]]} {}
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003992 }
3993 }
Paul Mackerras6e8c8702007-07-31 21:03:06 +10003994 return $i
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003995}
3996
3997proc initlayout {} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11003998 global rowidlist rowisopt rowfinal displayorder parentlist
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10003999 global numcommits canvxmax canv
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11004000 global nextcolor
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004001 global colormap rowtextx
Paul Mackerras9f1afe02006-02-19 22:44:47 +11004002
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11004003 set numcommits 0
4004 set displayorder {}
Paul Mackerras79b2c752006-04-02 20:47:40 +10004005 set parentlist {}
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11004006 set nextcolor 0
Paul Mackerras03800812007-08-29 21:45:21 +10004007 set rowidlist {}
4008 set rowisopt {}
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10004009 set rowfinal {}
Paul Mackerrasbe0cd092006-03-31 09:55:11 +11004010 set canvxmax [$canv cget -width]
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004011 catch {unset colormap}
4012 catch {unset rowtextx}
Paul Mackerrasac1276a2008-03-03 10:11:08 +11004013 setcanvscroll
Paul Mackerrasbe0cd092006-03-31 09:55:11 +11004014}
4015
4016proc setcanvscroll {} {
4017 global canv canv2 canv3 numcommits linespc canvxmax canvy0
Paul Mackerrasac1276a2008-03-03 10:11:08 +11004018 global lastscrollset lastscrollrows
Paul Mackerrasbe0cd092006-03-31 09:55:11 +11004019
4020 set ymax [expr {$canvy0 + ($numcommits - 0.5) * $linespc + 2}]
4021 $canv conf -scrollregion [list 0 0 $canvxmax $ymax]
4022 $canv2 conf -scrollregion [list 0 0 0 $ymax]
4023 $canv3 conf -scrollregion [list 0 0 0 $ymax]
Paul Mackerrasac1276a2008-03-03 10:11:08 +11004024 set lastscrollset [clock clicks -milliseconds]
4025 set lastscrollrows $numcommits
Paul Mackerras9f1afe02006-02-19 22:44:47 +11004026}
4027
4028proc visiblerows {} {
4029 global canv numcommits linespc
4030
4031 set ymax [lindex [$canv cget -scrollregion] 3]
4032 if {$ymax eq {} || $ymax == 0} return
4033 set f [$canv yview]
4034 set y0 [expr {int([lindex $f 0] * $ymax)}]
4035 set r0 [expr {int(($y0 - 3) / $linespc) - 1}]
4036 if {$r0 < 0} {
4037 set r0 0
4038 }
4039 set y1 [expr {int([lindex $f 1] * $ymax)}]
4040 set r1 [expr {int(($y1 - 3) / $linespc) + 1}]
4041 if {$r1 >= $numcommits} {
4042 set r1 [expr {$numcommits - 1}]
4043 }
4044 return [list $r0 $r1]
4045}
4046
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10004047proc layoutmore {} {
Paul Mackerras38dfe932007-12-06 20:50:31 +11004048 global commitidx viewcomplete curview
Paul Mackerras94b4a692008-05-20 20:51:06 +10004049 global numcommits pending_select curview
Paul Mackerrasac1276a2008-03-03 10:11:08 +11004050 global lastscrollset lastscrollrows commitinterest
Paul Mackerras9f1afe02006-02-19 22:44:47 +11004051
Paul Mackerrasac1276a2008-03-03 10:11:08 +11004052 if {$lastscrollrows < 100 || $viewcomplete($curview) ||
4053 [clock clicks -milliseconds] - $lastscrollset > 500} {
Paul Mackerrasa2c22362006-10-31 15:00:53 +11004054 setcanvscroll
4055 }
Paul Mackerrasd94f8cd2006-04-06 10:18:23 +10004056 if {[info exists pending_select] &&
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004057 [commitinview $pending_select $curview]} {
Alexander Gavrilov567c34e2008-07-26 20:13:45 +04004058 update
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004059 selectline [rowofcommit $pending_select] 1
Paul Mackerrasd94f8cd2006-04-06 10:18:23 +10004060 }
Paul Mackerrasac1276a2008-03-03 10:11:08 +11004061 drawvisible
Paul Mackerras219ea3a2006-09-07 10:21:39 +10004062}
4063
4064proc doshowlocalchanges {} {
Paul Mackerras38dfe932007-12-06 20:50:31 +11004065 global curview mainheadid
Paul Mackerras219ea3a2006-09-07 10:21:39 +10004066
Paul Mackerrasc11ff122008-05-26 10:11:33 +10004067 if {$mainheadid eq {}} return
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004068 if {[commitinview $mainheadid $curview]} {
Paul Mackerras219ea3a2006-09-07 10:21:39 +10004069 dodiffindex
Paul Mackerras38dfe932007-12-06 20:50:31 +11004070 } else {
4071 lappend commitinterest($mainheadid) {dodiffindex}
Paul Mackerras219ea3a2006-09-07 10:21:39 +10004072 }
4073}
4074
4075proc dohidelocalchanges {} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004076 global nullid nullid2 lserial curview
Paul Mackerras219ea3a2006-09-07 10:21:39 +10004077
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004078 if {[commitinview $nullid $curview]} {
Paul Mackerrasb8a938c2008-02-13 22:12:31 +11004079 removefakerow $nullid
Paul Mackerras8f489362007-07-13 19:49:37 +10004080 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004081 if {[commitinview $nullid2 $curview]} {
Paul Mackerrasb8a938c2008-02-13 22:12:31 +11004082 removefakerow $nullid2
Paul Mackerras219ea3a2006-09-07 10:21:39 +10004083 }
4084 incr lserial
4085}
4086
Paul Mackerras8f489362007-07-13 19:49:37 +10004087# spawn off a process to do git diff-index --cached HEAD
Paul Mackerras219ea3a2006-09-07 10:21:39 +10004088proc dodiffindex {} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004089 global lserial showlocalchanges
David Aguilarcb8329a2008-03-10 03:54:56 -07004090 global isworktree
Paul Mackerras219ea3a2006-09-07 10:21:39 +10004091
David Aguilarcb8329a2008-03-10 03:54:56 -07004092 if {!$showlocalchanges || !$isworktree} return
Paul Mackerras219ea3a2006-09-07 10:21:39 +10004093 incr lserial
Paul Mackerras8f489362007-07-13 19:49:37 +10004094 set fd [open "|git diff-index --cached HEAD" r]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10004095 fconfigure $fd -blocking 0
Alexander Gavrilove439e092008-07-13 16:40:47 +04004096 set i [reg_instance $fd]
4097 filerun $fd [list readdiffindex $fd $lserial $i]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10004098}
4099
Alexander Gavrilove439e092008-07-13 16:40:47 +04004100proc readdiffindex {fd serial inst} {
Paul Mackerrasfc2a2562007-12-26 23:03:43 +11004101 global mainheadid nullid nullid2 curview commitinfo commitdata lserial
Paul Mackerras219ea3a2006-09-07 10:21:39 +10004102
Paul Mackerras8f489362007-07-13 19:49:37 +10004103 set isdiff 1
Paul Mackerras219ea3a2006-09-07 10:21:39 +10004104 if {[gets $fd line] < 0} {
Paul Mackerras8f489362007-07-13 19:49:37 +10004105 if {![eof $fd]} {
4106 return 1
Paul Mackerras219ea3a2006-09-07 10:21:39 +10004107 }
Paul Mackerras8f489362007-07-13 19:49:37 +10004108 set isdiff 0
Paul Mackerras219ea3a2006-09-07 10:21:39 +10004109 }
4110 # we only need to see one line and we don't really care what it says...
Alexander Gavrilove439e092008-07-13 16:40:47 +04004111 stop_instance $inst
Paul Mackerras219ea3a2006-09-07 10:21:39 +10004112
Paul Mackerras24f7a662007-12-19 09:35:33 +11004113 if {$serial != $lserial} {
4114 return 0
Paul Mackerras8f489362007-07-13 19:49:37 +10004115 }
4116
Paul Mackerras24f7a662007-12-19 09:35:33 +11004117 # now see if there are any local changes not checked in to the index
4118 set fd [open "|git diff-files" r]
4119 fconfigure $fd -blocking 0
Alexander Gavrilove439e092008-07-13 16:40:47 +04004120 set i [reg_instance $fd]
4121 filerun $fd [list readdifffiles $fd $serial $i]
Paul Mackerras24f7a662007-12-19 09:35:33 +11004122
4123 if {$isdiff && ![commitinview $nullid2 $curview]} {
Paul Mackerras8f489362007-07-13 19:49:37 +10004124 # add the line for the changes in the index to the graph
Christian Stimmingd990ced2007-11-07 18:42:55 +01004125 set hl [mc "Local changes checked in to index but not committed"]
Paul Mackerras8f489362007-07-13 19:49:37 +10004126 set commitinfo($nullid2) [list $hl {} {} {} {} " $hl\n"]
4127 set commitdata($nullid2) "\n $hl\n"
Paul Mackerrasfc2a2562007-12-26 23:03:43 +11004128 if {[commitinview $nullid $curview]} {
Paul Mackerrasb8a938c2008-02-13 22:12:31 +11004129 removefakerow $nullid
Paul Mackerrasfc2a2562007-12-26 23:03:43 +11004130 }
Paul Mackerrasb8a938c2008-02-13 22:12:31 +11004131 insertfakerow $nullid2 $mainheadid
Paul Mackerras24f7a662007-12-19 09:35:33 +11004132 } elseif {!$isdiff && [commitinview $nullid2 $curview]} {
Paul Mackerrasb8a938c2008-02-13 22:12:31 +11004133 removefakerow $nullid2
Paul Mackerras8f489362007-07-13 19:49:37 +10004134 }
4135 return 0
4136}
4137
Alexander Gavrilove439e092008-07-13 16:40:47 +04004138proc readdifffiles {fd serial inst} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004139 global mainheadid nullid nullid2 curview
Paul Mackerras8f489362007-07-13 19:49:37 +10004140 global commitinfo commitdata lserial
4141
4142 set isdiff 1
4143 if {[gets $fd line] < 0} {
4144 if {![eof $fd]} {
4145 return 1
4146 }
4147 set isdiff 0
4148 }
4149 # we only need to see one line and we don't really care what it says...
Alexander Gavrilove439e092008-07-13 16:40:47 +04004150 stop_instance $inst
Paul Mackerras8f489362007-07-13 19:49:37 +10004151
Paul Mackerras24f7a662007-12-19 09:35:33 +11004152 if {$serial != $lserial} {
4153 return 0
4154 }
4155
4156 if {$isdiff && ![commitinview $nullid $curview]} {
Paul Mackerras219ea3a2006-09-07 10:21:39 +10004157 # add the line for the local diff to the graph
Christian Stimmingd990ced2007-11-07 18:42:55 +01004158 set hl [mc "Local uncommitted changes, not checked in to index"]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10004159 set commitinfo($nullid) [list $hl {} {} {} {} " $hl\n"]
4160 set commitdata($nullid) "\n $hl\n"
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004161 if {[commitinview $nullid2 $curview]} {
4162 set p $nullid2
4163 } else {
4164 set p $mainheadid
4165 }
Paul Mackerrasb8a938c2008-02-13 22:12:31 +11004166 insertfakerow $nullid $p
Paul Mackerras24f7a662007-12-19 09:35:33 +11004167 } elseif {!$isdiff && [commitinview $nullid $curview]} {
Paul Mackerrasb8a938c2008-02-13 22:12:31 +11004168 removefakerow $nullid
Paul Mackerras219ea3a2006-09-07 10:21:39 +10004169 }
4170 return 0
Paul Mackerras9f1afe02006-02-19 22:44:47 +11004171}
4172
Paul Mackerras8f0bc7e2007-08-24 22:16:42 +10004173proc nextuse {id row} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004174 global curview children
Paul Mackerras8f0bc7e2007-08-24 22:16:42 +10004175
4176 if {[info exists children($curview,$id)]} {
4177 foreach kid $children($curview,$id) {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004178 if {![commitinview $kid $curview]} {
Paul Mackerras03800812007-08-29 21:45:21 +10004179 return -1
4180 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004181 if {[rowofcommit $kid] > $row} {
4182 return [rowofcommit $kid]
Paul Mackerras8f0bc7e2007-08-24 22:16:42 +10004183 }
4184 }
4185 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004186 if {[commitinview $id $curview]} {
4187 return [rowofcommit $id]
Paul Mackerras8f0bc7e2007-08-24 22:16:42 +10004188 }
4189 return -1
4190}
4191
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10004192proc prevuse {id row} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004193 global curview children
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10004194
4195 set ret -1
4196 if {[info exists children($curview,$id)]} {
4197 foreach kid $children($curview,$id) {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004198 if {![commitinview $kid $curview]} break
4199 if {[rowofcommit $kid] < $row} {
4200 set ret [rowofcommit $kid]
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10004201 }
4202 }
4203 }
4204 return $ret
4205}
4206
Paul Mackerras03800812007-08-29 21:45:21 +10004207proc make_idlist {row} {
4208 global displayorder parentlist uparrowlen downarrowlen mingaplen
Paul Mackerras9257d8f2007-12-11 10:45:38 +11004209 global commitidx curview children
Paul Mackerras03800812007-08-29 21:45:21 +10004210
4211 set r [expr {$row - $mingaplen - $downarrowlen - 1}]
4212 if {$r < 0} {
4213 set r 0
4214 }
4215 set ra [expr {$row - $downarrowlen}]
4216 if {$ra < 0} {
4217 set ra 0
4218 }
4219 set rb [expr {$row + $uparrowlen}]
4220 if {$rb > $commitidx($curview)} {
4221 set rb $commitidx($curview)
4222 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004223 make_disporder $r [expr {$rb + 1}]
Paul Mackerras03800812007-08-29 21:45:21 +10004224 set ids {}
4225 for {} {$r < $ra} {incr r} {
4226 set nextid [lindex $displayorder [expr {$r + 1}]]
4227 foreach p [lindex $parentlist $r] {
4228 if {$p eq $nextid} continue
4229 set rn [nextuse $p $r]
4230 if {$rn >= $row &&
4231 $rn <= $r + $downarrowlen + $mingaplen + $uparrowlen} {
Paul Mackerras9257d8f2007-12-11 10:45:38 +11004232 lappend ids [list [ordertoken $p] $p]
Paul Mackerras03800812007-08-29 21:45:21 +10004233 }
4234 }
4235 }
4236 for {} {$r < $row} {incr r} {
4237 set nextid [lindex $displayorder [expr {$r + 1}]]
4238 foreach p [lindex $parentlist $r] {
4239 if {$p eq $nextid} continue
4240 set rn [nextuse $p $r]
4241 if {$rn < 0 || $rn >= $row} {
Paul Mackerras9257d8f2007-12-11 10:45:38 +11004242 lappend ids [list [ordertoken $p] $p]
Paul Mackerras03800812007-08-29 21:45:21 +10004243 }
4244 }
4245 }
4246 set id [lindex $displayorder $row]
Paul Mackerras9257d8f2007-12-11 10:45:38 +11004247 lappend ids [list [ordertoken $id] $id]
Paul Mackerras03800812007-08-29 21:45:21 +10004248 while {$r < $rb} {
4249 foreach p [lindex $parentlist $r] {
4250 set firstkid [lindex $children($curview,$p) 0]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004251 if {[rowofcommit $firstkid] < $row} {
Paul Mackerras9257d8f2007-12-11 10:45:38 +11004252 lappend ids [list [ordertoken $p] $p]
Paul Mackerras03800812007-08-29 21:45:21 +10004253 }
4254 }
4255 incr r
4256 set id [lindex $displayorder $r]
4257 if {$id ne {}} {
4258 set firstkid [lindex $children($curview,$id) 0]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004259 if {$firstkid ne {} && [rowofcommit $firstkid] < $row} {
Paul Mackerras9257d8f2007-12-11 10:45:38 +11004260 lappend ids [list [ordertoken $id] $id]
Paul Mackerras03800812007-08-29 21:45:21 +10004261 }
4262 }
4263 }
4264 set idlist {}
4265 foreach idx [lsort -unique $ids] {
4266 lappend idlist [lindex $idx 1]
4267 }
4268 return $idlist
4269}
4270
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10004271proc rowsequal {a b} {
4272 while {[set i [lsearch -exact $a {}]] >= 0} {
4273 set a [lreplace $a $i $i]
4274 }
4275 while {[set i [lsearch -exact $b {}]] >= 0} {
4276 set b [lreplace $b $i $i]
4277 }
4278 return [expr {$a eq $b}]
4279}
4280
4281proc makeupline {id row rend col} {
4282 global rowidlist uparrowlen downarrowlen mingaplen
4283
4284 for {set r $rend} {1} {set r $rstart} {
4285 set rstart [prevuse $id $r]
4286 if {$rstart < 0} return
4287 if {$rstart < $row} break
4288 }
4289 if {$rstart + $uparrowlen + $mingaplen + $downarrowlen < $rend} {
4290 set rstart [expr {$rend - $uparrowlen - 1}]
4291 }
4292 for {set r $rstart} {[incr r] <= $row} {} {
4293 set idlist [lindex $rowidlist $r]
4294 if {$idlist ne {} && [lsearch -exact $idlist $id] < 0} {
4295 set col [idcol $idlist $id $col]
4296 lset rowidlist $r [linsert $idlist $col $id]
4297 changedrow $r
4298 }
4299 }
4300}
4301
Paul Mackerras03800812007-08-29 21:45:21 +10004302proc layoutrows {row endrow} {
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10004303 global rowidlist rowisopt rowfinal displayorder
Paul Mackerras9f1afe02006-02-19 22:44:47 +11004304 global uparrowlen downarrowlen maxwidth mingaplen
Paul Mackerras6a90bff2007-06-18 09:48:23 +10004305 global children parentlist
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004306 global commitidx viewcomplete curview
Paul Mackerras9f1afe02006-02-19 22:44:47 +11004307
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004308 make_disporder [expr {$row - 1}] [expr {$endrow + $uparrowlen}]
Paul Mackerras03800812007-08-29 21:45:21 +10004309 set idlist {}
4310 if {$row > 0} {
Paul Mackerrasf56782a2007-09-15 09:04:11 +10004311 set rm1 [expr {$row - 1}]
4312 foreach id [lindex $rowidlist $rm1] {
Paul Mackerras03800812007-08-29 21:45:21 +10004313 if {$id ne {}} {
4314 lappend idlist $id
Paul Mackerras9f1afe02006-02-19 22:44:47 +11004315 }
4316 }
Paul Mackerrasf56782a2007-09-15 09:04:11 +10004317 set final [lindex $rowfinal $rm1]
Paul Mackerras8f0bc7e2007-08-24 22:16:42 +10004318 }
Paul Mackerras03800812007-08-29 21:45:21 +10004319 for {} {$row < $endrow} {incr row} {
4320 set rm1 [expr {$row - 1}]
Paul Mackerrasf56782a2007-09-15 09:04:11 +10004321 if {$rm1 < 0 || $idlist eq {}} {
Paul Mackerras03800812007-08-29 21:45:21 +10004322 set idlist [make_idlist $row]
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10004323 set final 1
Paul Mackerras03800812007-08-29 21:45:21 +10004324 } else {
4325 set id [lindex $displayorder $rm1]
4326 set col [lsearch -exact $idlist $id]
4327 set idlist [lreplace $idlist $col $col]
4328 foreach p [lindex $parentlist $rm1] {
4329 if {[lsearch -exact $idlist $p] < 0} {
4330 set col [idcol $idlist $p $col]
4331 set idlist [linsert $idlist $col $p]
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10004332 # if not the first child, we have to insert a line going up
4333 if {$id ne [lindex $children($curview,$p) 0]} {
4334 makeupline $p $rm1 $row $col
Paul Mackerras9f1afe02006-02-19 22:44:47 +11004335 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11004336 }
4337 }
Paul Mackerras03800812007-08-29 21:45:21 +10004338 set id [lindex $displayorder $row]
4339 if {$row > $downarrowlen} {
4340 set termrow [expr {$row - $downarrowlen - 1}]
4341 foreach p [lindex $parentlist $termrow] {
4342 set i [lsearch -exact $idlist $p]
4343 if {$i < 0} continue
4344 set nr [nextuse $p $termrow]
4345 if {$nr < 0 || $nr >= $row + $mingaplen + $uparrowlen} {
4346 set idlist [lreplace $idlist $i $i]
4347 }
4348 }
4349 }
4350 set col [lsearch -exact $idlist $id]
4351 if {$col < 0} {
4352 set col [idcol $idlist $id]
4353 set idlist [linsert $idlist $col $id]
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10004354 if {$children($curview,$id) ne {}} {
4355 makeupline $id $rm1 $row $col
4356 }
Paul Mackerras03800812007-08-29 21:45:21 +10004357 }
4358 set r [expr {$row + $uparrowlen - 1}]
4359 if {$r < $commitidx($curview)} {
4360 set x $col
4361 foreach p [lindex $parentlist $r] {
4362 if {[lsearch -exact $idlist $p] >= 0} continue
4363 set fk [lindex $children($curview,$p) 0]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004364 if {[rowofcommit $fk] < $row} {
Paul Mackerras03800812007-08-29 21:45:21 +10004365 set x [idcol $idlist $p $x]
4366 set idlist [linsert $idlist $x $p]
4367 }
4368 }
4369 if {[incr r] < $commitidx($curview)} {
4370 set p [lindex $displayorder $r]
4371 if {[lsearch -exact $idlist $p] < 0} {
4372 set fk [lindex $children($curview,$p) 0]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004373 if {$fk ne {} && [rowofcommit $fk] < $row} {
Paul Mackerras03800812007-08-29 21:45:21 +10004374 set x [idcol $idlist $p $x]
4375 set idlist [linsert $idlist $x $p]
4376 }
4377 }
4378 }
Paul Mackerras7b459a12007-08-13 14:52:00 +10004379 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11004380 }
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10004381 if {$final && !$viewcomplete($curview) &&
4382 $row + $uparrowlen + $mingaplen + $downarrowlen
4383 >= $commitidx($curview)} {
4384 set final 0
Paul Mackerras7b459a12007-08-13 14:52:00 +10004385 }
Paul Mackerras03800812007-08-29 21:45:21 +10004386 set l [llength $rowidlist]
4387 if {$row == $l} {
4388 lappend rowidlist $idlist
4389 lappend rowisopt 0
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10004390 lappend rowfinal $final
Paul Mackerras03800812007-08-29 21:45:21 +10004391 } elseif {$row < $l} {
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10004392 if {![rowsequal $idlist [lindex $rowidlist $row]]} {
Paul Mackerras03800812007-08-29 21:45:21 +10004393 lset rowidlist $row $idlist
4394 changedrow $row
Paul Mackerras9f1afe02006-02-19 22:44:47 +11004395 }
Paul Mackerrasf56782a2007-09-15 09:04:11 +10004396 lset rowfinal $row $final
Paul Mackerras9f1afe02006-02-19 22:44:47 +11004397 } else {
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10004398 set pad [ntimes [expr {$row - $l}] {}]
4399 set rowidlist [concat $rowidlist $pad]
Paul Mackerras03800812007-08-29 21:45:21 +10004400 lappend rowidlist $idlist
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10004401 set rowfinal [concat $rowfinal $pad]
4402 lappend rowfinal $final
Paul Mackerras03800812007-08-29 21:45:21 +10004403 set rowisopt [concat $rowisopt [ntimes [expr {$row - $l + 1}] 0]]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11004404 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11004405 }
4406 return $row
4407}
4408
Paul Mackerras03800812007-08-29 21:45:21 +10004409proc changedrow {row} {
4410 global displayorder iddrawn rowisopt need_redisplay
Paul Mackerras9f1afe02006-02-19 22:44:47 +11004411
Paul Mackerras03800812007-08-29 21:45:21 +10004412 set l [llength $rowisopt]
4413 if {$row < $l} {
4414 lset rowisopt $row 0
4415 if {$row + 1 < $l} {
4416 lset rowisopt [expr {$row + 1}] 0
4417 if {$row + 2 < $l} {
4418 lset rowisopt [expr {$row + 2}] 0
4419 }
4420 }
Paul Mackerras79b2c752006-04-02 20:47:40 +10004421 }
Paul Mackerras03800812007-08-29 21:45:21 +10004422 set id [lindex $displayorder $row]
4423 if {[info exists iddrawn($id)]} {
4424 set need_redisplay 1
Paul Mackerras9f1afe02006-02-19 22:44:47 +11004425 }
4426}
4427
4428proc insert_pad {row col npad} {
Paul Mackerras6e8c8702007-07-31 21:03:06 +10004429 global rowidlist
Paul Mackerras9f1afe02006-02-19 22:44:47 +11004430
4431 set pad [ntimes $npad {}]
Paul Mackerrase341c062007-08-12 12:42:57 +10004432 set idlist [lindex $rowidlist $row]
4433 set bef [lrange $idlist 0 [expr {$col - 1}]]
4434 set aft [lrange $idlist $col end]
4435 set i [lsearch -exact $aft {}]
4436 if {$i > 0} {
4437 set aft [lreplace $aft $i $i]
4438 }
4439 lset rowidlist $row [concat $bef $pad $aft]
Paul Mackerras03800812007-08-29 21:45:21 +10004440 changedrow $row
Paul Mackerras9f1afe02006-02-19 22:44:47 +11004441}
4442
4443proc optimize_rows {row col endrow} {
Paul Mackerras03800812007-08-29 21:45:21 +10004444 global rowidlist rowisopt displayorder curview children
Paul Mackerras9f1afe02006-02-19 22:44:47 +11004445
Paul Mackerras6e8c8702007-07-31 21:03:06 +10004446 if {$row < 1} {
4447 set row 1
4448 }
Paul Mackerras03800812007-08-29 21:45:21 +10004449 for {} {$row < $endrow} {incr row; set col 0} {
4450 if {[lindex $rowisopt $row]} continue
Paul Mackerras9f1afe02006-02-19 22:44:47 +11004451 set haspad 0
Paul Mackerras6e8c8702007-07-31 21:03:06 +10004452 set y0 [expr {$row - 1}]
4453 set ym [expr {$row - 2}]
Paul Mackerras03800812007-08-29 21:45:21 +10004454 set idlist [lindex $rowidlist $row]
4455 set previdlist [lindex $rowidlist $y0]
4456 if {$idlist eq {} || $previdlist eq {}} continue
4457 if {$ym >= 0} {
4458 set pprevidlist [lindex $rowidlist $ym]
4459 if {$pprevidlist eq {}} continue
4460 } else {
4461 set pprevidlist {}
4462 }
Paul Mackerras6e8c8702007-07-31 21:03:06 +10004463 set x0 -1
4464 set xm -1
4465 for {} {$col < [llength $idlist]} {incr col} {
4466 set id [lindex $idlist $col]
4467 if {[lindex $previdlist $col] eq $id} continue
4468 if {$id eq {}} {
Paul Mackerras9f1afe02006-02-19 22:44:47 +11004469 set haspad 1
4470 continue
4471 }
Paul Mackerras6e8c8702007-07-31 21:03:06 +10004472 set x0 [lsearch -exact $previdlist $id]
4473 if {$x0 < 0} continue
4474 set z [expr {$x0 - $col}]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11004475 set isarrow 0
Paul Mackerras6e8c8702007-07-31 21:03:06 +10004476 set z0 {}
4477 if {$ym >= 0} {
4478 set xm [lsearch -exact $pprevidlist $id]
4479 if {$xm >= 0} {
4480 set z0 [expr {$xm - $x0}]
4481 }
4482 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11004483 if {$z0 eq {}} {
Paul Mackerras92ed6662007-08-22 22:35:28 +10004484 # if row y0 is the first child of $id then it's not an arrow
4485 if {[lindex $children($curview,$id) 0] ne
4486 [lindex $displayorder $y0]} {
Paul Mackerras9f1afe02006-02-19 22:44:47 +11004487 set isarrow 1
4488 }
4489 }
Paul Mackerrase341c062007-08-12 12:42:57 +10004490 if {!$isarrow && $id ne [lindex $displayorder $row] &&
4491 [lsearch -exact [lindex $rowidlist [expr {$row+1}]] $id] < 0} {
4492 set isarrow 1
4493 }
Paul Mackerras3fc42792006-09-15 09:45:23 +10004494 # Looking at lines from this row to the previous row,
4495 # make them go straight up if they end in an arrow on
4496 # the previous row; otherwise make them go straight up
4497 # or at 45 degrees.
Paul Mackerras9f1afe02006-02-19 22:44:47 +11004498 if {$z < -1 || ($z < 0 && $isarrow)} {
Paul Mackerras3fc42792006-09-15 09:45:23 +10004499 # Line currently goes left too much;
4500 # insert pads in the previous row, then optimize it
Paul Mackerras9f1afe02006-02-19 22:44:47 +11004501 set npad [expr {-1 - $z + $isarrow}]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11004502 insert_pad $y0 $x0 $npad
4503 if {$y0 > 0} {
4504 optimize_rows $y0 $x0 $row
4505 }
Paul Mackerras6e8c8702007-07-31 21:03:06 +10004506 set previdlist [lindex $rowidlist $y0]
4507 set x0 [lsearch -exact $previdlist $id]
4508 set z [expr {$x0 - $col}]
4509 if {$z0 ne {}} {
4510 set pprevidlist [lindex $rowidlist $ym]
4511 set xm [lsearch -exact $pprevidlist $id]
4512 set z0 [expr {$xm - $x0}]
4513 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11004514 } elseif {$z > 1 || ($z > 0 && $isarrow)} {
Paul Mackerras3fc42792006-09-15 09:45:23 +10004515 # Line currently goes right too much;
Paul Mackerras6e8c8702007-07-31 21:03:06 +10004516 # insert pads in this line
Paul Mackerras9f1afe02006-02-19 22:44:47 +11004517 set npad [expr {$z - 1 + $isarrow}]
Paul Mackerrase341c062007-08-12 12:42:57 +10004518 insert_pad $row $col $npad
4519 set idlist [lindex $rowidlist $row]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11004520 incr col $npad
Paul Mackerras6e8c8702007-07-31 21:03:06 +10004521 set z [expr {$x0 - $col}]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11004522 set haspad 1
4523 }
Paul Mackerras6e8c8702007-07-31 21:03:06 +10004524 if {$z0 eq {} && !$isarrow && $ym >= 0} {
Paul Mackerraseb447a12006-03-18 23:11:37 +11004525 # this line links to its first child on row $row-2
Paul Mackerras6e8c8702007-07-31 21:03:06 +10004526 set id [lindex $displayorder $ym]
4527 set xc [lsearch -exact $pprevidlist $id]
Paul Mackerraseb447a12006-03-18 23:11:37 +11004528 if {$xc >= 0} {
4529 set z0 [expr {$xc - $x0}]
4530 }
4531 }
Paul Mackerras3fc42792006-09-15 09:45:23 +10004532 # avoid lines jigging left then immediately right
Paul Mackerras9f1afe02006-02-19 22:44:47 +11004533 if {$z0 ne {} && $z < 0 && $z0 > 0} {
4534 insert_pad $y0 $x0 1
Paul Mackerras6e8c8702007-07-31 21:03:06 +10004535 incr x0
4536 optimize_rows $y0 $x0 $row
4537 set previdlist [lindex $rowidlist $y0]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11004538 }
4539 }
4540 if {!$haspad} {
Paul Mackerras3fc42792006-09-15 09:45:23 +10004541 # Find the first column that doesn't have a line going right
Paul Mackerras9f1afe02006-02-19 22:44:47 +11004542 for {set col [llength $idlist]} {[incr col -1] >= 0} {} {
Paul Mackerras6e8c8702007-07-31 21:03:06 +10004543 set id [lindex $idlist $col]
4544 if {$id eq {}} break
4545 set x0 [lsearch -exact $previdlist $id]
4546 if {$x0 < 0} {
Paul Mackerraseb447a12006-03-18 23:11:37 +11004547 # check if this is the link to the first child
Paul Mackerras92ed6662007-08-22 22:35:28 +10004548 set kid [lindex $displayorder $y0]
4549 if {[lindex $children($curview,$id) 0] eq $kid} {
Paul Mackerraseb447a12006-03-18 23:11:37 +11004550 # it is, work out offset to child
Paul Mackerras92ed6662007-08-22 22:35:28 +10004551 set x0 [lsearch -exact $previdlist $kid]
Paul Mackerraseb447a12006-03-18 23:11:37 +11004552 }
4553 }
Paul Mackerras6e8c8702007-07-31 21:03:06 +10004554 if {$x0 <= $col} break
Paul Mackerras9f1afe02006-02-19 22:44:47 +11004555 }
Paul Mackerras3fc42792006-09-15 09:45:23 +10004556 # Insert a pad at that column as long as it has a line and
Paul Mackerras6e8c8702007-07-31 21:03:06 +10004557 # isn't the last column
4558 if {$x0 >= 0 && [incr col] < [llength $idlist]} {
Paul Mackerras9f1afe02006-02-19 22:44:47 +11004559 set idlist [linsert $idlist $col {}]
Paul Mackerras03800812007-08-29 21:45:21 +10004560 lset rowidlist $row $idlist
4561 changedrow $row
Paul Mackerras9f1afe02006-02-19 22:44:47 +11004562 }
4563 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11004564 }
4565}
4566
4567proc xc {row col} {
4568 global canvx0 linespc
4569 return [expr {$canvx0 + $col * $linespc}]
4570}
4571
4572proc yc {row} {
4573 global canvy0 linespc
4574 return [expr {$canvy0 + $row * $linespc}]
4575}
4576
Paul Mackerrasc934a8a2006-03-02 23:00:44 +11004577proc linewidth {id} {
4578 global thickerline lthickness
4579
4580 set wid $lthickness
4581 if {[info exists thickerline] && $id eq $thickerline} {
4582 set wid [expr {2 * $lthickness}]
4583 }
4584 return $wid
4585}
4586
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004587proc rowranges {id} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004588 global curview children uparrowlen downarrowlen
Paul Mackerras92ed6662007-08-22 22:35:28 +10004589 global rowidlist
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004590
Paul Mackerras92ed6662007-08-22 22:35:28 +10004591 set kids $children($curview,$id)
4592 if {$kids eq {}} {
4593 return {}
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004594 }
Paul Mackerras92ed6662007-08-22 22:35:28 +10004595 set ret {}
4596 lappend kids $id
4597 foreach child $kids {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004598 if {![commitinview $child $curview]} break
4599 set row [rowofcommit $child]
Paul Mackerras92ed6662007-08-22 22:35:28 +10004600 if {![info exists prev]} {
4601 lappend ret [expr {$row + 1}]
Paul Mackerras322a8cc2006-10-15 18:03:46 +10004602 } else {
Paul Mackerras92ed6662007-08-22 22:35:28 +10004603 if {$row <= $prevrow} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004604 puts "oops children of [shortids $id] out of order [shortids $child] $row <= [shortids $prev] $prevrow"
Paul Mackerras92ed6662007-08-22 22:35:28 +10004605 }
4606 # see if the line extends the whole way from prevrow to row
4607 if {$row > $prevrow + $uparrowlen + $downarrowlen &&
4608 [lsearch -exact [lindex $rowidlist \
4609 [expr {int(($row + $prevrow) / 2)}]] $id] < 0} {
4610 # it doesn't, see where it ends
4611 set r [expr {$prevrow + $downarrowlen}]
4612 if {[lsearch -exact [lindex $rowidlist $r] $id] < 0} {
4613 while {[incr r -1] > $prevrow &&
4614 [lsearch -exact [lindex $rowidlist $r] $id] < 0} {}
4615 } else {
4616 while {[incr r] <= $row &&
4617 [lsearch -exact [lindex $rowidlist $r] $id] >= 0} {}
4618 incr r -1
4619 }
4620 lappend ret $r
4621 # see where it starts up again
4622 set r [expr {$row - $uparrowlen}]
4623 if {[lsearch -exact [lindex $rowidlist $r] $id] < 0} {
4624 while {[incr r] < $row &&
4625 [lsearch -exact [lindex $rowidlist $r] $id] < 0} {}
4626 } else {
4627 while {[incr r -1] >= $prevrow &&
4628 [lsearch -exact [lindex $rowidlist $r] $id] >= 0} {}
4629 incr r
4630 }
4631 lappend ret $r
4632 }
Paul Mackerraseb447a12006-03-18 23:11:37 +11004633 }
Paul Mackerras92ed6662007-08-22 22:35:28 +10004634 if {$child eq $id} {
4635 lappend ret $row
4636 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004637 set prev $child
Paul Mackerras92ed6662007-08-22 22:35:28 +10004638 set prevrow $row
Paul Mackerraseb447a12006-03-18 23:11:37 +11004639 }
Paul Mackerras92ed6662007-08-22 22:35:28 +10004640 return $ret
Paul Mackerras9f1afe02006-02-19 22:44:47 +11004641}
4642
Paul Mackerras322a8cc2006-10-15 18:03:46 +10004643proc drawlineseg {id row endrow arrowlow} {
4644 global rowidlist displayorder iddrawn linesegs
Paul Mackerrase341c062007-08-12 12:42:57 +10004645 global canv colormap linespc curview maxlinelen parentlist
Paul Mackerras9f1afe02006-02-19 22:44:47 +11004646
Paul Mackerras322a8cc2006-10-15 18:03:46 +10004647 set cols [list [lsearch -exact [lindex $rowidlist $row] $id]]
4648 set le [expr {$row + 1}]
4649 set arrowhigh 1
4650 while {1} {
4651 set c [lsearch -exact [lindex $rowidlist $le] $id]
4652 if {$c < 0} {
4653 incr le -1
4654 break
4655 }
4656 lappend cols $c
4657 set x [lindex $displayorder $le]
4658 if {$x eq $id} {
4659 set arrowhigh 0
4660 break
4661 }
4662 if {[info exists iddrawn($x)] || $le == $endrow} {
4663 set c [lsearch -exact [lindex $rowidlist [expr {$le+1}]] $id]
4664 if {$c >= 0} {
4665 lappend cols $c
4666 set arrowhigh 0
4667 }
4668 break
4669 }
4670 incr le
4671 }
4672 if {$le <= $row} {
4673 return $row
4674 }
4675
4676 set lines {}
4677 set i 0
4678 set joinhigh 0
4679 if {[info exists linesegs($id)]} {
4680 set lines $linesegs($id)
4681 foreach li $lines {
4682 set r0 [lindex $li 0]
4683 if {$r0 > $row} {
4684 if {$r0 == $le && [lindex $li 1] - $row <= $maxlinelen} {
4685 set joinhigh 1
4686 }
4687 break
4688 }
4689 incr i
4690 }
4691 }
4692 set joinlow 0
4693 if {$i > 0} {
4694 set li [lindex $lines [expr {$i-1}]]
4695 set r1 [lindex $li 1]
4696 if {$r1 == $row && $le - [lindex $li 0] <= $maxlinelen} {
4697 set joinlow 1
4698 }
4699 }
4700
4701 set x [lindex $cols [expr {$le - $row}]]
4702 set xp [lindex $cols [expr {$le - 1 - $row}]]
4703 set dir [expr {$xp - $x}]
4704 if {$joinhigh} {
4705 set ith [lindex $lines $i 2]
4706 set coords [$canv coords $ith]
4707 set ah [$canv itemcget $ith -arrow]
4708 set arrowhigh [expr {$ah eq "first" || $ah eq "both"}]
4709 set x2 [lindex $cols [expr {$le + 1 - $row}]]
4710 if {$x2 ne {} && $x - $x2 == $dir} {
4711 set coords [lrange $coords 0 end-2]
4712 }
4713 } else {
4714 set coords [list [xc $le $x] [yc $le]]
4715 }
4716 if {$joinlow} {
4717 set itl [lindex $lines [expr {$i-1}] 2]
4718 set al [$canv itemcget $itl -arrow]
4719 set arrowlow [expr {$al eq "last" || $al eq "both"}]
Paul Mackerrase341c062007-08-12 12:42:57 +10004720 } elseif {$arrowlow} {
4721 if {[lsearch -exact [lindex $rowidlist [expr {$row-1}]] $id] >= 0 ||
4722 [lsearch -exact [lindex $parentlist [expr {$row-1}]] $id] >= 0} {
4723 set arrowlow 0
4724 }
Paul Mackerras322a8cc2006-10-15 18:03:46 +10004725 }
4726 set arrow [lindex {none first last both} [expr {$arrowhigh + 2*$arrowlow}]]
4727 for {set y $le} {[incr y -1] > $row} {} {
4728 set x $xp
4729 set xp [lindex $cols [expr {$y - 1 - $row}]]
4730 set ndir [expr {$xp - $x}]
4731 if {$dir != $ndir || $xp < 0} {
4732 lappend coords [xc $y $x] [yc $y]
4733 }
4734 set dir $ndir
4735 }
4736 if {!$joinlow} {
4737 if {$xp < 0} {
4738 # join parent line to first child
4739 set ch [lindex $displayorder $row]
4740 set xc [lsearch -exact [lindex $rowidlist $row] $ch]
4741 if {$xc < 0} {
4742 puts "oops: drawlineseg: child $ch not on row $row"
Paul Mackerrase341c062007-08-12 12:42:57 +10004743 } elseif {$xc != $x} {
4744 if {($arrowhigh && $le == $row + 1) || $dir == 0} {
4745 set d [expr {int(0.5 * $linespc)}]
4746 set x1 [xc $row $x]
4747 if {$xc < $x} {
4748 set x2 [expr {$x1 - $d}]
4749 } else {
4750 set x2 [expr {$x1 + $d}]
4751 }
4752 set y2 [yc $row]
4753 set y1 [expr {$y2 + $d}]
4754 lappend coords $x1 $y1 $x2 $y2
4755 } elseif {$xc < $x - 1} {
Paul Mackerras322a8cc2006-10-15 18:03:46 +10004756 lappend coords [xc $row [expr {$x-1}]] [yc $row]
4757 } elseif {$xc > $x + 1} {
4758 lappend coords [xc $row [expr {$x+1}]] [yc $row]
4759 }
4760 set x $xc
4761 }
4762 lappend coords [xc $row $x] [yc $row]
4763 } else {
4764 set xn [xc $row $xp]
4765 set yn [yc $row]
Paul Mackerrase341c062007-08-12 12:42:57 +10004766 lappend coords $xn $yn
Paul Mackerras322a8cc2006-10-15 18:03:46 +10004767 }
4768 if {!$joinhigh} {
Paul Mackerras322a8cc2006-10-15 18:03:46 +10004769 assigncolor $id
4770 set t [$canv create line $coords -width [linewidth $id] \
4771 -fill $colormap($id) -tags lines.$id -arrow $arrow]
4772 $canv lower $t
4773 bindline $t $id
4774 set lines [linsert $lines $i [list $row $le $t]]
4775 } else {
4776 $canv coords $ith $coords
4777 if {$arrow ne $ah} {
4778 $canv itemconf $ith -arrow $arrow
4779 }
4780 lset lines $i 0 $row
4781 }
4782 } else {
4783 set xo [lsearch -exact [lindex $rowidlist [expr {$row - 1}]] $id]
4784 set ndir [expr {$xo - $xp}]
4785 set clow [$canv coords $itl]
4786 if {$dir == $ndir} {
4787 set clow [lrange $clow 2 end]
4788 }
4789 set coords [concat $coords $clow]
4790 if {!$joinhigh} {
4791 lset lines [expr {$i-1}] 1 $le
Paul Mackerras322a8cc2006-10-15 18:03:46 +10004792 } else {
4793 # coalesce two pieces
4794 $canv delete $ith
4795 set b [lindex $lines [expr {$i-1}] 0]
4796 set e [lindex $lines $i 1]
4797 set lines [lreplace $lines [expr {$i-1}] $i [list $b $e $itl]]
4798 }
4799 $canv coords $itl $coords
4800 if {$arrow ne $al} {
4801 $canv itemconf $itl -arrow $arrow
4802 }
4803 }
4804
4805 set linesegs($id) $lines
4806 return $le
4807}
4808
4809proc drawparentlinks {id row} {
4810 global rowidlist canv colormap curview parentlist
Paul Mackerras513a54d2007-08-01 22:27:57 +10004811 global idpos linespc
Paul Mackerras322a8cc2006-10-15 18:03:46 +10004812
4813 set rowids [lindex $rowidlist $row]
4814 set col [lsearch -exact $rowids $id]
4815 if {$col < 0} return
4816 set olds [lindex $parentlist $row]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11004817 set row2 [expr {$row + 1}]
4818 set x [xc $row $col]
4819 set y [yc $row]
4820 set y2 [yc $row2]
Paul Mackerrase341c062007-08-12 12:42:57 +10004821 set d [expr {int(0.5 * $linespc)}]
Paul Mackerras513a54d2007-08-01 22:27:57 +10004822 set ymid [expr {$y + $d}]
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11004823 set ids [lindex $rowidlist $row2]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11004824 # rmx = right-most X coord used
4825 set rmx 0
Paul Mackerras9f1afe02006-02-19 22:44:47 +11004826 foreach p $olds {
Paul Mackerrasf3408442006-03-31 09:54:24 +11004827 set i [lsearch -exact $ids $p]
4828 if {$i < 0} {
4829 puts "oops, parent $p of $id not in list"
4830 continue
4831 }
4832 set x2 [xc $row2 $i]
4833 if {$x2 > $rmx} {
4834 set rmx $x2
4835 }
Paul Mackerras513a54d2007-08-01 22:27:57 +10004836 set j [lsearch -exact $rowids $p]
4837 if {$j < 0} {
Paul Mackerraseb447a12006-03-18 23:11:37 +11004838 # drawlineseg will do this one for us
4839 continue
4840 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11004841 assigncolor $p
4842 # should handle duplicated parents here...
4843 set coords [list $x $y]
Paul Mackerras513a54d2007-08-01 22:27:57 +10004844 if {$i != $col} {
4845 # if attaching to a vertical segment, draw a smaller
4846 # slant for visual distinctness
4847 if {$i == $j} {
4848 if {$i < $col} {
4849 lappend coords [expr {$x2 + $d}] $y $x2 $ymid
4850 } else {
4851 lappend coords [expr {$x2 - $d}] $y $x2 $ymid
4852 }
4853 } elseif {$i < $col && $i < $j} {
4854 # segment slants towards us already
4855 lappend coords [xc $row $j] $y
4856 } else {
4857 if {$i < $col - 1} {
4858 lappend coords [expr {$x2 + $linespc}] $y
4859 } elseif {$i > $col + 1} {
4860 lappend coords [expr {$x2 - $linespc}] $y
4861 }
4862 lappend coords $x2 $y2
4863 }
4864 } else {
4865 lappend coords $x2 $y2
Paul Mackerras9f1afe02006-02-19 22:44:47 +11004866 }
Paul Mackerrasc934a8a2006-03-02 23:00:44 +11004867 set t [$canv create line $coords -width [linewidth $p] \
Paul Mackerras9f1afe02006-02-19 22:44:47 +11004868 -fill $colormap($p) -tags lines.$p]
4869 $canv lower $t
4870 bindline $t $p
4871 }
Paul Mackerras322a8cc2006-10-15 18:03:46 +10004872 if {$rmx > [lindex $idpos($id) 1]} {
4873 lset idpos($id) 1 $rmx
4874 redrawtags $id
4875 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11004876}
4877
Paul Mackerrasc934a8a2006-03-02 23:00:44 +11004878proc drawlines {id} {
Paul Mackerras322a8cc2006-10-15 18:03:46 +10004879 global canv
Paul Mackerras9f1afe02006-02-19 22:44:47 +11004880
Paul Mackerras322a8cc2006-10-15 18:03:46 +10004881 $canv itemconf lines.$id -width [linewidth $id]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11004882}
4883
Paul Mackerras322a8cc2006-10-15 18:03:46 +10004884proc drawcmittext {id row col} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004885 global linespc canv canv2 canv3 fgcolor curview
4886 global cmitlisted commitinfo rowidlist parentlist
Paul Mackerras9f1afe02006-02-19 22:44:47 +11004887 global rowtextx idpos idtags idheads idotherrefs
Paul Mackerras03800812007-08-29 21:45:21 +10004888 global linehtag linentag linedtag selectedline
Paul Mackerrasc11ff122008-05-26 10:11:33 +10004889 global canvxmax boldrows boldnamerows fgcolor
4890 global mainheadid nullid nullid2 circleitem circlecolors
Paul Mackerras9f1afe02006-02-19 22:44:47 +11004891
Linus Torvalds1407ade2008-02-09 14:02:07 -08004892 # listed is 0 for boundary, 1 for normal, 2 for negative, 3 for left, 4 for right
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004893 set listed $cmitlisted($curview,$id)
Paul Mackerras219ea3a2006-09-07 10:21:39 +10004894 if {$id eq $nullid} {
4895 set ofill red
Paul Mackerras8f489362007-07-13 19:49:37 +10004896 } elseif {$id eq $nullid2} {
Paul Mackerrasef3192b2007-07-22 22:05:30 +10004897 set ofill green
Paul Mackerrasc11ff122008-05-26 10:11:33 +10004898 } elseif {$id eq $mainheadid} {
4899 set ofill yellow
Paul Mackerras219ea3a2006-09-07 10:21:39 +10004900 } else {
Paul Mackerrasc11ff122008-05-26 10:11:33 +10004901 set ofill [lindex $circlecolors $listed]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10004902 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11004903 set x [xc $row $col]
4904 set y [yc $row]
4905 set orad [expr {$linespc / 3}]
Linus Torvalds1407ade2008-02-09 14:02:07 -08004906 if {$listed <= 2} {
Paul Mackerrasc961b222007-07-09 22:45:47 +10004907 set t [$canv create oval [expr {$x - $orad}] [expr {$y - $orad}] \
4908 [expr {$x + $orad - 1}] [expr {$y + $orad - 1}] \
4909 -fill $ofill -outline $fgcolor -width 1 -tags circle]
Linus Torvalds1407ade2008-02-09 14:02:07 -08004910 } elseif {$listed == 3} {
Paul Mackerrasc961b222007-07-09 22:45:47 +10004911 # triangle pointing left for left-side commits
4912 set t [$canv create polygon \
4913 [expr {$x - $orad}] $y \
4914 [expr {$x + $orad - 1}] [expr {$y - $orad}] \
4915 [expr {$x + $orad - 1}] [expr {$y + $orad - 1}] \
4916 -fill $ofill -outline $fgcolor -width 1 -tags circle]
4917 } else {
4918 # triangle pointing right for right-side commits
4919 set t [$canv create polygon \
4920 [expr {$x + $orad - 1}] $y \
4921 [expr {$x - $orad}] [expr {$y - $orad}] \
4922 [expr {$x - $orad}] [expr {$y + $orad - 1}] \
4923 -fill $ofill -outline $fgcolor -width 1 -tags circle]
4924 }
Paul Mackerrasc11ff122008-05-26 10:11:33 +10004925 set circleitem($row) $t
Paul Mackerras9f1afe02006-02-19 22:44:47 +11004926 $canv raise $t
4927 $canv bind $t <1> {selcanvline {} %x %y}
Paul Mackerras322a8cc2006-10-15 18:03:46 +10004928 set rmx [llength [lindex $rowidlist $row]]
4929 set olds [lindex $parentlist $row]
4930 if {$olds ne {}} {
4931 set nextids [lindex $rowidlist [expr {$row + 1}]]
4932 foreach p $olds {
4933 set i [lsearch -exact $nextids $p]
4934 if {$i > $rmx} {
4935 set rmx $i
4936 }
4937 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11004938 }
Paul Mackerras322a8cc2006-10-15 18:03:46 +10004939 set xt [xc $row $rmx]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11004940 set rowtextx($row) $xt
4941 set idpos($id) [list $x $xt $y]
4942 if {[info exists idtags($id)] || [info exists idheads($id)]
4943 || [info exists idotherrefs($id)]} {
4944 set xt [drawtags $id $x $xt $y]
4945 }
4946 set headline [lindex $commitinfo($id) 0]
4947 set name [lindex $commitinfo($id) 1]
4948 set date [lindex $commitinfo($id) 2]
4949 set date [formatdate $date]
Paul Mackerras9c311b32007-10-04 22:27:13 +10004950 set font mainfont
4951 set nfont mainfont
Paul Mackerras476ca632008-01-07 22:16:31 +11004952 set isbold [ishighlighted $id]
Paul Mackerras908c3582006-05-20 09:38:11 +10004953 if {$isbold > 0} {
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004954 lappend boldrows $row
Paul Mackerras9c311b32007-10-04 22:27:13 +10004955 set font mainfontbold
Paul Mackerras908c3582006-05-20 09:38:11 +10004956 if {$isbold > 1} {
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004957 lappend boldnamerows $row
Paul Mackerras9c311b32007-10-04 22:27:13 +10004958 set nfont mainfontbold
Paul Mackerras908c3582006-05-20 09:38:11 +10004959 }
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004960 }
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10004961 set linehtag($row) [$canv create text $xt $y -anchor w -fill $fgcolor \
4962 -text $headline -font $font -tags text]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11004963 $canv bind $linehtag($row) <Button-3> "rowmenu %X %Y $id"
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10004964 set linentag($row) [$canv2 create text 3 $y -anchor w -fill $fgcolor \
4965 -text $name -font $nfont -tags text]
4966 set linedtag($row) [$canv3 create text 3 $y -anchor w -fill $fgcolor \
Paul Mackerras9c311b32007-10-04 22:27:13 +10004967 -text $date -font mainfont -tags text]
Paul Mackerras94b4a692008-05-20 20:51:06 +10004968 if {$selectedline == $row} {
Paul Mackerras03800812007-08-29 21:45:21 +10004969 make_secsel $row
4970 }
Paul Mackerras9c311b32007-10-04 22:27:13 +10004971 set xr [expr {$xt + [font measure $font $headline]}]
Paul Mackerrasbe0cd092006-03-31 09:55:11 +11004972 if {$xr > $canvxmax} {
4973 set canvxmax $xr
4974 setcanvscroll
4975 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11004976}
4977
4978proc drawcmitrow {row} {
Paul Mackerras03800812007-08-29 21:45:21 +10004979 global displayorder rowidlist nrows_drawn
Paul Mackerras005a2f42007-07-26 22:36:39 +10004980 global iddrawn markingmatches
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004981 global commitinfo numcommits
Paul Mackerras687c8762007-09-22 12:49:33 +10004982 global filehighlight fhighlights findpattern nhighlights
Paul Mackerras908c3582006-05-20 09:38:11 +10004983 global hlview vhighlights
Paul Mackerras164ff272006-05-29 19:50:02 +10004984 global highlight_related rhighlights
Paul Mackerras9f1afe02006-02-19 22:44:47 +11004985
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11004986 if {$row >= $numcommits} return
Paul Mackerras9f1afe02006-02-19 22:44:47 +11004987
4988 set id [lindex $displayorder $row]
Paul Mackerras476ca632008-01-07 22:16:31 +11004989 if {[info exists hlview] && ![info exists vhighlights($id)]} {
Paul Mackerras908c3582006-05-20 09:38:11 +10004990 askvhighlight $row $id
4991 }
Paul Mackerras476ca632008-01-07 22:16:31 +11004992 if {[info exists filehighlight] && ![info exists fhighlights($id)]} {
Paul Mackerras908c3582006-05-20 09:38:11 +10004993 askfilehighlight $row $id
4994 }
Paul Mackerras476ca632008-01-07 22:16:31 +11004995 if {$findpattern ne {} && ![info exists nhighlights($id)]} {
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10004996 askfindhighlight $row $id
Paul Mackerras908c3582006-05-20 09:38:11 +10004997 }
Paul Mackerras476ca632008-01-07 22:16:31 +11004998 if {$highlight_related ne [mc "None"] && ![info exists rhighlights($id)]} {
Paul Mackerras164ff272006-05-29 19:50:02 +10004999 askrelhighlight $row $id
5000 }
Paul Mackerras005a2f42007-07-26 22:36:39 +10005001 if {![info exists iddrawn($id)]} {
5002 set col [lsearch -exact [lindex $rowidlist $row] $id]
5003 if {$col < 0} {
5004 puts "oops, row $row id $id not in list"
5005 return
5006 }
5007 if {![info exists commitinfo($id)]} {
5008 getcommit $id
5009 }
5010 assigncolor $id
5011 drawcmittext $id $row $col
5012 set iddrawn($id) 1
Paul Mackerras03800812007-08-29 21:45:21 +10005013 incr nrows_drawn
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005014 }
Paul Mackerras005a2f42007-07-26 22:36:39 +10005015 if {$markingmatches} {
5016 markrowmatches $row $id
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005017 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005018}
5019
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005020proc drawcommits {row {endrow {}}} {
Paul Mackerras03800812007-08-29 21:45:21 +10005021 global numcommits iddrawn displayorder curview need_redisplay
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10005022 global parentlist rowidlist rowfinal uparrowlen downarrowlen nrows_drawn
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005023
5024 if {$row < 0} {
5025 set row 0
5026 }
5027 if {$endrow eq {}} {
5028 set endrow $row
5029 }
5030 if {$endrow >= $numcommits} {
5031 set endrow [expr {$numcommits - 1}]
5032 }
5033
Paul Mackerras03800812007-08-29 21:45:21 +10005034 set rl1 [expr {$row - $downarrowlen - 3}]
5035 if {$rl1 < 0} {
5036 set rl1 0
5037 }
5038 set ro1 [expr {$row - 3}]
5039 if {$ro1 < 0} {
5040 set ro1 0
5041 }
5042 set r2 [expr {$endrow + $uparrowlen + 3}]
5043 if {$r2 > $numcommits} {
5044 set r2 $numcommits
5045 }
5046 for {set r $rl1} {$r < $r2} {incr r} {
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10005047 if {[lindex $rowidlist $r] ne {} && [lindex $rowfinal $r]} {
Paul Mackerras03800812007-08-29 21:45:21 +10005048 if {$rl1 < $r} {
5049 layoutrows $rl1 $r
5050 }
5051 set rl1 [expr {$r + 1}]
5052 }
5053 }
5054 if {$rl1 < $r} {
5055 layoutrows $rl1 $r
5056 }
5057 optimize_rows $ro1 0 $r2
5058 if {$need_redisplay || $nrows_drawn > 2000} {
5059 clear_display
5060 drawvisible
5061 }
5062
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005063 # make the lines join to already-drawn rows either side
5064 set r [expr {$row - 1}]
5065 if {$r < 0 || ![info exists iddrawn([lindex $displayorder $r])]} {
5066 set r $row
5067 }
5068 set er [expr {$endrow + 1}]
5069 if {$er >= $numcommits ||
5070 ![info exists iddrawn([lindex $displayorder $er])]} {
5071 set er $endrow
5072 }
5073 for {} {$r <= $er} {incr r} {
5074 set id [lindex $displayorder $r]
5075 set wasdrawn [info exists iddrawn($id)]
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10005076 drawcmitrow $r
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005077 if {$r == $er} break
5078 set nextid [lindex $displayorder [expr {$r + 1}]]
Paul Mackerrase5ef6f92007-10-21 12:58:42 +10005079 if {$wasdrawn && [info exists iddrawn($nextid)]} continue
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005080 drawparentlinks $id $r
5081
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005082 set rowids [lindex $rowidlist $r]
5083 foreach lid $rowids {
5084 if {$lid eq {}} continue
Paul Mackerrase5ef6f92007-10-21 12:58:42 +10005085 if {[info exists lineend($lid)] && $lineend($lid) > $r} continue
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005086 if {$lid eq $id} {
5087 # see if this is the first child of any of its parents
5088 foreach p [lindex $parentlist $r] {
5089 if {[lsearch -exact $rowids $p] < 0} {
5090 # make this line extend up to the child
Paul Mackerrase5ef6f92007-10-21 12:58:42 +10005091 set lineend($p) [drawlineseg $p $r $er 0]
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005092 }
5093 }
Paul Mackerrase5ef6f92007-10-21 12:58:42 +10005094 } else {
5095 set lineend($lid) [drawlineseg $lid $r $er 1]
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005096 }
5097 }
5098 }
5099}
5100
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005101proc undolayout {row} {
5102 global uparrowlen mingaplen downarrowlen
5103 global rowidlist rowisopt rowfinal need_redisplay
5104
5105 set r [expr {$row - ($uparrowlen + $mingaplen + $downarrowlen)}]
5106 if {$r < 0} {
5107 set r 0
5108 }
5109 if {[llength $rowidlist] > $r} {
5110 incr r -1
5111 set rowidlist [lrange $rowidlist 0 $r]
5112 set rowfinal [lrange $rowfinal 0 $r]
5113 set rowisopt [lrange $rowisopt 0 $r]
5114 set need_redisplay 1
5115 run drawvisible
5116 }
5117}
5118
Paul Mackerras31c0eaa2007-12-30 22:41:14 +11005119proc drawvisible {} {
5120 global canv linespc curview vrowmod selectedline targetrow targetid
Paul Mackerras42a671f2008-01-02 09:59:39 +11005121 global need_redisplay cscroll numcommits
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005122
Paul Mackerras31c0eaa2007-12-30 22:41:14 +11005123 set fs [$canv yview]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005124 set ymax [lindex [$canv cget -scrollregion] 3]
Paul Mackerras5a7f5772008-01-15 22:45:36 +11005125 if {$ymax eq {} || $ymax == 0 || $numcommits == 0} return
Paul Mackerras31c0eaa2007-12-30 22:41:14 +11005126 set f0 [lindex $fs 0]
5127 set f1 [lindex $fs 1]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005128 set y0 [expr {int($f0 * $ymax)}]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005129 set y1 [expr {int($f1 * $ymax)}]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005130
Paul Mackerras31c0eaa2007-12-30 22:41:14 +11005131 if {[info exists targetid]} {
Paul Mackerras42a671f2008-01-02 09:59:39 +11005132 if {[commitinview $targetid $curview]} {
5133 set r [rowofcommit $targetid]
5134 if {$r != $targetrow} {
5135 # Fix up the scrollregion and change the scrolling position
5136 # now that our target row has moved.
5137 set diff [expr {($r - $targetrow) * $linespc}]
5138 set targetrow $r
5139 setcanvscroll
5140 set ymax [lindex [$canv cget -scrollregion] 3]
5141 incr y0 $diff
5142 incr y1 $diff
5143 set f0 [expr {$y0 / $ymax}]
5144 set f1 [expr {$y1 / $ymax}]
5145 allcanvs yview moveto $f0
5146 $cscroll set $f0 $f1
5147 set need_redisplay 1
5148 }
5149 } else {
5150 unset targetid
Paul Mackerras31c0eaa2007-12-30 22:41:14 +11005151 }
5152 }
5153
5154 set row [expr {int(($y0 - 3) / $linespc) - 1}]
5155 set endrow [expr {int(($y1 - 3) / $linespc) + 1}]
5156 if {$endrow >= $vrowmod($curview)} {
5157 update_arcrows $curview
5158 }
Paul Mackerras94b4a692008-05-20 20:51:06 +10005159 if {$selectedline ne {} &&
Paul Mackerras31c0eaa2007-12-30 22:41:14 +11005160 $row <= $selectedline && $selectedline <= $endrow} {
5161 set targetrow $selectedline
Paul Mackerrasac1276a2008-03-03 10:11:08 +11005162 } elseif {[info exists targetid]} {
Paul Mackerras31c0eaa2007-12-30 22:41:14 +11005163 set targetrow [expr {int(($row + $endrow) / 2)}]
5164 }
Paul Mackerrasac1276a2008-03-03 10:11:08 +11005165 if {[info exists targetrow]} {
5166 if {$targetrow >= $numcommits} {
5167 set targetrow [expr {$numcommits - 1}]
5168 }
5169 set targetid [commitonrow $targetrow]
Paul Mackerras42a671f2008-01-02 09:59:39 +11005170 }
Paul Mackerras31c0eaa2007-12-30 22:41:14 +11005171 drawcommits $row $endrow
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005172}
5173
5174proc clear_display {} {
Paul Mackerras03800812007-08-29 21:45:21 +10005175 global iddrawn linesegs need_redisplay nrows_drawn
Paul Mackerras164ff272006-05-29 19:50:02 +10005176 global vhighlights fhighlights nhighlights rhighlights
Paul Mackerrasa9779532008-05-22 21:12:19 +10005177 global linehtag linentag linedtag boldrows boldnamerows
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005178
5179 allcanvs delete all
5180 catch {unset iddrawn}
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005181 catch {unset linesegs}
Paul Mackerras94503a62008-05-19 09:48:45 +10005182 catch {unset linehtag}
5183 catch {unset linentag}
5184 catch {unset linedtag}
Paul Mackerrasa9779532008-05-22 21:12:19 +10005185 set boldrows {}
5186 set boldnamerows {}
Paul Mackerras908c3582006-05-20 09:38:11 +10005187 catch {unset vhighlights}
5188 catch {unset fhighlights}
5189 catch {unset nhighlights}
Paul Mackerras164ff272006-05-29 19:50:02 +10005190 catch {unset rhighlights}
Paul Mackerras03800812007-08-29 21:45:21 +10005191 set need_redisplay 0
5192 set nrows_drawn 0
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005193}
5194
Paul Mackerras50b44ec2006-04-04 10:16:22 +10005195proc findcrossings {id} {
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005196 global rowidlist parentlist numcommits displayorder
Paul Mackerras50b44ec2006-04-04 10:16:22 +10005197
5198 set cross {}
5199 set ccross {}
5200 foreach {s e} [rowranges $id] {
5201 if {$e >= $numcommits} {
5202 set e [expr {$numcommits - 1}]
Paul Mackerras50b44ec2006-04-04 10:16:22 +10005203 }
Paul Mackerrasd94f8cd2006-04-06 10:18:23 +10005204 if {$e <= $s} continue
Paul Mackerras50b44ec2006-04-04 10:16:22 +10005205 for {set row $e} {[incr row -1] >= $s} {} {
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005206 set x [lsearch -exact [lindex $rowidlist $row] $id]
5207 if {$x < 0} break
Paul Mackerras50b44ec2006-04-04 10:16:22 +10005208 set olds [lindex $parentlist $row]
5209 set kid [lindex $displayorder $row]
5210 set kidx [lsearch -exact [lindex $rowidlist $row] $kid]
5211 if {$kidx < 0} continue
5212 set nextrow [lindex $rowidlist [expr {$row + 1}]]
5213 foreach p $olds {
5214 set px [lsearch -exact $nextrow $p]
5215 if {$px < 0} continue
5216 if {($kidx < $x && $x < $px) || ($px < $x && $x < $kidx)} {
5217 if {[lsearch -exact $ccross $p] >= 0} continue
5218 if {$x == $px + ($kidx < $px? -1: 1)} {
5219 lappend ccross $p
5220 } elseif {[lsearch -exact $cross $p] < 0} {
5221 lappend cross $p
5222 }
5223 }
5224 }
Paul Mackerras50b44ec2006-04-04 10:16:22 +10005225 }
5226 }
5227 return [concat $ccross {{}} $cross]
5228}
5229
Paul Mackerrase5c2d852005-05-11 23:44:54 +00005230proc assigncolor {id} {
Paul Mackerrasaa81d972006-02-28 11:27:12 +11005231 global colormap colors nextcolor
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005232 global parents children children curview
Paul Mackerras6c20ff32005-06-22 19:53:32 +10005233
Paul Mackerras418c4c72006-02-07 09:10:18 +11005234 if {[info exists colormap($id)]} return
Paul Mackerrase5c2d852005-05-11 23:44:54 +00005235 set ncolors [llength $colors]
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10005236 if {[info exists children($curview,$id)]} {
5237 set kids $children($curview,$id)
Paul Mackerras79b2c752006-04-02 20:47:40 +10005238 } else {
5239 set kids {}
5240 }
5241 if {[llength $kids] == 1} {
5242 set child [lindex $kids 0]
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +00005243 if {[info exists colormap($child)]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005244 && [llength $parents($curview,$child)] == 1} {
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +00005245 set colormap($id) $colormap($child)
5246 return
Paul Mackerrase5c2d852005-05-11 23:44:54 +00005247 }
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +00005248 }
5249 set badcolors {}
Paul Mackerras50b44ec2006-04-04 10:16:22 +10005250 set origbad {}
5251 foreach x [findcrossings $id] {
5252 if {$x eq {}} {
5253 # delimiter between corner crossings and other crossings
5254 if {[llength $badcolors] >= $ncolors - 1} break
5255 set origbad $badcolors
Paul Mackerrase5c2d852005-05-11 23:44:54 +00005256 }
Paul Mackerras50b44ec2006-04-04 10:16:22 +10005257 if {[info exists colormap($x)]
5258 && [lsearch -exact $badcolors $colormap($x)] < 0} {
5259 lappend badcolors $colormap($x)
Paul Mackerras6c20ff32005-06-22 19:53:32 +10005260 }
5261 }
Paul Mackerras50b44ec2006-04-04 10:16:22 +10005262 if {[llength $badcolors] >= $ncolors} {
5263 set badcolors $origbad
5264 }
Paul Mackerras6c20ff32005-06-22 19:53:32 +10005265 set origbad $badcolors
5266 if {[llength $badcolors] < $ncolors - 1} {
Paul Mackerras79b2c752006-04-02 20:47:40 +10005267 foreach child $kids {
Paul Mackerras6c20ff32005-06-22 19:53:32 +10005268 if {[info exists colormap($child)]
5269 && [lsearch -exact $badcolors $colormap($child)] < 0} {
5270 lappend badcolors $colormap($child)
5271 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005272 foreach p $parents($curview,$child) {
Paul Mackerras79b2c752006-04-02 20:47:40 +10005273 if {[info exists colormap($p)]
5274 && [lsearch -exact $badcolors $colormap($p)] < 0} {
5275 lappend badcolors $colormap($p)
Paul Mackerrase5c2d852005-05-11 23:44:54 +00005276 }
5277 }
5278 }
Paul Mackerras6c20ff32005-06-22 19:53:32 +10005279 if {[llength $badcolors] >= $ncolors} {
5280 set badcolors $origbad
5281 }
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +00005282 }
5283 for {set i 0} {$i <= $ncolors} {incr i} {
5284 set c [lindex $colors $nextcolor]
5285 if {[incr nextcolor] >= $ncolors} {
5286 set nextcolor 0
Paul Mackerrase5c2d852005-05-11 23:44:54 +00005287 }
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +00005288 if {[lsearch -exact $badcolors $c]} break
5289 }
5290 set colormap($id) $c
5291}
5292
Paul Mackerrasa823a912005-06-21 10:01:38 +10005293proc bindline {t id} {
5294 global canv
5295
Paul Mackerrasa823a912005-06-21 10:01:38 +10005296 $canv bind $t <Enter> "lineenter %x %y $id"
5297 $canv bind $t <Motion> "linemotion %x %y $id"
5298 $canv bind $t <Leave> "lineleave $id"
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10005299 $canv bind $t <Button-1> "lineclick %x %y $id 1"
Paul Mackerrasa823a912005-06-21 10:01:38 +10005300}
5301
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10005302proc drawtags {id x xt y1} {
Paul Mackerras8a485712006-07-06 10:21:23 +10005303 global idtags idheads idotherrefs mainhead
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10005304 global linespc lthickness
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005305 global canv rowtextx curview fgcolor bgcolor
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10005306
5307 set marks {}
5308 set ntags 0
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10005309 set nheads 0
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10005310 if {[info exists idtags($id)]} {
5311 set marks $idtags($id)
5312 set ntags [llength $marks]
5313 }
5314 if {[info exists idheads($id)]} {
5315 set marks [concat $marks $idheads($id)]
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10005316 set nheads [llength $idheads($id)]
5317 }
5318 if {[info exists idotherrefs($id)]} {
5319 set marks [concat $marks $idotherrefs($id)]
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10005320 }
5321 if {$marks eq {}} {
5322 return $xt
5323 }
5324
5325 set delta [expr {int(0.5 * ($linespc - $lthickness))}]
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08005326 set yt [expr {$y1 - 0.5 * $linespc}]
5327 set yb [expr {$yt + $linespc - 1}]
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10005328 set xvals {}
5329 set wvals {}
Paul Mackerras8a485712006-07-06 10:21:23 +10005330 set i -1
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10005331 foreach tag $marks {
Paul Mackerras8a485712006-07-06 10:21:23 +10005332 incr i
5333 if {$i >= $ntags && $i < $ntags + $nheads && $tag eq $mainhead} {
Paul Mackerras9c311b32007-10-04 22:27:13 +10005334 set wid [font measure mainfontbold $tag]
Paul Mackerras8a485712006-07-06 10:21:23 +10005335 } else {
Paul Mackerras9c311b32007-10-04 22:27:13 +10005336 set wid [font measure mainfont $tag]
Paul Mackerras8a485712006-07-06 10:21:23 +10005337 }
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10005338 lappend xvals $xt
5339 lappend wvals $wid
5340 set xt [expr {$xt + $delta + $wid + $lthickness + $linespc}]
5341 }
5342 set t [$canv create line $x $y1 [lindex $xvals end] $y1 \
5343 -width $lthickness -fill black -tags tag.$id]
5344 $canv lower $t
5345 foreach tag $marks x $xvals wid $wvals {
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08005346 set xl [expr {$x + $delta}]
5347 set xr [expr {$x + $delta + $wid + $lthickness}]
Paul Mackerras9c311b32007-10-04 22:27:13 +10005348 set font mainfont
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10005349 if {[incr ntags -1] >= 0} {
5350 # draw a tag
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08005351 set t [$canv create polygon $x [expr {$yt + $delta}] $xl $yt \
5352 $xr $yt $xr $yb $xl $yb $x [expr {$yb - $delta}] \
Paul Mackerras106288c2005-08-19 23:11:39 +10005353 -width 1 -outline black -fill yellow -tags tag.$id]
5354 $canv bind $t <1> [list showtag $tag 1]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005355 set rowtextx([rowofcommit $id]) [expr {$xr + $linespc}]
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10005356 } else {
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10005357 # draw a head or other ref
5358 if {[incr nheads -1] >= 0} {
5359 set col green
Paul Mackerras8a485712006-07-06 10:21:23 +10005360 if {$tag eq $mainhead} {
Paul Mackerras9c311b32007-10-04 22:27:13 +10005361 set font mainfontbold
Paul Mackerras8a485712006-07-06 10:21:23 +10005362 }
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10005363 } else {
5364 set col "#ddddff"
5365 }
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08005366 set xl [expr {$xl - $delta/2}]
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10005367 $canv create polygon $x $yt $xr $yt $xr $yb $x $yb \
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10005368 -width 1 -outline black -fill $col -tags tag.$id
Josef Weidendorfera970fcf2006-04-18 23:53:07 +02005369 if {[regexp {^(remotes/.*/|remotes/)} $tag match remoteprefix]} {
Paul Mackerras9c311b32007-10-04 22:27:13 +10005370 set rwid [font measure mainfont $remoteprefix]
Josef Weidendorfera970fcf2006-04-18 23:53:07 +02005371 set xi [expr {$x + 1}]
5372 set yti [expr {$yt + 1}]
5373 set xri [expr {$x + $rwid}]
5374 $canv create polygon $xi $yti $xri $yti $xri $yb $xi $yb \
5375 -width 0 -fill "#ffddaa" -tags tag.$id
5376 }
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10005377 }
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10005378 set t [$canv create text $xl $y1 -anchor w -text $tag -fill $fgcolor \
Paul Mackerras8a485712006-07-06 10:21:23 +10005379 -font $font -tags [list tag.$id text]]
Paul Mackerras106288c2005-08-19 23:11:39 +10005380 if {$ntags >= 0} {
5381 $canv bind $t <1> [list showtag $tag 1]
Paul Mackerras10299152006-08-02 09:52:01 +10005382 } elseif {$nheads >= 0} {
5383 $canv bind $t <Button-3> [list headmenu %X %Y $id $tag]
Paul Mackerras106288c2005-08-19 23:11:39 +10005384 }
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10005385 }
5386 return $xt
5387}
5388
Paul Mackerras8d858d12005-08-05 09:52:16 +10005389proc xcoord {i level ln} {
5390 global canvx0 xspc1 xspc2
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +00005391
Paul Mackerras8d858d12005-08-05 09:52:16 +10005392 set x [expr {$canvx0 + $i * $xspc1($ln)}]
5393 if {$i > 0 && $i == $level} {
5394 set x [expr {$x + 0.5 * ($xspc2 - $xspc1($ln))}]
5395 } elseif {$i > $level} {
5396 set x [expr {$x + $xspc2 - $xspc1($ln)}]
5397 }
5398 return $x
5399}
5400
Paul Mackerras098dd8a2006-05-03 09:32:53 +10005401proc show_status {msg} {
Paul Mackerras9c311b32007-10-04 22:27:13 +10005402 global canv fgcolor
Paul Mackerras098dd8a2006-05-03 09:32:53 +10005403
5404 clear_display
Paul Mackerras9c311b32007-10-04 22:27:13 +10005405 $canv create text 3 3 -anchor nw -text $msg -font mainfont \
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10005406 -tags text -fill $fgcolor
Paul Mackerras098dd8a2006-05-03 09:32:53 +10005407}
5408
Paul Mackerras94a2eed2005-08-07 15:27:57 +10005409# Don't change the text pane cursor if it is currently the hand cursor,
5410# showing that we are over a sha1 ID link.
5411proc settextcursor {c} {
5412 global ctext curtextcursor
5413
5414 if {[$ctext cget -cursor] == $curtextcursor} {
5415 $ctext config -cursor $c
5416 }
5417 set curtextcursor $c
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +00005418}
5419
Paul Mackerrasa137a902007-10-23 21:12:49 +10005420proc nowbusy {what {name {}}} {
5421 global isbusy busyname statusw
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10005422
5423 if {[array names isbusy] eq {}} {
5424 . config -cursor watch
5425 settextcursor watch
5426 }
5427 set isbusy($what) 1
Paul Mackerrasa137a902007-10-23 21:12:49 +10005428 set busyname($what) $name
5429 if {$name ne {}} {
5430 $statusw conf -text $name
5431 }
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10005432}
5433
5434proc notbusy {what} {
Paul Mackerrasa137a902007-10-23 21:12:49 +10005435 global isbusy maincursor textcursor busyname statusw
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10005436
Paul Mackerrasa137a902007-10-23 21:12:49 +10005437 catch {
5438 unset isbusy($what)
5439 if {$busyname($what) ne {} &&
5440 [$statusw cget -text] eq $busyname($what)} {
5441 $statusw conf -text {}
5442 }
5443 }
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10005444 if {[array names isbusy] eq {}} {
5445 . config -cursor $maincursor
5446 settextcursor $textcursor
5447 }
5448}
5449
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00005450proc findmatches {f} {
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10005451 global findtype findstring
Christian Stimmingb007ee22007-11-07 18:44:35 +01005452 if {$findtype == [mc "Regexp"]} {
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10005453 set matches [regexp -indices -all -inline $findstring $f]
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00005454 } else {
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10005455 set fs $findstring
Christian Stimmingb007ee22007-11-07 18:44:35 +01005456 if {$findtype == [mc "IgnCase"]} {
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10005457 set f [string tolower $f]
5458 set fs [string tolower $fs]
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00005459 }
5460 set matches {}
5461 set i 0
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10005462 set l [string length $fs]
5463 while {[set j [string first $fs $f $i]] >= 0} {
5464 lappend matches [list $j [expr {$j+$l-1}]]
5465 set i [expr {$j + $l}]
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00005466 }
5467 }
5468 return $matches
5469}
5470
Paul Mackerrascca5d942007-10-27 21:16:56 +10005471proc dofind {{dirn 1} {wrap 1}} {
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10005472 global findstring findstartline findcurline selectedline numcommits
Paul Mackerrascca5d942007-10-27 21:16:56 +10005473 global gdttype filehighlight fh_serial find_dirn findallowwrap
Paul Mackerrasb74fd572005-07-16 07:46:13 -04005474
Paul Mackerrascca5d942007-10-27 21:16:56 +10005475 if {[info exists find_dirn]} {
5476 if {$find_dirn == $dirn} return
5477 stopfinding
5478 }
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00005479 focus .
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10005480 if {$findstring eq {} || $numcommits == 0} return
Paul Mackerras94b4a692008-05-20 20:51:06 +10005481 if {$selectedline eq {}} {
Paul Mackerrascca5d942007-10-27 21:16:56 +10005482 set findstartline [lindex [visiblerows] [expr {$dirn < 0}]]
Paul Mackerras98f350e2005-05-15 05:56:51 +00005483 } else {
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10005484 set findstartline $selectedline
Paul Mackerras98f350e2005-05-15 05:56:51 +00005485 }
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10005486 set findcurline $findstartline
Christian Stimmingb007ee22007-11-07 18:44:35 +01005487 nowbusy finding [mc "Searching"]
5488 if {$gdttype ne [mc "containing:"] && ![info exists filehighlight]} {
Paul Mackerras687c8762007-09-22 12:49:33 +10005489 after cancel do_file_hl $fh_serial
5490 do_file_hl $fh_serial
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10005491 }
Paul Mackerrascca5d942007-10-27 21:16:56 +10005492 set find_dirn $dirn
5493 set findallowwrap $wrap
5494 run findmore
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10005495}
5496
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10005497proc stopfinding {} {
5498 global find_dirn findcurline fprogcoord
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10005499
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10005500 if {[info exists find_dirn]} {
5501 unset find_dirn
5502 unset findcurline
5503 notbusy finding
5504 set fprogcoord 0
5505 adjustprogress
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10005506 }
5507}
5508
5509proc findmore {} {
Paul Mackerras687c8762007-09-22 12:49:33 +10005510 global commitdata commitinfo numcommits findpattern findloc
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005511 global findstartline findcurline findallowwrap
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10005512 global find_dirn gdttype fhighlights fprogcoord
Paul Mackerrascd2bcae2008-01-02 21:44:06 +11005513 global curview varcorder vrownum varccommits vrowmod
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10005514
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10005515 if {![info exists find_dirn]} {
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10005516 return 0
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00005517 }
Christian Stimmingb007ee22007-11-07 18:44:35 +01005518 set fldtypes [list [mc "Headline"] [mc "Author"] [mc "Date"] [mc "Committer"] [mc "CDate"] [mc "Comments"]]
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10005519 set l $findcurline
Paul Mackerrascca5d942007-10-27 21:16:56 +10005520 set moretodo 0
5521 if {$find_dirn > 0} {
5522 incr l
5523 if {$l >= $numcommits} {
5524 set l 0
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10005525 }
Paul Mackerrascca5d942007-10-27 21:16:56 +10005526 if {$l <= $findstartline} {
5527 set lim [expr {$findstartline + 1}]
5528 } else {
5529 set lim $numcommits
5530 set moretodo $findallowwrap
5531 }
Paul Mackerras98f350e2005-05-15 05:56:51 +00005532 } else {
Paul Mackerrascca5d942007-10-27 21:16:56 +10005533 if {$l == 0} {
5534 set l $numcommits
5535 }
5536 incr l -1
5537 if {$l >= $findstartline} {
5538 set lim [expr {$findstartline - 1}]
5539 } else {
5540 set lim -1
5541 set moretodo $findallowwrap
5542 }
Paul Mackerras98f350e2005-05-15 05:56:51 +00005543 }
Paul Mackerrascca5d942007-10-27 21:16:56 +10005544 set n [expr {($lim - $l) * $find_dirn}]
5545 if {$n > 500} {
5546 set n 500
5547 set moretodo 1
Paul Mackerras98f350e2005-05-15 05:56:51 +00005548 }
Paul Mackerrascd2bcae2008-01-02 21:44:06 +11005549 if {$l + ($find_dirn > 0? $n: 1) > $vrowmod($curview)} {
5550 update_arcrows $curview
5551 }
Paul Mackerras687c8762007-09-22 12:49:33 +10005552 set found 0
5553 set domore 1
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005554 set ai [bsearch $vrownum($curview) $l]
5555 set a [lindex $varcorder($curview) $ai]
5556 set arow [lindex $vrownum($curview) $ai]
5557 set ids [lindex $varccommits($curview,$a)]
5558 set arowend [expr {$arow + [llength $ids]}]
Christian Stimmingb007ee22007-11-07 18:44:35 +01005559 if {$gdttype eq [mc "containing:"]} {
Paul Mackerrascca5d942007-10-27 21:16:56 +10005560 for {} {$n > 0} {incr n -1; incr l $find_dirn} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005561 if {$l < $arow || $l >= $arowend} {
5562 incr ai $find_dirn
5563 set a [lindex $varcorder($curview) $ai]
5564 set arow [lindex $vrownum($curview) $ai]
5565 set ids [lindex $varccommits($curview,$a)]
5566 set arowend [expr {$arow + [llength $ids]}]
5567 }
5568 set id [lindex $ids [expr {$l - $arow}]]
Paul Mackerras687c8762007-09-22 12:49:33 +10005569 # shouldn't happen unless git log doesn't give all the commits...
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005570 if {![info exists commitdata($id)] ||
5571 ![doesmatch $commitdata($id)]} {
5572 continue
5573 }
Paul Mackerras687c8762007-09-22 12:49:33 +10005574 if {![info exists commitinfo($id)]} {
5575 getcommit $id
5576 }
5577 set info $commitinfo($id)
5578 foreach f $info ty $fldtypes {
Christian Stimmingb007ee22007-11-07 18:44:35 +01005579 if {($findloc eq [mc "All fields"] || $findloc eq $ty) &&
Paul Mackerras687c8762007-09-22 12:49:33 +10005580 [doesmatch $f]} {
5581 set found 1
5582 break
5583 }
5584 }
5585 if {$found} break
Paul Mackerras98f350e2005-05-15 05:56:51 +00005586 }
Paul Mackerras687c8762007-09-22 12:49:33 +10005587 } else {
Paul Mackerrascca5d942007-10-27 21:16:56 +10005588 for {} {$n > 0} {incr n -1; incr l $find_dirn} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005589 if {$l < $arow || $l >= $arowend} {
5590 incr ai $find_dirn
5591 set a [lindex $varcorder($curview) $ai]
5592 set arow [lindex $vrownum($curview) $ai]
5593 set ids [lindex $varccommits($curview,$a)]
5594 set arowend [expr {$arow + [llength $ids]}]
5595 }
5596 set id [lindex $ids [expr {$l - $arow}]]
Paul Mackerras476ca632008-01-07 22:16:31 +11005597 if {![info exists fhighlights($id)]} {
5598 # this sets fhighlights($id) to -1
Paul Mackerras687c8762007-09-22 12:49:33 +10005599 askfilehighlight $l $id
Paul Mackerrascd2bcae2008-01-02 21:44:06 +11005600 }
Paul Mackerras476ca632008-01-07 22:16:31 +11005601 if {$fhighlights($id) > 0} {
Paul Mackerrascd2bcae2008-01-02 21:44:06 +11005602 set found $domore
5603 break
5604 }
Paul Mackerras476ca632008-01-07 22:16:31 +11005605 if {$fhighlights($id) < 0} {
Paul Mackerras687c8762007-09-22 12:49:33 +10005606 if {$domore} {
5607 set domore 0
Paul Mackerrascca5d942007-10-27 21:16:56 +10005608 set findcurline [expr {$l - $find_dirn}]
Paul Mackerras687c8762007-09-22 12:49:33 +10005609 }
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10005610 }
5611 }
5612 }
Paul Mackerrascca5d942007-10-27 21:16:56 +10005613 if {$found || ($domore && !$moretodo)} {
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10005614 unset findcurline
Paul Mackerras687c8762007-09-22 12:49:33 +10005615 unset find_dirn
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10005616 notbusy finding
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10005617 set fprogcoord 0
5618 adjustprogress
5619 if {$found} {
5620 findselectline $l
5621 } else {
5622 bell
5623 }
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10005624 return 0
5625 }
Paul Mackerras687c8762007-09-22 12:49:33 +10005626 if {!$domore} {
5627 flushhighlights
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10005628 } else {
Paul Mackerrascca5d942007-10-27 21:16:56 +10005629 set findcurline [expr {$l - $find_dirn}]
Paul Mackerras687c8762007-09-22 12:49:33 +10005630 }
Paul Mackerrascca5d942007-10-27 21:16:56 +10005631 set n [expr {($findcurline - $findstartline) * $find_dirn - 1}]
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10005632 if {$n < 0} {
5633 incr n $numcommits
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10005634 }
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10005635 set fprogcoord [expr {$n * 1.0 / $numcommits}]
5636 adjustprogress
5637 return $domore
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00005638}
5639
5640proc findselectline {l} {
Paul Mackerras687c8762007-09-22 12:49:33 +10005641 global findloc commentend ctext findcurline markingmatches gdttype
Paul Mackerras005a2f42007-07-26 22:36:39 +10005642
5643 set markingmatches 1
5644 set findcurline $l
Paul Mackerrasd6982062005-08-06 22:06:06 +10005645 selectline $l 1
Christian Stimmingb007ee22007-11-07 18:44:35 +01005646 if {$findloc == [mc "All fields"] || $findloc == [mc "Comments"]} {
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00005647 # highlight the matches in the comments
5648 set f [$ctext get 1.0 $commentend]
5649 set matches [findmatches $f]
5650 foreach match $matches {
5651 set start [lindex $match 0]
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08005652 set end [expr {[lindex $match 1] + 1}]
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00005653 $ctext tag add found "1.0 + $start c" "1.0 + $end c"
5654 }
Paul Mackerras98f350e2005-05-15 05:56:51 +00005655 }
Paul Mackerras005a2f42007-07-26 22:36:39 +10005656 drawvisible
Paul Mackerras98f350e2005-05-15 05:56:51 +00005657}
5658
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10005659# mark the bits of a headline or author that match a find string
Paul Mackerras005a2f42007-07-26 22:36:39 +10005660proc markmatches {canv l str tag matches font row} {
5661 global selectedline
5662
Paul Mackerras98f350e2005-05-15 05:56:51 +00005663 set bbox [$canv bbox $tag]
5664 set x0 [lindex $bbox 0]
5665 set y0 [lindex $bbox 1]
5666 set y1 [lindex $bbox 3]
5667 foreach match $matches {
5668 set start [lindex $match 0]
5669 set end [lindex $match 1]
5670 if {$start > $end} continue
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08005671 set xoff [font measure $font [string range $str 0 [expr {$start-1}]]]
5672 set xlen [font measure $font [string range $str 0 [expr {$end}]]]
5673 set t [$canv create rect [expr {$x0+$xoff}] $y0 \
5674 [expr {$x0+$xlen+2}] $y1 \
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10005675 -outline {} -tags [list match$l matches] -fill yellow]
Paul Mackerras98f350e2005-05-15 05:56:51 +00005676 $canv lower $t
Paul Mackerras94b4a692008-05-20 20:51:06 +10005677 if {$row == $selectedline} {
Paul Mackerras005a2f42007-07-26 22:36:39 +10005678 $canv raise $t secsel
5679 }
Paul Mackerras98f350e2005-05-15 05:56:51 +00005680 }
5681}
5682
5683proc unmarkmatches {} {
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10005684 global markingmatches
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10005685
Paul Mackerras98f350e2005-05-15 05:56:51 +00005686 allcanvs delete matches
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10005687 set markingmatches 0
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10005688 stopfinding
Paul Mackerras98f350e2005-05-15 05:56:51 +00005689}
5690
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10005691proc selcanvline {w x y} {
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10005692 global canv canvy0 ctext linespc
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005693 global rowtextx
Paul Mackerras1db95b02005-05-09 04:08:39 +00005694 set ymax [lindex [$canv cget -scrollregion] 3]
Paul Mackerrascfb45632005-05-31 12:14:42 +00005695 if {$ymax == {}} return
Paul Mackerras1db95b02005-05-09 04:08:39 +00005696 set yfrac [lindex [$canv yview] 0]
5697 set y [expr {$y + $yfrac * $ymax}]
5698 set l [expr {int(($y - $canvy0) / $linespc + 0.5)}]
5699 if {$l < 0} {
5700 set l 0
5701 }
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10005702 if {$w eq $canv} {
Paul Mackerrasfc2a2562007-12-26 23:03:43 +11005703 set xmax [lindex [$canv cget -scrollregion] 2]
5704 set xleft [expr {[lindex [$canv xview] 0] * $xmax}]
5705 if {![info exists rowtextx($l)] || $xleft + $x < $rowtextx($l)} return
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10005706 }
Paul Mackerras98f350e2005-05-15 05:56:51 +00005707 unmarkmatches
Paul Mackerrasd6982062005-08-06 22:06:06 +10005708 selectline $l 1
Paul Mackerras5ad588d2005-05-10 01:02:55 +00005709}
5710
Linus Torvaldsb1ba39e2005-08-08 20:04:20 -07005711proc commit_descriptor {p} {
5712 global commitinfo
Paul Mackerrasb0934482006-05-15 09:56:08 +10005713 if {![info exists commitinfo($p)]} {
5714 getcommit $p
5715 }
Linus Torvaldsb1ba39e2005-08-08 20:04:20 -07005716 set l "..."
Paul Mackerrasb0934482006-05-15 09:56:08 +10005717 if {[llength $commitinfo($p)] > 1} {
Linus Torvaldsb1ba39e2005-08-08 20:04:20 -07005718 set l [lindex $commitinfo($p) 0]
5719 }
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10005720 return "$p ($l)\n"
Linus Torvaldsb1ba39e2005-08-08 20:04:20 -07005721}
5722
Paul Mackerras106288c2005-08-19 23:11:39 +10005723# append some text to the ctext widget, and make any SHA1 ID
5724# that we know about be a clickable link.
Sergey Vlasovf1b86292006-05-15 19:13:14 +04005725proc appendwithlinks {text tags} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005726 global ctext linknum curview pendinglinks
Paul Mackerras106288c2005-08-19 23:11:39 +10005727
5728 set start [$ctext index "end - 1c"]
Sergey Vlasovf1b86292006-05-15 19:13:14 +04005729 $ctext insert end $text $tags
Paul Mackerras106288c2005-08-19 23:11:39 +10005730 set links [regexp -indices -all -inline {[0-9a-f]{40}} $text]
5731 foreach l $links {
5732 set s [lindex $l 0]
5733 set e [lindex $l 1]
5734 set linkid [string range $text $s $e]
Paul Mackerras106288c2005-08-19 23:11:39 +10005735 incr e
Paul Mackerrasc73adce2007-09-27 10:35:05 +10005736 $ctext tag delete link$linknum
Paul Mackerras106288c2005-08-19 23:11:39 +10005737 $ctext tag add link$linknum "$start + $s c" "$start + $e c"
Paul Mackerras97645682007-08-23 22:24:38 +10005738 setlink $linkid link$linknum
Paul Mackerras106288c2005-08-19 23:11:39 +10005739 incr linknum
5740 }
Paul Mackerras97645682007-08-23 22:24:38 +10005741}
5742
5743proc setlink {id lk} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005744 global curview ctext pendinglinks commitinterest
Paul Mackerras97645682007-08-23 22:24:38 +10005745
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005746 if {[commitinview $id $curview]} {
Paul Mackerras97645682007-08-23 22:24:38 +10005747 $ctext tag conf $lk -foreground blue -underline 1
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005748 $ctext tag bind $lk <1> [list selectline [rowofcommit $id] 1]
Paul Mackerras97645682007-08-23 22:24:38 +10005749 $ctext tag bind $lk <Enter> {linkcursor %W 1}
5750 $ctext tag bind $lk <Leave> {linkcursor %W -1}
5751 } else {
5752 lappend pendinglinks($id) $lk
5753 lappend commitinterest($id) {makelink %I}
5754 }
5755}
5756
5757proc makelink {id} {
5758 global pendinglinks
5759
5760 if {![info exists pendinglinks($id)]} return
5761 foreach lk $pendinglinks($id) {
5762 setlink $id $lk
5763 }
5764 unset pendinglinks($id)
5765}
5766
5767proc linkcursor {w inc} {
5768 global linkentercount curtextcursor
5769
5770 if {[incr linkentercount $inc] > 0} {
5771 $w configure -cursor hand2
5772 } else {
5773 $w configure -cursor $curtextcursor
5774 if {$linkentercount < 0} {
5775 set linkentercount 0
5776 }
5777 }
Paul Mackerras106288c2005-08-19 23:11:39 +10005778}
5779
Rutger Nijlunsing6e5f7202006-04-05 10:24:03 +10005780proc viewnextline {dir} {
5781 global canv linespc
5782
5783 $canv delete hover
5784 set ymax [lindex [$canv cget -scrollregion] 3]
5785 set wnow [$canv yview]
5786 set wtop [expr {[lindex $wnow 0] * $ymax}]
5787 set newtop [expr {$wtop + $dir * $linespc}]
5788 if {$newtop < 0} {
5789 set newtop 0
5790 } elseif {$newtop > $ymax} {
5791 set newtop $ymax
5792 }
5793 allcanvs yview moveto [expr {$newtop * 1.0 / $ymax}]
5794}
5795
Paul Mackerrasef030b82006-06-04 11:50:38 +10005796# add a list of tag or branch names at position pos
5797# returns the number of names inserted
Paul Mackerrase11f1232007-06-16 20:29:25 +10005798proc appendrefs {pos ids var} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005799 global ctext linknum curview $var maxrefs
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10005800
Paul Mackerrasef030b82006-06-04 11:50:38 +10005801 if {[catch {$ctext index $pos}]} {
5802 return 0
5803 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10005804 $ctext conf -state normal
5805 $ctext delete $pos "$pos lineend"
5806 set tags {}
5807 foreach id $ids {
5808 foreach tag [set $var\($id\)] {
5809 lappend tags [list $tag $id]
5810 }
5811 }
Paul Mackerras0a4dd8b2007-06-16 21:21:57 +10005812 if {[llength $tags] > $maxrefs} {
5813 $ctext insert $pos "many ([llength $tags])"
5814 } else {
5815 set tags [lsort -index 0 -decreasing $tags]
5816 set sep {}
5817 foreach ti $tags {
5818 set id [lindex $ti 1]
5819 set lk link$linknum
5820 incr linknum
5821 $ctext tag delete $lk
5822 $ctext insert $pos $sep
5823 $ctext insert $pos [lindex $ti 0] $lk
Paul Mackerras97645682007-08-23 22:24:38 +10005824 setlink $id $lk
Paul Mackerras0a4dd8b2007-06-16 21:21:57 +10005825 set sep ", "
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10005826 }
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10005827 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10005828 $ctext conf -state disabled
Paul Mackerrasef030b82006-06-04 11:50:38 +10005829 return [llength $tags]
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10005830}
5831
5832# called when we have finished computing the nearby tags
Paul Mackerrase11f1232007-06-16 20:29:25 +10005833proc dispneartags {delay} {
5834 global selectedline currentid showneartags tagphase
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10005835
Paul Mackerras94b4a692008-05-20 20:51:06 +10005836 if {$selectedline eq {} || !$showneartags} return
Paul Mackerrase11f1232007-06-16 20:29:25 +10005837 after cancel dispnexttag
5838 if {$delay} {
5839 after 200 dispnexttag
5840 set tagphase -1
5841 } else {
5842 after idle dispnexttag
5843 set tagphase 0
5844 }
5845}
5846
5847proc dispnexttag {} {
5848 global selectedline currentid showneartags tagphase ctext
5849
Paul Mackerras94b4a692008-05-20 20:51:06 +10005850 if {$selectedline eq {} || !$showneartags} return
Paul Mackerrase11f1232007-06-16 20:29:25 +10005851 switch -- $tagphase {
5852 0 {
5853 set dtags [desctags $currentid]
5854 if {$dtags ne {}} {
5855 appendrefs precedes $dtags idtags
5856 }
5857 }
5858 1 {
5859 set atags [anctags $currentid]
5860 if {$atags ne {}} {
5861 appendrefs follows $atags idtags
5862 }
5863 }
5864 2 {
5865 set dheads [descheads $currentid]
5866 if {$dheads ne {}} {
5867 if {[appendrefs branch $dheads idheads] > 1
5868 && [$ctext get "branch -3c"] eq "h"} {
5869 # turn "Branch" into "Branches"
5870 $ctext conf -state normal
5871 $ctext insert "branch -2c" "es"
5872 $ctext conf -state disabled
5873 }
5874 }
Paul Mackerrasef030b82006-06-04 11:50:38 +10005875 }
5876 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10005877 if {[incr tagphase] <= 2} {
5878 after idle dispnexttag
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10005879 }
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10005880}
5881
Paul Mackerras03800812007-08-29 21:45:21 +10005882proc make_secsel {l} {
5883 global linehtag linentag linedtag canv canv2 canv3
5884
5885 if {![info exists linehtag($l)]} return
5886 $canv delete secsel
5887 set t [eval $canv create rect [$canv bbox $linehtag($l)] -outline {{}} \
5888 -tags secsel -fill [$canv cget -selectbackground]]
5889 $canv lower $t
5890 $canv2 delete secsel
5891 set t [eval $canv2 create rect [$canv2 bbox $linentag($l)] -outline {{}} \
5892 -tags secsel -fill [$canv2 cget -selectbackground]]
5893 $canv2 lower $t
5894 $canv3 delete secsel
5895 set t [eval $canv3 create rect [$canv3 bbox $linedtag($l)] -outline {{}} \
5896 -tags secsel -fill [$canv3 cget -selectbackground]]
5897 $canv3 lower $t
5898}
5899
Paul Mackerrasd6982062005-08-06 22:06:06 +10005900proc selectline {l isnew} {
Paul Mackerras03800812007-08-29 21:45:21 +10005901 global canv ctext commitinfo selectedline
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005902 global canvy0 linespc parents children curview
Paul Mackerras7fcceed2006-04-27 19:21:49 +10005903 global currentid sha1entry
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005904 global commentend idtags linknum
Paul Mackerrasd94f8cd2006-04-06 10:18:23 +10005905 global mergemax numcommits pending_select
Paul Mackerrase11f1232007-06-16 20:29:25 +10005906 global cmitmode showneartags allcommits
Paul Mackerrasc30acc72008-03-07 22:51:55 +11005907 global targetrow targetid lastscrollrows
Jeff King95293b52008-03-06 06:49:25 -05005908 global autoselect
Paul Mackerrasd6982062005-08-06 22:06:06 +10005909
Paul Mackerrasd94f8cd2006-04-06 10:18:23 +10005910 catch {unset pending_select}
Paul Mackerras84ba7342005-06-17 00:12:26 +00005911 $canv delete hover
Paul Mackerras9843c302005-08-30 10:57:11 +10005912 normalline
Paul Mackerras887c9962007-08-20 19:36:20 +10005913 unsel_reflist
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10005914 stopfinding
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11005915 if {$l < 0 || $l >= $numcommits} return
Paul Mackerrasac1276a2008-03-03 10:11:08 +11005916 set id [commitonrow $l]
5917 set targetid $id
5918 set targetrow $l
Paul Mackerrasc30acc72008-03-07 22:51:55 +11005919 set selectedline $l
5920 set currentid $id
5921 if {$lastscrollrows < $numcommits} {
5922 setcanvscroll
5923 }
Paul Mackerrasac1276a2008-03-03 10:11:08 +11005924
Paul Mackerras5ad588d2005-05-10 01:02:55 +00005925 set y [expr {$canvy0 + $l * $linespc}]
Paul Mackerras17386062005-05-18 22:51:00 +00005926 set ymax [lindex [$canv cget -scrollregion] 3]
Paul Mackerras58422152005-05-19 10:56:42 +00005927 set ytop [expr {$y - $linespc - 1}]
5928 set ybot [expr {$y + $linespc + 1}]
Paul Mackerras5ad588d2005-05-10 01:02:55 +00005929 set wnow [$canv yview]
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08005930 set wtop [expr {[lindex $wnow 0] * $ymax}]
5931 set wbot [expr {[lindex $wnow 1] * $ymax}]
Paul Mackerras58422152005-05-19 10:56:42 +00005932 set wh [expr {$wbot - $wtop}]
5933 set newtop $wtop
Paul Mackerras17386062005-05-18 22:51:00 +00005934 if {$ytop < $wtop} {
Paul Mackerras58422152005-05-19 10:56:42 +00005935 if {$ybot < $wtop} {
5936 set newtop [expr {$y - $wh / 2.0}]
5937 } else {
5938 set newtop $ytop
5939 if {$newtop > $wtop - $linespc} {
5940 set newtop [expr {$wtop - $linespc}]
5941 }
Paul Mackerras17386062005-05-18 22:51:00 +00005942 }
Paul Mackerras58422152005-05-19 10:56:42 +00005943 } elseif {$ybot > $wbot} {
5944 if {$ytop > $wbot} {
5945 set newtop [expr {$y - $wh / 2.0}]
5946 } else {
5947 set newtop [expr {$ybot - $wh}]
5948 if {$newtop < $wtop + $linespc} {
5949 set newtop [expr {$wtop + $linespc}]
5950 }
Paul Mackerras17386062005-05-18 22:51:00 +00005951 }
Paul Mackerras58422152005-05-19 10:56:42 +00005952 }
5953 if {$newtop != $wtop} {
5954 if {$newtop < 0} {
5955 set newtop 0
5956 }
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08005957 allcanvs yview moveto [expr {$newtop * 1.0 / $ymax}]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005958 drawvisible
Paul Mackerras5ad588d2005-05-10 01:02:55 +00005959 }
Paul Mackerrasd6982062005-08-06 22:06:06 +10005960
Paul Mackerras03800812007-08-29 21:45:21 +10005961 make_secsel $l
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005962
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10005963 if {$isnew} {
Paul Mackerrasfc2a2562007-12-26 23:03:43 +11005964 addtohistory [list selbyid $id]
Paul Mackerrasd6982062005-08-06 22:06:06 +10005965 }
5966
Paul Mackerras98f350e2005-05-15 05:56:51 +00005967 $sha1entry delete 0 end
5968 $sha1entry insert 0 $id
Jeff King95293b52008-03-06 06:49:25 -05005969 if {$autoselect} {
5970 $sha1entry selection from 0
5971 $sha1entry selection to end
5972 }
Paul Mackerras164ff272006-05-29 19:50:02 +10005973 rhighlight_sel $id
Paul Mackerras98f350e2005-05-15 05:56:51 +00005974
Paul Mackerras5ad588d2005-05-10 01:02:55 +00005975 $ctext conf -state normal
Paul Mackerras3ea06f92006-05-24 10:16:03 +10005976 clear_ctext
Paul Mackerras106288c2005-08-19 23:11:39 +10005977 set linknum 0
Paul Mackerrasd76afb12008-03-07 21:19:18 +11005978 if {![info exists commitinfo($id)]} {
5979 getcommit $id
5980 }
Paul Mackerras1db95b02005-05-09 04:08:39 +00005981 set info $commitinfo($id)
Paul Mackerras232475d2005-11-15 10:34:03 +11005982 set date [formatdate [lindex $info 2]]
Christian Stimmingd990ced2007-11-07 18:42:55 +01005983 $ctext insert end "[mc "Author"]: [lindex $info 1] $date\n"
Paul Mackerras232475d2005-11-15 10:34:03 +11005984 set date [formatdate [lindex $info 4]]
Christian Stimmingd990ced2007-11-07 18:42:55 +01005985 $ctext insert end "[mc "Committer"]: [lindex $info 3] $date\n"
Paul Mackerras887fe3c2005-05-21 07:35:37 +00005986 if {[info exists idtags($id)]} {
Christian Stimmingd990ced2007-11-07 18:42:55 +01005987 $ctext insert end [mc "Tags:"]
Paul Mackerras887fe3c2005-05-21 07:35:37 +00005988 foreach tag $idtags($id) {
5989 $ctext insert end " $tag"
5990 }
5991 $ctext insert end "\n"
5992 }
Mark Levedahl40b87ff2007-02-01 08:44:46 -05005993
Sergey Vlasovf1b86292006-05-15 19:13:14 +04005994 set headers {}
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005995 set olds $parents($curview,$id)
Paul Mackerras79b2c752006-04-02 20:47:40 +10005996 if {[llength $olds] > 1} {
Paul Mackerrasb77b0272006-02-07 09:13:52 +11005997 set np 0
Paul Mackerras79b2c752006-04-02 20:47:40 +10005998 foreach p $olds {
Paul Mackerrasb77b0272006-02-07 09:13:52 +11005999 if {$np >= $mergemax} {
6000 set tag mmax
6001 } else {
6002 set tag m$np
6003 }
Christian Stimmingd990ced2007-11-07 18:42:55 +01006004 $ctext insert end "[mc "Parent"]: " $tag
Sergey Vlasovf1b86292006-05-15 19:13:14 +04006005 appendwithlinks [commit_descriptor $p] {}
Paul Mackerrasb77b0272006-02-07 09:13:52 +11006006 incr np
6007 }
6008 } else {
Paul Mackerras79b2c752006-04-02 20:47:40 +10006009 foreach p $olds {
Christian Stimmingd990ced2007-11-07 18:42:55 +01006010 append headers "[mc "Parent"]: [commit_descriptor $p]"
Linus Torvalds8b192802005-08-07 13:58:56 -07006011 }
Linus Torvaldsb1ba39e2005-08-08 20:04:20 -07006012 }
Paul Mackerrasb77b0272006-02-07 09:13:52 +11006013
Paul Mackerras6a90bff2007-06-18 09:48:23 +10006014 foreach c $children($curview,$id) {
Christian Stimmingd990ced2007-11-07 18:42:55 +01006015 append headers "[mc "Child"]: [commit_descriptor $c]"
Linus Torvalds8b192802005-08-07 13:58:56 -07006016 }
Paul Mackerrasd6982062005-08-06 22:06:06 +10006017
6018 # make anything that looks like a SHA1 ID be a clickable link
Sergey Vlasovf1b86292006-05-15 19:13:14 +04006019 appendwithlinks $headers {}
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10006020 if {$showneartags} {
6021 if {![info exists allcommits]} {
6022 getallcommits
6023 }
Christian Stimmingd990ced2007-11-07 18:42:55 +01006024 $ctext insert end "[mc "Branch"]: "
Paul Mackerrasef030b82006-06-04 11:50:38 +10006025 $ctext mark set branch "end -1c"
6026 $ctext mark gravity branch left
Christian Stimmingd990ced2007-11-07 18:42:55 +01006027 $ctext insert end "\n[mc "Follows"]: "
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10006028 $ctext mark set follows "end -1c"
6029 $ctext mark gravity follows left
Christian Stimmingd990ced2007-11-07 18:42:55 +01006030 $ctext insert end "\n[mc "Precedes"]: "
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10006031 $ctext mark set precedes "end -1c"
6032 $ctext mark gravity precedes left
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10006033 $ctext insert end "\n"
Paul Mackerrase11f1232007-06-16 20:29:25 +10006034 dispneartags 1
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10006035 }
6036 $ctext insert end "\n"
Paul Mackerras43c25072006-09-27 10:56:02 +10006037 set comment [lindex $info 5]
6038 if {[string first "\r" $comment] >= 0} {
6039 set comment [string map {"\r" "\n "} $comment]
6040 }
6041 appendwithlinks $comment {comment}
Paul Mackerrasd6982062005-08-06 22:06:06 +10006042
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00006043 $ctext tag remove found 1.0 end
Paul Mackerras5ad588d2005-05-10 01:02:55 +00006044 $ctext conf -state disabled
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00006045 set commentend [$ctext index "end - 1c"]
Paul Mackerras5ad588d2005-05-10 01:02:55 +00006046
Christian Stimmingb007ee22007-11-07 18:44:35 +01006047 init_flist [mc "Comments"]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10006048 if {$cmitmode eq "tree"} {
6049 gettree $id
6050 } elseif {[llength $olds] <= 1} {
Paul Mackerrasd3272442005-11-28 20:41:56 +11006051 startdiff $id
Paul Mackerras7b5ff7e2006-03-30 20:50:40 +11006052 } else {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11006053 mergediff $id
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10006054 }
6055}
6056
Rutger Nijlunsing6e5f7202006-04-05 10:24:03 +10006057proc selfirstline {} {
6058 unmarkmatches
6059 selectline 0 1
6060}
6061
6062proc sellastline {} {
6063 global numcommits
6064 unmarkmatches
6065 set l [expr {$numcommits - 1}]
6066 selectline $l 1
6067}
6068
Paul Mackerrase5c2d852005-05-11 23:44:54 +00006069proc selnextline {dir} {
6070 global selectedline
Mark Levedahlbd441de2007-08-07 21:40:34 -04006071 focus .
Paul Mackerras94b4a692008-05-20 20:51:06 +10006072 if {$selectedline eq {}} return
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08006073 set l [expr {$selectedline + $dir}]
Paul Mackerras98f350e2005-05-15 05:56:51 +00006074 unmarkmatches
Paul Mackerrasd6982062005-08-06 22:06:06 +10006075 selectline $l 1
6076}
6077
Rutger Nijlunsing6e5f7202006-04-05 10:24:03 +10006078proc selnextpage {dir} {
6079 global canv linespc selectedline numcommits
6080
6081 set lpp [expr {([winfo height $canv] - 2) / $linespc}]
6082 if {$lpp < 1} {
6083 set lpp 1
6084 }
6085 allcanvs yview scroll [expr {$dir * $lpp}] units
Paul Mackerrase72ee5e2006-05-20 09:58:49 +10006086 drawvisible
Paul Mackerras94b4a692008-05-20 20:51:06 +10006087 if {$selectedline eq {}} return
Rutger Nijlunsing6e5f7202006-04-05 10:24:03 +10006088 set l [expr {$selectedline + $dir * $lpp}]
6089 if {$l < 0} {
6090 set l 0
6091 } elseif {$l >= $numcommits} {
6092 set l [expr $numcommits - 1]
6093 }
6094 unmarkmatches
Mark Levedahl40b87ff2007-02-01 08:44:46 -05006095 selectline $l 1
Rutger Nijlunsing6e5f7202006-04-05 10:24:03 +10006096}
6097
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10006098proc unselectline {} {
Paul Mackerras50b44ec2006-04-04 10:16:22 +10006099 global selectedline currentid
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10006100
Paul Mackerras94b4a692008-05-20 20:51:06 +10006101 set selectedline {}
Paul Mackerras50b44ec2006-04-04 10:16:22 +10006102 catch {unset currentid}
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10006103 allcanvs delete secsel
Paul Mackerras164ff272006-05-29 19:50:02 +10006104 rhighlight_none
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10006105}
6106
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10006107proc reselectline {} {
6108 global selectedline
6109
Paul Mackerras94b4a692008-05-20 20:51:06 +10006110 if {$selectedline ne {}} {
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10006111 selectline $selectedline 0
6112 }
6113}
6114
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10006115proc addtohistory {cmd} {
Paul Mackerras2516dae2006-04-21 10:35:31 +10006116 global history historyindex curview
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10006117
Paul Mackerras2516dae2006-04-21 10:35:31 +10006118 set elt [list $curview $cmd]
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10006119 if {$historyindex > 0
Paul Mackerras2516dae2006-04-21 10:35:31 +10006120 && [lindex $history [expr {$historyindex - 1}]] == $elt} {
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10006121 return
6122 }
6123
6124 if {$historyindex < [llength $history]} {
Paul Mackerras2516dae2006-04-21 10:35:31 +10006125 set history [lreplace $history $historyindex end $elt]
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10006126 } else {
Paul Mackerras2516dae2006-04-21 10:35:31 +10006127 lappend history $elt
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10006128 }
6129 incr historyindex
6130 if {$historyindex > 1} {
Junio C Hamanoe9937d22007-02-01 08:46:38 -05006131 .tf.bar.leftbut conf -state normal
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10006132 } else {
Junio C Hamanoe9937d22007-02-01 08:46:38 -05006133 .tf.bar.leftbut conf -state disabled
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10006134 }
Junio C Hamanoe9937d22007-02-01 08:46:38 -05006135 .tf.bar.rightbut conf -state disabled
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10006136}
6137
Paul Mackerras2516dae2006-04-21 10:35:31 +10006138proc godo {elt} {
6139 global curview
6140
6141 set view [lindex $elt 0]
6142 set cmd [lindex $elt 1]
6143 if {$curview != $view} {
6144 showview $view
6145 }
6146 eval $cmd
6147}
6148
Paul Mackerrasd6982062005-08-06 22:06:06 +10006149proc goback {} {
6150 global history historyindex
Mark Levedahlbd441de2007-08-07 21:40:34 -04006151 focus .
Paul Mackerrasd6982062005-08-06 22:06:06 +10006152
6153 if {$historyindex > 1} {
6154 incr historyindex -1
Paul Mackerras2516dae2006-04-21 10:35:31 +10006155 godo [lindex $history [expr {$historyindex - 1}]]
Junio C Hamanoe9937d22007-02-01 08:46:38 -05006156 .tf.bar.rightbut conf -state normal
Paul Mackerrasd6982062005-08-06 22:06:06 +10006157 }
6158 if {$historyindex <= 1} {
Junio C Hamanoe9937d22007-02-01 08:46:38 -05006159 .tf.bar.leftbut conf -state disabled
Paul Mackerrasd6982062005-08-06 22:06:06 +10006160 }
6161}
6162
6163proc goforw {} {
6164 global history historyindex
Mark Levedahlbd441de2007-08-07 21:40:34 -04006165 focus .
Paul Mackerrasd6982062005-08-06 22:06:06 +10006166
6167 if {$historyindex < [llength $history]} {
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10006168 set cmd [lindex $history $historyindex]
Paul Mackerrasd6982062005-08-06 22:06:06 +10006169 incr historyindex
Paul Mackerras2516dae2006-04-21 10:35:31 +10006170 godo $cmd
Junio C Hamanoe9937d22007-02-01 08:46:38 -05006171 .tf.bar.leftbut conf -state normal
Paul Mackerrasd6982062005-08-06 22:06:06 +10006172 }
6173 if {$historyindex >= [llength $history]} {
Junio C Hamanoe9937d22007-02-01 08:46:38 -05006174 .tf.bar.rightbut conf -state disabled
Paul Mackerrasd6982062005-08-06 22:06:06 +10006175 }
Paul Mackerras5ad588d2005-05-10 01:02:55 +00006176}
6177
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10006178proc gettree {id} {
Paul Mackerras8f489362007-07-13 19:49:37 +10006179 global treefilelist treeidlist diffids diffmergeid treepending
6180 global nullid nullid2
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10006181
6182 set diffids $id
6183 catch {unset diffmergeid}
6184 if {![info exists treefilelist($id)]} {
6185 if {![info exists treepending]} {
Paul Mackerras8f489362007-07-13 19:49:37 +10006186 if {$id eq $nullid} {
6187 set cmd [list | git ls-files]
6188 } elseif {$id eq $nullid2} {
6189 set cmd [list | git ls-files --stage -t]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10006190 } else {
Paul Mackerras8f489362007-07-13 19:49:37 +10006191 set cmd [list | git ls-tree -r $id]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10006192 }
6193 if {[catch {set gtf [open $cmd r]}]} {
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10006194 return
6195 }
6196 set treepending $id
6197 set treefilelist($id) {}
6198 set treeidlist($id) {}
6199 fconfigure $gtf -blocking 0
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10006200 filerun $gtf [list gettreeline $gtf $id]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10006201 }
6202 } else {
6203 setfilelist $id
6204 }
6205}
6206
6207proc gettreeline {gtf id} {
Paul Mackerras8f489362007-07-13 19:49:37 +10006208 global treefilelist treeidlist treepending cmitmode diffids nullid nullid2
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10006209
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10006210 set nl 0
6211 while {[incr nl] <= 1000 && [gets $gtf line] >= 0} {
Paul Mackerras8f489362007-07-13 19:49:37 +10006212 if {$diffids eq $nullid} {
6213 set fname $line
6214 } else {
Paul Mackerras9396cd32007-06-23 20:28:15 +10006215 set i [string first "\t" $line]
6216 if {$i < 0} continue
Paul Mackerras9396cd32007-06-23 20:28:15 +10006217 set fname [string range $line [expr {$i+1}] end]
Paul Mackerrasf31fa2c2008-04-28 09:40:50 +10006218 set line [string range $line 0 [expr {$i-1}]]
6219 if {$diffids ne $nullid2 && [lindex $line 1] ne "blob"} continue
6220 set sha1 [lindex $line 2]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10006221 if {[string index $fname 0] eq "\""} {
6222 set fname [lindex $fname 0]
6223 }
6224 lappend treeidlist($id) $sha1
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10006225 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10006226 lappend treefilelist($id) $fname
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10006227 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10006228 if {![eof $gtf]} {
6229 return [expr {$nl >= 1000? 2: 1}]
6230 }
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10006231 close $gtf
6232 unset treepending
6233 if {$cmitmode ne "tree"} {
6234 if {![info exists diffmergeid]} {
6235 gettreediffs $diffids
6236 }
6237 } elseif {$id ne $diffids} {
6238 gettree $diffids
6239 } else {
6240 setfilelist $id
6241 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10006242 return 0
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10006243}
6244
6245proc showfile {f} {
Paul Mackerras8f489362007-07-13 19:49:37 +10006246 global treefilelist treeidlist diffids nullid nullid2
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10006247 global ctext commentend
6248
6249 set i [lsearch -exact $treefilelist($diffids) $f]
6250 if {$i < 0} {
6251 puts "oops, $f not in list for id $diffids"
6252 return
6253 }
Paul Mackerras8f489362007-07-13 19:49:37 +10006254 if {$diffids eq $nullid} {
6255 if {[catch {set bf [open $f r]} err]} {
6256 puts "oops, can't read $f: $err"
Paul Mackerras219ea3a2006-09-07 10:21:39 +10006257 return
6258 }
6259 } else {
Paul Mackerras8f489362007-07-13 19:49:37 +10006260 set blob [lindex $treeidlist($diffids) $i]
6261 if {[catch {set bf [open [concat | git cat-file blob $blob] r]} err]} {
6262 puts "oops, error reading blob $blob: $err"
Paul Mackerras219ea3a2006-09-07 10:21:39 +10006263 return
6264 }
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10006265 }
6266 fconfigure $bf -blocking 0
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10006267 filerun $bf [list getblobline $bf $diffids]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10006268 $ctext config -state normal
Paul Mackerras3ea06f92006-05-24 10:16:03 +10006269 clear_ctext $commentend
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10006270 $ctext insert end "\n"
6271 $ctext insert end "$f\n" filesep
6272 $ctext config -state disabled
6273 $ctext yview $commentend
Paul Mackerras32f1b3e2007-09-28 21:27:39 +10006274 settabs 0
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10006275}
6276
6277proc getblobline {bf id} {
6278 global diffids cmitmode ctext
6279
6280 if {$id ne $diffids || $cmitmode ne "tree"} {
6281 catch {close $bf}
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10006282 return 0
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10006283 }
6284 $ctext config -state normal
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10006285 set nl 0
6286 while {[incr nl] <= 1000 && [gets $bf line] >= 0} {
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10006287 $ctext insert end "$line\n"
6288 }
6289 if {[eof $bf]} {
6290 # delete last newline
6291 $ctext delete "end - 2c" "end - 1c"
6292 close $bf
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10006293 return 0
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10006294 }
6295 $ctext config -state disabled
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10006296 return [expr {$nl >= 1000? 2: 1}]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10006297}
6298
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11006299proc mergediff {id} {
Paul Mackerras8d73b242007-10-06 20:22:00 +10006300 global diffmergeid mdifffd
Paul Mackerras7fcceed2006-04-27 19:21:49 +10006301 global diffids
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11006302 global parents
Johannes Sixt6675ea42008-02-13 17:27:30 +01006303 global diffcontext
Paul Mackerras3ed31a82008-04-26 16:00:00 +10006304 global limitdiffs vfilelimit curview
Paul Mackerrase2ed4322005-07-17 03:39:44 -04006305
Paul Mackerras3c461ff2005-07-20 09:13:46 -04006306 set diffmergeid $id
Paul Mackerras7a1d9d12006-03-22 10:21:45 +11006307 set diffids $id
Paul Mackerrasb77b0272006-02-07 09:13:52 +11006308 # this doesn't seem to actually affect anything...
Johannes Sixt6675ea42008-02-13 17:27:30 +01006309 set cmd [concat | git diff-tree --no-commit-id --cc -U$diffcontext $id]
Paul Mackerras3ed31a82008-04-26 16:00:00 +10006310 if {$limitdiffs && $vfilelimit($curview) ne {}} {
6311 set cmd [concat $cmd -- $vfilelimit($curview)]
Paul Mackerrasbd8f6772007-10-23 22:37:23 +10006312 }
Paul Mackerrasb77b0272006-02-07 09:13:52 +11006313 if {[catch {set mdf [open $cmd r]} err]} {
Christian Stimmingd990ced2007-11-07 18:42:55 +01006314 error_popup "[mc "Error getting merge diffs:"] $err"
Paul Mackerrasb77b0272006-02-07 09:13:52 +11006315 return
Paul Mackerras9d2a52e2005-07-27 22:15:47 -05006316 }
Paul Mackerrasb77b0272006-02-07 09:13:52 +11006317 fconfigure $mdf -blocking 0
6318 set mdifffd($id) $mdf
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11006319 set np [llength $parents($curview,$id)]
Paul Mackerras32f1b3e2007-09-28 21:27:39 +10006320 settabs $np
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10006321 filerun $mdf [list getmergediffline $mdf $id $np]
Paul Mackerras9d2a52e2005-07-27 22:15:47 -05006322}
6323
Paul Mackerras79b2c752006-04-02 20:47:40 +10006324proc getmergediffline {mdf id np} {
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10006325 global diffmergeid ctext cflist mergemax
Paul Mackerras7a1d9d12006-03-22 10:21:45 +11006326 global difffilestart mdifffd
Paul Mackerras9d2a52e2005-07-27 22:15:47 -05006327
Paul Mackerras9d2a52e2005-07-27 22:15:47 -05006328 $ctext conf -state normal
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10006329 set nr 0
6330 while {[incr nr] <= 1000 && [gets $mdf line] >= 0} {
6331 if {![info exists diffmergeid] || $id != $diffmergeid
6332 || $mdf != $mdifffd($id)} {
6333 close $mdf
6334 return 0
6335 }
6336 if {[regexp {^diff --cc (.*)} $line match fname]} {
6337 # start of a new file
6338 $ctext insert end "\n"
6339 set here [$ctext index "end - 1c"]
6340 lappend difffilestart $here
6341 add_flist [list $fname]
6342 set l [expr {(78 - [string length $fname]) / 2}]
6343 set pad [string range "----------------------------------------" 1 $l]
6344 $ctext insert end "$pad $fname $pad\n" filesep
6345 } elseif {[regexp {^@@} $line]} {
6346 $ctext insert end "$line\n" hunksep
6347 } elseif {[regexp {^[0-9a-f]{40}$} $line] || [regexp {^index} $line]} {
6348 # do nothing
6349 } else {
6350 # parse the prefix - one ' ', '-' or '+' for each parent
6351 set spaces {}
6352 set minuses {}
6353 set pluses {}
6354 set isbad 0
6355 for {set j 0} {$j < $np} {incr j} {
6356 set c [string range $line $j $j]
6357 if {$c == " "} {
6358 lappend spaces $j
6359 } elseif {$c == "-"} {
6360 lappend minuses $j
6361 } elseif {$c == "+"} {
6362 lappend pluses $j
6363 } else {
6364 set isbad 1
6365 break
6366 }
Paul Mackerras9d2a52e2005-07-27 22:15:47 -05006367 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10006368 set tags {}
6369 set num {}
6370 if {!$isbad && $minuses ne {} && $pluses eq {}} {
6371 # line doesn't appear in result, parents in $minuses have the line
6372 set num [lindex $minuses 0]
6373 } elseif {!$isbad && $pluses ne {} && $minuses eq {}} {
6374 # line appears in result, parents in $pluses don't have the line
6375 lappend tags mresult
6376 set num [lindex $spaces 0]
Paul Mackerras9d2a52e2005-07-27 22:15:47 -05006377 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10006378 if {$num ne {}} {
6379 if {$num >= $mergemax} {
6380 set num "max"
6381 }
6382 lappend tags m$num
6383 }
6384 $ctext insert end "$line\n" $tags
Paul Mackerras9d2a52e2005-07-27 22:15:47 -05006385 }
Paul Mackerras9d2a52e2005-07-27 22:15:47 -05006386 }
6387 $ctext conf -state disabled
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10006388 if {[eof $mdf]} {
6389 close $mdf
6390 return 0
Paul Mackerrasc8a4acb2005-07-29 09:23:03 -05006391 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10006392 return [expr {$nr >= 1000? 2: 1}]
Paul Mackerrasc8a4acb2005-07-29 09:23:03 -05006393}
6394
Paul Mackerras3c461ff2005-07-20 09:13:46 -04006395proc startdiff {ids} {
Paul Mackerras8f489362007-07-13 19:49:37 +10006396 global treediffs diffids treepending diffmergeid nullid nullid2
Paul Mackerras3c461ff2005-07-20 09:13:46 -04006397
Paul Mackerras32f1b3e2007-09-28 21:27:39 +10006398 settabs 1
Paul Mackerras3c461ff2005-07-20 09:13:46 -04006399 set diffids $ids
6400 catch {unset diffmergeid}
Paul Mackerras8f489362007-07-13 19:49:37 +10006401 if {![info exists treediffs($ids)] ||
6402 [lsearch -exact $ids $nullid] >= 0 ||
6403 [lsearch -exact $ids $nullid2] >= 0} {
Paul Mackerras3c461ff2005-07-20 09:13:46 -04006404 if {![info exists treepending]} {
6405 gettreediffs $ids
6406 }
6407 } else {
6408 addtocflist $ids
6409 }
6410}
6411
Paul Mackerras7a39a172007-10-23 10:15:11 +10006412proc path_filter {filter name} {
6413 foreach p $filter {
6414 set l [string length $p]
Paul Mackerras74a40c72007-10-24 10:16:56 +10006415 if {[string index $p end] eq "/"} {
6416 if {[string compare -length $l $p $name] == 0} {
6417 return 1
6418 }
6419 } else {
6420 if {[string compare -length $l $p $name] == 0 &&
6421 ([string length $name] == $l ||
6422 [string index $name $l] eq "/")} {
6423 return 1
6424 }
Paul Mackerras7a39a172007-10-23 10:15:11 +10006425 }
6426 }
6427 return 0
6428}
6429
Paul Mackerras3c461ff2005-07-20 09:13:46 -04006430proc addtocflist {ids} {
Paul Mackerras74a40c72007-10-24 10:16:56 +10006431 global treediffs
Paul Mackerras7a39a172007-10-23 10:15:11 +10006432
Paul Mackerras74a40c72007-10-24 10:16:56 +10006433 add_flist $treediffs($ids)
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10006434 getblobdiffs $ids
Paul Mackerrasd2610d12005-05-11 00:45:38 +00006435}
6436
Paul Mackerras219ea3a2006-09-07 10:21:39 +10006437proc diffcmd {ids flags} {
Paul Mackerras8f489362007-07-13 19:49:37 +10006438 global nullid nullid2
Paul Mackerras219ea3a2006-09-07 10:21:39 +10006439
6440 set i [lsearch -exact $ids $nullid]
Paul Mackerras8f489362007-07-13 19:49:37 +10006441 set j [lsearch -exact $ids $nullid2]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10006442 if {$i >= 0} {
Paul Mackerras8f489362007-07-13 19:49:37 +10006443 if {[llength $ids] > 1 && $j < 0} {
6444 # comparing working directory with some specific revision
6445 set cmd [concat | git diff-index $flags]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10006446 if {$i == 0} {
6447 lappend cmd -R [lindex $ids 1]
6448 } else {
6449 lappend cmd [lindex $ids 0]
6450 }
6451 } else {
Paul Mackerras8f489362007-07-13 19:49:37 +10006452 # comparing working directory with index
6453 set cmd [concat | git diff-files $flags]
6454 if {$j == 1} {
6455 lappend cmd -R
6456 }
6457 }
6458 } elseif {$j >= 0} {
6459 set cmd [concat | git diff-index --cached $flags]
6460 if {[llength $ids] > 1} {
6461 # comparing index with specific revision
6462 if {$i == 0} {
6463 lappend cmd -R [lindex $ids 1]
6464 } else {
6465 lappend cmd [lindex $ids 0]
6466 }
6467 } else {
6468 # comparing index with HEAD
Paul Mackerras219ea3a2006-09-07 10:21:39 +10006469 lappend cmd HEAD
6470 }
6471 } else {
Paul Mackerras8f489362007-07-13 19:49:37 +10006472 set cmd [concat | git diff-tree -r $flags $ids]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10006473 }
6474 return $cmd
6475}
6476
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10006477proc gettreediffs {ids} {
Paul Mackerras79b2c752006-04-02 20:47:40 +10006478 global treediff treepending
Paul Mackerras219ea3a2006-09-07 10:21:39 +10006479
Alexander Gavrilov72721312008-07-26 18:48:41 +04006480 if {[catch {set gdtf [open [diffcmd $ids {--no-commit-id}] r]}]} return
6481
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10006482 set treepending $ids
Paul Mackerras3c461ff2005-07-20 09:13:46 -04006483 set treediff {}
Paul Mackerrasd2610d12005-05-11 00:45:38 +00006484 fconfigure $gdtf -blocking 0
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10006485 filerun $gdtf [list gettreediffline $gdtf $ids]
Paul Mackerrasd2610d12005-05-11 00:45:38 +00006486}
6487
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10006488proc gettreediffline {gdtf ids} {
Paul Mackerras3c461ff2005-07-20 09:13:46 -04006489 global treediff treediffs treepending diffids diffmergeid
Paul Mackerras3ed31a82008-04-26 16:00:00 +10006490 global cmitmode vfilelimit curview limitdiffs
Paul Mackerras3c461ff2005-07-20 09:13:46 -04006491
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10006492 set nr 0
6493 while {[incr nr] <= 1000 && [gets $gdtf line] >= 0} {
Paul Mackerras9396cd32007-06-23 20:28:15 +10006494 set i [string first "\t" $line]
6495 if {$i >= 0} {
6496 set file [string range $line [expr {$i+1}] end]
6497 if {[string index $file 0] eq "\""} {
6498 set file [lindex $file 0]
6499 }
6500 lappend treediff $file
6501 }
Paul Mackerrasd2610d12005-05-11 00:45:38 +00006502 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10006503 if {![eof $gdtf]} {
6504 return [expr {$nr >= 1000? 2: 1}]
6505 }
6506 close $gdtf
Paul Mackerras3ed31a82008-04-26 16:00:00 +10006507 if {$limitdiffs && $vfilelimit($curview) ne {}} {
Paul Mackerras74a40c72007-10-24 10:16:56 +10006508 set flist {}
6509 foreach f $treediff {
Paul Mackerras3ed31a82008-04-26 16:00:00 +10006510 if {[path_filter $vfilelimit($curview) $f]} {
Paul Mackerras74a40c72007-10-24 10:16:56 +10006511 lappend flist $f
6512 }
6513 }
6514 set treediffs($ids) $flist
6515 } else {
6516 set treediffs($ids) $treediff
6517 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10006518 unset treepending
6519 if {$cmitmode eq "tree"} {
6520 gettree $diffids
6521 } elseif {$ids != $diffids} {
6522 if {![info exists diffmergeid]} {
6523 gettreediffs $diffids
6524 }
6525 } else {
6526 addtocflist $ids
6527 }
6528 return 0
Paul Mackerrasd2610d12005-05-11 00:45:38 +00006529}
6530
Steffen Prohaska890fae72007-08-12 12:05:46 +02006531# empty string or positive integer
6532proc diffcontextvalidate {v} {
6533 return [regexp {^(|[1-9][0-9]*)$} $v]
6534}
6535
6536proc diffcontextchange {n1 n2 op} {
6537 global diffcontextstring diffcontext
6538
6539 if {[string is integer -strict $diffcontextstring]} {
6540 if {$diffcontextstring > 0} {
6541 set diffcontext $diffcontextstring
6542 reselectline
6543 }
6544 }
6545}
6546
Steffen Prohaskab9b86002008-01-17 23:42:55 +01006547proc changeignorespace {} {
6548 reselectline
6549}
6550
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10006551proc getblobdiffs {ids} {
Paul Mackerras8d73b242007-10-06 20:22:00 +10006552 global blobdifffd diffids env
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10006553 global diffinhdr treediffs
Steffen Prohaska890fae72007-08-12 12:05:46 +02006554 global diffcontext
Steffen Prohaskab9b86002008-01-17 23:42:55 +01006555 global ignorespace
Paul Mackerras3ed31a82008-04-26 16:00:00 +10006556 global limitdiffs vfilelimit curview
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10006557
Paul Mackerras7a39a172007-10-23 10:15:11 +10006558 set cmd [diffcmd $ids "-p -C --no-commit-id -U$diffcontext"]
Steffen Prohaskab9b86002008-01-17 23:42:55 +01006559 if {$ignorespace} {
6560 append cmd " -w"
6561 }
Paul Mackerras3ed31a82008-04-26 16:00:00 +10006562 if {$limitdiffs && $vfilelimit($curview) ne {}} {
6563 set cmd [concat $cmd -- $vfilelimit($curview)]
Paul Mackerras7a39a172007-10-23 10:15:11 +10006564 }
6565 if {[catch {set bdf [open $cmd r]} err]} {
Paul Mackerrase5c2d852005-05-11 23:44:54 +00006566 puts "error getting diffs: $err"
6567 return
6568 }
Paul Mackerras4f2c2642005-07-17 11:11:44 -04006569 set diffinhdr 0
Paul Mackerrase5c2d852005-05-11 23:44:54 +00006570 fconfigure $bdf -blocking 0
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10006571 set blobdifffd($ids) $bdf
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10006572 filerun $bdf [list getblobdiffline $bdf $diffids]
Paul Mackerrase5c2d852005-05-11 23:44:54 +00006573}
6574
Paul Mackerras89b11d32006-05-02 19:55:31 +10006575proc setinlist {var i val} {
6576 global $var
6577
6578 while {[llength [set $var]] < $i} {
6579 lappend $var {}
6580 }
6581 if {[llength [set $var]] == $i} {
6582 lappend $var $val
6583 } else {
6584 lset $var $i $val
6585 }
6586}
6587
Paul Mackerras9396cd32007-06-23 20:28:15 +10006588proc makediffhdr {fname ids} {
6589 global ctext curdiffstart treediffs
6590
6591 set i [lsearch -exact $treediffs($ids) $fname]
6592 if {$i >= 0} {
6593 setinlist difffilestart $i $curdiffstart
6594 }
6595 set l [expr {(78 - [string length $fname]) / 2}]
6596 set pad [string range "----------------------------------------" 1 $l]
6597 $ctext insert $curdiffstart "$pad $fname $pad" filesep
6598}
6599
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10006600proc getblobdiffline {bdf ids} {
Paul Mackerras9396cd32007-06-23 20:28:15 +10006601 global diffids blobdifffd ctext curdiffstart
Paul Mackerras7eab2932005-07-20 12:25:54 -04006602 global diffnexthead diffnextnote difffilestart
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10006603 global diffinhdr treediffs
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10006604
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10006605 set nr 0
Paul Mackerrase5c2d852005-05-11 23:44:54 +00006606 $ctext conf -state normal
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10006607 while {[incr nr] <= 1000 && [gets $bdf line] >= 0} {
6608 if {$ids != $diffids || $bdf != $blobdifffd($ids)} {
6609 close $bdf
6610 return 0
Paul Mackerras89b11d32006-05-02 19:55:31 +10006611 }
Paul Mackerras9396cd32007-06-23 20:28:15 +10006612 if {![string compare -length 11 "diff --git " $line]} {
6613 # trim off "diff --git "
6614 set line [string range $line 11 end]
6615 set diffinhdr 1
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10006616 # start of a new file
6617 $ctext insert end "\n"
Paul Mackerras9396cd32007-06-23 20:28:15 +10006618 set curdiffstart [$ctext index "end - 1c"]
6619 $ctext insert end "\n" filesep
6620 # If the name hasn't changed the length will be odd,
6621 # the middle char will be a space, and the two bits either
6622 # side will be a/name and b/name, or "a/name" and "b/name".
6623 # If the name has changed we'll get "rename from" and
Johannes Sixtd1cb2982007-08-16 14:32:29 +02006624 # "rename to" or "copy from" and "copy to" lines following this,
6625 # and we'll use them to get the filenames.
Paul Mackerras9396cd32007-06-23 20:28:15 +10006626 # This complexity is necessary because spaces in the filename(s)
6627 # don't get escaped.
6628 set l [string length $line]
6629 set i [expr {$l / 2}]
6630 if {!(($l & 1) && [string index $line $i] eq " " &&
6631 [string range $line 2 [expr {$i - 1}]] eq \
6632 [string range $line [expr {$i + 3}] end])} {
6633 continue
Paul Mackerras89b11d32006-05-02 19:55:31 +10006634 }
Paul Mackerras9396cd32007-06-23 20:28:15 +10006635 # unescape if quoted and chop off the a/ from the front
6636 if {[string index $line 0] eq "\""} {
6637 set fname [string range [lindex $line 0] 2 end]
6638 } else {
6639 set fname [string range $line 2 [expr {$i - 1}]]
Paul Mackerrase5c2d852005-05-11 23:44:54 +00006640 }
Paul Mackerras9396cd32007-06-23 20:28:15 +10006641 makediffhdr $fname $ids
6642
6643 } elseif {[regexp {^@@ -([0-9]+)(,[0-9]+)? \+([0-9]+)(,[0-9]+)? @@(.*)} \
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10006644 $line match f1l f1c f2l f2c rest]} {
6645 $ctext insert end "$line\n" hunksep
6646 set diffinhdr 0
Paul Mackerras9396cd32007-06-23 20:28:15 +10006647
6648 } elseif {$diffinhdr} {
Johannes Sixt5e85ec42007-10-02 16:16:54 +02006649 if {![string compare -length 12 "rename from " $line]} {
Johannes Sixtd1cb2982007-08-16 14:32:29 +02006650 set fname [string range $line [expr 6 + [string first " from " $line] ] end]
Paul Mackerras9396cd32007-06-23 20:28:15 +10006651 if {[string index $fname 0] eq "\""} {
6652 set fname [lindex $fname 0]
6653 }
6654 set i [lsearch -exact $treediffs($ids) $fname]
6655 if {$i >= 0} {
6656 setinlist difffilestart $i $curdiffstart
6657 }
Johannes Sixtd1cb2982007-08-16 14:32:29 +02006658 } elseif {![string compare -length 10 $line "rename to "] ||
6659 ![string compare -length 8 $line "copy to "]} {
6660 set fname [string range $line [expr 4 + [string first " to " $line] ] end]
Paul Mackerras9396cd32007-06-23 20:28:15 +10006661 if {[string index $fname 0] eq "\""} {
6662 set fname [lindex $fname 0]
6663 }
6664 makediffhdr $fname $ids
6665 } elseif {[string compare -length 3 $line "---"] == 0} {
6666 # do nothing
6667 continue
6668 } elseif {[string compare -length 3 $line "+++"] == 0} {
6669 set diffinhdr 0
6670 continue
6671 }
6672 $ctext insert end "$line\n" filesep
6673
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10006674 } else {
6675 set x [string range $line 0 0]
6676 if {$x == "-" || $x == "+"} {
6677 set tag [expr {$x == "+"}]
6678 $ctext insert end "$line\n" d$tag
6679 } elseif {$x == " "} {
6680 $ctext insert end "$line\n"
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10006681 } else {
Paul Mackerras9396cd32007-06-23 20:28:15 +10006682 # "\ No newline at end of file",
6683 # or something else we don't recognize
6684 $ctext insert end "$line\n" hunksep
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10006685 }
Paul Mackerrase5c2d852005-05-11 23:44:54 +00006686 }
6687 }
6688 $ctext conf -state disabled
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10006689 if {[eof $bdf]} {
6690 close $bdf
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10006691 return 0
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10006692 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10006693 return [expr {$nr >= 1000? 2: 1}]
Paul Mackerrase5c2d852005-05-11 23:44:54 +00006694}
6695
Paul Mackerrasa8d610a2007-04-19 11:39:12 +10006696proc changediffdisp {} {
6697 global ctext diffelide
6698
6699 $ctext tag conf d0 -elide [lindex $diffelide 0]
6700 $ctext tag conf d1 -elide [lindex $diffelide 1]
6701}
6702
Paul Mackerrasf4c54b32008-05-10 13:15:36 +10006703proc highlightfile {loc cline} {
6704 global ctext cflist cflist_top
6705
6706 $ctext yview $loc
6707 $cflist tag remove highlight $cflist_top.0 "$cflist_top.0 lineend"
6708 $cflist tag add highlight $cline.0 "$cline.0 lineend"
6709 $cflist see $cline.0
6710 set cflist_top $cline
6711}
6712
OGAWA Hirofumi67c22872006-09-27 12:32:19 +09006713proc prevfile {} {
Paul Mackerrasf4c54b32008-05-10 13:15:36 +10006714 global difffilestart ctext cmitmode
6715
6716 if {$cmitmode eq "tree"} return
6717 set prev 0.0
6718 set prevline 1
OGAWA Hirofumi67c22872006-09-27 12:32:19 +09006719 set here [$ctext index @0,0]
6720 foreach loc $difffilestart {
6721 if {[$ctext compare $loc >= $here]} {
Paul Mackerrasf4c54b32008-05-10 13:15:36 +10006722 highlightfile $prev $prevline
OGAWA Hirofumi67c22872006-09-27 12:32:19 +09006723 return
6724 }
6725 set prev $loc
Paul Mackerrasf4c54b32008-05-10 13:15:36 +10006726 incr prevline
OGAWA Hirofumi67c22872006-09-27 12:32:19 +09006727 }
Paul Mackerrasf4c54b32008-05-10 13:15:36 +10006728 highlightfile $prev $prevline
OGAWA Hirofumi67c22872006-09-27 12:32:19 +09006729}
6730
Paul Mackerras39ad8572005-05-19 12:35:53 +00006731proc nextfile {} {
Paul Mackerrasf4c54b32008-05-10 13:15:36 +10006732 global difffilestart ctext cmitmode
6733
6734 if {$cmitmode eq "tree"} return
Paul Mackerras39ad8572005-05-19 12:35:53 +00006735 set here [$ctext index @0,0]
Paul Mackerrasf4c54b32008-05-10 13:15:36 +10006736 set line 1
Paul Mackerras7fcceed2006-04-27 19:21:49 +10006737 foreach loc $difffilestart {
Paul Mackerrasf4c54b32008-05-10 13:15:36 +10006738 incr line
Paul Mackerras7fcceed2006-04-27 19:21:49 +10006739 if {[$ctext compare $loc > $here]} {
Paul Mackerrasf4c54b32008-05-10 13:15:36 +10006740 highlightfile $loc $line
OGAWA Hirofumi67c22872006-09-27 12:32:19 +09006741 return
Paul Mackerras39ad8572005-05-19 12:35:53 +00006742 }
6743 }
Paul Mackerras1db95b02005-05-09 04:08:39 +00006744}
6745
Paul Mackerras3ea06f92006-05-24 10:16:03 +10006746proc clear_ctext {{first 1.0}} {
6747 global ctext smarktop smarkbot
Paul Mackerras97645682007-08-23 22:24:38 +10006748 global pendinglinks
Paul Mackerras3ea06f92006-05-24 10:16:03 +10006749
Paul Mackerras1902c272006-05-25 21:25:13 +10006750 set l [lindex [split $first .] 0]
6751 if {![info exists smarktop] || [$ctext compare $first < $smarktop.0]} {
6752 set smarktop $l
Paul Mackerras3ea06f92006-05-24 10:16:03 +10006753 }
Paul Mackerras1902c272006-05-25 21:25:13 +10006754 if {![info exists smarkbot] || [$ctext compare $first < $smarkbot.0]} {
6755 set smarkbot $l
Paul Mackerras3ea06f92006-05-24 10:16:03 +10006756 }
6757 $ctext delete $first end
Paul Mackerras97645682007-08-23 22:24:38 +10006758 if {$first eq "1.0"} {
6759 catch {unset pendinglinks}
6760 }
Paul Mackerras3ea06f92006-05-24 10:16:03 +10006761}
6762
Paul Mackerras32f1b3e2007-09-28 21:27:39 +10006763proc settabs {{firstab {}}} {
Paul Mackerras9c311b32007-10-04 22:27:13 +10006764 global firsttabstop tabstop ctext have_tk85
Paul Mackerras32f1b3e2007-09-28 21:27:39 +10006765
6766 if {$firstab ne {} && $have_tk85} {
6767 set firsttabstop $firstab
6768 }
Paul Mackerras9c311b32007-10-04 22:27:13 +10006769 set w [font measure textfont "0"]
Paul Mackerras32f1b3e2007-09-28 21:27:39 +10006770 if {$firsttabstop != 0} {
Paul Mackerras64b5f142007-10-04 22:19:24 +10006771 $ctext conf -tabs [list [expr {($firsttabstop + $tabstop) * $w}] \
6772 [expr {($firsttabstop + 2 * $tabstop) * $w}]]
Paul Mackerras32f1b3e2007-09-28 21:27:39 +10006773 } elseif {$have_tk85 || $tabstop != 8} {
6774 $ctext conf -tabs [expr {$tabstop * $w}]
6775 } else {
6776 $ctext conf -tabs {}
6777 }
Paul Mackerras3ea06f92006-05-24 10:16:03 +10006778}
6779
6780proc incrsearch {name ix op} {
Paul Mackerras1902c272006-05-25 21:25:13 +10006781 global ctext searchstring searchdirn
Paul Mackerras3ea06f92006-05-24 10:16:03 +10006782
6783 $ctext tag remove found 1.0 end
Paul Mackerras1902c272006-05-25 21:25:13 +10006784 if {[catch {$ctext index anchor}]} {
6785 # no anchor set, use start of selection, or of visible area
6786 set sel [$ctext tag ranges sel]
6787 if {$sel ne {}} {
6788 $ctext mark set anchor [lindex $sel 0]
6789 } elseif {$searchdirn eq "-forwards"} {
6790 $ctext mark set anchor @0,0
6791 } else {
6792 $ctext mark set anchor @0,[winfo height $ctext]
6793 }
6794 }
Paul Mackerras3ea06f92006-05-24 10:16:03 +10006795 if {$searchstring ne {}} {
Paul Mackerras1902c272006-05-25 21:25:13 +10006796 set here [$ctext search $searchdirn -- $searchstring anchor]
6797 if {$here ne {}} {
6798 $ctext see $here
6799 }
Paul Mackerras3ea06f92006-05-24 10:16:03 +10006800 searchmarkvisible 1
6801 }
6802}
6803
6804proc dosearch {} {
Paul Mackerras1902c272006-05-25 21:25:13 +10006805 global sstring ctext searchstring searchdirn
Paul Mackerras3ea06f92006-05-24 10:16:03 +10006806
6807 focus $sstring
6808 $sstring icursor end
Paul Mackerras1902c272006-05-25 21:25:13 +10006809 set searchdirn -forwards
6810 if {$searchstring ne {}} {
6811 set sel [$ctext tag ranges sel]
6812 if {$sel ne {}} {
6813 set start "[lindex $sel 0] + 1c"
6814 } elseif {[catch {set start [$ctext index anchor]}]} {
6815 set start "@0,0"
6816 }
6817 set match [$ctext search -count mlen -- $searchstring $start]
6818 $ctext tag remove sel 1.0 end
6819 if {$match eq {}} {
6820 bell
6821 return
6822 }
6823 $ctext see $match
6824 set mend "$match + $mlen c"
6825 $ctext tag add sel $match $mend
6826 $ctext mark unset anchor
Paul Mackerras3ea06f92006-05-24 10:16:03 +10006827 }
Paul Mackerras1902c272006-05-25 21:25:13 +10006828}
6829
6830proc dosearchback {} {
6831 global sstring ctext searchstring searchdirn
6832
6833 focus $sstring
6834 $sstring icursor end
6835 set searchdirn -backwards
6836 if {$searchstring ne {}} {
6837 set sel [$ctext tag ranges sel]
6838 if {$sel ne {}} {
6839 set start [lindex $sel 0]
6840 } elseif {[catch {set start [$ctext index anchor]}]} {
6841 set start @0,[winfo height $ctext]
6842 }
6843 set match [$ctext search -backwards -count ml -- $searchstring $start]
6844 $ctext tag remove sel 1.0 end
6845 if {$match eq {}} {
6846 bell
6847 return
6848 }
6849 $ctext see $match
6850 set mend "$match + $ml c"
6851 $ctext tag add sel $match $mend
6852 $ctext mark unset anchor
6853 }
Paul Mackerras3ea06f92006-05-24 10:16:03 +10006854}
6855
6856proc searchmark {first last} {
6857 global ctext searchstring
6858
6859 set mend $first.0
6860 while {1} {
6861 set match [$ctext search -count mlen -- $searchstring $mend $last.end]
6862 if {$match eq {}} break
6863 set mend "$match + $mlen c"
6864 $ctext tag add found $match $mend
6865 }
6866}
6867
6868proc searchmarkvisible {doall} {
6869 global ctext smarktop smarkbot
6870
6871 set topline [lindex [split [$ctext index @0,0] .] 0]
6872 set botline [lindex [split [$ctext index @0,[winfo height $ctext]] .] 0]
6873 if {$doall || $botline < $smarktop || $topline > $smarkbot} {
6874 # no overlap with previous
6875 searchmark $topline $botline
6876 set smarktop $topline
6877 set smarkbot $botline
6878 } else {
6879 if {$topline < $smarktop} {
6880 searchmark $topline [expr {$smarktop-1}]
6881 set smarktop $topline
6882 }
6883 if {$botline > $smarkbot} {
6884 searchmark [expr {$smarkbot+1}] $botline
6885 set smarkbot $botline
6886 }
6887 }
6888}
6889
6890proc scrolltext {f0 f1} {
Paul Mackerras1902c272006-05-25 21:25:13 +10006891 global searchstring
Paul Mackerras3ea06f92006-05-24 10:16:03 +10006892
Pekka Kaitaniemi8809d692008-03-08 14:27:23 +02006893 .bleft.bottom.sb set $f0 $f1
Paul Mackerras3ea06f92006-05-24 10:16:03 +10006894 if {$searchstring ne {}} {
6895 searchmarkvisible 0
6896 }
6897}
6898
Paul Mackerras1d10f362005-05-15 12:55:47 +00006899proc setcoords {} {
Paul Mackerras9c311b32007-10-04 22:27:13 +10006900 global linespc charspc canvx0 canvy0
Paul Mackerrasf6075eb2005-08-18 09:30:10 +10006901 global xspc1 xspc2 lthickness
Paul Mackerras8d858d12005-08-05 09:52:16 +10006902
Paul Mackerras9c311b32007-10-04 22:27:13 +10006903 set linespc [font metrics mainfont -linespace]
6904 set charspc [font measure mainfont "m"]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006905 set canvy0 [expr {int(3 + 0.5 * $linespc)}]
6906 set canvx0 [expr {int(3 + 0.5 * $linespc)}]
Paul Mackerrasf6075eb2005-08-18 09:30:10 +10006907 set lthickness [expr {int($linespc / 9) + 1}]
Paul Mackerras8d858d12005-08-05 09:52:16 +10006908 set xspc1(0) $linespc
6909 set xspc2 $linespc
Paul Mackerras9a40c502005-05-12 23:46:16 +00006910}
Paul Mackerras1db95b02005-05-09 04:08:39 +00006911
Paul Mackerras1d10f362005-05-15 12:55:47 +00006912proc redisplay {} {
Paul Mackerrasbe0cd092006-03-31 09:55:11 +11006913 global canv
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006914 global selectedline
6915
6916 set ymax [lindex [$canv cget -scrollregion] 3]
6917 if {$ymax eq {} || $ymax == 0} return
6918 set span [$canv yview]
6919 clear_display
Paul Mackerrasbe0cd092006-03-31 09:55:11 +11006920 setcanvscroll
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006921 allcanvs yview moveto [lindex $span 0]
6922 drawvisible
Paul Mackerras94b4a692008-05-20 20:51:06 +10006923 if {$selectedline ne {}} {
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006924 selectline $selectedline 0
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10006925 allcanvs yview moveto [lindex $span 0]
Paul Mackerras1db95b02005-05-09 04:08:39 +00006926 }
6927}
Paul Mackerras1d10f362005-05-15 12:55:47 +00006928
Paul Mackerras0ed1dd32007-10-06 18:27:37 +10006929proc parsefont {f n} {
6930 global fontattr
6931
6932 set fontattr($f,family) [lindex $n 0]
6933 set s [lindex $n 1]
6934 if {$s eq {} || $s == 0} {
6935 set s 10
6936 } elseif {$s < 0} {
6937 set s [expr {int(-$s / [winfo fpixels . 1p] + 0.5)}]
Paul Mackerras9c311b32007-10-04 22:27:13 +10006938 }
Paul Mackerras0ed1dd32007-10-06 18:27:37 +10006939 set fontattr($f,size) $s
6940 set fontattr($f,weight) normal
6941 set fontattr($f,slant) roman
6942 foreach style [lrange $n 2 end] {
6943 switch -- $style {
6944 "normal" -
6945 "bold" {set fontattr($f,weight) $style}
6946 "roman" -
6947 "italic" {set fontattr($f,slant) $style}
6948 }
Paul Mackerras9c311b32007-10-04 22:27:13 +10006949 }
Paul Mackerras0ed1dd32007-10-06 18:27:37 +10006950}
6951
6952proc fontflags {f {isbold 0}} {
6953 global fontattr
6954
6955 return [list -family $fontattr($f,family) -size $fontattr($f,size) \
6956 -weight [expr {$isbold? "bold": $fontattr($f,weight)}] \
6957 -slant $fontattr($f,slant)]
6958}
6959
6960proc fontname {f} {
6961 global fontattr
6962
6963 set n [list $fontattr($f,family) $fontattr($f,size)]
6964 if {$fontattr($f,weight) eq "bold"} {
6965 lappend n "bold"
Paul Mackerras9c311b32007-10-04 22:27:13 +10006966 }
Paul Mackerras0ed1dd32007-10-06 18:27:37 +10006967 if {$fontattr($f,slant) eq "italic"} {
6968 lappend n "italic"
Paul Mackerras9c311b32007-10-04 22:27:13 +10006969 }
Paul Mackerras0ed1dd32007-10-06 18:27:37 +10006970 return $n
Paul Mackerras9c311b32007-10-04 22:27:13 +10006971}
6972
Paul Mackerras1d10f362005-05-15 12:55:47 +00006973proc incrfont {inc} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11006974 global mainfont textfont ctext canv cflist showrefstop
Paul Mackerras0ed1dd32007-10-06 18:27:37 +10006975 global stopped entries fontattr
6976
Paul Mackerras1d10f362005-05-15 12:55:47 +00006977 unmarkmatches
Paul Mackerras0ed1dd32007-10-06 18:27:37 +10006978 set s $fontattr(mainfont,size)
Paul Mackerras9c311b32007-10-04 22:27:13 +10006979 incr s $inc
6980 if {$s < 1} {
6981 set s 1
6982 }
Paul Mackerras0ed1dd32007-10-06 18:27:37 +10006983 set fontattr(mainfont,size) $s
Paul Mackerras9c311b32007-10-04 22:27:13 +10006984 font config mainfont -size $s
6985 font config mainfontbold -size $s
Paul Mackerras0ed1dd32007-10-06 18:27:37 +10006986 set mainfont [fontname mainfont]
6987 set s $fontattr(textfont,size)
Paul Mackerras9c311b32007-10-04 22:27:13 +10006988 incr s $inc
6989 if {$s < 1} {
6990 set s 1
6991 }
Paul Mackerras0ed1dd32007-10-06 18:27:37 +10006992 set fontattr(textfont,size) $s
Paul Mackerras9c311b32007-10-04 22:27:13 +10006993 font config textfont -size $s
6994 font config textfontbold -size $s
Paul Mackerras0ed1dd32007-10-06 18:27:37 +10006995 set textfont [fontname textfont]
Paul Mackerras1d10f362005-05-15 12:55:47 +00006996 setcoords
Paul Mackerras32f1b3e2007-09-28 21:27:39 +10006997 settabs
Paul Mackerras1d10f362005-05-15 12:55:47 +00006998 redisplay
Paul Mackerras1db95b02005-05-09 04:08:39 +00006999}
Paul Mackerras1d10f362005-05-15 12:55:47 +00007000
Paul Mackerrasee3dc722005-06-25 16:37:13 +10007001proc clearsha1 {} {
7002 global sha1entry sha1string
7003 if {[string length $sha1string] == 40} {
7004 $sha1entry delete 0 end
7005 }
7006}
7007
Paul Mackerras887fe3c2005-05-21 07:35:37 +00007008proc sha1change {n1 n2 op} {
7009 global sha1string currentid sha1but
7010 if {$sha1string == {}
7011 || ([info exists currentid] && $sha1string == $currentid)} {
7012 set state disabled
7013 } else {
7014 set state normal
7015 }
7016 if {[$sha1but cget -state] == $state} return
7017 if {$state == "normal"} {
Christian Stimmingd990ced2007-11-07 18:42:55 +01007018 $sha1but conf -state normal -relief raised -text "[mc "Goto:"] "
Paul Mackerras887fe3c2005-05-21 07:35:37 +00007019 } else {
Christian Stimmingd990ced2007-11-07 18:42:55 +01007020 $sha1but conf -state disabled -relief flat -text "[mc "SHA1 ID:"] "
Paul Mackerras887fe3c2005-05-21 07:35:37 +00007021 }
7022}
7023
7024proc gotocommit {} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11007025 global sha1string tagids headids curview varcid
Paul Mackerrasf3b8b3c2005-07-18 12:16:35 -04007026
Paul Mackerras887fe3c2005-05-21 07:35:37 +00007027 if {$sha1string == {}
7028 || ([info exists currentid] && $sha1string == $currentid)} return
7029 if {[info exists tagids($sha1string)]} {
7030 set id $tagids($sha1string)
Stephen Rothwelle1007122006-03-30 16:13:12 +11007031 } elseif {[info exists headids($sha1string)]} {
7032 set id $headids($sha1string)
Paul Mackerras887fe3c2005-05-21 07:35:37 +00007033 } else {
7034 set id [string tolower $sha1string]
Paul Mackerrasf3b8b3c2005-07-18 12:16:35 -04007035 if {[regexp {^[0-9a-f]{4,39}$} $id]} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11007036 set matches [array names varcid "$curview,$id*"]
Paul Mackerrasf3b8b3c2005-07-18 12:16:35 -04007037 if {$matches ne {}} {
7038 if {[llength $matches] > 1} {
Christian Stimmingd990ced2007-11-07 18:42:55 +01007039 error_popup [mc "Short SHA1 id %s is ambiguous" $id]
Paul Mackerrasf3b8b3c2005-07-18 12:16:35 -04007040 return
7041 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11007042 set id [lindex [split [lindex $matches 0] ","] 1]
Paul Mackerrasf3b8b3c2005-07-18 12:16:35 -04007043 }
7044 }
Paul Mackerras887fe3c2005-05-21 07:35:37 +00007045 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11007046 if {[commitinview $id $curview]} {
7047 selectline [rowofcommit $id] 1
Paul Mackerras887fe3c2005-05-21 07:35:37 +00007048 return
7049 }
Paul Mackerrasf3b8b3c2005-07-18 12:16:35 -04007050 if {[regexp {^[0-9a-fA-F]{4,}$} $sha1string]} {
Christian Stimmingd990ced2007-11-07 18:42:55 +01007051 set msg [mc "SHA1 id %s is not known" $sha1string]
Paul Mackerras887fe3c2005-05-21 07:35:37 +00007052 } else {
Christian Stimmingd990ced2007-11-07 18:42:55 +01007053 set msg [mc "Tag/Head %s is not known" $sha1string]
Paul Mackerras887fe3c2005-05-21 07:35:37 +00007054 }
Christian Stimmingd990ced2007-11-07 18:42:55 +01007055 error_popup $msg
Paul Mackerras887fe3c2005-05-21 07:35:37 +00007056}
7057
Paul Mackerras84ba7342005-06-17 00:12:26 +00007058proc lineenter {x y id} {
7059 global hoverx hovery hoverid hovertimer
7060 global commitinfo canv
7061
Paul Mackerras8ed16482006-03-02 22:56:44 +11007062 if {![info exists commitinfo($id)] && ![getcommit $id]} return
Paul Mackerras84ba7342005-06-17 00:12:26 +00007063 set hoverx $x
7064 set hovery $y
7065 set hoverid $id
7066 if {[info exists hovertimer]} {
7067 after cancel $hovertimer
7068 }
7069 set hovertimer [after 500 linehover]
7070 $canv delete hover
7071}
7072
7073proc linemotion {x y id} {
7074 global hoverx hovery hoverid hovertimer
7075
7076 if {[info exists hoverid] && $id == $hoverid} {
7077 set hoverx $x
7078 set hovery $y
7079 if {[info exists hovertimer]} {
7080 after cancel $hovertimer
7081 }
7082 set hovertimer [after 500 linehover]
7083 }
7084}
7085
7086proc lineleave {id} {
7087 global hoverid hovertimer canv
7088
7089 if {[info exists hoverid] && $id == $hoverid} {
7090 $canv delete hover
7091 if {[info exists hovertimer]} {
7092 after cancel $hovertimer
7093 unset hovertimer
7094 }
7095 unset hoverid
7096 }
7097}
7098
7099proc linehover {} {
7100 global hoverx hovery hoverid hovertimer
7101 global canv linespc lthickness
Paul Mackerras9c311b32007-10-04 22:27:13 +10007102 global commitinfo
Paul Mackerras84ba7342005-06-17 00:12:26 +00007103
7104 set text [lindex $commitinfo($hoverid) 0]
7105 set ymax [lindex [$canv cget -scrollregion] 3]
7106 if {$ymax == {}} return
7107 set yfrac [lindex [$canv yview] 0]
7108 set x [expr {$hoverx + 2 * $linespc}]
7109 set y [expr {$hovery + $yfrac * $ymax - $linespc / 2}]
7110 set x0 [expr {$x - 2 * $lthickness}]
7111 set y0 [expr {$y - 2 * $lthickness}]
Paul Mackerras9c311b32007-10-04 22:27:13 +10007112 set x1 [expr {$x + [font measure mainfont $text] + 2 * $lthickness}]
Paul Mackerras84ba7342005-06-17 00:12:26 +00007113 set y1 [expr {$y + $linespc + 2 * $lthickness}]
7114 set t [$canv create rectangle $x0 $y0 $x1 $y1 \
7115 -fill \#ffff80 -outline black -width 1 -tags hover]
7116 $canv raise $t
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10007117 set t [$canv create text $x $y -anchor nw -text $text -tags hover \
Paul Mackerras9c311b32007-10-04 22:27:13 +10007118 -font mainfont]
Paul Mackerras84ba7342005-06-17 00:12:26 +00007119 $canv raise $t
7120}
7121
Paul Mackerras9843c302005-08-30 10:57:11 +10007122proc clickisonarrow {id y} {
Paul Mackerras50b44ec2006-04-04 10:16:22 +10007123 global lthickness
Paul Mackerras9843c302005-08-30 10:57:11 +10007124
Paul Mackerras50b44ec2006-04-04 10:16:22 +10007125 set ranges [rowranges $id]
Paul Mackerras9843c302005-08-30 10:57:11 +10007126 set thresh [expr {2 * $lthickness + 6}]
Paul Mackerras50b44ec2006-04-04 10:16:22 +10007127 set n [expr {[llength $ranges] - 1}]
Paul Mackerrasf6342482006-02-28 10:02:03 +11007128 for {set i 1} {$i < $n} {incr i} {
Paul Mackerras50b44ec2006-04-04 10:16:22 +10007129 set row [lindex $ranges $i]
Paul Mackerrasf6342482006-02-28 10:02:03 +11007130 if {abs([yc $row] - $y) < $thresh} {
7131 return $i
Paul Mackerras9843c302005-08-30 10:57:11 +10007132 }
7133 }
7134 return {}
7135}
7136
Paul Mackerrasf6342482006-02-28 10:02:03 +11007137proc arrowjump {id n y} {
Paul Mackerras50b44ec2006-04-04 10:16:22 +10007138 global canv
Paul Mackerras9843c302005-08-30 10:57:11 +10007139
Paul Mackerrasf6342482006-02-28 10:02:03 +11007140 # 1 <-> 2, 3 <-> 4, etc...
7141 set n [expr {(($n - 1) ^ 1) + 1}]
Paul Mackerras50b44ec2006-04-04 10:16:22 +10007142 set row [lindex [rowranges $id] $n]
Paul Mackerrasf6342482006-02-28 10:02:03 +11007143 set yt [yc $row]
Paul Mackerras9843c302005-08-30 10:57:11 +10007144 set ymax [lindex [$canv cget -scrollregion] 3]
7145 if {$ymax eq {} || $ymax <= 0} return
7146 set view [$canv yview]
7147 set yspan [expr {[lindex $view 1] - [lindex $view 0]}]
7148 set yfrac [expr {$yt / $ymax - $yspan / 2}]
7149 if {$yfrac < 0} {
7150 set yfrac 0
7151 }
Paul Mackerrasf6342482006-02-28 10:02:03 +11007152 allcanvs yview moveto $yfrac
Paul Mackerras9843c302005-08-30 10:57:11 +10007153}
7154
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10007155proc lineclick {x y id isnew} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11007156 global ctext commitinfo children canv thickerline curview
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10007157
Paul Mackerras8ed16482006-03-02 22:56:44 +11007158 if {![info exists commitinfo($id)] && ![getcommit $id]} return
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10007159 unmarkmatches
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10007160 unselectline
Paul Mackerras9843c302005-08-30 10:57:11 +10007161 normalline
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10007162 $canv delete hover
Paul Mackerras9843c302005-08-30 10:57:11 +10007163 # draw this line thicker than normal
Paul Mackerras9843c302005-08-30 10:57:11 +10007164 set thickerline $id
Paul Mackerrasc934a8a2006-03-02 23:00:44 +11007165 drawlines $id
Paul Mackerras9843c302005-08-30 10:57:11 +10007166 if {$isnew} {
7167 set ymax [lindex [$canv cget -scrollregion] 3]
7168 if {$ymax eq {}} return
7169 set yfrac [lindex [$canv yview] 0]
7170 set y [expr {$y + $yfrac * $ymax}]
7171 }
7172 set dirn [clickisonarrow $id $y]
7173 if {$dirn ne {}} {
7174 arrowjump $id $dirn $y
7175 return
7176 }
7177
7178 if {$isnew} {
7179 addtohistory [list lineclick $x $y $id 0]
7180 }
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10007181 # fill the details pane with info about this line
7182 $ctext conf -state normal
Paul Mackerras3ea06f92006-05-24 10:16:03 +10007183 clear_ctext
Paul Mackerras32f1b3e2007-09-28 21:27:39 +10007184 settabs 0
Christian Stimmingd990ced2007-11-07 18:42:55 +01007185 $ctext insert end "[mc "Parent"]:\t"
Paul Mackerras97645682007-08-23 22:24:38 +10007186 $ctext insert end $id link0
7187 setlink $id link0
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10007188 set info $commitinfo($id)
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10007189 $ctext insert end "\n\t[lindex $info 0]\n"
Christian Stimmingd990ced2007-11-07 18:42:55 +01007190 $ctext insert end "\t[mc "Author"]:\t[lindex $info 1]\n"
Paul Mackerras232475d2005-11-15 10:34:03 +11007191 set date [formatdate [lindex $info 2]]
Christian Stimmingd990ced2007-11-07 18:42:55 +01007192 $ctext insert end "\t[mc "Date"]:\t$date\n"
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10007193 set kids $children($curview,$id)
Paul Mackerras79b2c752006-04-02 20:47:40 +10007194 if {$kids ne {}} {
Christian Stimmingd990ced2007-11-07 18:42:55 +01007195 $ctext insert end "\n[mc "Children"]:"
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10007196 set i 0
Paul Mackerras79b2c752006-04-02 20:47:40 +10007197 foreach child $kids {
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10007198 incr i
Paul Mackerras8ed16482006-03-02 22:56:44 +11007199 if {![info exists commitinfo($child)] && ![getcommit $child]} continue
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10007200 set info $commitinfo($child)
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10007201 $ctext insert end "\n\t"
Paul Mackerras97645682007-08-23 22:24:38 +10007202 $ctext insert end $child link$i
7203 setlink $child link$i
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10007204 $ctext insert end "\n\t[lindex $info 0]"
Christian Stimmingd990ced2007-11-07 18:42:55 +01007205 $ctext insert end "\n\t[mc "Author"]:\t[lindex $info 1]"
Paul Mackerras232475d2005-11-15 10:34:03 +11007206 set date [formatdate [lindex $info 2]]
Christian Stimmingd990ced2007-11-07 18:42:55 +01007207 $ctext insert end "\n\t[mc "Date"]:\t$date\n"
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10007208 }
7209 }
7210 $ctext conf -state disabled
Paul Mackerras7fcceed2006-04-27 19:21:49 +10007211 init_flist {}
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10007212}
7213
Paul Mackerras9843c302005-08-30 10:57:11 +10007214proc normalline {} {
7215 global thickerline
7216 if {[info exists thickerline]} {
Paul Mackerrasc934a8a2006-03-02 23:00:44 +11007217 set id $thickerline
Paul Mackerras9843c302005-08-30 10:57:11 +10007218 unset thickerline
Paul Mackerrasc934a8a2006-03-02 23:00:44 +11007219 drawlines $id
Paul Mackerras9843c302005-08-30 10:57:11 +10007220 }
7221}
7222
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10007223proc selbyid {id} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11007224 global curview
7225 if {[commitinview $id $curview]} {
7226 selectline [rowofcommit $id] 1
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10007227 }
7228}
7229
7230proc mstime {} {
7231 global startmstime
7232 if {![info exists startmstime]} {
7233 set startmstime [clock clicks -milliseconds]
7234 }
7235 return [format "%.3f" [expr {([clock click -milliseconds] - $startmstime) / 1000.0}]]
7236}
7237
7238proc rowmenu {x y id} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11007239 global rowctxmenu selectedline rowmenuid curview
Paul Mackerras8f489362007-07-13 19:49:37 +10007240 global nullid nullid2 fakerowmenu mainhead
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10007241
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10007242 stopfinding
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007243 set rowmenuid $id
Paul Mackerras94b4a692008-05-20 20:51:06 +10007244 if {$selectedline eq {} || [rowofcommit $id] eq $selectedline} {
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10007245 set state disabled
7246 } else {
7247 set state normal
7248 }
Paul Mackerras8f489362007-07-13 19:49:37 +10007249 if {$id ne $nullid && $id ne $nullid2} {
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007250 set menu $rowctxmenu
Michele Ballabio5e3502d2008-05-02 17:46:20 +02007251 if {$mainhead ne {}} {
7252 $menu entryconfigure 7 -label [mc "Reset %s branch to here" $mainhead]
7253 } else {
7254 $menu entryconfigure 7 -label [mc "Detached head: can't reset" $mainhead] -state disabled
7255 }
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007256 } else {
7257 set menu $fakerowmenu
7258 }
Christian Stimmingd990ced2007-11-07 18:42:55 +01007259 $menu entryconfigure [mc "Diff this -> selected"] -state $state
7260 $menu entryconfigure [mc "Diff selected -> this"] -state $state
7261 $menu entryconfigure [mc "Make patch"] -state $state
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007262 tk_popup $menu $x $y
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10007263}
7264
7265proc diffvssel {dirn} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11007266 global rowmenuid selectedline
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10007267
Paul Mackerras94b4a692008-05-20 20:51:06 +10007268 if {$selectedline eq {}} return
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10007269 if {$dirn} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11007270 set oldid [commitonrow $selectedline]
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10007271 set newid $rowmenuid
7272 } else {
7273 set oldid $rowmenuid
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11007274 set newid [commitonrow $selectedline]
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10007275 }
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10007276 addtohistory [list doseldiff $oldid $newid]
7277 doseldiff $oldid $newid
7278}
7279
7280proc doseldiff {oldid newid} {
Paul Mackerras7fcceed2006-04-27 19:21:49 +10007281 global ctext
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10007282 global commitinfo
7283
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10007284 $ctext conf -state normal
Paul Mackerras3ea06f92006-05-24 10:16:03 +10007285 clear_ctext
Christian Stimmingd990ced2007-11-07 18:42:55 +01007286 init_flist [mc "Top"]
7287 $ctext insert end "[mc "From"] "
Paul Mackerras97645682007-08-23 22:24:38 +10007288 $ctext insert end $oldid link0
7289 setlink $oldid link0
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10007290 $ctext insert end "\n "
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10007291 $ctext insert end [lindex $commitinfo($oldid) 0]
Christian Stimmingd990ced2007-11-07 18:42:55 +01007292 $ctext insert end "\n\n[mc "To"] "
Paul Mackerras97645682007-08-23 22:24:38 +10007293 $ctext insert end $newid link1
7294 setlink $newid link1
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10007295 $ctext insert end "\n "
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10007296 $ctext insert end [lindex $commitinfo($newid) 0]
7297 $ctext insert end "\n"
7298 $ctext conf -state disabled
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10007299 $ctext tag remove found 1.0 end
Paul Mackerrasd3272442005-11-28 20:41:56 +11007300 startdiff [list $oldid $newid]
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10007301}
7302
Paul Mackerras74daedb2005-06-27 19:27:32 +10007303proc mkpatch {} {
7304 global rowmenuid currentid commitinfo patchtop patchnum
7305
7306 if {![info exists currentid]} return
7307 set oldid $currentid
7308 set oldhead [lindex $commitinfo($oldid) 0]
7309 set newid $rowmenuid
7310 set newhead [lindex $commitinfo($newid) 0]
7311 set top .patch
7312 set patchtop $top
7313 catch {destroy $top}
7314 toplevel $top
Christian Stimmingd990ced2007-11-07 18:42:55 +01007315 label $top.title -text [mc "Generate patch"]
Paul Mackerras4a2139f2005-06-29 09:47:48 +10007316 grid $top.title - -pady 10
Christian Stimmingd990ced2007-11-07 18:42:55 +01007317 label $top.from -text [mc "From:"]
Paul Mackerras4a2139f2005-06-29 09:47:48 +10007318 entry $top.fromsha1 -width 40 -relief flat
Paul Mackerras74daedb2005-06-27 19:27:32 +10007319 $top.fromsha1 insert 0 $oldid
7320 $top.fromsha1 conf -state readonly
7321 grid $top.from $top.fromsha1 -sticky w
Paul Mackerras4a2139f2005-06-29 09:47:48 +10007322 entry $top.fromhead -width 60 -relief flat
Paul Mackerras74daedb2005-06-27 19:27:32 +10007323 $top.fromhead insert 0 $oldhead
7324 $top.fromhead conf -state readonly
7325 grid x $top.fromhead -sticky w
Christian Stimmingd990ced2007-11-07 18:42:55 +01007326 label $top.to -text [mc "To:"]
Paul Mackerras4a2139f2005-06-29 09:47:48 +10007327 entry $top.tosha1 -width 40 -relief flat
Paul Mackerras74daedb2005-06-27 19:27:32 +10007328 $top.tosha1 insert 0 $newid
7329 $top.tosha1 conf -state readonly
7330 grid $top.to $top.tosha1 -sticky w
Paul Mackerras4a2139f2005-06-29 09:47:48 +10007331 entry $top.tohead -width 60 -relief flat
Paul Mackerras74daedb2005-06-27 19:27:32 +10007332 $top.tohead insert 0 $newhead
7333 $top.tohead conf -state readonly
7334 grid x $top.tohead -sticky w
Christian Stimmingd990ced2007-11-07 18:42:55 +01007335 button $top.rev -text [mc "Reverse"] -command mkpatchrev -padx 5
Paul Mackerras74daedb2005-06-27 19:27:32 +10007336 grid $top.rev x -pady 10
Christian Stimmingd990ced2007-11-07 18:42:55 +01007337 label $top.flab -text [mc "Output file:"]
Paul Mackerras74daedb2005-06-27 19:27:32 +10007338 entry $top.fname -width 60
7339 $top.fname insert 0 [file normalize "patch$patchnum.patch"]
7340 incr patchnum
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10007341 grid $top.flab $top.fname -sticky w
Paul Mackerras74daedb2005-06-27 19:27:32 +10007342 frame $top.buts
Christian Stimmingd990ced2007-11-07 18:42:55 +01007343 button $top.buts.gen -text [mc "Generate"] -command mkpatchgo
7344 button $top.buts.can -text [mc "Cancel"] -command mkpatchcan
Paul Mackerras74daedb2005-06-27 19:27:32 +10007345 grid $top.buts.gen $top.buts.can
7346 grid columnconfigure $top.buts 0 -weight 1 -uniform a
7347 grid columnconfigure $top.buts 1 -weight 1 -uniform a
7348 grid $top.buts - -pady 10 -sticky ew
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10007349 focus $top.fname
Paul Mackerras74daedb2005-06-27 19:27:32 +10007350}
7351
7352proc mkpatchrev {} {
7353 global patchtop
7354
7355 set oldid [$patchtop.fromsha1 get]
7356 set oldhead [$patchtop.fromhead get]
7357 set newid [$patchtop.tosha1 get]
7358 set newhead [$patchtop.tohead get]
7359 foreach e [list fromsha1 fromhead tosha1 tohead] \
7360 v [list $newid $newhead $oldid $oldhead] {
7361 $patchtop.$e conf -state normal
7362 $patchtop.$e delete 0 end
7363 $patchtop.$e insert 0 $v
7364 $patchtop.$e conf -state readonly
7365 }
7366}
7367
7368proc mkpatchgo {} {
Paul Mackerras8f489362007-07-13 19:49:37 +10007369 global patchtop nullid nullid2
Paul Mackerras74daedb2005-06-27 19:27:32 +10007370
7371 set oldid [$patchtop.fromsha1 get]
7372 set newid [$patchtop.tosha1 get]
7373 set fname [$patchtop.fname get]
Paul Mackerras8f489362007-07-13 19:49:37 +10007374 set cmd [diffcmd [list $oldid $newid] -p]
Paul Mackerrasd372e212007-09-15 12:08:38 +10007375 # trim off the initial "|"
7376 set cmd [lrange $cmd 1 end]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007377 lappend cmd >$fname &
7378 if {[catch {eval exec $cmd} err]} {
Christian Stimmingd990ced2007-11-07 18:42:55 +01007379 error_popup "[mc "Error creating patch:"] $err"
Paul Mackerras74daedb2005-06-27 19:27:32 +10007380 }
7381 catch {destroy $patchtop}
7382 unset patchtop
7383}
7384
7385proc mkpatchcan {} {
7386 global patchtop
7387
7388 catch {destroy $patchtop}
7389 unset patchtop
7390}
7391
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10007392proc mktag {} {
7393 global rowmenuid mktagtop commitinfo
7394
7395 set top .maketag
7396 set mktagtop $top
7397 catch {destroy $top}
7398 toplevel $top
Christian Stimmingd990ced2007-11-07 18:42:55 +01007399 label $top.title -text [mc "Create tag"]
Paul Mackerras4a2139f2005-06-29 09:47:48 +10007400 grid $top.title - -pady 10
Christian Stimmingd990ced2007-11-07 18:42:55 +01007401 label $top.id -text [mc "ID:"]
Paul Mackerras4a2139f2005-06-29 09:47:48 +10007402 entry $top.sha1 -width 40 -relief flat
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10007403 $top.sha1 insert 0 $rowmenuid
7404 $top.sha1 conf -state readonly
7405 grid $top.id $top.sha1 -sticky w
Paul Mackerras4a2139f2005-06-29 09:47:48 +10007406 entry $top.head -width 60 -relief flat
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10007407 $top.head insert 0 [lindex $commitinfo($rowmenuid) 0]
7408 $top.head conf -state readonly
7409 grid x $top.head -sticky w
Christian Stimmingd990ced2007-11-07 18:42:55 +01007410 label $top.tlab -text [mc "Tag name:"]
Paul Mackerras4a2139f2005-06-29 09:47:48 +10007411 entry $top.tag -width 60
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10007412 grid $top.tlab $top.tag -sticky w
7413 frame $top.buts
Christian Stimmingd990ced2007-11-07 18:42:55 +01007414 button $top.buts.gen -text [mc "Create"] -command mktaggo
7415 button $top.buts.can -text [mc "Cancel"] -command mktagcan
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10007416 grid $top.buts.gen $top.buts.can
7417 grid columnconfigure $top.buts 0 -weight 1 -uniform a
7418 grid columnconfigure $top.buts 1 -weight 1 -uniform a
7419 grid $top.buts - -pady 10 -sticky ew
7420 focus $top.tag
7421}
7422
7423proc domktag {} {
7424 global mktagtop env tagids idtags
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10007425
7426 set id [$mktagtop.sha1 get]
7427 set tag [$mktagtop.tag get]
7428 if {$tag == {}} {
Christian Stimmingd990ced2007-11-07 18:42:55 +01007429 error_popup [mc "No tag name specified"]
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10007430 return
7431 }
7432 if {[info exists tagids($tag)]} {
Christian Stimmingd990ced2007-11-07 18:42:55 +01007433 error_popup [mc "Tag \"%s\" already exists" $tag]
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10007434 return
7435 }
7436 if {[catch {
Gerrit Pape48750d62008-02-11 10:57:40 +00007437 exec git tag $tag $id
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10007438 } err]} {
Christian Stimmingd990ced2007-11-07 18:42:55 +01007439 error_popup "[mc "Error creating tag:"] $err"
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10007440 return
7441 }
7442
7443 set tagids($tag) $id
7444 lappend idtags($id) $tag
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10007445 redrawtags $id
Paul Mackerrasceadfe92006-08-08 20:55:36 +10007446 addedtag $id
Paul Mackerras887c9962007-08-20 19:36:20 +10007447 dispneartags 0
7448 run refill_reflist
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10007449}
7450
7451proc redrawtags {id} {
Paul Mackerrasc11ff122008-05-26 10:11:33 +10007452 global canv linehtag idpos currentid curview cmitlisted
7453 global canvxmax iddrawn circleitem mainheadid circlecolors
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10007454
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11007455 if {![commitinview $id $curview]} return
Paul Mackerras322a8cc2006-10-15 18:03:46 +10007456 if {![info exists iddrawn($id)]} return
Paul Mackerrasfc2a2562007-12-26 23:03:43 +11007457 set row [rowofcommit $id]
Paul Mackerrasc11ff122008-05-26 10:11:33 +10007458 if {$id eq $mainheadid} {
7459 set ofill yellow
7460 } else {
7461 set ofill [lindex $circlecolors $cmitlisted($curview,$id)]
7462 }
7463 $canv itemconf $circleitem($row) -fill $ofill
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10007464 $canv delete tag.$id
7465 set xt [eval drawtags $id $idpos($id)]
Paul Mackerrasfc2a2562007-12-26 23:03:43 +11007466 $canv coords $linehtag($row) $xt [lindex $idpos($id) 2]
7467 set text [$canv itemcget $linehtag($row) -text]
7468 set font [$canv itemcget $linehtag($row) -font]
7469 set xr [expr {$xt + [font measure $font $text]}]
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10007470 if {$xr > $canvxmax} {
7471 set canvxmax $xr
7472 setcanvscroll
7473 }
Paul Mackerrasfc2a2562007-12-26 23:03:43 +11007474 if {[info exists currentid] && $currentid == $id} {
7475 make_secsel $row
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10007476 }
7477}
7478
7479proc mktagcan {} {
7480 global mktagtop
7481
7482 catch {destroy $mktagtop}
7483 unset mktagtop
7484}
7485
7486proc mktaggo {} {
7487 domktag
7488 mktagcan
7489}
7490
Paul Mackerras4a2139f2005-06-29 09:47:48 +10007491proc writecommit {} {
7492 global rowmenuid wrcomtop commitinfo wrcomcmd
7493
7494 set top .writecommit
7495 set wrcomtop $top
7496 catch {destroy $top}
7497 toplevel $top
Christian Stimmingd990ced2007-11-07 18:42:55 +01007498 label $top.title -text [mc "Write commit to file"]
Paul Mackerras4a2139f2005-06-29 09:47:48 +10007499 grid $top.title - -pady 10
Christian Stimmingd990ced2007-11-07 18:42:55 +01007500 label $top.id -text [mc "ID:"]
Paul Mackerras4a2139f2005-06-29 09:47:48 +10007501 entry $top.sha1 -width 40 -relief flat
7502 $top.sha1 insert 0 $rowmenuid
7503 $top.sha1 conf -state readonly
7504 grid $top.id $top.sha1 -sticky w
7505 entry $top.head -width 60 -relief flat
7506 $top.head insert 0 [lindex $commitinfo($rowmenuid) 0]
7507 $top.head conf -state readonly
7508 grid x $top.head -sticky w
Christian Stimmingd990ced2007-11-07 18:42:55 +01007509 label $top.clab -text [mc "Command:"]
Paul Mackerras4a2139f2005-06-29 09:47:48 +10007510 entry $top.cmd -width 60 -textvariable wrcomcmd
7511 grid $top.clab $top.cmd -sticky w -pady 10
Christian Stimmingd990ced2007-11-07 18:42:55 +01007512 label $top.flab -text [mc "Output file:"]
Paul Mackerras4a2139f2005-06-29 09:47:48 +10007513 entry $top.fname -width 60
7514 $top.fname insert 0 [file normalize "commit-[string range $rowmenuid 0 6]"]
7515 grid $top.flab $top.fname -sticky w
7516 frame $top.buts
Christian Stimmingd990ced2007-11-07 18:42:55 +01007517 button $top.buts.gen -text [mc "Write"] -command wrcomgo
7518 button $top.buts.can -text [mc "Cancel"] -command wrcomcan
Paul Mackerras4a2139f2005-06-29 09:47:48 +10007519 grid $top.buts.gen $top.buts.can
7520 grid columnconfigure $top.buts 0 -weight 1 -uniform a
7521 grid columnconfigure $top.buts 1 -weight 1 -uniform a
7522 grid $top.buts - -pady 10 -sticky ew
7523 focus $top.fname
7524}
7525
7526proc wrcomgo {} {
7527 global wrcomtop
7528
7529 set id [$wrcomtop.sha1 get]
7530 set cmd "echo $id | [$wrcomtop.cmd get]"
7531 set fname [$wrcomtop.fname get]
7532 if {[catch {exec sh -c $cmd >$fname &} err]} {
Christian Stimmingd990ced2007-11-07 18:42:55 +01007533 error_popup "[mc "Error writing commit:"] $err"
Paul Mackerras4a2139f2005-06-29 09:47:48 +10007534 }
7535 catch {destroy $wrcomtop}
7536 unset wrcomtop
7537}
7538
7539proc wrcomcan {} {
7540 global wrcomtop
7541
7542 catch {destroy $wrcomtop}
7543 unset wrcomtop
7544}
7545
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10007546proc mkbranch {} {
7547 global rowmenuid mkbrtop
7548
7549 set top .makebranch
7550 catch {destroy $top}
7551 toplevel $top
Christian Stimmingd990ced2007-11-07 18:42:55 +01007552 label $top.title -text [mc "Create new branch"]
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10007553 grid $top.title - -pady 10
Christian Stimmingd990ced2007-11-07 18:42:55 +01007554 label $top.id -text [mc "ID:"]
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10007555 entry $top.sha1 -width 40 -relief flat
7556 $top.sha1 insert 0 $rowmenuid
7557 $top.sha1 conf -state readonly
7558 grid $top.id $top.sha1 -sticky w
Christian Stimmingd990ced2007-11-07 18:42:55 +01007559 label $top.nlab -text [mc "Name:"]
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10007560 entry $top.name -width 40
7561 grid $top.nlab $top.name -sticky w
7562 frame $top.buts
Christian Stimmingd990ced2007-11-07 18:42:55 +01007563 button $top.buts.go -text [mc "Create"] -command [list mkbrgo $top]
7564 button $top.buts.can -text [mc "Cancel"] -command "catch {destroy $top}"
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10007565 grid $top.buts.go $top.buts.can
7566 grid columnconfigure $top.buts 0 -weight 1 -uniform a
7567 grid columnconfigure $top.buts 1 -weight 1 -uniform a
7568 grid $top.buts - -pady 10 -sticky ew
7569 focus $top.name
7570}
7571
7572proc mkbrgo {top} {
7573 global headids idheads
7574
7575 set name [$top.name get]
7576 set id [$top.sha1 get]
7577 if {$name eq {}} {
Christian Stimmingd990ced2007-11-07 18:42:55 +01007578 error_popup [mc "Please specify a name for the new branch"]
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10007579 return
7580 }
7581 catch {destroy $top}
7582 nowbusy newbranch
7583 update
7584 if {[catch {
7585 exec git branch $name $id
7586 } err]} {
7587 notbusy newbranch
7588 error_popup $err
7589 } else {
Paul Mackerrase11f1232007-06-16 20:29:25 +10007590 set headids($name) $id
7591 lappend idheads($id) $name
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10007592 addedhead $id $name
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10007593 notbusy newbranch
7594 redrawtags $id
Paul Mackerrase11f1232007-06-16 20:29:25 +10007595 dispneartags 0
Paul Mackerras887c9962007-08-20 19:36:20 +10007596 run refill_reflist
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10007597 }
7598}
7599
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10007600proc cherrypick {} {
Paul Mackerras468bcae2008-03-03 10:19:35 +11007601 global rowmenuid curview
Paul Mackerrasb8a938c2008-02-13 22:12:31 +11007602 global mainhead mainheadid
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10007603
Paul Mackerrase11f1232007-06-16 20:29:25 +10007604 set oldhead [exec git rev-parse HEAD]
7605 set dheads [descheads $rowmenuid]
7606 if {$dheads ne {} && [lsearch -exact $dheads $oldhead] >= 0} {
Christian Stimmingd990ced2007-11-07 18:42:55 +01007607 set ok [confirm_popup [mc "Commit %s is already\
7608 included in branch %s -- really re-apply it?" \
7609 [string range $rowmenuid 0 7] $mainhead]]
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10007610 if {!$ok} return
7611 }
Christian Stimmingd990ced2007-11-07 18:42:55 +01007612 nowbusy cherrypick [mc "Cherry-picking"]
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10007613 update
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10007614 # Unfortunately git-cherry-pick writes stuff to stderr even when
7615 # no error occurs, and exec takes that as an indication of error...
7616 if {[catch {exec sh -c "git cherry-pick -r $rowmenuid 2>&1"} err]} {
7617 notbusy cherrypick
7618 error_popup $err
7619 return
7620 }
7621 set newhead [exec git rev-parse HEAD]
7622 if {$newhead eq $oldhead} {
7623 notbusy cherrypick
Christian Stimmingd990ced2007-11-07 18:42:55 +01007624 error_popup [mc "No changes committed"]
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10007625 return
7626 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10007627 addnewchild $newhead $oldhead
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11007628 if {[commitinview $oldhead $curview]} {
7629 insertrow $newhead $oldhead $curview
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10007630 if {$mainhead ne {}} {
Paul Mackerrase11f1232007-06-16 20:29:25 +10007631 movehead $newhead $mainhead
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10007632 movedhead $newhead $mainhead
7633 }
Paul Mackerrasc11ff122008-05-26 10:11:33 +10007634 set mainheadid $newhead
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10007635 redrawtags $oldhead
7636 redrawtags $newhead
Paul Mackerras46308ea2008-01-15 22:16:32 +11007637 selbyid $newhead
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10007638 }
7639 notbusy cherrypick
7640}
7641
Paul Mackerras6fb735a2006-10-19 10:09:06 +10007642proc resethead {} {
Paul Mackerrasb8a938c2008-02-13 22:12:31 +11007643 global mainhead rowmenuid confirm_ok resettype
Paul Mackerras6fb735a2006-10-19 10:09:06 +10007644
7645 set confirm_ok 0
7646 set w ".confirmreset"
7647 toplevel $w
7648 wm transient $w .
Christian Stimmingd990ced2007-11-07 18:42:55 +01007649 wm title $w [mc "Confirm reset"]
Paul Mackerras6fb735a2006-10-19 10:09:06 +10007650 message $w.m -text \
Christian Stimmingd990ced2007-11-07 18:42:55 +01007651 [mc "Reset branch %s to %s?" $mainhead [string range $rowmenuid 0 7]] \
Paul Mackerras6fb735a2006-10-19 10:09:06 +10007652 -justify center -aspect 1000
7653 pack $w.m -side top -fill x -padx 20 -pady 20
7654 frame $w.f -relief sunken -border 2
Christian Stimmingd990ced2007-11-07 18:42:55 +01007655 message $w.f.rt -text [mc "Reset type:"] -aspect 1000
Paul Mackerras6fb735a2006-10-19 10:09:06 +10007656 grid $w.f.rt -sticky w
7657 set resettype mixed
7658 radiobutton $w.f.soft -value soft -variable resettype -justify left \
Christian Stimmingd990ced2007-11-07 18:42:55 +01007659 -text [mc "Soft: Leave working tree and index untouched"]
Paul Mackerras6fb735a2006-10-19 10:09:06 +10007660 grid $w.f.soft -sticky w
7661 radiobutton $w.f.mixed -value mixed -variable resettype -justify left \
Christian Stimmingd990ced2007-11-07 18:42:55 +01007662 -text [mc "Mixed: Leave working tree untouched, reset index"]
Paul Mackerras6fb735a2006-10-19 10:09:06 +10007663 grid $w.f.mixed -sticky w
7664 radiobutton $w.f.hard -value hard -variable resettype -justify left \
Christian Stimmingd990ced2007-11-07 18:42:55 +01007665 -text [mc "Hard: Reset working tree and index\n(discard ALL local changes)"]
Paul Mackerras6fb735a2006-10-19 10:09:06 +10007666 grid $w.f.hard -sticky w
7667 pack $w.f -side top -fill x
Christian Stimmingd990ced2007-11-07 18:42:55 +01007668 button $w.ok -text [mc OK] -command "set confirm_ok 1; destroy $w"
Paul Mackerras6fb735a2006-10-19 10:09:06 +10007669 pack $w.ok -side left -fill x -padx 20 -pady 20
Christian Stimmingd990ced2007-11-07 18:42:55 +01007670 button $w.cancel -text [mc Cancel] -command "destroy $w"
Paul Mackerras6fb735a2006-10-19 10:09:06 +10007671 pack $w.cancel -side right -fill x -padx 20 -pady 20
7672 bind $w <Visibility> "grab $w; focus $w"
7673 tkwait window $w
7674 if {!$confirm_ok} return
Paul Mackerras706d6c32007-06-26 11:09:49 +10007675 if {[catch {set fd [open \
Paul Mackerras08ba8202008-05-12 10:18:38 +10007676 [list | git reset --$resettype $rowmenuid 2>@1] r]} err]} {
Paul Mackerras6fb735a2006-10-19 10:09:06 +10007677 error_popup $err
7678 } else {
Paul Mackerras706d6c32007-06-26 11:09:49 +10007679 dohidelocalchanges
Paul Mackerrasa137a902007-10-23 21:12:49 +10007680 filerun $fd [list readresetstat $fd]
Christian Stimmingd990ced2007-11-07 18:42:55 +01007681 nowbusy reset [mc "Resetting"]
Paul Mackerras46308ea2008-01-15 22:16:32 +11007682 selbyid $rowmenuid
Paul Mackerras706d6c32007-06-26 11:09:49 +10007683 }
7684}
7685
Paul Mackerrasa137a902007-10-23 21:12:49 +10007686proc readresetstat {fd} {
7687 global mainhead mainheadid showlocalchanges rprogcoord
Paul Mackerras706d6c32007-06-26 11:09:49 +10007688
7689 if {[gets $fd line] >= 0} {
7690 if {[regexp {([0-9]+)% \(([0-9]+)/([0-9]+)\)} $line match p m n]} {
Paul Mackerrasa137a902007-10-23 21:12:49 +10007691 set rprogcoord [expr {1.0 * $m / $n}]
7692 adjustprogress
Paul Mackerras706d6c32007-06-26 11:09:49 +10007693 }
7694 return 1
7695 }
Paul Mackerrasa137a902007-10-23 21:12:49 +10007696 set rprogcoord 0
7697 adjustprogress
Paul Mackerras706d6c32007-06-26 11:09:49 +10007698 notbusy reset
7699 if {[catch {close $fd} err]} {
7700 error_popup $err
7701 }
7702 set oldhead $mainheadid
7703 set newhead [exec git rev-parse HEAD]
7704 if {$newhead ne $oldhead} {
7705 movehead $newhead $mainhead
7706 movedhead $newhead $mainhead
7707 set mainheadid $newhead
Paul Mackerras6fb735a2006-10-19 10:09:06 +10007708 redrawtags $oldhead
Paul Mackerras706d6c32007-06-26 11:09:49 +10007709 redrawtags $newhead
Paul Mackerras6fb735a2006-10-19 10:09:06 +10007710 }
7711 if {$showlocalchanges} {
7712 doshowlocalchanges
7713 }
Paul Mackerras706d6c32007-06-26 11:09:49 +10007714 return 0
Paul Mackerras6fb735a2006-10-19 10:09:06 +10007715}
7716
Paul Mackerras10299152006-08-02 09:52:01 +10007717# context menu for a head
7718proc headmenu {x y id head} {
Paul Mackerras00609462007-06-17 17:08:35 +10007719 global headmenuid headmenuhead headctxmenu mainhead
Paul Mackerras10299152006-08-02 09:52:01 +10007720
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10007721 stopfinding
Paul Mackerras10299152006-08-02 09:52:01 +10007722 set headmenuid $id
7723 set headmenuhead $head
Paul Mackerras00609462007-06-17 17:08:35 +10007724 set state normal
7725 if {$head eq $mainhead} {
7726 set state disabled
7727 }
7728 $headctxmenu entryconfigure 0 -state $state
7729 $headctxmenu entryconfigure 1 -state $state
Paul Mackerras10299152006-08-02 09:52:01 +10007730 tk_popup $headctxmenu $x $y
7731}
7732
7733proc cobranch {} {
Paul Mackerrasc11ff122008-05-26 10:11:33 +10007734 global headmenuid headmenuhead headids
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007735 global showlocalchanges mainheadid
Paul Mackerras10299152006-08-02 09:52:01 +10007736
7737 # check the tree is clean first??
Christian Stimmingd990ced2007-11-07 18:42:55 +01007738 nowbusy checkout [mc "Checking out"]
Paul Mackerras10299152006-08-02 09:52:01 +10007739 update
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007740 dohidelocalchanges
Paul Mackerras10299152006-08-02 09:52:01 +10007741 if {[catch {
Paul Mackerras08ba8202008-05-12 10:18:38 +10007742 set fd [open [list | git checkout $headmenuhead 2>@1] r]
Paul Mackerras10299152006-08-02 09:52:01 +10007743 } err]} {
7744 notbusy checkout
7745 error_popup $err
Paul Mackerras08ba8202008-05-12 10:18:38 +10007746 if {$showlocalchanges} {
7747 dodiffindex
Paul Mackerras10299152006-08-02 09:52:01 +10007748 }
Paul Mackerras08ba8202008-05-12 10:18:38 +10007749 } else {
7750 filerun $fd [list readcheckoutstat $fd $headmenuhead $headmenuid]
Paul Mackerras6fb735a2006-10-19 10:09:06 +10007751 }
Paul Mackerras08ba8202008-05-12 10:18:38 +10007752}
7753
7754proc readcheckoutstat {fd newhead newheadid} {
7755 global mainhead mainheadid headids showlocalchanges progresscoords
7756
7757 if {[gets $fd line] >= 0} {
7758 if {[regexp {([0-9]+)% \(([0-9]+)/([0-9]+)\)} $line match p m n]} {
7759 set progresscoords [list 0 [expr {1.0 * $m / $n}]]
7760 adjustprogress
7761 }
7762 return 1
7763 }
7764 set progresscoords {0 0}
7765 adjustprogress
7766 notbusy checkout
7767 if {[catch {close $fd} err]} {
7768 error_popup $err
7769 }
Paul Mackerrasc11ff122008-05-26 10:11:33 +10007770 set oldmainid $mainheadid
Paul Mackerras08ba8202008-05-12 10:18:38 +10007771 set mainhead $newhead
7772 set mainheadid $newheadid
Paul Mackerrasc11ff122008-05-26 10:11:33 +10007773 redrawtags $oldmainid
Paul Mackerras08ba8202008-05-12 10:18:38 +10007774 redrawtags $newheadid
7775 selbyid $newheadid
Paul Mackerras6fb735a2006-10-19 10:09:06 +10007776 if {$showlocalchanges} {
7777 dodiffindex
Paul Mackerras10299152006-08-02 09:52:01 +10007778 }
7779}
7780
7781proc rmbranch {} {
Paul Mackerrase11f1232007-06-16 20:29:25 +10007782 global headmenuid headmenuhead mainhead
Paul Mackerrasb1054ac2007-08-15 10:09:47 +10007783 global idheads
Paul Mackerras10299152006-08-02 09:52:01 +10007784
7785 set head $headmenuhead
7786 set id $headmenuid
Paul Mackerras00609462007-06-17 17:08:35 +10007787 # this check shouldn't be needed any more...
Paul Mackerras10299152006-08-02 09:52:01 +10007788 if {$head eq $mainhead} {
Christian Stimmingd990ced2007-11-07 18:42:55 +01007789 error_popup [mc "Cannot delete the currently checked-out branch"]
Paul Mackerras10299152006-08-02 09:52:01 +10007790 return
7791 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10007792 set dheads [descheads $id]
Paul Mackerrasd7b16112007-08-17 17:57:31 +10007793 if {[llength $dheads] == 1 && $idheads($dheads) eq $head} {
Paul Mackerras10299152006-08-02 09:52:01 +10007794 # the stuff on this branch isn't on any other branch
Christian Stimmingd990ced2007-11-07 18:42:55 +01007795 if {![confirm_popup [mc "The commits on branch %s aren't on any other\
7796 branch.\nReally delete branch %s?" $head $head]]} return
Paul Mackerras10299152006-08-02 09:52:01 +10007797 }
7798 nowbusy rmbranch
7799 update
7800 if {[catch {exec git branch -D $head} err]} {
7801 notbusy rmbranch
7802 error_popup $err
7803 return
7804 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10007805 removehead $id $head
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10007806 removedhead $id $head
Paul Mackerras10299152006-08-02 09:52:01 +10007807 redrawtags $id
7808 notbusy rmbranch
Paul Mackerrase11f1232007-06-16 20:29:25 +10007809 dispneartags 0
Paul Mackerras887c9962007-08-20 19:36:20 +10007810 run refill_reflist
7811}
7812
7813# Display a list of tags and heads
7814proc showrefs {} {
Paul Mackerras9c311b32007-10-04 22:27:13 +10007815 global showrefstop bgcolor fgcolor selectbgcolor
7816 global bglist fglist reflistfilter reflist maincursor
Paul Mackerras887c9962007-08-20 19:36:20 +10007817
7818 set top .showrefs
7819 set showrefstop $top
7820 if {[winfo exists $top]} {
7821 raise $top
7822 refill_reflist
7823 return
7824 }
7825 toplevel $top
Christian Stimmingd990ced2007-11-07 18:42:55 +01007826 wm title $top [mc "Tags and heads: %s" [file tail [pwd]]]
Paul Mackerras887c9962007-08-20 19:36:20 +10007827 text $top.list -background $bgcolor -foreground $fgcolor \
Paul Mackerras9c311b32007-10-04 22:27:13 +10007828 -selectbackground $selectbgcolor -font mainfont \
Paul Mackerras887c9962007-08-20 19:36:20 +10007829 -xscrollcommand "$top.xsb set" -yscrollcommand "$top.ysb set" \
7830 -width 30 -height 20 -cursor $maincursor \
7831 -spacing1 1 -spacing3 1 -state disabled
7832 $top.list tag configure highlight -background $selectbgcolor
7833 lappend bglist $top.list
7834 lappend fglist $top.list
7835 scrollbar $top.ysb -command "$top.list yview" -orient vertical
7836 scrollbar $top.xsb -command "$top.list xview" -orient horizontal
7837 grid $top.list $top.ysb -sticky nsew
7838 grid $top.xsb x -sticky ew
7839 frame $top.f
Paul Mackerrasb039f0a2008-01-06 15:54:46 +11007840 label $top.f.l -text "[mc "Filter"]: "
7841 entry $top.f.e -width 20 -textvariable reflistfilter
Paul Mackerras887c9962007-08-20 19:36:20 +10007842 set reflistfilter "*"
7843 trace add variable reflistfilter write reflistfilter_change
7844 pack $top.f.e -side right -fill x -expand 1
7845 pack $top.f.l -side left
7846 grid $top.f - -sticky ew -pady 2
Paul Mackerrasb039f0a2008-01-06 15:54:46 +11007847 button $top.close -command [list destroy $top] -text [mc "Close"]
Paul Mackerras887c9962007-08-20 19:36:20 +10007848 grid $top.close -
7849 grid columnconfigure $top 0 -weight 1
7850 grid rowconfigure $top 0 -weight 1
7851 bind $top.list <1> {break}
7852 bind $top.list <B1-Motion> {break}
7853 bind $top.list <ButtonRelease-1> {sel_reflist %W %x %y; break}
7854 set reflist {}
7855 refill_reflist
7856}
7857
7858proc sel_reflist {w x y} {
7859 global showrefstop reflist headids tagids otherrefids
7860
7861 if {![winfo exists $showrefstop]} return
7862 set l [lindex [split [$w index "@$x,$y"] "."] 0]
7863 set ref [lindex $reflist [expr {$l-1}]]
7864 set n [lindex $ref 0]
7865 switch -- [lindex $ref 1] {
7866 "H" {selbyid $headids($n)}
7867 "T" {selbyid $tagids($n)}
7868 "o" {selbyid $otherrefids($n)}
7869 }
7870 $showrefstop.list tag add highlight $l.0 "$l.0 lineend"
7871}
7872
7873proc unsel_reflist {} {
7874 global showrefstop
7875
7876 if {![info exists showrefstop] || ![winfo exists $showrefstop]} return
7877 $showrefstop.list tag remove highlight 0.0 end
7878}
7879
7880proc reflistfilter_change {n1 n2 op} {
7881 global reflistfilter
7882
7883 after cancel refill_reflist
7884 after 200 refill_reflist
7885}
7886
7887proc refill_reflist {} {
7888 global reflist reflistfilter showrefstop headids tagids otherrefids
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11007889 global curview commitinterest
Paul Mackerras887c9962007-08-20 19:36:20 +10007890
7891 if {![info exists showrefstop] || ![winfo exists $showrefstop]} return
7892 set refs {}
7893 foreach n [array names headids] {
7894 if {[string match $reflistfilter $n]} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11007895 if {[commitinview $headids($n) $curview]} {
Paul Mackerras887c9962007-08-20 19:36:20 +10007896 lappend refs [list $n H]
7897 } else {
7898 set commitinterest($headids($n)) {run refill_reflist}
7899 }
7900 }
7901 }
7902 foreach n [array names tagids] {
7903 if {[string match $reflistfilter $n]} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11007904 if {[commitinview $tagids($n) $curview]} {
Paul Mackerras887c9962007-08-20 19:36:20 +10007905 lappend refs [list $n T]
7906 } else {
7907 set commitinterest($tagids($n)) {run refill_reflist}
7908 }
7909 }
7910 }
7911 foreach n [array names otherrefids] {
7912 if {[string match $reflistfilter $n]} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11007913 if {[commitinview $otherrefids($n) $curview]} {
Paul Mackerras887c9962007-08-20 19:36:20 +10007914 lappend refs [list $n o]
7915 } else {
7916 set commitinterest($otherrefids($n)) {run refill_reflist}
7917 }
7918 }
7919 }
7920 set refs [lsort -index 0 $refs]
7921 if {$refs eq $reflist} return
7922
7923 # Update the contents of $showrefstop.list according to the
7924 # differences between $reflist (old) and $refs (new)
7925 $showrefstop.list conf -state normal
7926 $showrefstop.list insert end "\n"
7927 set i 0
7928 set j 0
7929 while {$i < [llength $reflist] || $j < [llength $refs]} {
7930 if {$i < [llength $reflist]} {
7931 if {$j < [llength $refs]} {
7932 set cmp [string compare [lindex $reflist $i 0] \
7933 [lindex $refs $j 0]]
7934 if {$cmp == 0} {
7935 set cmp [string compare [lindex $reflist $i 1] \
7936 [lindex $refs $j 1]]
7937 }
7938 } else {
7939 set cmp -1
7940 }
7941 } else {
7942 set cmp 1
7943 }
7944 switch -- $cmp {
7945 -1 {
7946 $showrefstop.list delete "[expr {$j+1}].0" "[expr {$j+2}].0"
7947 incr i
7948 }
7949 0 {
7950 incr i
7951 incr j
7952 }
7953 1 {
7954 set l [expr {$j + 1}]
7955 $showrefstop.list image create $l.0 -align baseline \
7956 -image reficon-[lindex $refs $j 1] -padx 2
7957 $showrefstop.list insert $l.1 "[lindex $refs $j 0]\n"
7958 incr j
7959 }
7960 }
7961 }
7962 set reflist $refs
7963 # delete last newline
7964 $showrefstop.list delete end-2c end-1c
7965 $showrefstop.list conf -state disabled
Paul Mackerras10299152006-08-02 09:52:01 +10007966}
7967
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10007968# Stuff for finding nearby tags
7969proc getallcommits {} {
Paul Mackerras5cd15b62007-08-30 21:54:17 +10007970 global allcommits nextarc seeds allccache allcwait cachedarcs allcupdate
7971 global idheads idtags idotherrefs allparents tagobjid
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10007972
Paul Mackerrasa69b2d12007-08-13 15:02:02 +10007973 if {![info exists allcommits]} {
Paul Mackerrasa69b2d12007-08-13 15:02:02 +10007974 set nextarc 0
7975 set allcommits 0
7976 set seeds {}
Paul Mackerras5cd15b62007-08-30 21:54:17 +10007977 set allcwait 0
7978 set cachedarcs 0
7979 set allccache [file join [gitdir] "gitk.cache"]
7980 if {![catch {
7981 set f [open $allccache r]
7982 set allcwait 1
7983 getcache $f
7984 }]} return
Paul Mackerrasa69b2d12007-08-13 15:02:02 +10007985 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10007986
Paul Mackerras5cd15b62007-08-30 21:54:17 +10007987 if {$allcwait} {
7988 return
Paul Mackerrase11f1232007-06-16 20:29:25 +10007989 }
Paul Mackerras5cd15b62007-08-30 21:54:17 +10007990 set cmd [list | git rev-list --parents]
7991 set allcupdate [expr {$seeds ne {}}]
7992 if {!$allcupdate} {
7993 set ids "--all"
7994 } else {
7995 set refs [concat [array names idheads] [array names idtags] \
7996 [array names idotherrefs]]
7997 set ids {}
7998 set tagobjs {}
7999 foreach name [array names tagobjid] {
8000 lappend tagobjs $tagobjid($name)
8001 }
8002 foreach id [lsort -unique $refs] {
8003 if {![info exists allparents($id)] &&
8004 [lsearch -exact $tagobjs $id] < 0} {
8005 lappend ids $id
8006 }
8007 }
8008 if {$ids ne {}} {
8009 foreach id $seeds {
8010 lappend ids "^$id"
8011 }
8012 }
8013 }
8014 if {$ids ne {}} {
8015 set fd [open [concat $cmd $ids] r]
8016 fconfigure $fd -blocking 0
8017 incr allcommits
8018 nowbusy allcommits
8019 filerun $fd [list getallclines $fd]
8020 } else {
8021 dispneartags 0
8022 }
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10008023}
8024
Paul Mackerrase11f1232007-06-16 20:29:25 +10008025# Since most commits have 1 parent and 1 child, we group strings of
8026# such commits into "arcs" joining branch/merge points (BMPs), which
8027# are commits that either don't have 1 parent or don't have 1 child.
8028#
8029# arcnos(id) - incoming arcs for BMP, arc we're on for other nodes
8030# arcout(id) - outgoing arcs for BMP
8031# arcids(a) - list of IDs on arc including end but not start
8032# arcstart(a) - BMP ID at start of arc
8033# arcend(a) - BMP ID at end of arc
8034# growing(a) - arc a is still growing
8035# arctags(a) - IDs out of arcids (excluding end) that have tags
8036# archeads(a) - IDs out of arcids (excluding end) that have heads
8037# The start of an arc is at the descendent end, so "incoming" means
8038# coming from descendents, and "outgoing" means going towards ancestors.
Paul Mackerrascec7bec2006-08-02 09:38:10 +10008039
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10008040proc getallclines {fd} {
Paul Mackerras5cd15b62007-08-30 21:54:17 +10008041 global allparents allchildren idtags idheads nextarc
Paul Mackerrase11f1232007-06-16 20:29:25 +10008042 global arcnos arcids arctags arcout arcend arcstart archeads growing
Paul Mackerras5cd15b62007-08-30 21:54:17 +10008043 global seeds allcommits cachedarcs allcupdate
8044
Paul Mackerrase11f1232007-06-16 20:29:25 +10008045 set nid 0
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10008046 while {[incr nid] <= 1000 && [gets $fd line] >= 0} {
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10008047 set id [lindex $line 0]
Paul Mackerrase11f1232007-06-16 20:29:25 +10008048 if {[info exists allparents($id)]} {
8049 # seen it already
8050 continue
8051 }
Paul Mackerras5cd15b62007-08-30 21:54:17 +10008052 set cachedarcs 0
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10008053 set olds [lrange $line 1 end]
8054 set allparents($id) $olds
8055 if {![info exists allchildren($id)]} {
8056 set allchildren($id) {}
Paul Mackerrase11f1232007-06-16 20:29:25 +10008057 set arcnos($id) {}
8058 lappend seeds $id
8059 } else {
8060 set a $arcnos($id)
8061 if {[llength $olds] == 1 && [llength $a] == 1} {
8062 lappend arcids($a) $id
8063 if {[info exists idtags($id)]} {
8064 lappend arctags($a) $id
8065 }
8066 if {[info exists idheads($id)]} {
8067 lappend archeads($a) $id
8068 }
8069 if {[info exists allparents($olds)]} {
8070 # seen parent already
8071 if {![info exists arcout($olds)]} {
8072 splitarc $olds
8073 }
8074 lappend arcids($a) $olds
8075 set arcend($a) $olds
8076 unset growing($a)
8077 }
8078 lappend allchildren($olds) $id
8079 lappend arcnos($olds) $a
8080 continue
8081 }
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10008082 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10008083 foreach a $arcnos($id) {
8084 lappend arcids($a) $id
8085 set arcend($a) $id
8086 unset growing($a)
8087 }
8088
8089 set ao {}
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10008090 foreach p $olds {
8091 lappend allchildren($p) $id
Paul Mackerrase11f1232007-06-16 20:29:25 +10008092 set a [incr nextarc]
8093 set arcstart($a) $id
8094 set archeads($a) {}
8095 set arctags($a) {}
8096 set archeads($a) {}
8097 set arcids($a) {}
8098 lappend ao $a
8099 set growing($a) 1
8100 if {[info exists allparents($p)]} {
8101 # seen it already, may need to make a new branch
8102 if {![info exists arcout($p)]} {
8103 splitarc $p
8104 }
8105 lappend arcids($a) $p
8106 set arcend($a) $p
8107 unset growing($a)
8108 }
8109 lappend arcnos($p) $a
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10008110 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10008111 set arcout($id) $ao
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10008112 }
Paul Mackerrasf3326b62007-06-18 22:39:21 +10008113 if {$nid > 0} {
8114 global cached_dheads cached_dtags cached_atags
8115 catch {unset cached_dheads}
8116 catch {unset cached_dtags}
8117 catch {unset cached_atags}
8118 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10008119 if {![eof $fd]} {
8120 return [expr {$nid >= 1000? 2: 1}]
8121 }
Paul Mackerras5cd15b62007-08-30 21:54:17 +10008122 set cacheok 1
8123 if {[catch {
8124 fconfigure $fd -blocking 1
8125 close $fd
8126 } err]} {
8127 # got an error reading the list of commits
8128 # if we were updating, try rereading the whole thing again
8129 if {$allcupdate} {
8130 incr allcommits -1
8131 dropcache $err
8132 return
8133 }
Christian Stimmingd990ced2007-11-07 18:42:55 +01008134 error_popup "[mc "Error reading commit topology information;\
Paul Mackerras5cd15b62007-08-30 21:54:17 +10008135 branch and preceding/following tag information\
Christian Stimmingd990ced2007-11-07 18:42:55 +01008136 will be incomplete."]\n($err)"
Paul Mackerras5cd15b62007-08-30 21:54:17 +10008137 set cacheok 0
8138 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10008139 if {[incr allcommits -1] == 0} {
8140 notbusy allcommits
Paul Mackerras5cd15b62007-08-30 21:54:17 +10008141 if {$cacheok} {
8142 run savecache
8143 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10008144 }
8145 dispneartags 0
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10008146 return 0
Paul Mackerrase11f1232007-06-16 20:29:25 +10008147}
8148
8149proc recalcarc {a} {
8150 global arctags archeads arcids idtags idheads
8151
8152 set at {}
8153 set ah {}
8154 foreach id [lrange $arcids($a) 0 end-1] {
8155 if {[info exists idtags($id)]} {
8156 lappend at $id
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10008157 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10008158 if {[info exists idheads($id)]} {
8159 lappend ah $id
8160 }
8161 }
8162 set arctags($a) $at
8163 set archeads($a) $ah
8164}
8165
8166proc splitarc {p} {
Paul Mackerras5cd15b62007-08-30 21:54:17 +10008167 global arcnos arcids nextarc arctags archeads idtags idheads
Paul Mackerrase11f1232007-06-16 20:29:25 +10008168 global arcstart arcend arcout allparents growing
8169
8170 set a $arcnos($p)
8171 if {[llength $a] != 1} {
8172 puts "oops splitarc called but [llength $a] arcs already"
8173 return
8174 }
8175 set a [lindex $a 0]
8176 set i [lsearch -exact $arcids($a) $p]
8177 if {$i < 0} {
8178 puts "oops splitarc $p not in arc $a"
8179 return
8180 }
8181 set na [incr nextarc]
8182 if {[info exists arcend($a)]} {
8183 set arcend($na) $arcend($a)
8184 } else {
8185 set l [lindex $allparents([lindex $arcids($a) end]) 0]
8186 set j [lsearch -exact $arcnos($l) $a]
8187 set arcnos($l) [lreplace $arcnos($l) $j $j $na]
8188 }
8189 set tail [lrange $arcids($a) [expr {$i+1}] end]
8190 set arcids($a) [lrange $arcids($a) 0 $i]
8191 set arcend($a) $p
8192 set arcstart($na) $p
8193 set arcout($p) $na
8194 set arcids($na) $tail
8195 if {[info exists growing($a)]} {
8196 set growing($na) 1
8197 unset growing($a)
8198 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10008199
8200 foreach id $tail {
8201 if {[llength $arcnos($id)] == 1} {
8202 set arcnos($id) $na
8203 } else {
8204 set j [lsearch -exact $arcnos($id) $a]
8205 set arcnos($id) [lreplace $arcnos($id) $j $j $na]
8206 }
8207 }
8208
8209 # reconstruct tags and heads lists
8210 if {$arctags($a) ne {} || $archeads($a) ne {}} {
8211 recalcarc $a
8212 recalcarc $na
8213 } else {
8214 set arctags($na) {}
8215 set archeads($na) {}
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10008216 }
8217}
8218
Paul Mackerrase11f1232007-06-16 20:29:25 +10008219# Update things for a new commit added that is a child of one
8220# existing commit. Used when cherry-picking.
8221proc addnewchild {id p} {
Paul Mackerras5cd15b62007-08-30 21:54:17 +10008222 global allparents allchildren idtags nextarc
Paul Mackerrase11f1232007-06-16 20:29:25 +10008223 global arcnos arcids arctags arcout arcend arcstart archeads growing
Paul Mackerras719c2b92007-08-29 22:41:34 +10008224 global seeds allcommits
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10008225
Paul Mackerras3ebba3c2007-10-20 22:10:52 +10008226 if {![info exists allcommits] || ![info exists arcnos($p)]} return
Paul Mackerrase11f1232007-06-16 20:29:25 +10008227 set allparents($id) [list $p]
8228 set allchildren($id) {}
8229 set arcnos($id) {}
8230 lappend seeds $id
Paul Mackerrase11f1232007-06-16 20:29:25 +10008231 lappend allchildren($p) $id
8232 set a [incr nextarc]
8233 set arcstart($a) $id
8234 set archeads($a) {}
8235 set arctags($a) {}
8236 set arcids($a) [list $p]
8237 set arcend($a) $p
8238 if {![info exists arcout($p)]} {
8239 splitarc $p
8240 }
8241 lappend arcnos($p) $a
8242 set arcout($id) [list $a]
8243}
8244
Paul Mackerras5cd15b62007-08-30 21:54:17 +10008245# This implements a cache for the topology information.
8246# The cache saves, for each arc, the start and end of the arc,
8247# the ids on the arc, and the outgoing arcs from the end.
8248proc readcache {f} {
8249 global arcnos arcids arcout arcstart arcend arctags archeads nextarc
8250 global idtags idheads allparents cachedarcs possible_seeds seeds growing
8251 global allcwait
8252
8253 set a $nextarc
8254 set lim $cachedarcs
8255 if {$lim - $a > 500} {
8256 set lim [expr {$a + 500}]
8257 }
8258 if {[catch {
8259 if {$a == $lim} {
8260 # finish reading the cache and setting up arctags, etc.
8261 set line [gets $f]
8262 if {$line ne "1"} {error "bad final version"}
8263 close $f
8264 foreach id [array names idtags] {
8265 if {[info exists arcnos($id)] && [llength $arcnos($id)] == 1 &&
8266 [llength $allparents($id)] == 1} {
8267 set a [lindex $arcnos($id) 0]
8268 if {$arctags($a) eq {}} {
8269 recalcarc $a
8270 }
8271 }
8272 }
8273 foreach id [array names idheads] {
8274 if {[info exists arcnos($id)] && [llength $arcnos($id)] == 1 &&
8275 [llength $allparents($id)] == 1} {
8276 set a [lindex $arcnos($id) 0]
8277 if {$archeads($a) eq {}} {
8278 recalcarc $a
8279 }
8280 }
8281 }
8282 foreach id [lsort -unique $possible_seeds] {
8283 if {$arcnos($id) eq {}} {
8284 lappend seeds $id
8285 }
8286 }
8287 set allcwait 0
8288 } else {
8289 while {[incr a] <= $lim} {
8290 set line [gets $f]
8291 if {[llength $line] != 3} {error "bad line"}
8292 set s [lindex $line 0]
8293 set arcstart($a) $s
8294 lappend arcout($s) $a
8295 if {![info exists arcnos($s)]} {
8296 lappend possible_seeds $s
8297 set arcnos($s) {}
8298 }
8299 set e [lindex $line 1]
8300 if {$e eq {}} {
8301 set growing($a) 1
8302 } else {
8303 set arcend($a) $e
8304 if {![info exists arcout($e)]} {
8305 set arcout($e) {}
8306 }
8307 }
8308 set arcids($a) [lindex $line 2]
8309 foreach id $arcids($a) {
8310 lappend allparents($s) $id
8311 set s $id
8312 lappend arcnos($id) $a
8313 }
8314 if {![info exists allparents($s)]} {
8315 set allparents($s) {}
8316 }
8317 set arctags($a) {}
8318 set archeads($a) {}
8319 }
8320 set nextarc [expr {$a - 1}]
8321 }
8322 } err]} {
8323 dropcache $err
8324 return 0
8325 }
8326 if {!$allcwait} {
8327 getallcommits
8328 }
8329 return $allcwait
8330}
8331
8332proc getcache {f} {
8333 global nextarc cachedarcs possible_seeds
8334
8335 if {[catch {
8336 set line [gets $f]
8337 if {[llength $line] != 2 || [lindex $line 0] ne "1"} {error "bad version"}
8338 # make sure it's an integer
8339 set cachedarcs [expr {int([lindex $line 1])}]
8340 if {$cachedarcs < 0} {error "bad number of arcs"}
8341 set nextarc 0
8342 set possible_seeds {}
8343 run readcache $f
8344 } err]} {
8345 dropcache $err
8346 }
8347 return 0
8348}
8349
8350proc dropcache {err} {
8351 global allcwait nextarc cachedarcs seeds
8352
8353 #puts "dropping cache ($err)"
8354 foreach v {arcnos arcout arcids arcstart arcend growing \
8355 arctags archeads allparents allchildren} {
8356 global $v
8357 catch {unset $v}
8358 }
8359 set allcwait 0
8360 set nextarc 0
8361 set cachedarcs 0
8362 set seeds {}
8363 getallcommits
8364}
8365
8366proc writecache {f} {
8367 global cachearc cachedarcs allccache
8368 global arcstart arcend arcnos arcids arcout
8369
8370 set a $cachearc
8371 set lim $cachedarcs
8372 if {$lim - $a > 1000} {
8373 set lim [expr {$a + 1000}]
8374 }
8375 if {[catch {
8376 while {[incr a] <= $lim} {
8377 if {[info exists arcend($a)]} {
8378 puts $f [list $arcstart($a) $arcend($a) $arcids($a)]
8379 } else {
8380 puts $f [list $arcstart($a) {} $arcids($a)]
8381 }
8382 }
8383 } err]} {
8384 catch {close $f}
8385 catch {file delete $allccache}
8386 #puts "writing cache failed ($err)"
8387 return 0
8388 }
8389 set cachearc [expr {$a - 1}]
8390 if {$a > $cachedarcs} {
8391 puts $f "1"
8392 close $f
8393 return 0
8394 }
8395 return 1
8396}
8397
8398proc savecache {} {
8399 global nextarc cachedarcs cachearc allccache
8400
8401 if {$nextarc == $cachedarcs} return
8402 set cachearc 0
8403 set cachedarcs $nextarc
8404 catch {
8405 set f [open $allccache w]
8406 puts $f [list 1 $cachedarcs]
8407 run writecache $f
8408 }
8409}
8410
Paul Mackerrase11f1232007-06-16 20:29:25 +10008411# Returns 1 if a is an ancestor of b, -1 if b is an ancestor of a,
8412# or 0 if neither is true.
8413proc anc_or_desc {a b} {
8414 global arcout arcstart arcend arcnos cached_isanc
8415
8416 if {$arcnos($a) eq $arcnos($b)} {
8417 # Both are on the same arc(s); either both are the same BMP,
8418 # or if one is not a BMP, the other is also not a BMP or is
8419 # the BMP at end of the arc (and it only has 1 incoming arc).
Paul Mackerras69c0b5d2007-07-04 21:57:04 +10008420 # Or both can be BMPs with no incoming arcs.
8421 if {$a eq $b || $arcnos($a) eq {}} {
Paul Mackerrase11f1232007-06-16 20:29:25 +10008422 return 0
8423 }
8424 # assert {[llength $arcnos($a)] == 1}
8425 set arc [lindex $arcnos($a) 0]
8426 set i [lsearch -exact $arcids($arc) $a]
8427 set j [lsearch -exact $arcids($arc) $b]
8428 if {$i < 0 || $i > $j} {
8429 return 1
8430 } else {
8431 return -1
8432 }
8433 }
8434
8435 if {![info exists arcout($a)]} {
8436 set arc [lindex $arcnos($a) 0]
8437 if {[info exists arcend($arc)]} {
8438 set aend $arcend($arc)
8439 } else {
8440 set aend {}
8441 }
8442 set a $arcstart($arc)
8443 } else {
8444 set aend $a
8445 }
8446 if {![info exists arcout($b)]} {
8447 set arc [lindex $arcnos($b) 0]
8448 if {[info exists arcend($arc)]} {
8449 set bend $arcend($arc)
8450 } else {
8451 set bend {}
8452 }
8453 set b $arcstart($arc)
8454 } else {
8455 set bend $b
8456 }
8457 if {$a eq $bend} {
8458 return 1
8459 }
8460 if {$b eq $aend} {
8461 return -1
8462 }
8463 if {[info exists cached_isanc($a,$bend)]} {
8464 if {$cached_isanc($a,$bend)} {
8465 return 1
8466 }
8467 }
8468 if {[info exists cached_isanc($b,$aend)]} {
8469 if {$cached_isanc($b,$aend)} {
8470 return -1
8471 }
8472 if {[info exists cached_isanc($a,$bend)]} {
8473 return 0
8474 }
8475 }
8476
8477 set todo [list $a $b]
8478 set anc($a) a
8479 set anc($b) b
8480 for {set i 0} {$i < [llength $todo]} {incr i} {
8481 set x [lindex $todo $i]
8482 if {$anc($x) eq {}} {
8483 continue
8484 }
8485 foreach arc $arcnos($x) {
8486 set xd $arcstart($arc)
8487 if {$xd eq $bend} {
8488 set cached_isanc($a,$bend) 1
8489 set cached_isanc($b,$aend) 0
8490 return 1
8491 } elseif {$xd eq $aend} {
8492 set cached_isanc($b,$aend) 1
8493 set cached_isanc($a,$bend) 0
8494 return -1
8495 }
8496 if {![info exists anc($xd)]} {
8497 set anc($xd) $anc($x)
8498 lappend todo $xd
8499 } elseif {$anc($xd) ne $anc($x)} {
8500 set anc($xd) {}
8501 }
8502 }
8503 }
8504 set cached_isanc($a,$bend) 0
8505 set cached_isanc($b,$aend) 0
8506 return 0
8507}
8508
8509# This identifies whether $desc has an ancestor that is
8510# a growing tip of the graph and which is not an ancestor of $anc
8511# and returns 0 if so and 1 if not.
8512# If we subsequently discover a tag on such a growing tip, and that
8513# turns out to be a descendent of $anc (which it could, since we
8514# don't necessarily see children before parents), then $desc
8515# isn't a good choice to display as a descendent tag of
8516# $anc (since it is the descendent of another tag which is
8517# a descendent of $anc). Similarly, $anc isn't a good choice to
8518# display as a ancestor tag of $desc.
8519#
8520proc is_certain {desc anc} {
8521 global arcnos arcout arcstart arcend growing problems
8522
8523 set certain {}
8524 if {[llength $arcnos($anc)] == 1} {
8525 # tags on the same arc are certain
8526 if {$arcnos($desc) eq $arcnos($anc)} {
8527 return 1
8528 }
8529 if {![info exists arcout($anc)]} {
8530 # if $anc is partway along an arc, use the start of the arc instead
8531 set a [lindex $arcnos($anc) 0]
8532 set anc $arcstart($a)
8533 }
8534 }
8535 if {[llength $arcnos($desc)] > 1 || [info exists arcout($desc)]} {
8536 set x $desc
8537 } else {
8538 set a [lindex $arcnos($desc) 0]
8539 set x $arcend($a)
8540 }
8541 if {$x == $anc} {
8542 return 1
8543 }
8544 set anclist [list $x]
8545 set dl($x) 1
8546 set nnh 1
8547 set ngrowanc 0
8548 for {set i 0} {$i < [llength $anclist] && ($nnh > 0 || $ngrowanc > 0)} {incr i} {
8549 set x [lindex $anclist $i]
8550 if {$dl($x)} {
8551 incr nnh -1
8552 }
8553 set done($x) 1
8554 foreach a $arcout($x) {
8555 if {[info exists growing($a)]} {
8556 if {![info exists growanc($x)] && $dl($x)} {
8557 set growanc($x) 1
8558 incr ngrowanc
8559 }
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10008560 } else {
Paul Mackerrase11f1232007-06-16 20:29:25 +10008561 set y $arcend($a)
8562 if {[info exists dl($y)]} {
8563 if {$dl($y)} {
8564 if {!$dl($x)} {
8565 set dl($y) 0
8566 if {![info exists done($y)]} {
8567 incr nnh -1
8568 }
8569 if {[info exists growanc($x)]} {
8570 incr ngrowanc -1
8571 }
8572 set xl [list $y]
8573 for {set k 0} {$k < [llength $xl]} {incr k} {
8574 set z [lindex $xl $k]
8575 foreach c $arcout($z) {
8576 if {[info exists arcend($c)]} {
8577 set v $arcend($c)
8578 if {[info exists dl($v)] && $dl($v)} {
8579 set dl($v) 0
8580 if {![info exists done($v)]} {
8581 incr nnh -1
8582 }
8583 if {[info exists growanc($v)]} {
8584 incr ngrowanc -1
8585 }
8586 lappend xl $v
8587 }
8588 }
8589 }
8590 }
8591 }
8592 }
8593 } elseif {$y eq $anc || !$dl($x)} {
8594 set dl($y) 0
8595 lappend anclist $y
8596 } else {
8597 set dl($y) 1
8598 lappend anclist $y
8599 incr nnh
8600 }
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10008601 }
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10008602 }
8603 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10008604 foreach x [array names growanc] {
8605 if {$dl($x)} {
8606 return 0
8607 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10008608 return 0
Paul Mackerrase11f1232007-06-16 20:29:25 +10008609 }
8610 return 1
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10008611}
8612
Paul Mackerrase11f1232007-06-16 20:29:25 +10008613proc validate_arctags {a} {
8614 global arctags idtags
8615
8616 set i -1
8617 set na $arctags($a)
8618 foreach id $arctags($a) {
8619 incr i
8620 if {![info exists idtags($id)]} {
8621 set na [lreplace $na $i $i]
8622 incr i -1
8623 }
8624 }
8625 set arctags($a) $na
8626}
8627
8628proc validate_archeads {a} {
8629 global archeads idheads
8630
8631 set i -1
8632 set na $archeads($a)
8633 foreach id $archeads($a) {
8634 incr i
8635 if {![info exists idheads($id)]} {
8636 set na [lreplace $na $i $i]
8637 incr i -1
8638 }
8639 }
8640 set archeads($a) $na
8641}
8642
8643# Return the list of IDs that have tags that are descendents of id,
8644# ignoring IDs that are descendents of IDs already reported.
8645proc desctags {id} {
8646 global arcnos arcstart arcids arctags idtags allparents
8647 global growing cached_dtags
8648
8649 if {![info exists allparents($id)]} {
8650 return {}
8651 }
8652 set t1 [clock clicks -milliseconds]
8653 set argid $id
8654 if {[llength $arcnos($id)] == 1 && [llength $allparents($id)] == 1} {
8655 # part-way along an arc; check that arc first
8656 set a [lindex $arcnos($id) 0]
8657 if {$arctags($a) ne {}} {
8658 validate_arctags $a
8659 set i [lsearch -exact $arcids($a) $id]
8660 set tid {}
8661 foreach t $arctags($a) {
8662 set j [lsearch -exact $arcids($a) $t]
8663 if {$j >= $i} break
8664 set tid $t
8665 }
8666 if {$tid ne {}} {
8667 return $tid
8668 }
8669 }
8670 set id $arcstart($a)
8671 if {[info exists idtags($id)]} {
8672 return $id
8673 }
8674 }
8675 if {[info exists cached_dtags($id)]} {
8676 return $cached_dtags($id)
8677 }
8678
8679 set origid $id
8680 set todo [list $id]
8681 set queued($id) 1
8682 set nc 1
8683 for {set i 0} {$i < [llength $todo] && $nc > 0} {incr i} {
8684 set id [lindex $todo $i]
8685 set done($id) 1
8686 set ta [info exists hastaggedancestor($id)]
8687 if {!$ta} {
8688 incr nc -1
8689 }
8690 # ignore tags on starting node
8691 if {!$ta && $i > 0} {
8692 if {[info exists idtags($id)]} {
8693 set tagloc($id) $id
8694 set ta 1
8695 } elseif {[info exists cached_dtags($id)]} {
8696 set tagloc($id) $cached_dtags($id)
8697 set ta 1
8698 }
8699 }
8700 foreach a $arcnos($id) {
8701 set d $arcstart($a)
8702 if {!$ta && $arctags($a) ne {}} {
8703 validate_arctags $a
8704 if {$arctags($a) ne {}} {
8705 lappend tagloc($id) [lindex $arctags($a) end]
8706 }
8707 }
8708 if {$ta || $arctags($a) ne {}} {
8709 set tomark [list $d]
8710 for {set j 0} {$j < [llength $tomark]} {incr j} {
8711 set dd [lindex $tomark $j]
8712 if {![info exists hastaggedancestor($dd)]} {
8713 if {[info exists done($dd)]} {
8714 foreach b $arcnos($dd) {
8715 lappend tomark $arcstart($b)
8716 }
8717 if {[info exists tagloc($dd)]} {
8718 unset tagloc($dd)
8719 }
8720 } elseif {[info exists queued($dd)]} {
8721 incr nc -1
8722 }
8723 set hastaggedancestor($dd) 1
8724 }
8725 }
8726 }
8727 if {![info exists queued($d)]} {
8728 lappend todo $d
8729 set queued($d) 1
8730 if {![info exists hastaggedancestor($d)]} {
8731 incr nc
8732 }
8733 }
8734 }
8735 }
8736 set tags {}
8737 foreach id [array names tagloc] {
8738 if {![info exists hastaggedancestor($id)]} {
8739 foreach t $tagloc($id) {
8740 if {[lsearch -exact $tags $t] < 0} {
8741 lappend tags $t
8742 }
8743 }
8744 }
8745 }
8746 set t2 [clock clicks -milliseconds]
8747 set loopix $i
8748
8749 # remove tags that are descendents of other tags
8750 for {set i 0} {$i < [llength $tags]} {incr i} {
8751 set a [lindex $tags $i]
8752 for {set j 0} {$j < $i} {incr j} {
8753 set b [lindex $tags $j]
8754 set r [anc_or_desc $a $b]
8755 if {$r == 1} {
8756 set tags [lreplace $tags $j $j]
8757 incr j -1
8758 incr i -1
8759 } elseif {$r == -1} {
8760 set tags [lreplace $tags $i $i]
8761 incr i -1
8762 break
8763 }
8764 }
8765 }
8766
8767 if {[array names growing] ne {}} {
8768 # graph isn't finished, need to check if any tag could get
8769 # eclipsed by another tag coming later. Simply ignore any
8770 # tags that could later get eclipsed.
8771 set ctags {}
8772 foreach t $tags {
8773 if {[is_certain $t $origid]} {
8774 lappend ctags $t
8775 }
8776 }
8777 if {$tags eq $ctags} {
8778 set cached_dtags($origid) $tags
8779 } else {
8780 set tags $ctags
8781 }
8782 } else {
8783 set cached_dtags($origid) $tags
8784 }
8785 set t3 [clock clicks -milliseconds]
8786 if {0 && $t3 - $t1 >= 100} {
8787 puts "iterating descendents ($loopix/[llength $todo] nodes) took\
8788 [expr {$t2-$t1}]+[expr {$t3-$t2}]ms, $nc candidates left"
8789 }
8790 return $tags
8791}
8792
8793proc anctags {id} {
8794 global arcnos arcids arcout arcend arctags idtags allparents
8795 global growing cached_atags
8796
8797 if {![info exists allparents($id)]} {
8798 return {}
8799 }
8800 set t1 [clock clicks -milliseconds]
8801 set argid $id
8802 if {[llength $arcnos($id)] == 1 && [llength $allparents($id)] == 1} {
8803 # part-way along an arc; check that arc first
8804 set a [lindex $arcnos($id) 0]
8805 if {$arctags($a) ne {}} {
8806 validate_arctags $a
8807 set i [lsearch -exact $arcids($a) $id]
8808 foreach t $arctags($a) {
8809 set j [lsearch -exact $arcids($a) $t]
8810 if {$j > $i} {
8811 return $t
8812 }
8813 }
8814 }
8815 if {![info exists arcend($a)]} {
8816 return {}
8817 }
8818 set id $arcend($a)
8819 if {[info exists idtags($id)]} {
8820 return $id
8821 }
8822 }
8823 if {[info exists cached_atags($id)]} {
8824 return $cached_atags($id)
8825 }
8826
8827 set origid $id
8828 set todo [list $id]
8829 set queued($id) 1
8830 set taglist {}
8831 set nc 1
8832 for {set i 0} {$i < [llength $todo] && $nc > 0} {incr i} {
8833 set id [lindex $todo $i]
8834 set done($id) 1
8835 set td [info exists hastaggeddescendent($id)]
8836 if {!$td} {
8837 incr nc -1
8838 }
8839 # ignore tags on starting node
8840 if {!$td && $i > 0} {
8841 if {[info exists idtags($id)]} {
8842 set tagloc($id) $id
8843 set td 1
8844 } elseif {[info exists cached_atags($id)]} {
8845 set tagloc($id) $cached_atags($id)
8846 set td 1
8847 }
8848 }
8849 foreach a $arcout($id) {
8850 if {!$td && $arctags($a) ne {}} {
8851 validate_arctags $a
8852 if {$arctags($a) ne {}} {
8853 lappend tagloc($id) [lindex $arctags($a) 0]
8854 }
8855 }
8856 if {![info exists arcend($a)]} continue
8857 set d $arcend($a)
8858 if {$td || $arctags($a) ne {}} {
8859 set tomark [list $d]
8860 for {set j 0} {$j < [llength $tomark]} {incr j} {
8861 set dd [lindex $tomark $j]
8862 if {![info exists hastaggeddescendent($dd)]} {
8863 if {[info exists done($dd)]} {
8864 foreach b $arcout($dd) {
8865 if {[info exists arcend($b)]} {
8866 lappend tomark $arcend($b)
8867 }
8868 }
8869 if {[info exists tagloc($dd)]} {
8870 unset tagloc($dd)
8871 }
8872 } elseif {[info exists queued($dd)]} {
8873 incr nc -1
8874 }
8875 set hastaggeddescendent($dd) 1
8876 }
8877 }
8878 }
8879 if {![info exists queued($d)]} {
8880 lappend todo $d
8881 set queued($d) 1
8882 if {![info exists hastaggeddescendent($d)]} {
8883 incr nc
8884 }
8885 }
8886 }
8887 }
8888 set t2 [clock clicks -milliseconds]
8889 set loopix $i
8890 set tags {}
8891 foreach id [array names tagloc] {
8892 if {![info exists hastaggeddescendent($id)]} {
8893 foreach t $tagloc($id) {
8894 if {[lsearch -exact $tags $t] < 0} {
8895 lappend tags $t
8896 }
8897 }
8898 }
8899 }
8900
8901 # remove tags that are ancestors of other tags
8902 for {set i 0} {$i < [llength $tags]} {incr i} {
8903 set a [lindex $tags $i]
8904 for {set j 0} {$j < $i} {incr j} {
8905 set b [lindex $tags $j]
8906 set r [anc_or_desc $a $b]
8907 if {$r == -1} {
8908 set tags [lreplace $tags $j $j]
8909 incr j -1
8910 incr i -1
8911 } elseif {$r == 1} {
8912 set tags [lreplace $tags $i $i]
8913 incr i -1
8914 break
8915 }
8916 }
8917 }
8918
8919 if {[array names growing] ne {}} {
8920 # graph isn't finished, need to check if any tag could get
8921 # eclipsed by another tag coming later. Simply ignore any
8922 # tags that could later get eclipsed.
8923 set ctags {}
8924 foreach t $tags {
8925 if {[is_certain $origid $t]} {
8926 lappend ctags $t
8927 }
8928 }
8929 if {$tags eq $ctags} {
8930 set cached_atags($origid) $tags
8931 } else {
8932 set tags $ctags
8933 }
8934 } else {
8935 set cached_atags($origid) $tags
8936 }
8937 set t3 [clock clicks -milliseconds]
8938 if {0 && $t3 - $t1 >= 100} {
8939 puts "iterating ancestors ($loopix/[llength $todo] nodes) took\
8940 [expr {$t2-$t1}]+[expr {$t3-$t2}]ms, $nc candidates left"
8941 }
8942 return $tags
8943}
8944
8945# Return the list of IDs that have heads that are descendents of id,
8946# including id itself if it has a head.
8947proc descheads {id} {
8948 global arcnos arcstart arcids archeads idheads cached_dheads
8949 global allparents
8950
8951 if {![info exists allparents($id)]} {
8952 return {}
8953 }
Paul Mackerrasf3326b62007-06-18 22:39:21 +10008954 set aret {}
Paul Mackerrase11f1232007-06-16 20:29:25 +10008955 if {[llength $arcnos($id)] == 1 && [llength $allparents($id)] == 1} {
8956 # part-way along an arc; check it first
8957 set a [lindex $arcnos($id) 0]
8958 if {$archeads($a) ne {}} {
8959 validate_archeads $a
8960 set i [lsearch -exact $arcids($a) $id]
8961 foreach t $archeads($a) {
8962 set j [lsearch -exact $arcids($a) $t]
8963 if {$j > $i} break
Paul Mackerrasf3326b62007-06-18 22:39:21 +10008964 lappend aret $t
Paul Mackerrase11f1232007-06-16 20:29:25 +10008965 }
8966 }
8967 set id $arcstart($a)
8968 }
8969 set origid $id
8970 set todo [list $id]
8971 set seen($id) 1
Paul Mackerrasf3326b62007-06-18 22:39:21 +10008972 set ret {}
Paul Mackerrase11f1232007-06-16 20:29:25 +10008973 for {set i 0} {$i < [llength $todo]} {incr i} {
8974 set id [lindex $todo $i]
8975 if {[info exists cached_dheads($id)]} {
8976 set ret [concat $ret $cached_dheads($id)]
8977 } else {
8978 if {[info exists idheads($id)]} {
8979 lappend ret $id
8980 }
8981 foreach a $arcnos($id) {
8982 if {$archeads($a) ne {}} {
Paul Mackerras706d6c32007-06-26 11:09:49 +10008983 validate_archeads $a
8984 if {$archeads($a) ne {}} {
8985 set ret [concat $ret $archeads($a)]
8986 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10008987 }
8988 set d $arcstart($a)
8989 if {![info exists seen($d)]} {
8990 lappend todo $d
8991 set seen($d) 1
8992 }
8993 }
8994 }
8995 }
8996 set ret [lsort -unique $ret]
8997 set cached_dheads($origid) $ret
Paul Mackerrasf3326b62007-06-18 22:39:21 +10008998 return [concat $ret $aret]
Paul Mackerrase11f1232007-06-16 20:29:25 +10008999}
9000
Paul Mackerrasceadfe92006-08-08 20:55:36 +10009001proc addedtag {id} {
Paul Mackerrase11f1232007-06-16 20:29:25 +10009002 global arcnos arcout cached_dtags cached_atags
Paul Mackerrasceadfe92006-08-08 20:55:36 +10009003
Paul Mackerrase11f1232007-06-16 20:29:25 +10009004 if {![info exists arcnos($id)]} return
9005 if {![info exists arcout($id)]} {
9006 recalcarc [lindex $arcnos($id) 0]
Paul Mackerrasceadfe92006-08-08 20:55:36 +10009007 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10009008 catch {unset cached_dtags}
9009 catch {unset cached_atags}
Paul Mackerrasceadfe92006-08-08 20:55:36 +10009010}
9011
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10009012proc addedhead {hid head} {
Paul Mackerrase11f1232007-06-16 20:29:25 +10009013 global arcnos arcout cached_dheads
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10009014
Paul Mackerrase11f1232007-06-16 20:29:25 +10009015 if {![info exists arcnos($hid)]} return
9016 if {![info exists arcout($hid)]} {
9017 recalcarc [lindex $arcnos($hid) 0]
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10009018 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10009019 catch {unset cached_dheads}
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10009020}
9021
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10009022proc removedhead {hid head} {
Paul Mackerrase11f1232007-06-16 20:29:25 +10009023 global cached_dheads
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10009024
Paul Mackerrase11f1232007-06-16 20:29:25 +10009025 catch {unset cached_dheads}
Paul Mackerras10299152006-08-02 09:52:01 +10009026}
9027
Paul Mackerrase11f1232007-06-16 20:29:25 +10009028proc movedhead {hid head} {
9029 global arcnos arcout cached_dheads
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10009030
Paul Mackerrase11f1232007-06-16 20:29:25 +10009031 if {![info exists arcnos($hid)]} return
9032 if {![info exists arcout($hid)]} {
9033 recalcarc [lindex $arcnos($hid) 0]
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10009034 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10009035 catch {unset cached_dheads}
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10009036}
9037
Paul Mackerrascec7bec2006-08-02 09:38:10 +10009038proc changedrefs {} {
Paul Mackerrase11f1232007-06-16 20:29:25 +10009039 global cached_dheads cached_dtags cached_atags
9040 global arctags archeads arcnos arcout idheads idtags
Paul Mackerrascec7bec2006-08-02 09:38:10 +10009041
Paul Mackerrase11f1232007-06-16 20:29:25 +10009042 foreach id [concat [array names idheads] [array names idtags]] {
9043 if {[info exists arcnos($id)] && ![info exists arcout($id)]} {
9044 set a [lindex $arcnos($id) 0]
9045 if {![info exists donearc($a)]} {
9046 recalcarc $a
9047 set donearc($a) 1
9048 }
Paul Mackerrascec7bec2006-08-02 09:38:10 +10009049 }
9050 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10009051 catch {unset cached_dtags}
9052 catch {unset cached_atags}
9053 catch {unset cached_dheads}
Paul Mackerrascec7bec2006-08-02 09:38:10 +10009054}
9055
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10009056proc rereadrefs {} {
Paul Mackerrasfc2a2562007-12-26 23:03:43 +11009057 global idtags idheads idotherrefs mainheadid
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10009058
9059 set refids [concat [array names idtags] \
9060 [array names idheads] [array names idotherrefs]]
9061 foreach id $refids {
9062 if {![info exists ref($id)]} {
9063 set ref($id) [listrefs $id]
9064 }
9065 }
Paul Mackerrasfc2a2562007-12-26 23:03:43 +11009066 set oldmainhead $mainheadid
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10009067 readrefs
Paul Mackerrascec7bec2006-08-02 09:38:10 +10009068 changedrefs
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10009069 set refids [lsort -unique [concat $refids [array names idtags] \
9070 [array names idheads] [array names idotherrefs]]]
9071 foreach id $refids {
9072 set v [listrefs $id]
Paul Mackerrasc11ff122008-05-26 10:11:33 +10009073 if {![info exists ref($id)] || $ref($id) != $v} {
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10009074 redrawtags $id
9075 }
9076 }
Paul Mackerrasc11ff122008-05-26 10:11:33 +10009077 if {$oldmainhead ne $mainheadid} {
9078 redrawtags $oldmainhead
9079 redrawtags $mainheadid
9080 }
Paul Mackerras887c9962007-08-20 19:36:20 +10009081 run refill_reflist
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10009082}
9083
Junio C Hamano2e1ded42006-06-11 09:50:47 -07009084proc listrefs {id} {
9085 global idtags idheads idotherrefs
9086
9087 set x {}
9088 if {[info exists idtags($id)]} {
9089 set x $idtags($id)
9090 }
9091 set y {}
9092 if {[info exists idheads($id)]} {
9093 set y $idheads($id)
9094 }
9095 set z {}
9096 if {[info exists idotherrefs($id)]} {
9097 set z $idotherrefs($id)
9098 }
9099 return [list $x $y $z]
9100}
9101
Paul Mackerras106288c2005-08-19 23:11:39 +10009102proc showtag {tag isnew} {
Paul Mackerras62d3ea62006-09-11 10:36:53 +10009103 global ctext tagcontents tagids linknum tagobjid
Paul Mackerras106288c2005-08-19 23:11:39 +10009104
9105 if {$isnew} {
9106 addtohistory [list showtag $tag 0]
9107 }
9108 $ctext conf -state normal
Paul Mackerras3ea06f92006-05-24 10:16:03 +10009109 clear_ctext
Paul Mackerras32f1b3e2007-09-28 21:27:39 +10009110 settabs 0
Paul Mackerras106288c2005-08-19 23:11:39 +10009111 set linknum 0
Paul Mackerras62d3ea62006-09-11 10:36:53 +10009112 if {![info exists tagcontents($tag)]} {
9113 catch {
9114 set tagcontents($tag) [exec git cat-file tag $tagobjid($tag)]
9115 }
9116 }
Paul Mackerras106288c2005-08-19 23:11:39 +10009117 if {[info exists tagcontents($tag)]} {
9118 set text $tagcontents($tag)
9119 } else {
Christian Stimmingd990ced2007-11-07 18:42:55 +01009120 set text "[mc "Tag"]: $tag\n[mc "Id"]: $tagids($tag)"
Paul Mackerras106288c2005-08-19 23:11:39 +10009121 }
Sergey Vlasovf1b86292006-05-15 19:13:14 +04009122 appendwithlinks $text {}
Paul Mackerras106288c2005-08-19 23:11:39 +10009123 $ctext conf -state disabled
Paul Mackerras7fcceed2006-04-27 19:21:49 +10009124 init_flist {}
Paul Mackerras106288c2005-08-19 23:11:39 +10009125}
9126
Paul Mackerras1d10f362005-05-15 12:55:47 +00009127proc doquit {} {
9128 global stopped
Thomas Arcila314f5de2008-03-24 12:55:36 +01009129 global gitktmpdir
9130
Paul Mackerras1d10f362005-05-15 12:55:47 +00009131 set stopped 100
Mark Levedahlb6047c52007-02-08 22:22:24 -05009132 savestuff .
Paul Mackerras1d10f362005-05-15 12:55:47 +00009133 destroy .
Thomas Arcila314f5de2008-03-24 12:55:36 +01009134
9135 if {[info exists gitktmpdir]} {
9136 catch {file delete -force $gitktmpdir}
9137 }
Paul Mackerras1d10f362005-05-15 12:55:47 +00009138}
9139
Paul Mackerras9a7558f2007-10-06 20:16:06 +10009140proc mkfontdisp {font top which} {
9141 global fontattr fontpref $font
9142
9143 set fontpref($font) [set $font]
9144 button $top.${font}but -text $which -font optionfont \
9145 -command [list choosefont $font $which]
9146 label $top.$font -relief flat -font $font \
9147 -text $fontattr($font,family) -justify left
9148 grid x $top.${font}but $top.$font -sticky w
9149}
9150
9151proc choosefont {font which} {
9152 global fontparam fontlist fonttop fontattr
9153
9154 set fontparam(which) $which
9155 set fontparam(font) $font
9156 set fontparam(family) [font actual $font -family]
9157 set fontparam(size) $fontattr($font,size)
9158 set fontparam(weight) $fontattr($font,weight)
9159 set fontparam(slant) $fontattr($font,slant)
9160 set top .gitkfont
9161 set fonttop $top
9162 if {![winfo exists $top]} {
9163 font create sample
9164 eval font config sample [font actual $font]
9165 toplevel $top
Christian Stimmingd990ced2007-11-07 18:42:55 +01009166 wm title $top [mc "Gitk font chooser"]
Paul Mackerrasb039f0a2008-01-06 15:54:46 +11009167 label $top.l -textvariable fontparam(which)
Paul Mackerras9a7558f2007-10-06 20:16:06 +10009168 pack $top.l -side top
9169 set fontlist [lsort [font families]]
9170 frame $top.f
9171 listbox $top.f.fam -listvariable fontlist \
9172 -yscrollcommand [list $top.f.sb set]
9173 bind $top.f.fam <<ListboxSelect>> selfontfam
9174 scrollbar $top.f.sb -command [list $top.f.fam yview]
9175 pack $top.f.sb -side right -fill y
9176 pack $top.f.fam -side left -fill both -expand 1
9177 pack $top.f -side top -fill both -expand 1
9178 frame $top.g
9179 spinbox $top.g.size -from 4 -to 40 -width 4 \
9180 -textvariable fontparam(size) \
9181 -validatecommand {string is integer -strict %s}
9182 checkbutton $top.g.bold -padx 5 \
Christian Stimmingd990ced2007-11-07 18:42:55 +01009183 -font {{Times New Roman} 12 bold} -text [mc "B"] -indicatoron 0 \
Paul Mackerras9a7558f2007-10-06 20:16:06 +10009184 -variable fontparam(weight) -onvalue bold -offvalue normal
9185 checkbutton $top.g.ital -padx 5 \
Christian Stimmingd990ced2007-11-07 18:42:55 +01009186 -font {{Times New Roman} 12 italic} -text [mc "I"] -indicatoron 0 \
Paul Mackerras9a7558f2007-10-06 20:16:06 +10009187 -variable fontparam(slant) -onvalue italic -offvalue roman
9188 pack $top.g.size $top.g.bold $top.g.ital -side left
9189 pack $top.g -side top
9190 canvas $top.c -width 150 -height 50 -border 2 -relief sunk \
9191 -background white
9192 $top.c create text 100 25 -anchor center -text $which -font sample \
9193 -fill black -tags text
9194 bind $top.c <Configure> [list centertext $top.c]
9195 pack $top.c -side top -fill x
9196 frame $top.buts
Paul Mackerrasb039f0a2008-01-06 15:54:46 +11009197 button $top.buts.ok -text [mc "OK"] -command fontok -default active
9198 button $top.buts.can -text [mc "Cancel"] -command fontcan -default normal
Paul Mackerras9a7558f2007-10-06 20:16:06 +10009199 grid $top.buts.ok $top.buts.can
9200 grid columnconfigure $top.buts 0 -weight 1 -uniform a
9201 grid columnconfigure $top.buts 1 -weight 1 -uniform a
9202 pack $top.buts -side bottom -fill x
9203 trace add variable fontparam write chg_fontparam
9204 } else {
9205 raise $top
9206 $top.c itemconf text -text $which
9207 }
9208 set i [lsearch -exact $fontlist $fontparam(family)]
9209 if {$i >= 0} {
9210 $top.f.fam selection set $i
9211 $top.f.fam see $i
9212 }
9213}
9214
9215proc centertext {w} {
9216 $w coords text [expr {[winfo width $w] / 2}] [expr {[winfo height $w] / 2}]
9217}
9218
9219proc fontok {} {
9220 global fontparam fontpref prefstop
9221
9222 set f $fontparam(font)
9223 set fontpref($f) [list $fontparam(family) $fontparam(size)]
9224 if {$fontparam(weight) eq "bold"} {
9225 lappend fontpref($f) "bold"
9226 }
9227 if {$fontparam(slant) eq "italic"} {
9228 lappend fontpref($f) "italic"
9229 }
9230 set w $prefstop.$f
9231 $w conf -text $fontparam(family) -font $fontpref($f)
9232
9233 fontcan
9234}
9235
9236proc fontcan {} {
9237 global fonttop fontparam
9238
9239 if {[info exists fonttop]} {
9240 catch {destroy $fonttop}
9241 catch {font delete sample}
9242 unset fonttop
9243 unset fontparam
9244 }
9245}
9246
9247proc selfontfam {} {
9248 global fonttop fontparam
9249
9250 set i [$fonttop.f.fam curselection]
9251 if {$i ne {}} {
9252 set fontparam(family) [$fonttop.f.fam get $i]
9253 }
9254}
9255
9256proc chg_fontparam {v sub op} {
9257 global fontparam
9258
9259 font config sample -$sub $fontparam($sub)
9260}
9261
Paul Mackerras712fcc02005-11-30 09:28:16 +11009262proc doprefs {} {
Paul Mackerras8d73b242007-10-06 20:22:00 +10009263 global maxwidth maxgraphpct
Paul Mackerras219ea3a2006-09-07 10:21:39 +10009264 global oldprefs prefstop showneartags showlocalchanges
Mark Levedahl60378c02007-05-20 12:12:48 -04009265 global bgcolor fgcolor ctext diffcolors selectbgcolor
Thomas Arcila314f5de2008-03-24 12:55:36 +01009266 global tabstop limitdiffs autoselect extdifftool
Paul Mackerras232475d2005-11-15 10:34:03 +11009267
Paul Mackerras712fcc02005-11-30 09:28:16 +11009268 set top .gitkprefs
9269 set prefstop $top
9270 if {[winfo exists $top]} {
9271 raise $top
9272 return
Paul Mackerras757f17b2005-11-21 09:56:07 +11009273 }
Paul Mackerras3de07112007-10-23 22:40:50 +10009274 foreach v {maxwidth maxgraphpct showneartags showlocalchanges \
Paul Mackerras94503912007-10-23 10:33:38 +10009275 limitdiffs tabstop} {
Paul Mackerras712fcc02005-11-30 09:28:16 +11009276 set oldprefs($v) [set $v]
Paul Mackerras232475d2005-11-15 10:34:03 +11009277 }
Paul Mackerras712fcc02005-11-30 09:28:16 +11009278 toplevel $top
Christian Stimmingd990ced2007-11-07 18:42:55 +01009279 wm title $top [mc "Gitk preferences"]
9280 label $top.ldisp -text [mc "Commit list display options"]
Paul Mackerras712fcc02005-11-30 09:28:16 +11009281 grid $top.ldisp - -sticky w -pady 10
9282 label $top.spacer -text " "
Christian Stimmingd990ced2007-11-07 18:42:55 +01009283 label $top.maxwidthl -text [mc "Maximum graph width (lines)"] \
Paul Mackerras712fcc02005-11-30 09:28:16 +11009284 -font optionfont
9285 spinbox $top.maxwidth -from 0 -to 100 -width 4 -textvariable maxwidth
9286 grid $top.spacer $top.maxwidthl $top.maxwidth -sticky w
Christian Stimmingd990ced2007-11-07 18:42:55 +01009287 label $top.maxpctl -text [mc "Maximum graph width (% of pane)"] \
Paul Mackerras712fcc02005-11-30 09:28:16 +11009288 -font optionfont
9289 spinbox $top.maxpct -from 1 -to 100 -width 4 -textvariable maxgraphpct
9290 grid x $top.maxpctl $top.maxpct -sticky w
Paul Mackerras219ea3a2006-09-07 10:21:39 +10009291 frame $top.showlocal
Christian Stimmingd990ced2007-11-07 18:42:55 +01009292 label $top.showlocal.l -text [mc "Show local changes"] -font optionfont
Paul Mackerras219ea3a2006-09-07 10:21:39 +10009293 checkbutton $top.showlocal.b -variable showlocalchanges
9294 pack $top.showlocal.b $top.showlocal.l -side left
9295 grid x $top.showlocal -sticky w
Jeff King95293b52008-03-06 06:49:25 -05009296 frame $top.autoselect
9297 label $top.autoselect.l -text [mc "Auto-select SHA1"] -font optionfont
9298 checkbutton $top.autoselect.b -variable autoselect
9299 pack $top.autoselect.b $top.autoselect.l -side left
9300 grid x $top.autoselect -sticky w
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10009301
Christian Stimmingd990ced2007-11-07 18:42:55 +01009302 label $top.ddisp -text [mc "Diff display options"]
Paul Mackerras712fcc02005-11-30 09:28:16 +11009303 grid $top.ddisp - -sticky w -pady 10
Christian Stimmingd990ced2007-11-07 18:42:55 +01009304 label $top.tabstopl -text [mc "Tab spacing"] -font optionfont
Paul Mackerras94503912007-10-23 10:33:38 +10009305 spinbox $top.tabstop -from 1 -to 20 -width 4 -textvariable tabstop
9306 grid x $top.tabstopl $top.tabstop -sticky w
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10009307 frame $top.ntag
Christian Stimmingd990ced2007-11-07 18:42:55 +01009308 label $top.ntag.l -text [mc "Display nearby tags"] -font optionfont
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10009309 checkbutton $top.ntag.b -variable showneartags
9310 pack $top.ntag.b $top.ntag.l -side left
9311 grid x $top.ntag -sticky w
Paul Mackerras7a39a172007-10-23 10:15:11 +10009312 frame $top.ldiff
Christian Stimmingd990ced2007-11-07 18:42:55 +01009313 label $top.ldiff.l -text [mc "Limit diffs to listed paths"] -font optionfont
Paul Mackerras7a39a172007-10-23 10:15:11 +10009314 checkbutton $top.ldiff.b -variable limitdiffs
9315 pack $top.ldiff.b $top.ldiff.l -side left
9316 grid x $top.ldiff -sticky w
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10009317
Thomas Arcila314f5de2008-03-24 12:55:36 +01009318 entry $top.extdifft -textvariable extdifftool
9319 frame $top.extdifff
9320 label $top.extdifff.l -text [mc "External diff tool" ] -font optionfont \
9321 -padx 10
9322 button $top.extdifff.b -text [mc "Choose..."] -font optionfont \
9323 -command choose_extdiff
9324 pack $top.extdifff.l $top.extdifff.b -side left
9325 grid x $top.extdifff $top.extdifft -sticky w
9326
Christian Stimmingd990ced2007-11-07 18:42:55 +01009327 label $top.cdisp -text [mc "Colors: press to choose"]
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10009328 grid $top.cdisp - -sticky w -pady 10
9329 label $top.bg -padx 40 -relief sunk -background $bgcolor
Christian Stimmingd990ced2007-11-07 18:42:55 +01009330 button $top.bgbut -text [mc "Background"] -font optionfont \
Gerrit Pape80dd7b42008-03-26 18:45:26 +00009331 -command [list choosecolor bgcolor {} $top.bg background setbg]
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10009332 grid x $top.bgbut $top.bg -sticky w
9333 label $top.fg -padx 40 -relief sunk -background $fgcolor
Christian Stimmingd990ced2007-11-07 18:42:55 +01009334 button $top.fgbut -text [mc "Foreground"] -font optionfont \
Gerrit Pape80dd7b42008-03-26 18:45:26 +00009335 -command [list choosecolor fgcolor {} $top.fg foreground setfg]
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10009336 grid x $top.fgbut $top.fg -sticky w
9337 label $top.diffold -padx 40 -relief sunk -background [lindex $diffcolors 0]
Christian Stimmingd990ced2007-11-07 18:42:55 +01009338 button $top.diffoldbut -text [mc "Diff: old lines"] -font optionfont \
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10009339 -command [list choosecolor diffcolors 0 $top.diffold "diff old lines" \
9340 [list $ctext tag conf d0 -foreground]]
9341 grid x $top.diffoldbut $top.diffold -sticky w
9342 label $top.diffnew -padx 40 -relief sunk -background [lindex $diffcolors 1]
Christian Stimmingd990ced2007-11-07 18:42:55 +01009343 button $top.diffnewbut -text [mc "Diff: new lines"] -font optionfont \
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10009344 -command [list choosecolor diffcolors 1 $top.diffnew "diff new lines" \
9345 [list $ctext tag conf d1 -foreground]]
9346 grid x $top.diffnewbut $top.diffnew -sticky w
9347 label $top.hunksep -padx 40 -relief sunk -background [lindex $diffcolors 2]
Christian Stimmingd990ced2007-11-07 18:42:55 +01009348 button $top.hunksepbut -text [mc "Diff: hunk header"] -font optionfont \
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10009349 -command [list choosecolor diffcolors 2 $top.hunksep \
9350 "diff hunk header" \
9351 [list $ctext tag conf hunksep -foreground]]
9352 grid x $top.hunksepbut $top.hunksep -sticky w
Mark Levedahl60378c02007-05-20 12:12:48 -04009353 label $top.selbgsep -padx 40 -relief sunk -background $selectbgcolor
Christian Stimmingd990ced2007-11-07 18:42:55 +01009354 button $top.selbgbut -text [mc "Select bg"] -font optionfont \
Gerrit Pape80dd7b42008-03-26 18:45:26 +00009355 -command [list choosecolor selectbgcolor {} $top.selbgsep background setselbg]
Mark Levedahl60378c02007-05-20 12:12:48 -04009356 grid x $top.selbgbut $top.selbgsep -sticky w
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10009357
Christian Stimmingd990ced2007-11-07 18:42:55 +01009358 label $top.cfont -text [mc "Fonts: press to choose"]
Paul Mackerras9a7558f2007-10-06 20:16:06 +10009359 grid $top.cfont - -sticky w -pady 10
Christian Stimmingd990ced2007-11-07 18:42:55 +01009360 mkfontdisp mainfont $top [mc "Main font"]
9361 mkfontdisp textfont $top [mc "Diff display font"]
9362 mkfontdisp uifont $top [mc "User interface font"]
Paul Mackerras9a7558f2007-10-06 20:16:06 +10009363
Paul Mackerras712fcc02005-11-30 09:28:16 +11009364 frame $top.buts
Christian Stimmingd990ced2007-11-07 18:42:55 +01009365 button $top.buts.ok -text [mc "OK"] -command prefsok -default active
Christian Stimmingd990ced2007-11-07 18:42:55 +01009366 button $top.buts.can -text [mc "Cancel"] -command prefscan -default normal
Paul Mackerras712fcc02005-11-30 09:28:16 +11009367 grid $top.buts.ok $top.buts.can
9368 grid columnconfigure $top.buts 0 -weight 1 -uniform a
9369 grid columnconfigure $top.buts 1 -weight 1 -uniform a
9370 grid $top.buts - - -pady 10 -sticky ew
Eygene Ryabinkin3a950e92007-03-27 14:36:59 +04009371 bind $top <Visibility> "focus $top.buts.ok"
Paul Mackerras712fcc02005-11-30 09:28:16 +11009372}
9373
Thomas Arcila314f5de2008-03-24 12:55:36 +01009374proc choose_extdiff {} {
9375 global extdifftool
9376
9377 set prog [tk_getOpenFile -title "External diff tool" -multiple false]
9378 if {$prog ne {}} {
9379 set extdifftool $prog
9380 }
9381}
9382
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10009383proc choosecolor {v vi w x cmd} {
9384 global $v
9385
9386 set c [tk_chooseColor -initialcolor [lindex [set $v] $vi] \
Christian Stimmingd990ced2007-11-07 18:42:55 +01009387 -title [mc "Gitk: choose color for %s" $x]]
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10009388 if {$c eq {}} return
9389 $w conf -background $c
9390 lset $v $vi $c
9391 eval $cmd $c
9392}
9393
Mark Levedahl60378c02007-05-20 12:12:48 -04009394proc setselbg {c} {
9395 global bglist cflist
9396 foreach w $bglist {
9397 $w configure -selectbackground $c
9398 }
9399 $cflist tag configure highlight \
9400 -background [$cflist cget -selectbackground]
9401 allcanvs itemconf secsel -fill $c
9402}
9403
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10009404proc setbg {c} {
9405 global bglist
9406
9407 foreach w $bglist {
9408 $w conf -background $c
9409 }
9410}
9411
9412proc setfg {c} {
9413 global fglist canv
9414
9415 foreach w $fglist {
9416 $w conf -foreground $c
9417 }
9418 allcanvs itemconf text -fill $c
9419 $canv itemconf circle -outline $c
9420}
9421
Paul Mackerras712fcc02005-11-30 09:28:16 +11009422proc prefscan {} {
Paul Mackerras94503912007-10-23 10:33:38 +10009423 global oldprefs prefstop
Paul Mackerras712fcc02005-11-30 09:28:16 +11009424
Paul Mackerras3de07112007-10-23 22:40:50 +10009425 foreach v {maxwidth maxgraphpct showneartags showlocalchanges \
Paul Mackerras94503912007-10-23 10:33:38 +10009426 limitdiffs tabstop} {
9427 global $v
Paul Mackerras712fcc02005-11-30 09:28:16 +11009428 set $v $oldprefs($v)
9429 }
9430 catch {destroy $prefstop}
9431 unset prefstop
Paul Mackerras9a7558f2007-10-06 20:16:06 +10009432 fontcan
Paul Mackerras712fcc02005-11-30 09:28:16 +11009433}
9434
9435proc prefsok {} {
9436 global maxwidth maxgraphpct
Paul Mackerras219ea3a2006-09-07 10:21:39 +10009437 global oldprefs prefstop showneartags showlocalchanges
Paul Mackerras9a7558f2007-10-06 20:16:06 +10009438 global fontpref mainfont textfont uifont
Paul Mackerras7b3b1512007-10-27 21:23:20 +10009439 global limitdiffs treediffs
Paul Mackerras712fcc02005-11-30 09:28:16 +11009440
9441 catch {destroy $prefstop}
9442 unset prefstop
Paul Mackerras9a7558f2007-10-06 20:16:06 +10009443 fontcan
9444 set fontchanged 0
9445 if {$mainfont ne $fontpref(mainfont)} {
9446 set mainfont $fontpref(mainfont)
9447 parsefont mainfont $mainfont
9448 eval font configure mainfont [fontflags mainfont]
9449 eval font configure mainfontbold [fontflags mainfont 1]
9450 setcoords
9451 set fontchanged 1
9452 }
9453 if {$textfont ne $fontpref(textfont)} {
9454 set textfont $fontpref(textfont)
9455 parsefont textfont $textfont
9456 eval font configure textfont [fontflags textfont]
9457 eval font configure textfontbold [fontflags textfont 1]
9458 }
9459 if {$uifont ne $fontpref(uifont)} {
9460 set uifont $fontpref(uifont)
9461 parsefont uifont $uifont
9462 eval font configure uifont [fontflags uifont]
9463 }
Paul Mackerras32f1b3e2007-09-28 21:27:39 +10009464 settabs
Paul Mackerras219ea3a2006-09-07 10:21:39 +10009465 if {$showlocalchanges != $oldprefs(showlocalchanges)} {
9466 if {$showlocalchanges} {
9467 doshowlocalchanges
9468 } else {
9469 dohidelocalchanges
9470 }
9471 }
Paul Mackerras74a40c72007-10-24 10:16:56 +10009472 if {$limitdiffs != $oldprefs(limitdiffs)} {
9473 # treediffs elements are limited by path
9474 catch {unset treediffs}
9475 }
Paul Mackerras9a7558f2007-10-06 20:16:06 +10009476 if {$fontchanged || $maxwidth != $oldprefs(maxwidth)
Paul Mackerras712fcc02005-11-30 09:28:16 +11009477 || $maxgraphpct != $oldprefs(maxgraphpct)} {
9478 redisplay
Paul Mackerras7a39a172007-10-23 10:15:11 +10009479 } elseif {$showneartags != $oldprefs(showneartags) ||
9480 $limitdiffs != $oldprefs(limitdiffs)} {
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10009481 reselectline
Paul Mackerras712fcc02005-11-30 09:28:16 +11009482 }
9483}
9484
9485proc formatdate {d} {
Arjen Laarhovene8b5f4b2007-08-14 22:02:04 +02009486 global datetimeformat
Paul Mackerras219ea3a2006-09-07 10:21:39 +10009487 if {$d ne {}} {
Arjen Laarhovene8b5f4b2007-08-14 22:02:04 +02009488 set d [clock format $d -format $datetimeformat]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10009489 }
9490 return $d
Paul Mackerras232475d2005-11-15 10:34:03 +11009491}
9492
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +11009493# This list of encoding names and aliases is distilled from
9494# http://www.iana.org/assignments/character-sets.
9495# Not all of them are supported by Tcl.
9496set encoding_aliases {
9497 { ANSI_X3.4-1968 iso-ir-6 ANSI_X3.4-1986 ISO_646.irv:1991 ASCII
9498 ISO646-US US-ASCII us IBM367 cp367 csASCII }
9499 { ISO-10646-UTF-1 csISO10646UTF1 }
9500 { ISO_646.basic:1983 ref csISO646basic1983 }
9501 { INVARIANT csINVARIANT }
9502 { ISO_646.irv:1983 iso-ir-2 irv csISO2IntlRefVersion }
9503 { BS_4730 iso-ir-4 ISO646-GB gb uk csISO4UnitedKingdom }
9504 { NATS-SEFI iso-ir-8-1 csNATSSEFI }
9505 { NATS-SEFI-ADD iso-ir-8-2 csNATSSEFIADD }
9506 { NATS-DANO iso-ir-9-1 csNATSDANO }
9507 { NATS-DANO-ADD iso-ir-9-2 csNATSDANOADD }
9508 { SEN_850200_B iso-ir-10 FI ISO646-FI ISO646-SE se csISO10Swedish }
9509 { SEN_850200_C iso-ir-11 ISO646-SE2 se2 csISO11SwedishForNames }
9510 { KS_C_5601-1987 iso-ir-149 KS_C_5601-1989 KSC_5601 korean csKSC56011987 }
9511 { ISO-2022-KR csISO2022KR }
9512 { EUC-KR csEUCKR }
9513 { ISO-2022-JP csISO2022JP }
9514 { ISO-2022-JP-2 csISO2022JP2 }
9515 { JIS_C6220-1969-jp JIS_C6220-1969 iso-ir-13 katakana x0201-7
9516 csISO13JISC6220jp }
9517 { JIS_C6220-1969-ro iso-ir-14 jp ISO646-JP csISO14JISC6220ro }
9518 { IT iso-ir-15 ISO646-IT csISO15Italian }
9519 { PT iso-ir-16 ISO646-PT csISO16Portuguese }
9520 { ES iso-ir-17 ISO646-ES csISO17Spanish }
9521 { greek7-old iso-ir-18 csISO18Greek7Old }
9522 { latin-greek iso-ir-19 csISO19LatinGreek }
9523 { DIN_66003 iso-ir-21 de ISO646-DE csISO21German }
9524 { NF_Z_62-010_(1973) iso-ir-25 ISO646-FR1 csISO25French }
9525 { Latin-greek-1 iso-ir-27 csISO27LatinGreek1 }
9526 { ISO_5427 iso-ir-37 csISO5427Cyrillic }
9527 { JIS_C6226-1978 iso-ir-42 csISO42JISC62261978 }
9528 { BS_viewdata iso-ir-47 csISO47BSViewdata }
9529 { INIS iso-ir-49 csISO49INIS }
9530 { INIS-8 iso-ir-50 csISO50INIS8 }
9531 { INIS-cyrillic iso-ir-51 csISO51INISCyrillic }
9532 { ISO_5427:1981 iso-ir-54 ISO5427Cyrillic1981 }
9533 { ISO_5428:1980 iso-ir-55 csISO5428Greek }
9534 { GB_1988-80 iso-ir-57 cn ISO646-CN csISO57GB1988 }
9535 { GB_2312-80 iso-ir-58 chinese csISO58GB231280 }
9536 { NS_4551-1 iso-ir-60 ISO646-NO no csISO60DanishNorwegian
9537 csISO60Norwegian1 }
9538 { NS_4551-2 ISO646-NO2 iso-ir-61 no2 csISO61Norwegian2 }
9539 { NF_Z_62-010 iso-ir-69 ISO646-FR fr csISO69French }
9540 { videotex-suppl iso-ir-70 csISO70VideotexSupp1 }
9541 { PT2 iso-ir-84 ISO646-PT2 csISO84Portuguese2 }
9542 { ES2 iso-ir-85 ISO646-ES2 csISO85Spanish2 }
9543 { MSZ_7795.3 iso-ir-86 ISO646-HU hu csISO86Hungarian }
9544 { JIS_C6226-1983 iso-ir-87 x0208 JIS_X0208-1983 csISO87JISX0208 }
9545 { greek7 iso-ir-88 csISO88Greek7 }
9546 { ASMO_449 ISO_9036 arabic7 iso-ir-89 csISO89ASMO449 }
9547 { iso-ir-90 csISO90 }
9548 { JIS_C6229-1984-a iso-ir-91 jp-ocr-a csISO91JISC62291984a }
9549 { JIS_C6229-1984-b iso-ir-92 ISO646-JP-OCR-B jp-ocr-b
9550 csISO92JISC62991984b }
9551 { JIS_C6229-1984-b-add iso-ir-93 jp-ocr-b-add csISO93JIS62291984badd }
9552 { JIS_C6229-1984-hand iso-ir-94 jp-ocr-hand csISO94JIS62291984hand }
9553 { JIS_C6229-1984-hand-add iso-ir-95 jp-ocr-hand-add
9554 csISO95JIS62291984handadd }
9555 { JIS_C6229-1984-kana iso-ir-96 csISO96JISC62291984kana }
9556 { ISO_2033-1983 iso-ir-98 e13b csISO2033 }
9557 { ANSI_X3.110-1983 iso-ir-99 CSA_T500-1983 NAPLPS csISO99NAPLPS }
9558 { ISO_8859-1:1987 iso-ir-100 ISO_8859-1 ISO-8859-1 latin1 l1 IBM819
9559 CP819 csISOLatin1 }
9560 { ISO_8859-2:1987 iso-ir-101 ISO_8859-2 ISO-8859-2 latin2 l2 csISOLatin2 }
9561 { T.61-7bit iso-ir-102 csISO102T617bit }
9562 { T.61-8bit T.61 iso-ir-103 csISO103T618bit }
9563 { ISO_8859-3:1988 iso-ir-109 ISO_8859-3 ISO-8859-3 latin3 l3 csISOLatin3 }
9564 { ISO_8859-4:1988 iso-ir-110 ISO_8859-4 ISO-8859-4 latin4 l4 csISOLatin4 }
9565 { ECMA-cyrillic iso-ir-111 KOI8-E csISO111ECMACyrillic }
9566 { CSA_Z243.4-1985-1 iso-ir-121 ISO646-CA csa7-1 ca csISO121Canadian1 }
9567 { CSA_Z243.4-1985-2 iso-ir-122 ISO646-CA2 csa7-2 csISO122Canadian2 }
9568 { CSA_Z243.4-1985-gr iso-ir-123 csISO123CSAZ24341985gr }
9569 { ISO_8859-6:1987 iso-ir-127 ISO_8859-6 ISO-8859-6 ECMA-114 ASMO-708
9570 arabic csISOLatinArabic }
9571 { ISO_8859-6-E csISO88596E ISO-8859-6-E }
9572 { ISO_8859-6-I csISO88596I ISO-8859-6-I }
9573 { ISO_8859-7:1987 iso-ir-126 ISO_8859-7 ISO-8859-7 ELOT_928 ECMA-118
9574 greek greek8 csISOLatinGreek }
9575 { T.101-G2 iso-ir-128 csISO128T101G2 }
9576 { ISO_8859-8:1988 iso-ir-138 ISO_8859-8 ISO-8859-8 hebrew
9577 csISOLatinHebrew }
9578 { ISO_8859-8-E csISO88598E ISO-8859-8-E }
9579 { ISO_8859-8-I csISO88598I ISO-8859-8-I }
9580 { CSN_369103 iso-ir-139 csISO139CSN369103 }
9581 { JUS_I.B1.002 iso-ir-141 ISO646-YU js yu csISO141JUSIB1002 }
9582 { ISO_6937-2-add iso-ir-142 csISOTextComm }
9583 { IEC_P27-1 iso-ir-143 csISO143IECP271 }
9584 { ISO_8859-5:1988 iso-ir-144 ISO_8859-5 ISO-8859-5 cyrillic
9585 csISOLatinCyrillic }
9586 { JUS_I.B1.003-serb iso-ir-146 serbian csISO146Serbian }
9587 { JUS_I.B1.003-mac macedonian iso-ir-147 csISO147Macedonian }
9588 { ISO_8859-9:1989 iso-ir-148 ISO_8859-9 ISO-8859-9 latin5 l5 csISOLatin5 }
9589 { greek-ccitt iso-ir-150 csISO150 csISO150GreekCCITT }
9590 { NC_NC00-10:81 cuba iso-ir-151 ISO646-CU csISO151Cuba }
9591 { ISO_6937-2-25 iso-ir-152 csISO6937Add }
9592 { GOST_19768-74 ST_SEV_358-88 iso-ir-153 csISO153GOST1976874 }
9593 { ISO_8859-supp iso-ir-154 latin1-2-5 csISO8859Supp }
9594 { ISO_10367-box iso-ir-155 csISO10367Box }
9595 { ISO-8859-10 iso-ir-157 l6 ISO_8859-10:1992 csISOLatin6 latin6 }
9596 { latin-lap lap iso-ir-158 csISO158Lap }
9597 { JIS_X0212-1990 x0212 iso-ir-159 csISO159JISX02121990 }
9598 { DS_2089 DS2089 ISO646-DK dk csISO646Danish }
9599 { us-dk csUSDK }
9600 { dk-us csDKUS }
9601 { JIS_X0201 X0201 csHalfWidthKatakana }
9602 { KSC5636 ISO646-KR csKSC5636 }
9603 { ISO-10646-UCS-2 csUnicode }
9604 { ISO-10646-UCS-4 csUCS4 }
9605 { DEC-MCS dec csDECMCS }
9606 { hp-roman8 roman8 r8 csHPRoman8 }
9607 { macintosh mac csMacintosh }
9608 { IBM037 cp037 ebcdic-cp-us ebcdic-cp-ca ebcdic-cp-wt ebcdic-cp-nl
9609 csIBM037 }
9610 { IBM038 EBCDIC-INT cp038 csIBM038 }
9611 { IBM273 CP273 csIBM273 }
9612 { IBM274 EBCDIC-BE CP274 csIBM274 }
9613 { IBM275 EBCDIC-BR cp275 csIBM275 }
9614 { IBM277 EBCDIC-CP-DK EBCDIC-CP-NO csIBM277 }
9615 { IBM278 CP278 ebcdic-cp-fi ebcdic-cp-se csIBM278 }
9616 { IBM280 CP280 ebcdic-cp-it csIBM280 }
9617 { IBM281 EBCDIC-JP-E cp281 csIBM281 }
9618 { IBM284 CP284 ebcdic-cp-es csIBM284 }
9619 { IBM285 CP285 ebcdic-cp-gb csIBM285 }
9620 { IBM290 cp290 EBCDIC-JP-kana csIBM290 }
9621 { IBM297 cp297 ebcdic-cp-fr csIBM297 }
9622 { IBM420 cp420 ebcdic-cp-ar1 csIBM420 }
9623 { IBM423 cp423 ebcdic-cp-gr csIBM423 }
9624 { IBM424 cp424 ebcdic-cp-he csIBM424 }
9625 { IBM437 cp437 437 csPC8CodePage437 }
9626 { IBM500 CP500 ebcdic-cp-be ebcdic-cp-ch csIBM500 }
9627 { IBM775 cp775 csPC775Baltic }
9628 { IBM850 cp850 850 csPC850Multilingual }
9629 { IBM851 cp851 851 csIBM851 }
9630 { IBM852 cp852 852 csPCp852 }
9631 { IBM855 cp855 855 csIBM855 }
9632 { IBM857 cp857 857 csIBM857 }
9633 { IBM860 cp860 860 csIBM860 }
9634 { IBM861 cp861 861 cp-is csIBM861 }
9635 { IBM862 cp862 862 csPC862LatinHebrew }
9636 { IBM863 cp863 863 csIBM863 }
9637 { IBM864 cp864 csIBM864 }
9638 { IBM865 cp865 865 csIBM865 }
9639 { IBM866 cp866 866 csIBM866 }
9640 { IBM868 CP868 cp-ar csIBM868 }
9641 { IBM869 cp869 869 cp-gr csIBM869 }
9642 { IBM870 CP870 ebcdic-cp-roece ebcdic-cp-yu csIBM870 }
9643 { IBM871 CP871 ebcdic-cp-is csIBM871 }
9644 { IBM880 cp880 EBCDIC-Cyrillic csIBM880 }
9645 { IBM891 cp891 csIBM891 }
9646 { IBM903 cp903 csIBM903 }
9647 { IBM904 cp904 904 csIBBM904 }
9648 { IBM905 CP905 ebcdic-cp-tr csIBM905 }
9649 { IBM918 CP918 ebcdic-cp-ar2 csIBM918 }
9650 { IBM1026 CP1026 csIBM1026 }
9651 { EBCDIC-AT-DE csIBMEBCDICATDE }
9652 { EBCDIC-AT-DE-A csEBCDICATDEA }
9653 { EBCDIC-CA-FR csEBCDICCAFR }
9654 { EBCDIC-DK-NO csEBCDICDKNO }
9655 { EBCDIC-DK-NO-A csEBCDICDKNOA }
9656 { EBCDIC-FI-SE csEBCDICFISE }
9657 { EBCDIC-FI-SE-A csEBCDICFISEA }
9658 { EBCDIC-FR csEBCDICFR }
9659 { EBCDIC-IT csEBCDICIT }
9660 { EBCDIC-PT csEBCDICPT }
9661 { EBCDIC-ES csEBCDICES }
9662 { EBCDIC-ES-A csEBCDICESA }
9663 { EBCDIC-ES-S csEBCDICESS }
9664 { EBCDIC-UK csEBCDICUK }
9665 { EBCDIC-US csEBCDICUS }
9666 { UNKNOWN-8BIT csUnknown8BiT }
9667 { MNEMONIC csMnemonic }
9668 { MNEM csMnem }
9669 { VISCII csVISCII }
9670 { VIQR csVIQR }
9671 { KOI8-R csKOI8R }
9672 { IBM00858 CCSID00858 CP00858 PC-Multilingual-850+euro }
9673 { IBM00924 CCSID00924 CP00924 ebcdic-Latin9--euro }
9674 { IBM01140 CCSID01140 CP01140 ebcdic-us-37+euro }
9675 { IBM01141 CCSID01141 CP01141 ebcdic-de-273+euro }
9676 { IBM01142 CCSID01142 CP01142 ebcdic-dk-277+euro ebcdic-no-277+euro }
9677 { IBM01143 CCSID01143 CP01143 ebcdic-fi-278+euro ebcdic-se-278+euro }
9678 { IBM01144 CCSID01144 CP01144 ebcdic-it-280+euro }
9679 { IBM01145 CCSID01145 CP01145 ebcdic-es-284+euro }
9680 { IBM01146 CCSID01146 CP01146 ebcdic-gb-285+euro }
9681 { IBM01147 CCSID01147 CP01147 ebcdic-fr-297+euro }
9682 { IBM01148 CCSID01148 CP01148 ebcdic-international-500+euro }
9683 { IBM01149 CCSID01149 CP01149 ebcdic-is-871+euro }
9684 { IBM1047 IBM-1047 }
9685 { PTCP154 csPTCP154 PT154 CP154 Cyrillic-Asian }
9686 { Amiga-1251 Ami1251 Amiga1251 Ami-1251 }
9687 { UNICODE-1-1 csUnicode11 }
9688 { CESU-8 csCESU-8 }
9689 { BOCU-1 csBOCU-1 }
9690 { UNICODE-1-1-UTF-7 csUnicode11UTF7 }
9691 { ISO-8859-14 iso-ir-199 ISO_8859-14:1998 ISO_8859-14 latin8 iso-celtic
9692 l8 }
9693 { ISO-8859-15 ISO_8859-15 Latin-9 }
9694 { ISO-8859-16 iso-ir-226 ISO_8859-16:2001 ISO_8859-16 latin10 l10 }
9695 { GBK CP936 MS936 windows-936 }
9696 { JIS_Encoding csJISEncoding }
9697 { Shift_JIS MS_Kanji csShiftJIS }
9698 { Extended_UNIX_Code_Packed_Format_for_Japanese csEUCPkdFmtJapanese
9699 EUC-JP }
9700 { Extended_UNIX_Code_Fixed_Width_for_Japanese csEUCFixWidJapanese }
9701 { ISO-10646-UCS-Basic csUnicodeASCII }
9702 { ISO-10646-Unicode-Latin1 csUnicodeLatin1 ISO-10646 }
9703 { ISO-Unicode-IBM-1261 csUnicodeIBM1261 }
9704 { ISO-Unicode-IBM-1268 csUnicodeIBM1268 }
9705 { ISO-Unicode-IBM-1276 csUnicodeIBM1276 }
9706 { ISO-Unicode-IBM-1264 csUnicodeIBM1264 }
9707 { ISO-Unicode-IBM-1265 csUnicodeIBM1265 }
9708 { ISO-8859-1-Windows-3.0-Latin-1 csWindows30Latin1 }
9709 { ISO-8859-1-Windows-3.1-Latin-1 csWindows31Latin1 }
9710 { ISO-8859-2-Windows-Latin-2 csWindows31Latin2 }
9711 { ISO-8859-9-Windows-Latin-5 csWindows31Latin5 }
9712 { Adobe-Standard-Encoding csAdobeStandardEncoding }
9713 { Ventura-US csVenturaUS }
9714 { Ventura-International csVenturaInternational }
9715 { PC8-Danish-Norwegian csPC8DanishNorwegian }
9716 { PC8-Turkish csPC8Turkish }
9717 { IBM-Symbols csIBMSymbols }
9718 { IBM-Thai csIBMThai }
9719 { HP-Legal csHPLegal }
9720 { HP-Pi-font csHPPiFont }
9721 { HP-Math8 csHPMath8 }
9722 { Adobe-Symbol-Encoding csHPPSMath }
9723 { HP-DeskTop csHPDesktop }
9724 { Ventura-Math csVenturaMath }
9725 { Microsoft-Publishing csMicrosoftPublishing }
9726 { Windows-31J csWindows31J }
9727 { GB2312 csGB2312 }
9728 { Big5 csBig5 }
9729}
9730
9731proc tcl_encoding {enc} {
9732 global encoding_aliases
9733 set names [encoding names]
9734 set lcnames [string tolower $names]
9735 set enc [string tolower $enc]
9736 set i [lsearch -exact $lcnames $enc]
9737 if {$i < 0} {
9738 # look for "isonnn" instead of "iso-nnn" or "iso_nnn"
9739 if {[regsub {^iso[-_]} $enc iso encx]} {
9740 set i [lsearch -exact $lcnames $encx]
9741 }
9742 }
9743 if {$i < 0} {
9744 foreach l $encoding_aliases {
9745 set ll [string tolower $l]
9746 if {[lsearch -exact $ll $enc] < 0} continue
9747 # look through the aliases for one that tcl knows about
9748 foreach e $ll {
9749 set i [lsearch -exact $lcnames $e]
9750 if {$i < 0} {
9751 if {[regsub {^iso[-_]} $e iso ex]} {
9752 set i [lsearch -exact $lcnames $ex]
9753 }
9754 }
9755 if {$i >= 0} break
9756 }
9757 break
9758 }
9759 }
9760 if {$i >= 0} {
9761 return [lindex $names $i]
9762 }
9763 return {}
9764}
9765
Paul Mackerras5d7589d2007-10-20 21:21:03 +10009766# First check that Tcl/Tk is recent enough
9767if {[catch {package require Tk 8.4} err]} {
Christian Stimmingd990ced2007-11-07 18:42:55 +01009768 show_error {} . [mc "Sorry, gitk cannot run with this version of Tcl/Tk.\n\
9769 Gitk requires at least Tcl/Tk 8.4."]
Paul Mackerras5d7589d2007-10-20 21:21:03 +10009770 exit 1
9771}
9772
Paul Mackerras1d10f362005-05-15 12:55:47 +00009773# defaults...
Timo Hirvonen8974c6f2006-05-24 10:57:40 +03009774set wrcomcmd "git diff-tree --stdin -p --pretty"
Junio C Hamano671bc152005-11-27 16:12:51 -08009775
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +11009776set gitencoding {}
Junio C Hamano671bc152005-11-27 16:12:51 -08009777catch {
Paul Mackerras27cb61c2007-02-15 08:54:34 +11009778 set gitencoding [exec git config --get i18n.commitencoding]
Junio C Hamano671bc152005-11-27 16:12:51 -08009779}
9780if {$gitencoding == ""} {
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +11009781 set gitencoding "utf-8"
9782}
9783set tclencoding [tcl_encoding $gitencoding]
9784if {$tclencoding == {}} {
9785 puts stderr "Warning: encoding $gitencoding is not supported by Tcl/Tk"
Junio C Hamano671bc152005-11-27 16:12:51 -08009786}
Paul Mackerras1d10f362005-05-15 12:55:47 +00009787
9788set mainfont {Helvetica 9}
Paul Mackerras1d10f362005-05-15 12:55:47 +00009789set textfont {Courier 9}
Keith Packard4840be62006-04-04 00:19:45 -07009790set uifont {Helvetica 9 bold}
Mark Levedahl7e12f1a2007-05-20 11:45:50 -04009791set tabstop 8
Paul Mackerrasb74fd572005-07-16 07:46:13 -04009792set findmergefiles 0
Paul Mackerras8d858d12005-08-05 09:52:16 +10009793set maxgraphpct 50
Paul Mackerrasf6075eb2005-08-18 09:30:10 +10009794set maxwidth 16
Paul Mackerras232475d2005-11-15 10:34:03 +11009795set revlistorder 0
Paul Mackerras757f17b2005-11-21 09:56:07 +11009796set fastdate 0
Paul Mackerras6e8c8702007-07-31 21:03:06 +10009797set uparrowlen 5
9798set downarrowlen 5
9799set mingaplen 100
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10009800set cmitmode "patch"
Sergey Vlasovf1b86292006-05-15 19:13:14 +04009801set wrapcomment "none"
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10009802set showneartags 1
Paul Mackerras0a4dd8b2007-06-16 21:21:57 +10009803set maxrefs 20
Paul Mackerras322a8cc2006-10-15 18:03:46 +10009804set maxlinelen 200
Paul Mackerras219ea3a2006-09-07 10:21:39 +10009805set showlocalchanges 1
Paul Mackerras7a39a172007-10-23 10:15:11 +10009806set limitdiffs 1
Arjen Laarhovene8b5f4b2007-08-14 22:02:04 +02009807set datetimeformat "%Y-%m-%d %H:%M:%S"
Jeff King95293b52008-03-06 06:49:25 -05009808set autoselect 1
Paul Mackerras1d10f362005-05-15 12:55:47 +00009809
Thomas Arcila314f5de2008-03-24 12:55:36 +01009810set extdifftool "meld"
9811
Paul Mackerras1d10f362005-05-15 12:55:47 +00009812set colors {green red blue magenta darkgrey brown orange}
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10009813set bgcolor white
9814set fgcolor black
9815set diffcolors {red "#00a000" blue}
Steffen Prohaska890fae72007-08-12 12:05:46 +02009816set diffcontext 3
Steffen Prohaskab9b86002008-01-17 23:42:55 +01009817set ignorespace 0
Mark Levedahl60378c02007-05-20 12:12:48 -04009818set selectbgcolor gray85
Paul Mackerras1d10f362005-05-15 12:55:47 +00009819
Paul Mackerrasc11ff122008-05-26 10:11:33 +10009820set circlecolors {white blue gray blue blue}
9821
Christian Stimming663c3aa2007-11-07 18:40:59 +01009822## For msgcat loading, first locate the installation location.
9823if { [info exists ::env(GITK_MSGSDIR)] } {
9824 ## Msgsdir was manually set in the environment.
9825 set gitk_msgsdir $::env(GITK_MSGSDIR)
9826} else {
9827 ## Let's guess the prefix from argv0.
9828 set gitk_prefix [file dirname [file dirname [file normalize $argv0]]]
9829 set gitk_libdir [file join $gitk_prefix share gitk lib]
9830 set gitk_msgsdir [file join $gitk_libdir msgs]
9831 unset gitk_prefix
9832}
9833
9834## Internationalization (i18n) through msgcat and gettext. See
9835## http://www.gnu.org/software/gettext/manual/html_node/Tcl.html
9836package require msgcat
9837namespace import ::msgcat::mc
9838## And eventually load the actual message catalog
9839::msgcat::mcload $gitk_msgsdir
9840
Paul Mackerras1d10f362005-05-15 12:55:47 +00009841catch {source ~/.gitk}
9842
Paul Mackerras712fcc02005-11-30 09:28:16 +11009843font create optionfont -family sans-serif -size -12
Paul Mackerras17386062005-05-18 22:51:00 +00009844
Paul Mackerras0ed1dd32007-10-06 18:27:37 +10009845parsefont mainfont $mainfont
9846eval font create mainfont [fontflags mainfont]
9847eval font create mainfontbold [fontflags mainfont 1]
9848
9849parsefont textfont $textfont
9850eval font create textfont [fontflags textfont]
9851eval font create textfontbold [fontflags textfont 1]
9852
9853parsefont uifont $uifont
9854eval font create uifont [fontflags uifont]
Paul Mackerras1db95b02005-05-09 04:08:39 +00009855
Paul Mackerrasb039f0a2008-01-06 15:54:46 +11009856setoptions
9857
Paul Mackerrasaa81d972006-02-28 11:27:12 +11009858# check that we can find a .git directory somewhere...
Alex Riesen6c87d602007-07-29 22:29:45 +02009859if {[catch {set gitdir [gitdir]}]} {
Christian Stimmingd990ced2007-11-07 18:42:55 +01009860 show_error {} . [mc "Cannot find a git repository here."]
Alex Riesen6c87d602007-07-29 22:29:45 +02009861 exit 1
9862}
Paul Mackerrasaa81d972006-02-28 11:27:12 +11009863if {![file isdirectory $gitdir]} {
Christian Stimmingd990ced2007-11-07 18:42:55 +01009864 show_error {} . [mc "Cannot find the git directory \"%s\"." $gitdir]
Paul Mackerrasaa81d972006-02-28 11:27:12 +11009865 exit 1
9866}
9867
Paul Mackerrascdaee5d2007-07-12 22:29:49 +10009868set revtreeargs {}
Paul Mackerras098dd8a2006-05-03 09:32:53 +10009869set cmdline_files {}
Paul Mackerrascdaee5d2007-07-12 22:29:49 +10009870set i 0
Yann Dirson2d480852008-02-21 21:23:31 +01009871set revtreeargscmd {}
Paul Mackerrascdaee5d2007-07-12 22:29:49 +10009872foreach arg $argv {
Yann Dirson2d480852008-02-21 21:23:31 +01009873 switch -glob -- $arg {
Paul Mackerras6ebedab2007-07-13 13:45:55 +10009874 "" { }
Paul Mackerrascdaee5d2007-07-12 22:29:49 +10009875 "--" {
9876 set cmdline_files [lrange $argv [expr {$i + 1}] end]
9877 break
9878 }
Yann Dirson2d480852008-02-21 21:23:31 +01009879 "--argscmd=*" {
9880 set revtreeargscmd [string range $arg 10 end]
9881 }
Paul Mackerrascdaee5d2007-07-12 22:29:49 +10009882 default {
9883 lappend revtreeargs $arg
9884 }
9885 }
9886 incr i
9887}
9888
9889if {$i >= [llength $argv] && $revtreeargs ne {}} {
Paul Mackerras3ed31a82008-04-26 16:00:00 +10009890 # no -- on command line, but some arguments (other than --argscmd)
Paul Mackerras098dd8a2006-05-03 09:32:53 +10009891 if {[catch {
Timo Hirvonen8974c6f2006-05-24 10:57:40 +03009892 set f [eval exec git rev-parse --no-revs --no-flags $revtreeargs]
Paul Mackerras098dd8a2006-05-03 09:32:53 +10009893 set cmdline_files [split $f "\n"]
9894 set n [llength $cmdline_files]
9895 set revtreeargs [lrange $revtreeargs 0 end-$n]
Paul Mackerrascdaee5d2007-07-12 22:29:49 +10009896 # Unfortunately git rev-parse doesn't produce an error when
9897 # something is both a revision and a filename. To be consistent
9898 # with git log and git rev-list, check revtreeargs for filenames.
9899 foreach arg $revtreeargs {
9900 if {[file exists $arg]} {
Christian Stimmingd990ced2007-11-07 18:42:55 +01009901 show_error {} . [mc "Ambiguous argument '%s': both revision\
9902 and filename" $arg]
Paul Mackerrascdaee5d2007-07-12 22:29:49 +10009903 exit 1
9904 }
9905 }
Paul Mackerras098dd8a2006-05-03 09:32:53 +10009906 } err]} {
9907 # unfortunately we get both stdout and stderr in $err,
9908 # so look for "fatal:".
9909 set i [string first "fatal:" $err]
9910 if {$i > 0} {
Junio C Hamanob5e09632006-05-26 00:07:15 -07009911 set err [string range $err [expr {$i + 6}] end]
Paul Mackerras098dd8a2006-05-03 09:32:53 +10009912 }
Christian Stimmingd990ced2007-11-07 18:42:55 +01009913 show_error {} . "[mc "Bad arguments to gitk:"]\n$err"
Paul Mackerras098dd8a2006-05-03 09:32:53 +10009914 exit 1
9915 }
9916}
9917
Paul Mackerras219ea3a2006-09-07 10:21:39 +10009918set nullid "0000000000000000000000000000000000000000"
Paul Mackerras8f489362007-07-13 19:49:37 +10009919set nullid2 "0000000000000000000000000000000000000001"
Thomas Arcila314f5de2008-03-24 12:55:36 +01009920set nullfile "/dev/null"
Paul Mackerras8f489362007-07-13 19:49:37 +10009921
Paul Mackerras32f1b3e2007-09-28 21:27:39 +10009922set have_tk85 [expr {[package vcompare $tk_version "8.5"] >= 0}]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10009923
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10009924set runq {}
Paul Mackerrasd6982062005-08-06 22:06:06 +10009925set history {}
9926set historyindex 0
Paul Mackerras908c3582006-05-20 09:38:11 +10009927set fh_serial 0
Paul Mackerras908c3582006-05-20 09:38:11 +10009928set nhl_names {}
Paul Mackerras63b79192006-05-20 21:31:52 +10009929set highlight_paths {}
Paul Mackerras687c8762007-09-22 12:49:33 +10009930set findpattern {}
Paul Mackerras1902c272006-05-25 21:25:13 +10009931set searchdirn -forwards
Paul Mackerras4e7d6772006-05-30 21:33:07 +10009932set boldrows {}
9933set boldnamerows {}
Paul Mackerrasa8d610a2007-04-19 11:39:12 +10009934set diffelide {0 0}
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10009935set markingmatches 0
Paul Mackerras97645682007-08-23 22:24:38 +10009936set linkentercount 0
Paul Mackerras03800812007-08-29 21:45:21 +10009937set need_redisplay 0
9938set nrows_drawn 0
Paul Mackerras32f1b3e2007-09-28 21:27:39 +10009939set firsttabstop 0
Paul Mackerras9f1afe02006-02-19 22:44:47 +11009940
Paul Mackerras50b44ec2006-04-04 10:16:22 +10009941set nextviewnum 1
9942set curview 0
Paul Mackerrasa90a6d22006-04-25 17:12:46 +10009943set selectedview 0
Christian Stimmingb007ee22007-11-07 18:44:35 +01009944set selectedhlview [mc "None"]
9945set highlight_related [mc "None"]
Paul Mackerras687c8762007-09-22 12:49:33 +10009946set highlight_files {}
Paul Mackerras50b44ec2006-04-04 10:16:22 +10009947set viewfiles(0) {}
Paul Mackerrasa90a6d22006-04-25 17:12:46 +10009948set viewperm(0) 0
Paul Mackerras098dd8a2006-05-03 09:32:53 +10009949set viewargs(0) {}
Yann Dirson2d480852008-02-21 21:23:31 +01009950set viewargscmd(0) {}
Paul Mackerras50b44ec2006-04-04 10:16:22 +10009951
Paul Mackerras94b4a692008-05-20 20:51:06 +10009952set selectedline {}
Paul Mackerras6df74032008-05-11 22:13:02 +10009953set numcommits 0
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11009954set loginstance 0
Paul Mackerras098dd8a2006-05-03 09:32:53 +10009955set cmdlineok 0
Paul Mackerras1db95b02005-05-09 04:08:39 +00009956set stopped 0
Paul Mackerras1db95b02005-05-09 04:08:39 +00009957set stuffsaved 0
Paul Mackerras74daedb2005-06-27 19:27:32 +10009958set patchnum 0
Paul Mackerras219ea3a2006-09-07 10:21:39 +10009959set lserial 0
David Aguilarcb8329a2008-03-10 03:54:56 -07009960set isworktree [expr {[exec git rev-parse --is-inside-work-tree] == "true"}]
Paul Mackerras1db95b02005-05-09 04:08:39 +00009961setcoords
Paul Mackerrasd94f8cd2006-04-06 10:18:23 +10009962makewindow
Paul Mackerras0eafba12007-07-23 21:35:03 +10009963# wait for the window to become visible
9964tkwait visibility .
Doug Maxey6c283322006-12-10 14:31:46 -06009965wm title . "[file tail $argv0]: [file tail [pwd]]"
Paul Mackerras887fe3c2005-05-21 07:35:37 +00009966readrefs
Paul Mackerrasa8aaf192006-04-23 22:45:55 +10009967
Yann Dirson2d480852008-02-21 21:23:31 +01009968if {$cmdline_files ne {} || $revtreeargs ne {} || $revtreeargscmd ne {}} {
Paul Mackerras50b44ec2006-04-04 10:16:22 +10009969 # create a view for the files/dirs specified on the command line
9970 set curview 1
Paul Mackerrasa90a6d22006-04-25 17:12:46 +10009971 set selectedview 1
Paul Mackerras50b44ec2006-04-04 10:16:22 +10009972 set nextviewnum 2
Christian Stimmingd990ced2007-11-07 18:42:55 +01009973 set viewname(1) [mc "Command line"]
Paul Mackerras50b44ec2006-04-04 10:16:22 +10009974 set viewfiles(1) $cmdline_files
Paul Mackerras098dd8a2006-05-03 09:32:53 +10009975 set viewargs(1) $revtreeargs
Yann Dirson2d480852008-02-21 21:23:31 +01009976 set viewargscmd(1) $revtreeargscmd
Paul Mackerrasa90a6d22006-04-25 17:12:46 +10009977 set viewperm(1) 0
Paul Mackerras3ed31a82008-04-26 16:00:00 +10009978 set vdatemode(1) 0
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10009979 addviewmenu 1
Christian Stimmingd990ced2007-11-07 18:42:55 +01009980 .bar.view entryconf [mc "Edit view..."] -state normal
9981 .bar.view entryconf [mc "Delete view"] -state normal
Paul Mackerras50b44ec2006-04-04 10:16:22 +10009982}
Paul Mackerrasa90a6d22006-04-25 17:12:46 +10009983
9984if {[info exists permviews]} {
9985 foreach v $permviews {
9986 set n $nextviewnum
9987 incr nextviewnum
9988 set viewname($n) [lindex $v 0]
9989 set viewfiles($n) [lindex $v 1]
Paul Mackerras098dd8a2006-05-03 09:32:53 +10009990 set viewargs($n) [lindex $v 2]
Yann Dirson2d480852008-02-21 21:23:31 +01009991 set viewargscmd($n) [lindex $v 3]
Paul Mackerrasa90a6d22006-04-25 17:12:46 +10009992 set viewperm($n) 1
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10009993 addviewmenu $n
Paul Mackerrasa90a6d22006-04-25 17:12:46 +10009994 }
9995}
Alexander Gavrilov567c34e2008-07-26 20:13:45 +04009996getcommits {}