blob: a0214b7004f141b7c918a5360d85f8f9e2db285c [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 }
Paul Mackerrasee66e082008-05-09 10:14:07 +1000158 "-[puabwcrRBMC]" -
159 "--no-renames" - "--full-index" - "--binary" - "--abbrev=*" -
160 "--find-copies-harder" - "-l*" - "--ext-diff" - "--no-ext-diff" -
161 "--src-prefix=*" - "--dst-prefix=*" - "--no-prefix" -
162 "-O*" - "--text" - "--full-diff" - "--ignore-space-at-eol" -
163 "--ignore-space-change" - "-U*" - "--unified=*" {
Paul Mackerras29582282008-11-18 19:44:20 +1100164 # These request or affect diff output, which we don't want.
165 # Some could be used to set our defaults for diff display.
Paul Mackerrasee66e082008-05-09 10:14:07 +1000166 lappend diffargs $arg
167 }
Paul Mackerrasee66e082008-05-09 10:14:07 +1000168 "--raw" - "--patch-with-raw" - "--patch-with-stat" -
169 "--name-only" - "--name-status" - "--color" - "--color-words" -
170 "--log-size" - "--pretty=*" - "--decorate" - "--abbrev-commit" -
171 "--cc" - "-z" - "--header" - "--parents" - "--boundary" -
172 "--no-color" - "-g" - "--walk-reflogs" - "--no-walk" -
173 "--timestamp" - "relative-date" - "--date=*" - "--stdin" -
174 "--objects" - "--objects-edge" - "--reverse" {
Paul Mackerras29582282008-11-18 19:44:20 +1100175 # These cause our parsing of git log's output to fail, or else
176 # they're options we want to set ourselves, so ignore them.
Paul Mackerrasee66e082008-05-09 10:14:07 +1000177 }
Paul Mackerrasee66e082008-05-09 10:14:07 +1000178 "--stat=*" - "--numstat" - "--shortstat" - "--summary" -
179 "--check" - "--exit-code" - "--quiet" - "--topo-order" -
180 "--full-history" - "--dense" - "--sparse" -
181 "--follow" - "--left-right" - "--encoding=*" {
Paul Mackerras29582282008-11-18 19:44:20 +1100182 # These are harmless, and some are even useful
Paul Mackerrasee66e082008-05-09 10:14:07 +1000183 lappend glflags $arg
184 }
Paul Mackerrasee66e082008-05-09 10:14:07 +1000185 "--diff-filter=*" - "--no-merges" - "--unpacked" -
186 "--max-count=*" - "--skip=*" - "--since=*" - "--after=*" -
187 "--until=*" - "--before=*" - "--max-age=*" - "--min-age=*" -
188 "--author=*" - "--committer=*" - "--grep=*" - "-[iE]" -
189 "--remove-empty" - "--first-parent" - "--cherry-pick" -
Dirk Suesserottf687aaa2009-05-21 15:35:40 +0200190 "-S*" - "--pickaxe-all" - "--pickaxe-regex" -
191 "--simplify-by-decoration" {
Paul Mackerras29582282008-11-18 19:44:20 +1100192 # These mean that we get a subset of the commits
Paul Mackerrasee66e082008-05-09 10:14:07 +1000193 set filtered 1
194 lappend glflags $arg
195 }
Paul Mackerrasee66e082008-05-09 10:14:07 +1000196 "-n" {
Paul Mackerras29582282008-11-18 19:44:20 +1100197 # This appears to be the only one that has a value as a
198 # separate word following it
Paul Mackerrasee66e082008-05-09 10:14:07 +1000199 set filtered 1
200 set nextisval 1
201 lappend glflags $arg
202 }
Paul Mackerras6e7e87c2008-12-02 09:17:46 +1100203 "--not" - "--all" {
Paul Mackerrasee66e082008-05-09 10:14:07 +1000204 lappend revargs $arg
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000205 }
206 "--merge" {
207 set vmergeonly($n) 1
Paul Mackerrasee66e082008-05-09 10:14:07 +1000208 # git rev-parse doesn't understand --merge
209 lappend revargs --gitk-symmetric-diff-marker MERGE_HEAD...HEAD
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000210 }
Paul Mackerrasee66e082008-05-09 10:14:07 +1000211 "-*" {
Paul Mackerras29582282008-11-18 19:44:20 +1100212 # Other flag arguments including -<n>
Paul Mackerrasee66e082008-05-09 10:14:07 +1000213 if {[string is digit -strict [string range $arg 1 end]]} {
214 set filtered 1
215 } else {
216 # a flag argument that we don't recognize;
217 # that means we can't optimize
218 set allknown 0
219 }
220 lappend glflags $arg
221 }
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000222 default {
Paul Mackerras29582282008-11-18 19:44:20 +1100223 # Non-flag arguments specify commits or ranges of commits
Paul Mackerrasee66e082008-05-09 10:14:07 +1000224 if {[string match "*...*" $arg]} {
225 lappend revargs --gitk-symmetric-diff-marker
226 }
227 lappend revargs $arg
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000228 }
229 }
230 }
Paul Mackerrasee66e082008-05-09 10:14:07 +1000231 set vdflags($n) $diffargs
232 set vflags($n) $glflags
233 set vrevs($n) $revargs
234 set vfiltered($n) $filtered
235 set vorigargs($n) $origargs
236 return $allknown
237}
238
239proc parseviewrevs {view revs} {
240 global vposids vnegids
241
242 if {$revs eq {}} {
243 set revs HEAD
244 }
245 if {[catch {set ids [eval exec git rev-parse $revs]} err]} {
246 # we get stdout followed by stderr in $err
247 # for an unknown rev, git rev-parse echoes it and then errors out
248 set errlines [split $err "\n"]
249 set badrev {}
250 for {set l 0} {$l < [llength $errlines]} {incr l} {
251 set line [lindex $errlines $l]
252 if {!([string length $line] == 40 && [string is xdigit $line])} {
253 if {[string match "fatal:*" $line]} {
254 if {[string match "fatal: ambiguous argument*" $line]
255 && $badrev ne {}} {
256 if {[llength $badrev] == 1} {
257 set err "unknown revision $badrev"
258 } else {
259 set err "unknown revisions: [join $badrev ", "]"
260 }
261 } else {
262 set err [join [lrange $errlines $l end] "\n"]
263 }
264 break
265 }
266 lappend badrev $line
267 }
268 }
Christian Stimming3945d2c2008-09-12 11:39:43 +0200269 error_popup "[mc "Error parsing revisions:"] $err"
Paul Mackerrasee66e082008-05-09 10:14:07 +1000270 return {}
271 }
272 set ret {}
273 set pos {}
274 set neg {}
275 set sdm 0
276 foreach id [split $ids "\n"] {
277 if {$id eq "--gitk-symmetric-diff-marker"} {
278 set sdm 4
279 } elseif {[string match "^*" $id]} {
280 if {$sdm != 1} {
281 lappend ret $id
282 if {$sdm == 3} {
283 set sdm 0
284 }
285 }
286 lappend neg [string range $id 1 end]
287 } else {
288 if {$sdm != 2} {
289 lappend ret $id
290 } else {
Thomas Rast2b1fbf92009-08-05 23:15:36 +0200291 lset ret end $id...[lindex $ret end]
Paul Mackerrasee66e082008-05-09 10:14:07 +1000292 }
293 lappend pos $id
294 }
295 incr sdm -1
296 }
297 set vposids($view) $pos
298 set vnegids($view) $neg
299 return $ret
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000300}
301
Paul Mackerrasf9e0b6f2008-03-04 21:14:17 +1100302# Start off a git log process and arrange to read its output
Paul Mackerrasda7c24d2006-05-02 11:15:29 +1000303proc start_rev_list {view} {
Paul Mackerras6df74032008-05-11 22:13:02 +1000304 global startmsecs commitidx viewcomplete curview
Alexander Gavrilove439e092008-07-13 16:40:47 +0400305 global tclencoding
Paul Mackerrasee66e082008-05-09 10:14:07 +1000306 global viewargs viewargscmd viewfiles vfilelimit
Paul Mackerrasd375ef92008-10-21 10:18:12 +1100307 global showlocalchanges
Alexander Gavrilove439e092008-07-13 16:40:47 +0400308 global viewactive viewinstances vmergeonly
Paul Mackerrascdc84292008-11-18 19:54:14 +1100309 global mainheadid viewmainheadid viewmainheadid_orig
Paul Mackerrasee66e082008-05-09 10:14:07 +1000310 global vcanopt vflags vrevs vorigargs
Paul Mackerras38ad0912005-12-01 22:42:46 +1100311
312 set startmsecs [clock clicks -milliseconds]
Paul Mackerrasda7c24d2006-05-02 11:15:29 +1000313 set commitidx($view) 0
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000314 # these are set this way for the error exits
315 set viewcomplete($view) 1
316 set viewactive($view) 0
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100317 varcinit $view
318
Yann Dirson2d480852008-02-21 21:23:31 +0100319 set args $viewargs($view)
320 if {$viewargscmd($view) ne {}} {
321 if {[catch {
322 set str [exec sh -c $viewargscmd($view)]
323 } err]} {
Christian Stimming3945d2c2008-09-12 11:39:43 +0200324 error_popup "[mc "Error executing --argscmd command:"] $err"
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000325 return 0
Yann Dirson2d480852008-02-21 21:23:31 +0100326 }
327 set args [concat $args [split $str "\n"]]
328 }
Paul Mackerrasee66e082008-05-09 10:14:07 +1000329 set vcanopt($view) [parseviewargs $view $args]
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000330
331 set files $viewfiles($view)
332 if {$vmergeonly($view)} {
333 set files [unmerged_files $files]
334 if {$files eq {}} {
335 global nr_unmerged
336 if {$nr_unmerged == 0} {
337 error_popup [mc "No files selected: --merge specified but\
338 no files are unmerged."]
339 } else {
340 error_popup [mc "No files selected: --merge specified but\
341 no unmerged files are within file limit."]
342 }
343 return 0
344 }
345 }
346 set vfilelimit($view) $files
347
Paul Mackerrasee66e082008-05-09 10:14:07 +1000348 if {$vcanopt($view)} {
349 set revs [parseviewrevs $view $vrevs($view)]
350 if {$revs eq {}} {
351 return 0
352 }
353 set args [concat $vflags($view) $revs]
354 } else {
355 set args $vorigargs($view)
356 }
357
Paul Mackerras418c4c72006-02-07 09:10:18 +1100358 if {[catch {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100359 set fd [open [concat | git log --no-color -z --pretty=raw --parents \
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000360 --boundary $args "--" $files] r]
Paul Mackerras418c4c72006-02-07 09:10:18 +1100361 } err]} {
Paul Mackerras00abadb2007-12-20 10:25:50 +1100362 error_popup "[mc "Error executing git log:"] $err"
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000363 return 0
Paul Mackerras38ad0912005-12-01 22:42:46 +1100364 }
Alexander Gavrilove439e092008-07-13 16:40:47 +0400365 set i [reg_instance $fd]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100366 set viewinstances($view) [list $i]
Paul Mackerrascdc84292008-11-18 19:54:14 +1100367 set viewmainheadid($view) $mainheadid
368 set viewmainheadid_orig($view) $mainheadid
369 if {$files ne {} && $mainheadid ne {}} {
370 get_viewmainhead $view
371 }
372 if {$showlocalchanges && $viewmainheadid($view) ne {}} {
373 interestedin $viewmainheadid($view) dodiffindex
Paul Mackerras3e6b8932007-09-15 09:33:39 +1000374 }
Mark Levedahl86da5b62007-07-17 18:42:04 -0400375 fconfigure $fd -blocking 0 -translation lf -eofchar {}
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +1100376 if {$tclencoding != {}} {
Paul Mackerrasda7c24d2006-05-02 11:15:29 +1000377 fconfigure $fd -encoding $tclencoding
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +1100378 }
Paul Mackerrasf806f0f2008-02-24 12:16:56 +1100379 filerun $fd [list getcommitlines $fd $i $view 0]
Christian Stimmingd990ced2007-11-07 18:42:55 +0100380 nowbusy $view [mc "Reading"]
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000381 set viewcomplete($view) 0
382 set viewactive($view) 1
383 return 1
Paul Mackerras38ad0912005-12-01 22:42:46 +1100384}
385
Alexander Gavrilove2f90ee2008-07-12 16:09:28 +0400386proc stop_instance {inst} {
387 global commfd leftover
388
389 set fd $commfd($inst)
390 catch {
391 set pid [pid $fd]
Alexander Gavrilovb6326e92008-07-15 00:35:42 +0400392
393 if {$::tcl_platform(platform) eq {windows}} {
394 exec kill -f $pid
395 } else {
396 exec kill $pid
397 }
Alexander Gavrilove2f90ee2008-07-12 16:09:28 +0400398 }
399 catch {close $fd}
400 nukefile $fd
401 unset commfd($inst)
402 unset leftover($inst)
403}
404
405proc stop_backends {} {
406 global commfd
407
408 foreach inst [array names commfd] {
409 stop_instance $inst
410 }
411}
412
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100413proc stop_rev_list {view} {
Alexander Gavrilove2f90ee2008-07-12 16:09:28 +0400414 global viewinstances
Paul Mackerras22626ef2006-04-17 09:56:02 +1000415
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100416 foreach inst $viewinstances($view) {
Alexander Gavrilove2f90ee2008-07-12 16:09:28 +0400417 stop_instance $inst
Paul Mackerras22626ef2006-04-17 09:56:02 +1000418 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100419 set viewinstances($view) {}
Paul Mackerras22626ef2006-04-17 09:56:02 +1000420}
421
Alexander Gavrilov567c34e2008-07-26 20:13:45 +0400422proc reset_pending_select {selid} {
Alexander Gavrilov39816d62008-08-23 12:27:44 +0400423 global pending_select mainheadid selectheadid
Alexander Gavrilov567c34e2008-07-26 20:13:45 +0400424
425 if {$selid ne {}} {
426 set pending_select $selid
Alexander Gavrilov39816d62008-08-23 12:27:44 +0400427 } elseif {$selectheadid ne {}} {
428 set pending_select $selectheadid
Alexander Gavrilov567c34e2008-07-26 20:13:45 +0400429 } else {
430 set pending_select $mainheadid
431 }
432}
433
434proc getcommits {selid} {
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000435 global canv curview need_redisplay viewactive
Sven Verdoolaegeb5c2f302005-11-29 22:15:51 +0100436
Paul Mackerrasda7c24d2006-05-02 11:15:29 +1000437 initlayout
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000438 if {[start_rev_list $curview]} {
Alexander Gavrilov567c34e2008-07-26 20:13:45 +0400439 reset_pending_select $selid
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000440 show_status [mc "Reading commits..."]
441 set need_redisplay 1
442 } else {
443 show_status [mc "No commits selected"]
444 }
Paul Mackerras1d10f362005-05-15 12:55:47 +0000445}
446
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100447proc updatecommits {} {
Paul Mackerrasee66e082008-05-09 10:14:07 +1000448 global curview vcanopt vorigargs vfilelimit viewinstances
Alexander Gavrilove439e092008-07-13 16:40:47 +0400449 global viewactive viewcomplete tclencoding
450 global startmsecs showneartags showlocalchanges
Paul Mackerrascdc84292008-11-18 19:54:14 +1100451 global mainheadid viewmainheadid viewmainheadid_orig pending_select
Paul Mackerras92e22ca2008-03-11 22:21:39 +1100452 global isworktree
Paul Mackerrasee66e082008-05-09 10:14:07 +1000453 global varcid vposids vnegids vflags vrevs
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100454
Paul Mackerras92e22ca2008-03-11 22:21:39 +1100455 set isworktree [expr {[exec git rev-parse --is-inside-work-tree] == "true"}]
Paul Mackerrasfc2a2562007-12-26 23:03:43 +1100456 rereadrefs
Paul Mackerrascdc84292008-11-18 19:54:14 +1100457 set view $curview
458 if {$mainheadid ne $viewmainheadid_orig($view)} {
459 if {$showlocalchanges} {
Paul Mackerraseb5f8c92007-12-29 21:13:34 +1100460 dohidelocalchanges
461 }
Paul Mackerrascdc84292008-11-18 19:54:14 +1100462 set viewmainheadid($view) $mainheadid
463 set viewmainheadid_orig($view) $mainheadid
464 if {$vfilelimit($view) ne {}} {
465 get_viewmainhead $view
Paul Mackerraseb5f8c92007-12-29 21:13:34 +1100466 }
467 }
Paul Mackerrascdc84292008-11-18 19:54:14 +1100468 if {$showlocalchanges} {
469 doshowlocalchanges
470 }
Paul Mackerrasee66e082008-05-09 10:14:07 +1000471 if {$vcanopt($view)} {
472 set oldpos $vposids($view)
473 set oldneg $vnegids($view)
474 set revs [parseviewrevs $view $vrevs($view)]
475 if {$revs eq {}} {
476 return
477 }
478 # note: getting the delta when negative refs change is hard,
479 # and could require multiple git log invocations, so in that
480 # case we ask git log for all the commits (not just the delta)
481 if {$oldneg eq $vnegids($view)} {
482 set newrevs {}
483 set npos 0
484 # take out positive refs that we asked for before or
485 # that we have already seen
486 foreach rev $revs {
487 if {[string length $rev] == 40} {
488 if {[lsearch -exact $oldpos $rev] < 0
489 && ![info exists varcid($view,$rev)]} {
490 lappend newrevs $rev
491 incr npos
492 }
493 } else {
494 lappend $newrevs $rev
495 }
496 }
497 if {$npos == 0} return
498 set revs $newrevs
499 set vposids($view) [lsort -unique [concat $oldpos $vposids($view)]]
500 }
501 set args [concat $vflags($view) $revs --not $oldpos]
502 } else {
503 set args $vorigargs($view)
504 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100505 if {[catch {
506 set fd [open [concat | git log --no-color -z --pretty=raw --parents \
Paul Mackerrasee66e082008-05-09 10:14:07 +1000507 --boundary $args "--" $vfilelimit($view)] r]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100508 } err]} {
Christian Stimming3945d2c2008-09-12 11:39:43 +0200509 error_popup "[mc "Error executing git log:"] $err"
Paul Mackerrasee66e082008-05-09 10:14:07 +1000510 return
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100511 }
512 if {$viewactive($view) == 0} {
513 set startmsecs [clock clicks -milliseconds]
514 }
Alexander Gavrilove439e092008-07-13 16:40:47 +0400515 set i [reg_instance $fd]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100516 lappend viewinstances($view) $i
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100517 fconfigure $fd -blocking 0 -translation lf -eofchar {}
518 if {$tclencoding != {}} {
519 fconfigure $fd -encoding $tclencoding
520 }
Paul Mackerrasf806f0f2008-02-24 12:16:56 +1100521 filerun $fd [list getcommitlines $fd $i $view 1]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100522 incr viewactive($view)
523 set viewcomplete($view) 0
Alexander Gavrilov567c34e2008-07-26 20:13:45 +0400524 reset_pending_select {}
Michele Ballabiob56e0a92009-03-30 21:17:25 +0200525 nowbusy $view [mc "Reading"]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100526 if {$showneartags} {
527 getallcommits
528 }
529}
530
531proc reloadcommits {} {
532 global curview viewcomplete selectedline currentid thickerline
533 global showneartags treediffs commitinterest cached_commitrow
Paul Mackerras6df74032008-05-11 22:13:02 +1000534 global targetid
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100535
Alexander Gavrilov567c34e2008-07-26 20:13:45 +0400536 set selid {}
537 if {$selectedline ne {}} {
538 set selid $currentid
539 }
540
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100541 if {!$viewcomplete($curview)} {
542 stop_rev_list $curview
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100543 }
544 resetvarcs $curview
Paul Mackerras94b4a692008-05-20 20:51:06 +1000545 set selectedline {}
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100546 catch {unset currentid}
547 catch {unset thickerline}
548 catch {unset treediffs}
549 readrefs
550 changedrefs
551 if {$showneartags} {
552 getallcommits
553 }
554 clear_display
555 catch {unset commitinterest}
556 catch {unset cached_commitrow}
Paul Mackerras42a671f2008-01-02 09:59:39 +1100557 catch {unset targetid}
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100558 setcanvscroll
Alexander Gavrilov567c34e2008-07-26 20:13:45 +0400559 getcommits $selid
Paul Mackerrase7297a12008-01-15 22:30:40 +1100560 return 0
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100561}
562
Paul Mackerras6e8c8702007-07-31 21:03:06 +1000563# This makes a string representation of a positive integer which
564# sorts as a string in numerical order
565proc strrep {n} {
566 if {$n < 16} {
567 return [format "%x" $n]
568 } elseif {$n < 256} {
569 return [format "x%.2x" $n]
570 } elseif {$n < 65536} {
571 return [format "y%.4x" $n]
572 }
573 return [format "z%.8x" $n]
574}
575
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100576# Procedures used in reordering commits from git log (without
577# --topo-order) into the order for display.
578
579proc varcinit {view} {
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100580 global varcstart vupptr vdownptr vleftptr vbackptr varctok varcrow
581 global vtokmod varcmod vrowmod varcix vlastins
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100582
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100583 set varcstart($view) {{}}
584 set vupptr($view) {0}
585 set vdownptr($view) {0}
586 set vleftptr($view) {0}
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100587 set vbackptr($view) {0}
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100588 set varctok($view) {{}}
589 set varcrow($view) {{}}
590 set vtokmod($view) {}
591 set varcmod($view) 0
Paul Mackerrase5b37ac2007-12-12 18:13:51 +1100592 set vrowmod($view) 0
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100593 set varcix($view) {{}}
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100594 set vlastins($view) {0}
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100595}
596
597proc resetvarcs {view} {
598 global varcid varccommits parents children vseedcount ordertok
599
600 foreach vid [array names varcid $view,*] {
601 unset varcid($vid)
602 unset children($vid)
603 unset parents($vid)
604 }
605 # some commits might have children but haven't been seen yet
606 foreach vid [array names children $view,*] {
607 unset children($vid)
608 }
609 foreach va [array names varccommits $view,*] {
610 unset varccommits($va)
611 }
612 foreach vd [array names vseedcount $view,*] {
613 unset vseedcount($vd)
614 }
Paul Mackerras9257d8f2007-12-11 10:45:38 +1100615 catch {unset ordertok}
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100616}
617
Paul Mackerras468bcae2008-03-03 10:19:35 +1100618# returns a list of the commits with no children
619proc seeds {v} {
620 global vdownptr vleftptr varcstart
621
622 set ret {}
623 set a [lindex $vdownptr($v) 0]
624 while {$a != 0} {
625 lappend ret [lindex $varcstart($v) $a]
626 set a [lindex $vleftptr($v) $a]
627 }
628 return $ret
629}
630
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100631proc newvarc {view id} {
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000632 global varcid varctok parents children vdatemode
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100633 global vupptr vdownptr vleftptr vbackptr varcrow varcix varcstart
634 global commitdata commitinfo vseedcount varccommits vlastins
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100635
636 set a [llength $varctok($view)]
637 set vid $view,$id
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000638 if {[llength $children($vid)] == 0 || $vdatemode($view)} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100639 if {![info exists commitinfo($id)]} {
640 parsecommit $id $commitdata($id) 1
641 }
642 set cdate [lindex $commitinfo($id) 4]
643 if {![string is integer -strict $cdate]} {
644 set cdate 0
645 }
646 if {![info exists vseedcount($view,$cdate)]} {
647 set vseedcount($view,$cdate) -1
648 }
649 set c [incr vseedcount($view,$cdate)]
650 set cdate [expr {$cdate ^ 0xffffffff}]
651 set tok "s[strrep $cdate][strrep $c]"
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100652 } else {
653 set tok {}
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100654 }
655 set ka 0
656 if {[llength $children($vid)] > 0} {
657 set kid [lindex $children($vid) end]
658 set k $varcid($view,$kid)
659 if {[string compare [lindex $varctok($view) $k] $tok] > 0} {
660 set ki $kid
661 set ka $k
662 set tok [lindex $varctok($view) $k]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100663 }
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100664 }
665 if {$ka != 0} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100666 set i [lsearch -exact $parents($view,$ki) $id]
667 set j [expr {[llength $parents($view,$ki)] - 1 - $i}]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100668 append tok [strrep $j]
669 }
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100670 set c [lindex $vlastins($view) $ka]
671 if {$c == 0 || [string compare $tok [lindex $varctok($view) $c]] < 0} {
672 set c $ka
673 set b [lindex $vdownptr($view) $ka]
674 } else {
675 set b [lindex $vleftptr($view) $c]
676 }
677 while {$b != 0 && [string compare $tok [lindex $varctok($view) $b]] >= 0} {
678 set c $b
679 set b [lindex $vleftptr($view) $c]
680 }
681 if {$c == $ka} {
682 lset vdownptr($view) $ka $a
683 lappend vbackptr($view) 0
684 } else {
685 lset vleftptr($view) $c $a
686 lappend vbackptr($view) $c
687 }
688 lset vlastins($view) $ka $a
689 lappend vupptr($view) $ka
690 lappend vleftptr($view) $b
691 if {$b != 0} {
692 lset vbackptr($view) $b $a
693 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100694 lappend varctok($view) $tok
695 lappend varcstart($view) $id
696 lappend vdownptr($view) 0
697 lappend varcrow($view) {}
698 lappend varcix($view) {}
Paul Mackerrase5b37ac2007-12-12 18:13:51 +1100699 set varccommits($view,$a) {}
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100700 lappend vlastins($view) 0
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100701 return $a
702}
703
704proc splitvarc {p v} {
Paul Mackerras52b8ea92009-03-02 09:38:17 +1100705 global varcid varcstart varccommits varctok vtokmod
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100706 global vupptr vdownptr vleftptr vbackptr varcix varcrow vlastins
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100707
708 set oa $varcid($v,$p)
Paul Mackerras52b8ea92009-03-02 09:38:17 +1100709 set otok [lindex $varctok($v) $oa]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100710 set ac $varccommits($v,$oa)
711 set i [lsearch -exact $varccommits($v,$oa) $p]
712 if {$i <= 0} return
713 set na [llength $varctok($v)]
714 # "%" sorts before "0"...
Paul Mackerras52b8ea92009-03-02 09:38:17 +1100715 set tok "$otok%[strrep $i]"
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100716 lappend varctok($v) $tok
717 lappend varcrow($v) {}
718 lappend varcix($v) {}
719 set varccommits($v,$oa) [lrange $ac 0 [expr {$i - 1}]]
720 set varccommits($v,$na) [lrange $ac $i end]
721 lappend varcstart($v) $p
722 foreach id $varccommits($v,$na) {
723 set varcid($v,$id) $na
724 }
725 lappend vdownptr($v) [lindex $vdownptr($v) $oa]
Paul Mackerras841ea822008-02-18 10:44:33 +1100726 lappend vlastins($v) [lindex $vlastins($v) $oa]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100727 lset vdownptr($v) $oa $na
Paul Mackerras841ea822008-02-18 10:44:33 +1100728 lset vlastins($v) $oa 0
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100729 lappend vupptr($v) $oa
730 lappend vleftptr($v) 0
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100731 lappend vbackptr($v) 0
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100732 for {set b [lindex $vdownptr($v) $na]} {$b != 0} {set b [lindex $vleftptr($v) $b]} {
733 lset vupptr($v) $b $na
734 }
Paul Mackerras52b8ea92009-03-02 09:38:17 +1100735 if {[string compare $otok $vtokmod($v)] <= 0} {
736 modify_arc $v $oa
737 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100738}
739
740proc renumbervarc {a v} {
741 global parents children varctok varcstart varccommits
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000742 global vupptr vdownptr vleftptr vbackptr vlastins varcid vtokmod vdatemode
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100743
744 set t1 [clock clicks -milliseconds]
745 set todo {}
746 set isrelated($a) 1
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100747 set kidchanged($a) 1
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100748 set ntot 0
749 while {$a != 0} {
750 if {[info exists isrelated($a)]} {
751 lappend todo $a
752 set id [lindex $varccommits($v,$a) end]
753 foreach p $parents($v,$id) {
754 if {[info exists varcid($v,$p)]} {
755 set isrelated($varcid($v,$p)) 1
756 }
757 }
758 }
759 incr ntot
760 set b [lindex $vdownptr($v) $a]
761 if {$b == 0} {
762 while {$a != 0} {
763 set b [lindex $vleftptr($v) $a]
764 if {$b != 0} break
765 set a [lindex $vupptr($v) $a]
766 }
767 }
768 set a $b
769 }
770 foreach a $todo {
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100771 if {![info exists kidchanged($a)]} continue
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100772 set id [lindex $varcstart($v) $a]
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100773 if {[llength $children($v,$id)] > 1} {
774 set children($v,$id) [lsort -command [list vtokcmp $v] \
775 $children($v,$id)]
776 }
777 set oldtok [lindex $varctok($v) $a]
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000778 if {!$vdatemode($v)} {
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100779 set tok {}
780 } else {
781 set tok $oldtok
782 }
783 set ka 0
Paul Mackerrasc8c9f3d2008-01-06 13:54:58 +1100784 set kid [last_real_child $v,$id]
785 if {$kid ne {}} {
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100786 set k $varcid($v,$kid)
787 if {[string compare [lindex $varctok($v) $k] $tok] > 0} {
788 set ki $kid
789 set ka $k
790 set tok [lindex $varctok($v) $k]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100791 }
792 }
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100793 if {$ka != 0} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100794 set i [lsearch -exact $parents($v,$ki) $id]
795 set j [expr {[llength $parents($v,$ki)] - 1 - $i}]
796 append tok [strrep $j]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100797 }
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100798 if {$tok eq $oldtok} {
799 continue
800 }
801 set id [lindex $varccommits($v,$a) end]
802 foreach p $parents($v,$id) {
803 if {[info exists varcid($v,$p)]} {
804 set kidchanged($varcid($v,$p)) 1
805 } else {
806 set sortkids($p) 1
807 }
808 }
809 lset varctok($v) $a $tok
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100810 set b [lindex $vupptr($v) $a]
811 if {$b != $ka} {
Paul Mackerras9257d8f2007-12-11 10:45:38 +1100812 if {[string compare [lindex $varctok($v) $ka] $vtokmod($v)] < 0} {
813 modify_arc $v $ka
Paul Mackerras38dfe932007-12-06 20:50:31 +1100814 }
Paul Mackerras9257d8f2007-12-11 10:45:38 +1100815 if {[string compare [lindex $varctok($v) $b] $vtokmod($v)] < 0} {
816 modify_arc $v $b
Paul Mackerras38dfe932007-12-06 20:50:31 +1100817 }
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100818 set c [lindex $vbackptr($v) $a]
819 set d [lindex $vleftptr($v) $a]
820 if {$c == 0} {
821 lset vdownptr($v) $b $d
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100822 } else {
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100823 lset vleftptr($v) $c $d
824 }
825 if {$d != 0} {
826 lset vbackptr($v) $d $c
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100827 }
Paul Mackerras841ea822008-02-18 10:44:33 +1100828 if {[lindex $vlastins($v) $b] == $a} {
829 lset vlastins($v) $b $c
830 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100831 lset vupptr($v) $a $ka
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100832 set c [lindex $vlastins($v) $ka]
833 if {$c == 0 || \
834 [string compare $tok [lindex $varctok($v) $c]] < 0} {
835 set c $ka
836 set b [lindex $vdownptr($v) $ka]
837 } else {
838 set b [lindex $vleftptr($v) $c]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100839 }
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100840 while {$b != 0 && \
841 [string compare $tok [lindex $varctok($v) $b]] >= 0} {
842 set c $b
843 set b [lindex $vleftptr($v) $c]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100844 }
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100845 if {$c == $ka} {
846 lset vdownptr($v) $ka $a
847 lset vbackptr($v) $a 0
848 } else {
849 lset vleftptr($v) $c $a
850 lset vbackptr($v) $a $c
851 }
852 lset vleftptr($v) $a $b
853 if {$b != 0} {
854 lset vbackptr($v) $b $a
855 }
856 lset vlastins($v) $ka $a
857 }
858 }
859 foreach id [array names sortkids] {
860 if {[llength $children($v,$id)] > 1} {
861 set children($v,$id) [lsort -command [list vtokcmp $v] \
862 $children($v,$id)]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100863 }
864 }
865 set t2 [clock clicks -milliseconds]
866 #puts "renumbervarc did [llength $todo] of $ntot arcs in [expr {$t2-$t1}]ms"
867}
868
Paul Mackerrasf806f0f2008-02-24 12:16:56 +1100869# Fix up the graph after we have found out that in view $v,
870# $p (a commit that we have already seen) is actually the parent
871# of the last commit in arc $a.
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100872proc fix_reversal {p a v} {
Paul Mackerras24f7a662007-12-19 09:35:33 +1100873 global varcid varcstart varctok vupptr
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100874
875 set pa $varcid($v,$p)
876 if {$p ne [lindex $varcstart($v) $pa]} {
877 splitvarc $p $v
878 set pa $varcid($v,$p)
879 }
Paul Mackerras24f7a662007-12-19 09:35:33 +1100880 # seeds always need to be renumbered
881 if {[lindex $vupptr($v) $pa] == 0 ||
882 [string compare [lindex $varctok($v) $a] \
883 [lindex $varctok($v) $pa]] > 0} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100884 renumbervarc $pa $v
885 }
886}
887
888proc insertrow {id p v} {
Paul Mackerrasb8a938c2008-02-13 22:12:31 +1100889 global cmitlisted children parents varcid varctok vtokmod
890 global varccommits ordertok commitidx numcommits curview
891 global targetid targetrow
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100892
Paul Mackerrasb8a938c2008-02-13 22:12:31 +1100893 readcommit $id
894 set vid $v,$id
895 set cmitlisted($vid) 1
896 set children($vid) {}
897 set parents($vid) [list $p]
898 set a [newvarc $v $id]
899 set varcid($vid) $a
900 if {[string compare [lindex $varctok($v) $a] $vtokmod($v)] < 0} {
901 modify_arc $v $a
902 }
903 lappend varccommits($v,$a) $id
904 set vp $v,$p
905 if {[llength [lappend children($vp) $id]] > 1} {
906 set children($vp) [lsort -command [list vtokcmp $v] $children($vp)]
907 catch {unset ordertok}
908 }
909 fix_reversal $p $a $v
910 incr commitidx($v)
911 if {$v == $curview} {
912 set numcommits $commitidx($v)
913 setcanvscroll
914 if {[info exists targetid]} {
915 if {![comes_before $targetid $p]} {
916 incr targetrow
917 }
918 }
919 }
920}
921
922proc insertfakerow {id p} {
923 global varcid varccommits parents children cmitlisted
924 global commitidx varctok vtokmod targetid targetrow curview numcommits
925
926 set v $curview
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100927 set a $varcid($v,$p)
928 set i [lsearch -exact $varccommits($v,$a) $p]
929 if {$i < 0} {
Paul Mackerrasb8a938c2008-02-13 22:12:31 +1100930 puts "oops: insertfakerow can't find [shortids $p] on arc $a"
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100931 return
932 }
933 set children($v,$id) {}
934 set parents($v,$id) [list $p]
935 set varcid($v,$id) $a
Paul Mackerras9257d8f2007-12-11 10:45:38 +1100936 lappend children($v,$p) $id
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100937 set cmitlisted($v,$id) 1
Paul Mackerrasb8a938c2008-02-13 22:12:31 +1100938 set numcommits [incr commitidx($v)]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100939 # note we deliberately don't update varcstart($v) even if $i == 0
940 set varccommits($v,$a) [linsert $varccommits($v,$a) $i $id]
Paul Mackerrasc9cfdc92008-03-04 21:32:38 +1100941 modify_arc $v $a $i
Paul Mackerras42a671f2008-01-02 09:59:39 +1100942 if {[info exists targetid]} {
943 if {![comes_before $targetid $p]} {
944 incr targetrow
945 }
946 }
Paul Mackerrasb8a938c2008-02-13 22:12:31 +1100947 setcanvscroll
Paul Mackerras9257d8f2007-12-11 10:45:38 +1100948 drawvisible
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100949}
950
Paul Mackerrasb8a938c2008-02-13 22:12:31 +1100951proc removefakerow {id} {
Paul Mackerras9257d8f2007-12-11 10:45:38 +1100952 global varcid varccommits parents children commitidx
Paul Mackerrasfc2a2562007-12-26 23:03:43 +1100953 global varctok vtokmod cmitlisted currentid selectedline
Paul Mackerrasb8a938c2008-02-13 22:12:31 +1100954 global targetid curview numcommits
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100955
Paul Mackerrasb8a938c2008-02-13 22:12:31 +1100956 set v $curview
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100957 if {[llength $parents($v,$id)] != 1} {
Paul Mackerrasb8a938c2008-02-13 22:12:31 +1100958 puts "oops: removefakerow [shortids $id] has [llength $parents($v,$id)] parents"
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100959 return
960 }
961 set p [lindex $parents($v,$id) 0]
962 set a $varcid($v,$id)
963 set i [lsearch -exact $varccommits($v,$a) $id]
964 if {$i < 0} {
Paul Mackerrasb8a938c2008-02-13 22:12:31 +1100965 puts "oops: removefakerow can't find [shortids $id] on arc $a"
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100966 return
967 }
968 unset varcid($v,$id)
969 set varccommits($v,$a) [lreplace $varccommits($v,$a) $i $i]
970 unset parents($v,$id)
971 unset children($v,$id)
972 unset cmitlisted($v,$id)
Paul Mackerrasb8a938c2008-02-13 22:12:31 +1100973 set numcommits [incr commitidx($v) -1]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100974 set j [lsearch -exact $children($v,$p) $id]
975 if {$j >= 0} {
976 set children($v,$p) [lreplace $children($v,$p) $j $j]
977 }
Paul Mackerrasc9cfdc92008-03-04 21:32:38 +1100978 modify_arc $v $a $i
Paul Mackerrasfc2a2562007-12-26 23:03:43 +1100979 if {[info exist currentid] && $id eq $currentid} {
980 unset currentid
Paul Mackerras94b4a692008-05-20 20:51:06 +1000981 set selectedline {}
Paul Mackerrasfc2a2562007-12-26 23:03:43 +1100982 }
Paul Mackerras42a671f2008-01-02 09:59:39 +1100983 if {[info exists targetid] && $targetid eq $id} {
984 set targetid $p
985 }
Paul Mackerrasb8a938c2008-02-13 22:12:31 +1100986 setcanvscroll
Paul Mackerras9257d8f2007-12-11 10:45:38 +1100987 drawvisible
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100988}
989
Paul Mackerrasc8c9f3d2008-01-06 13:54:58 +1100990proc first_real_child {vp} {
991 global children nullid nullid2
992
993 foreach id $children($vp) {
994 if {$id ne $nullid && $id ne $nullid2} {
995 return $id
996 }
997 }
998 return {}
999}
1000
1001proc last_real_child {vp} {
1002 global children nullid nullid2
1003
1004 set kids $children($vp)
1005 for {set i [llength $kids]} {[incr i -1] >= 0} {} {
1006 set id [lindex $kids $i]
1007 if {$id ne $nullid && $id ne $nullid2} {
1008 return $id
1009 }
1010 }
1011 return {}
1012}
1013
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001014proc vtokcmp {v a b} {
1015 global varctok varcid
1016
1017 return [string compare [lindex $varctok($v) $varcid($v,$a)] \
1018 [lindex $varctok($v) $varcid($v,$b)]]
1019}
1020
Paul Mackerrasc9cfdc92008-03-04 21:32:38 +11001021# This assumes that if lim is not given, the caller has checked that
1022# arc a's token is less than $vtokmod($v)
Paul Mackerrase5b37ac2007-12-12 18:13:51 +11001023proc modify_arc {v a {lim {}}} {
1024 global varctok vtokmod varcmod varcrow vupptr curview vrowmod varccommits
Paul Mackerras9257d8f2007-12-11 10:45:38 +11001025
Paul Mackerrasc9cfdc92008-03-04 21:32:38 +11001026 if {$lim ne {}} {
1027 set c [string compare [lindex $varctok($v) $a] $vtokmod($v)]
1028 if {$c > 0} return
1029 if {$c == 0} {
1030 set r [lindex $varcrow($v) $a]
1031 if {$r ne {} && $vrowmod($v) <= $r + $lim} return
1032 }
1033 }
Paul Mackerras9257d8f2007-12-11 10:45:38 +11001034 set vtokmod($v) [lindex $varctok($v) $a]
1035 set varcmod($v) $a
1036 if {$v == $curview} {
1037 while {$a != 0 && [lindex $varcrow($v) $a] eq {}} {
1038 set a [lindex $vupptr($v) $a]
Paul Mackerrase5b37ac2007-12-12 18:13:51 +11001039 set lim {}
Paul Mackerras9257d8f2007-12-11 10:45:38 +11001040 }
Paul Mackerrase5b37ac2007-12-12 18:13:51 +11001041 set r 0
1042 if {$a != 0} {
1043 if {$lim eq {}} {
1044 set lim [llength $varccommits($v,$a)]
1045 }
1046 set r [expr {[lindex $varcrow($v) $a] + $lim}]
1047 }
1048 set vrowmod($v) $r
Paul Mackerras0c278862007-12-11 20:09:53 +11001049 undolayout $r
Paul Mackerras9257d8f2007-12-11 10:45:38 +11001050 }
1051}
1052
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001053proc update_arcrows {v} {
Paul Mackerrase5b37ac2007-12-12 18:13:51 +11001054 global vtokmod varcmod vrowmod varcrow commitidx currentid selectedline
Paul Mackerras24f7a662007-12-19 09:35:33 +11001055 global varcid vrownum varcorder varcix varccommits
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001056 global vupptr vdownptr vleftptr varctok
Paul Mackerras24f7a662007-12-19 09:35:33 +11001057 global displayorder parentlist curview cached_commitrow
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001058
Paul Mackerrasc9cfdc92008-03-04 21:32:38 +11001059 if {$vrowmod($v) == $commitidx($v)} return
1060 if {$v == $curview} {
1061 if {[llength $displayorder] > $vrowmod($v)} {
1062 set displayorder [lrange $displayorder 0 [expr {$vrowmod($v) - 1}]]
1063 set parentlist [lrange $parentlist 0 [expr {$vrowmod($v) - 1}]]
1064 }
1065 catch {unset cached_commitrow}
1066 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001067 set narctot [expr {[llength $varctok($v)] - 1}]
1068 set a $varcmod($v)
1069 while {$a != 0 && [lindex $varcix($v) $a] eq {}} {
1070 # go up the tree until we find something that has a row number,
1071 # or we get to a seed
1072 set a [lindex $vupptr($v) $a]
1073 }
1074 if {$a == 0} {
1075 set a [lindex $vdownptr($v) 0]
1076 if {$a == 0} return
1077 set vrownum($v) {0}
1078 set varcorder($v) [list $a]
1079 lset varcix($v) $a 0
1080 lset varcrow($v) $a 0
1081 set arcn 0
1082 set row 0
1083 } else {
1084 set arcn [lindex $varcix($v) $a]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001085 if {[llength $vrownum($v)] > $arcn + 1} {
1086 set vrownum($v) [lrange $vrownum($v) 0 $arcn]
1087 set varcorder($v) [lrange $varcorder($v) 0 $arcn]
1088 }
1089 set row [lindex $varcrow($v) $a]
1090 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001091 while {1} {
1092 set p $a
1093 incr row [llength $varccommits($v,$a)]
1094 # go down if possible
1095 set b [lindex $vdownptr($v) $a]
1096 if {$b == 0} {
1097 # if not, go left, or go up until we can go left
1098 while {$a != 0} {
1099 set b [lindex $vleftptr($v) $a]
1100 if {$b != 0} break
1101 set a [lindex $vupptr($v) $a]
1102 }
1103 if {$a == 0} break
1104 }
1105 set a $b
1106 incr arcn
1107 lappend vrownum($v) $row
1108 lappend varcorder($v) $a
1109 lset varcix($v) $a $arcn
1110 lset varcrow($v) $a $row
1111 }
Paul Mackerrase5b37ac2007-12-12 18:13:51 +11001112 set vtokmod($v) [lindex $varctok($v) $p]
1113 set varcmod($v) $p
1114 set vrowmod($v) $row
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001115 if {[info exists currentid]} {
1116 set selectedline [rowofcommit $currentid]
1117 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001118}
1119
1120# Test whether view $v contains commit $id
1121proc commitinview {id v} {
1122 global varcid
1123
1124 return [info exists varcid($v,$id)]
1125}
1126
1127# Return the row number for commit $id in the current view
1128proc rowofcommit {id} {
1129 global varcid varccommits varcrow curview cached_commitrow
Paul Mackerras9257d8f2007-12-11 10:45:38 +11001130 global varctok vtokmod
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001131
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001132 set v $curview
1133 if {![info exists varcid($v,$id)]} {
1134 puts "oops rowofcommit no arc for [shortids $id]"
1135 return {}
1136 }
1137 set a $varcid($v,$id)
Paul Mackerrasfc2a2562007-12-26 23:03:43 +11001138 if {[string compare [lindex $varctok($v) $a] $vtokmod($v)] >= 0} {
Paul Mackerras9257d8f2007-12-11 10:45:38 +11001139 update_arcrows $v
1140 }
Paul Mackerras31c0eaa2007-12-30 22:41:14 +11001141 if {[info exists cached_commitrow($id)]} {
1142 return $cached_commitrow($id)
1143 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001144 set i [lsearch -exact $varccommits($v,$a) $id]
1145 if {$i < 0} {
1146 puts "oops didn't find commit [shortids $id] in arc $a"
1147 return {}
1148 }
1149 incr i [lindex $varcrow($v) $a]
1150 set cached_commitrow($id) $i
1151 return $i
1152}
1153
Paul Mackerras42a671f2008-01-02 09:59:39 +11001154# Returns 1 if a is on an earlier row than b, otherwise 0
1155proc comes_before {a b} {
1156 global varcid varctok curview
1157
1158 set v $curview
1159 if {$a eq $b || ![info exists varcid($v,$a)] || \
1160 ![info exists varcid($v,$b)]} {
1161 return 0
1162 }
1163 if {$varcid($v,$a) != $varcid($v,$b)} {
1164 return [expr {[string compare [lindex $varctok($v) $varcid($v,$a)] \
1165 [lindex $varctok($v) $varcid($v,$b)]] < 0}]
1166 }
1167 return [expr {[rowofcommit $a] < [rowofcommit $b]}]
1168}
1169
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001170proc bsearch {l elt} {
1171 if {[llength $l] == 0 || $elt <= [lindex $l 0]} {
1172 return 0
1173 }
1174 set lo 0
1175 set hi [llength $l]
1176 while {$hi - $lo > 1} {
1177 set mid [expr {int(($lo + $hi) / 2)}]
1178 set t [lindex $l $mid]
1179 if {$elt < $t} {
1180 set hi $mid
1181 } elseif {$elt > $t} {
1182 set lo $mid
1183 } else {
1184 return $mid
1185 }
1186 }
1187 return $lo
1188}
1189
1190# Make sure rows $start..$end-1 are valid in displayorder and parentlist
1191proc make_disporder {start end} {
1192 global vrownum curview commitidx displayorder parentlist
Paul Mackerrase5b37ac2007-12-12 18:13:51 +11001193 global varccommits varcorder parents vrowmod varcrow
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001194 global d_valid_start d_valid_end
1195
Paul Mackerrase5b37ac2007-12-12 18:13:51 +11001196 if {$end > $vrowmod($curview)} {
Paul Mackerras9257d8f2007-12-11 10:45:38 +11001197 update_arcrows $curview
1198 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001199 set ai [bsearch $vrownum($curview) $start]
1200 set start [lindex $vrownum($curview) $ai]
1201 set narc [llength $vrownum($curview)]
1202 for {set r $start} {$ai < $narc && $r < $end} {incr ai} {
1203 set a [lindex $varcorder($curview) $ai]
1204 set l [llength $displayorder]
1205 set al [llength $varccommits($curview,$a)]
1206 if {$l < $r + $al} {
1207 if {$l < $r} {
1208 set pad [ntimes [expr {$r - $l}] {}]
1209 set displayorder [concat $displayorder $pad]
1210 set parentlist [concat $parentlist $pad]
1211 } elseif {$l > $r} {
1212 set displayorder [lrange $displayorder 0 [expr {$r - 1}]]
1213 set parentlist [lrange $parentlist 0 [expr {$r - 1}]]
1214 }
1215 foreach id $varccommits($curview,$a) {
1216 lappend displayorder $id
1217 lappend parentlist $parents($curview,$id)
1218 }
Paul Mackerras17529cf92008-01-12 21:46:31 +11001219 } elseif {[lindex $displayorder [expr {$r + $al - 1}]] eq {}} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001220 set i $r
1221 foreach id $varccommits($curview,$a) {
1222 lset displayorder $i $id
1223 lset parentlist $i $parents($curview,$id)
1224 incr i
1225 }
1226 }
1227 incr r $al
1228 }
1229}
1230
1231proc commitonrow {row} {
1232 global displayorder
1233
1234 set id [lindex $displayorder $row]
1235 if {$id eq {}} {
1236 make_disporder $row [expr {$row + 1}]
1237 set id [lindex $displayorder $row]
1238 }
1239 return $id
1240}
1241
1242proc closevarcs {v} {
1243 global varctok varccommits varcid parents children
Paul Mackerrasd375ef92008-10-21 10:18:12 +11001244 global cmitlisted commitidx vtokmod
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001245
1246 set missing_parents 0
1247 set scripts {}
1248 set narcs [llength $varctok($v)]
1249 for {set a 1} {$a < $narcs} {incr a} {
1250 set id [lindex $varccommits($v,$a) end]
1251 foreach p $parents($v,$id) {
1252 if {[info exists varcid($v,$p)]} continue
1253 # add p as a new commit
1254 incr missing_parents
1255 set cmitlisted($v,$p) 0
1256 set parents($v,$p) {}
1257 if {[llength $children($v,$p)] == 1 &&
1258 [llength $parents($v,$id)] == 1} {
1259 set b $a
1260 } else {
1261 set b [newvarc $v $p]
1262 }
1263 set varcid($v,$p) $b
Paul Mackerras9257d8f2007-12-11 10:45:38 +11001264 if {[string compare [lindex $varctok($v) $b] $vtokmod($v)] < 0} {
1265 modify_arc $v $b
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001266 }
Paul Mackerrase5b37ac2007-12-12 18:13:51 +11001267 lappend varccommits($v,$b) $p
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001268 incr commitidx($v)
Paul Mackerrasd375ef92008-10-21 10:18:12 +11001269 set scripts [check_interest $p $scripts]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001270 }
1271 }
1272 if {$missing_parents > 0} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001273 foreach s $scripts {
1274 eval $s
1275 }
1276 }
1277}
1278
Paul Mackerrasf806f0f2008-02-24 12:16:56 +11001279# Use $rwid as a substitute for $id, i.e. reparent $id's children to $rwid
1280# Assumes we already have an arc for $rwid.
1281proc rewrite_commit {v id rwid} {
1282 global children parents varcid varctok vtokmod varccommits
1283
1284 foreach ch $children($v,$id) {
1285 # make $rwid be $ch's parent in place of $id
1286 set i [lsearch -exact $parents($v,$ch) $id]
1287 if {$i < 0} {
1288 puts "oops rewrite_commit didn't find $id in parent list for $ch"
1289 }
1290 set parents($v,$ch) [lreplace $parents($v,$ch) $i $i $rwid]
1291 # add $ch to $rwid's children and sort the list if necessary
1292 if {[llength [lappend children($v,$rwid) $ch]] > 1} {
1293 set children($v,$rwid) [lsort -command [list vtokcmp $v] \
1294 $children($v,$rwid)]
1295 }
1296 # fix the graph after joining $id to $rwid
1297 set a $varcid($v,$ch)
1298 fix_reversal $rwid $a $v
Paul Mackerrasc9cfdc92008-03-04 21:32:38 +11001299 # parentlist is wrong for the last element of arc $a
1300 # even if displayorder is right, hence the 3rd arg here
1301 modify_arc $v $a [expr {[llength $varccommits($v,$a)] - 1}]
Paul Mackerrasf806f0f2008-02-24 12:16:56 +11001302 }
1303}
1304
Paul Mackerrasd375ef92008-10-21 10:18:12 +11001305# Mechanism for registering a command to be executed when we come
1306# across a particular commit. To handle the case when only the
1307# prefix of the commit is known, the commitinterest array is now
1308# indexed by the first 4 characters of the ID. Each element is a
1309# list of id, cmd pairs.
1310proc interestedin {id cmd} {
1311 global commitinterest
1312
1313 lappend commitinterest([string range $id 0 3]) $id $cmd
1314}
1315
1316proc check_interest {id scripts} {
1317 global commitinterest
1318
1319 set prefix [string range $id 0 3]
1320 if {[info exists commitinterest($prefix)]} {
1321 set newlist {}
1322 foreach {i script} $commitinterest($prefix) {
1323 if {[string match "$i*" $id]} {
1324 lappend scripts [string map [list "%I" $id "%P" $i] $script]
1325 } else {
1326 lappend newlist $i $script
1327 }
1328 }
1329 if {$newlist ne {}} {
1330 set commitinterest($prefix) $newlist
1331 } else {
1332 unset commitinterest($prefix)
1333 }
1334 }
1335 return $scripts
1336}
1337
Paul Mackerrasf806f0f2008-02-24 12:16:56 +11001338proc getcommitlines {fd inst view updating} {
Paul Mackerrasd375ef92008-10-21 10:18:12 +11001339 global cmitlisted leftover
Paul Mackerras3ed31a82008-04-26 16:00:00 +10001340 global commitidx commitdata vdatemode
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001341 global parents children curview hlview
Paul Mackerras468bcae2008-03-03 10:19:35 +11001342 global idpending ordertok
Paul Mackerras3ed31a82008-04-26 16:00:00 +10001343 global varccommits varcid varctok vtokmod vfilelimit
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +00001344
Paul Mackerrasd1e46752006-08-16 20:02:32 +10001345 set stuff [read $fd 500000]
Paul Mackerras005a2f42007-07-26 22:36:39 +10001346 # git log doesn't terminate the last commit with a null...
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001347 if {$stuff == {} && $leftover($inst) ne {} && [eof $fd]} {
Paul Mackerras005a2f42007-07-26 22:36:39 +10001348 set stuff "\0"
1349 }
Paul Mackerrasb490a992005-06-22 10:25:38 +10001350 if {$stuff == {}} {
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10001351 if {![eof $fd]} {
1352 return 1
1353 }
Paul Mackerras6df74032008-05-11 22:13:02 +10001354 global commfd viewcomplete viewactive viewname
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001355 global viewinstances
1356 unset commfd($inst)
1357 set i [lsearch -exact $viewinstances($view) $inst]
1358 if {$i >= 0} {
1359 set viewinstances($view) [lreplace $viewinstances($view) $i $i]
Paul Mackerrasb0cdca92007-08-23 19:35:51 +10001360 }
Paul Mackerrasf0654862005-07-18 14:29:03 -04001361 # set it blocking so we wait for the process to terminate
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10001362 fconfigure $fd -blocking 1
Paul Mackerras098dd8a2006-05-03 09:32:53 +10001363 if {[catch {close $fd} err]} {
1364 set fv {}
1365 if {$view != $curview} {
1366 set fv " for the \"$viewname($view)\" view"
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10001367 }
Paul Mackerras098dd8a2006-05-03 09:32:53 +10001368 if {[string range $err 0 4] == "usage"} {
1369 set err "Gitk: error reading commits$fv:\
Paul Mackerrasf9e0b6f2008-03-04 21:14:17 +11001370 bad arguments to git log."
Paul Mackerras098dd8a2006-05-03 09:32:53 +10001371 if {$viewname($view) eq "Command line"} {
1372 append err \
Paul Mackerrasf9e0b6f2008-03-04 21:14:17 +11001373 " (Note: arguments to gitk are passed to git log\
Paul Mackerras098dd8a2006-05-03 09:32:53 +10001374 to allow selection of commits to be displayed.)"
1375 }
1376 } else {
1377 set err "Error reading commits$fv: $err"
1378 }
1379 error_popup $err
Paul Mackerras1d10f362005-05-15 12:55:47 +00001380 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001381 if {[incr viewactive($view) -1] <= 0} {
1382 set viewcomplete($view) 1
1383 # Check if we have seen any ids listed as parents that haven't
1384 # appeared in the list
1385 closevarcs $view
1386 notbusy $view
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001387 }
Paul Mackerras098dd8a2006-05-03 09:32:53 +10001388 if {$view == $curview} {
Paul Mackerrasac1276a2008-03-03 10:11:08 +11001389 run chewcommits
Paul Mackerras9a40c502005-05-12 23:46:16 +00001390 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10001391 return 0
Paul Mackerras9a40c502005-05-12 23:46:16 +00001392 }
Paul Mackerrasb490a992005-06-22 10:25:38 +10001393 set start 0
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11001394 set gotsome 0
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001395 set scripts {}
Paul Mackerrasb490a992005-06-22 10:25:38 +10001396 while 1 {
1397 set i [string first "\0" $stuff $start]
1398 if {$i < 0} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001399 append leftover($inst) [string range $stuff $start end]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11001400 break
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +00001401 }
Paul Mackerrasb490a992005-06-22 10:25:38 +10001402 if {$start == 0} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001403 set cmit $leftover($inst)
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11001404 append cmit [string range $stuff 0 [expr {$i - 1}]]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001405 set leftover($inst) {}
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11001406 } else {
1407 set cmit [string range $stuff $start [expr {$i - 1}]]
Paul Mackerrasb490a992005-06-22 10:25:38 +10001408 }
1409 set start [expr {$i + 1}]
Paul Mackerrase5ea7012005-08-18 20:40:39 +10001410 set j [string first "\n" $cmit]
1411 set ok 0
Paul Mackerras16c1ff92006-03-30 18:43:51 +11001412 set listed 1
Paul Mackerrasc961b222007-07-09 22:45:47 +10001413 if {$j >= 0 && [string match "commit *" $cmit]} {
1414 set ids [string range $cmit 7 [expr {$j - 1}]]
Linus Torvalds1407ade2008-02-09 14:02:07 -08001415 if {[string match {[-^<>]*} $ids]} {
Paul Mackerrasc961b222007-07-09 22:45:47 +10001416 switch -- [string index $ids 0] {
1417 "-" {set listed 0}
Linus Torvalds1407ade2008-02-09 14:02:07 -08001418 "^" {set listed 2}
1419 "<" {set listed 3}
1420 ">" {set listed 4}
Paul Mackerrasc961b222007-07-09 22:45:47 +10001421 }
Paul Mackerras16c1ff92006-03-30 18:43:51 +11001422 set ids [string range $ids 1 end]
1423 }
Paul Mackerrase5ea7012005-08-18 20:40:39 +10001424 set ok 1
1425 foreach id $ids {
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11001426 if {[string length $id] != 40} {
Paul Mackerrase5ea7012005-08-18 20:40:39 +10001427 set ok 0
1428 break
1429 }
1430 }
1431 }
1432 if {!$ok} {
Paul Mackerras7e952e72005-06-27 20:04:26 +10001433 set shortcmit $cmit
1434 if {[string length $shortcmit] > 80} {
1435 set shortcmit "[string range $shortcmit 0 80]..."
1436 }
Christian Stimmingd990ced2007-11-07 18:42:55 +01001437 error_popup "[mc "Can't parse git log output:"] {$shortcmit}"
Paul Mackerrasb490a992005-06-22 10:25:38 +10001438 exit 1
1439 }
Paul Mackerrase5ea7012005-08-18 20:40:39 +10001440 set id [lindex $ids 0]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001441 set vid $view,$id
Paul Mackerrasf806f0f2008-02-24 12:16:56 +11001442
1443 if {!$listed && $updating && ![info exists varcid($vid)] &&
Paul Mackerras3ed31a82008-04-26 16:00:00 +10001444 $vfilelimit($view) ne {}} {
Paul Mackerrasf806f0f2008-02-24 12:16:56 +11001445 # git log doesn't rewrite parents for unlisted commits
1446 # when doing path limiting, so work around that here
1447 # by working out the rewritten parent with git rev-list
1448 # and if we already know about it, using the rewritten
1449 # parent as a substitute parent for $id's children.
1450 if {![catch {
1451 set rwid [exec git rev-list --first-parent --max-count=1 \
Paul Mackerras3ed31a82008-04-26 16:00:00 +10001452 $id -- $vfilelimit($view)]
Paul Mackerrasf806f0f2008-02-24 12:16:56 +11001453 }]} {
1454 if {$rwid ne {} && [info exists varcid($view,$rwid)]} {
1455 # use $rwid in place of $id
1456 rewrite_commit $view $id $rwid
1457 continue
1458 }
1459 }
1460 }
1461
Paul Mackerrasf1bf4ee2008-02-16 17:47:31 +11001462 set a 0
1463 if {[info exists varcid($vid)]} {
1464 if {$cmitlisted($vid) || !$listed} continue
1465 set a $varcid($vid)
1466 }
Paul Mackerras16c1ff92006-03-30 18:43:51 +11001467 if {$listed} {
1468 set olds [lrange $ids 1 end]
Paul Mackerras16c1ff92006-03-30 18:43:51 +11001469 } else {
1470 set olds {}
1471 }
Paul Mackerrasf7a3e8d2006-03-18 10:04:48 +11001472 set commitdata($id) [string range $cmit [expr {$j + 1}] end]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001473 set cmitlisted($vid) $listed
1474 set parents($vid) $olds
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001475 if {![info exists children($vid)]} {
1476 set children($vid) {}
Paul Mackerrasf1bf4ee2008-02-16 17:47:31 +11001477 } elseif {$a == 0 && [llength $children($vid)] == 1} {
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +11001478 set k [lindex $children($vid) 0]
1479 if {[llength $parents($view,$k)] == 1 &&
Paul Mackerras3ed31a82008-04-26 16:00:00 +10001480 (!$vdatemode($view) ||
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +11001481 $varcid($view,$k) == [llength $varctok($view)] - 1)} {
1482 set a $varcid($view,$k)
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001483 }
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10001484 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001485 if {$a == 0} {
1486 # new arc
1487 set a [newvarc $view $id]
1488 }
Paul Mackerrase5b37ac2007-12-12 18:13:51 +11001489 if {[string compare [lindex $varctok($view) $a] $vtokmod($view)] < 0} {
1490 modify_arc $view $a
1491 }
Paul Mackerrasf1bf4ee2008-02-16 17:47:31 +11001492 if {![info exists varcid($vid)]} {
1493 set varcid($vid) $a
1494 lappend varccommits($view,$a) $id
1495 incr commitidx($view)
1496 }
Paul Mackerrase5b37ac2007-12-12 18:13:51 +11001497
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001498 set i 0
1499 foreach p $olds {
1500 if {$i == 0 || [lsearch -exact $olds $p] >= $i} {
1501 set vp $view,$p
1502 if {[llength [lappend children($vp) $id]] > 1 &&
1503 [vtokcmp $view [lindex $children($vp) end-1] $id] > 0} {
1504 set children($vp) [lsort -command [list vtokcmp $view] \
1505 $children($vp)]
Paul Mackerras9257d8f2007-12-11 10:45:38 +11001506 catch {unset ordertok}
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001507 }
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +11001508 if {[info exists varcid($view,$p)]} {
1509 fix_reversal $p $a $view
1510 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001511 }
1512 incr i
1513 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001514
Paul Mackerrasd375ef92008-10-21 10:18:12 +11001515 set scripts [check_interest $id $scripts]
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11001516 set gotsome 1
Paul Mackerras9f1afe02006-02-19 22:44:47 +11001517 }
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11001518 if {$gotsome} {
Paul Mackerrasac1276a2008-03-03 10:11:08 +11001519 global numcommits hlview
1520
1521 if {$view == $curview} {
1522 set numcommits $commitidx($view)
1523 run chewcommits
1524 }
1525 if {[info exists hlview] && $view == $hlview} {
1526 # we never actually get here...
1527 run vhighlightmore
1528 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001529 foreach s $scripts {
1530 eval $s
1531 }
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11001532 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10001533 return 2
Paul Mackerrascfb45632005-05-31 12:14:42 +00001534}
1535
Paul Mackerrasac1276a2008-03-03 10:11:08 +11001536proc chewcommits {} {
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10001537 global curview hlview viewcomplete
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001538 global pending_select
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +00001539
Paul Mackerrasac1276a2008-03-03 10:11:08 +11001540 layoutmore
1541 if {$viewcomplete($curview)} {
1542 global commitidx varctok
1543 global numcommits startmsecs
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10001544
Paul Mackerrasac1276a2008-03-03 10:11:08 +11001545 if {[info exists pending_select]} {
Alexander Gavrilov835e62a2008-07-26 20:15:54 +04001546 update
1547 reset_pending_select {}
1548
1549 if {[commitinview $pending_select $curview]} {
1550 selectline [rowofcommit $pending_select] 1
1551 } else {
1552 set row [first_real_row]
1553 selectline $row 1
1554 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10001555 }
Paul Mackerrasac1276a2008-03-03 10:11:08 +11001556 if {$commitidx($curview) > 0} {
1557 #set ms [expr {[clock clicks -milliseconds] - $startmsecs}]
1558 #puts "overall $ms ms for $numcommits commits"
1559 #puts "[llength $varctok($view)] arcs, $commitidx($view) commits"
1560 } else {
1561 show_status [mc "No commits selected"]
1562 }
1563 notbusy layout
Paul Mackerrasb6645502005-08-11 09:56:23 +10001564 }
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10001565 return 0
Paul Mackerras1db95b02005-05-09 04:08:39 +00001566}
1567
Alexander Gavrilov590915d2008-11-09 18:06:07 +03001568proc do_readcommit {id} {
1569 global tclencoding
1570
1571 # Invoke git-log to handle automatic encoding conversion
1572 set fd [open [concat | git log --no-color --pretty=raw -1 $id] r]
1573 # Read the results using i18n.logoutputencoding
1574 fconfigure $fd -translation lf -eofchar {}
1575 if {$tclencoding != {}} {
1576 fconfigure $fd -encoding $tclencoding
1577 }
1578 set contents [read $fd]
1579 close $fd
1580 # Remove the heading line
1581 regsub {^commit [0-9a-f]+\n} $contents {} contents
1582
1583 return $contents
1584}
1585
Paul Mackerras1db95b02005-05-09 04:08:39 +00001586proc readcommit {id} {
Alexander Gavrilov590915d2008-11-09 18:06:07 +03001587 if {[catch {set contents [do_readcommit $id]}]} return
1588 parsecommit $id $contents 1
Paul Mackerrasb490a992005-06-22 10:25:38 +10001589}
1590
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11001591proc parsecommit {id contents listed} {
Sven Verdoolaegeb5c2f302005-11-29 22:15:51 +01001592 global commitinfo cdate
1593
1594 set inhdr 1
1595 set comment {}
1596 set headline {}
1597 set auname {}
1598 set audate {}
1599 set comname {}
1600 set comdate {}
Paul Mackerras232475d2005-11-15 10:34:03 +11001601 set hdrend [string first "\n\n" $contents]
1602 if {$hdrend < 0} {
1603 # should never happen...
1604 set hdrend [string length $contents]
1605 }
1606 set header [string range $contents 0 [expr {$hdrend - 1}]]
1607 set comment [string range $contents [expr {$hdrend + 2}] end]
1608 foreach line [split $header "\n"] {
Kevin Ballard61f57cb2008-12-18 01:26:48 -08001609 set line [split $line " "]
Paul Mackerras232475d2005-11-15 10:34:03 +11001610 set tag [lindex $line 0]
1611 if {$tag == "author"} {
1612 set audate [lindex $line end-1]
Kevin Ballard61f57cb2008-12-18 01:26:48 -08001613 set auname [join [lrange $line 1 end-2] " "]
Paul Mackerras232475d2005-11-15 10:34:03 +11001614 } elseif {$tag == "committer"} {
1615 set comdate [lindex $line end-1]
Kevin Ballard61f57cb2008-12-18 01:26:48 -08001616 set comname [join [lrange $line 1 end-2] " "]
Paul Mackerras1db95b02005-05-09 04:08:39 +00001617 }
1618 }
Paul Mackerras232475d2005-11-15 10:34:03 +11001619 set headline {}
Paul Mackerras43c25072006-09-27 10:56:02 +10001620 # take the first non-blank line of the comment as the headline
1621 set headline [string trimleft $comment]
1622 set i [string first "\n" $headline]
Paul Mackerras232475d2005-11-15 10:34:03 +11001623 if {$i >= 0} {
Paul Mackerras43c25072006-09-27 10:56:02 +10001624 set headline [string range $headline 0 $i]
1625 }
1626 set headline [string trimright $headline]
1627 set i [string first "\r" $headline]
1628 if {$i >= 0} {
1629 set headline [string trimright [string range $headline 0 $i]]
Paul Mackerras232475d2005-11-15 10:34:03 +11001630 }
1631 if {!$listed} {
Paul Mackerrasf9e0b6f2008-03-04 21:14:17 +11001632 # git log indents the comment by 4 spaces;
Timo Hirvonen8974c6f2006-05-24 10:57:40 +03001633 # if we got this via git cat-file, add the indentation
Paul Mackerras232475d2005-11-15 10:34:03 +11001634 set newcomment {}
1635 foreach line [split $comment "\n"] {
1636 append newcomment " "
1637 append newcomment $line
Paul Mackerrasf6e28692005-11-20 23:08:22 +11001638 append newcomment "\n"
Paul Mackerras232475d2005-11-15 10:34:03 +11001639 }
1640 set comment $newcomment
Paul Mackerras1db95b02005-05-09 04:08:39 +00001641 }
1642 if {$comdate != {}} {
Paul Mackerrascfb45632005-05-31 12:14:42 +00001643 set cdate($id) $comdate
Paul Mackerras1db95b02005-05-09 04:08:39 +00001644 }
Paul Mackerrase5c2d852005-05-11 23:44:54 +00001645 set commitinfo($id) [list $headline $auname $audate \
1646 $comname $comdate $comment]
Paul Mackerras1db95b02005-05-09 04:08:39 +00001647}
1648
Paul Mackerrasf7a3e8d2006-03-18 10:04:48 +11001649proc getcommit {id} {
Paul Mackerras79b2c752006-04-02 20:47:40 +10001650 global commitdata commitinfo
Paul Mackerras8ed16482006-03-02 22:56:44 +11001651
Paul Mackerrasf7a3e8d2006-03-18 10:04:48 +11001652 if {[info exists commitdata($id)]} {
1653 parsecommit $id $commitdata($id) 1
Paul Mackerras8ed16482006-03-02 22:56:44 +11001654 } else {
1655 readcommit $id
1656 if {![info exists commitinfo($id)]} {
Christian Stimmingd990ced2007-11-07 18:42:55 +01001657 set commitinfo($id) [list [mc "No commit information available"]]
Paul Mackerras8ed16482006-03-02 22:56:44 +11001658 }
1659 }
1660 return 1
1661}
1662
Paul Mackerrasd375ef92008-10-21 10:18:12 +11001663# Expand an abbreviated commit ID to a list of full 40-char IDs that match
1664# and are present in the current view.
1665# This is fairly slow...
1666proc longid {prefix} {
1667 global varcid curview
1668
1669 set ids {}
1670 foreach match [array names varcid "$curview,$prefix*"] {
1671 lappend ids [lindex [split $match ","] 1]
1672 }
1673 return $ids
1674}
1675
Paul Mackerras887fe3c2005-05-21 07:35:37 +00001676proc readrefs {} {
Paul Mackerras62d3ea62006-09-11 10:36:53 +10001677 global tagids idtags headids idheads tagobjid
Paul Mackerras219ea3a2006-09-07 10:21:39 +10001678 global otherrefids idotherrefs mainhead mainheadid
Alexander Gavrilov39816d62008-08-23 12:27:44 +04001679 global selecthead selectheadid
Thomas Rastffe15292009-08-03 23:53:36 +02001680 global hideremotes
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10001681
Sven Verdoolaegeb5c2f302005-11-29 22:15:51 +01001682 foreach v {tagids idtags headids idheads otherrefids idotherrefs} {
1683 catch {unset $v}
1684 }
Paul Mackerras62d3ea62006-09-11 10:36:53 +10001685 set refd [open [list | git show-ref -d] r]
1686 while {[gets $refd line] >= 0} {
1687 if {[string index $line 40] ne " "} continue
1688 set id [string range $line 0 39]
1689 set ref [string range $line 41 end]
1690 if {![string match "refs/*" $ref]} continue
1691 set name [string range $ref 5 end]
1692 if {[string match "remotes/*" $name]} {
Thomas Rastffe15292009-08-03 23:53:36 +02001693 if {![string match "*/HEAD" $name] && !$hideremotes} {
Paul Mackerras62d3ea62006-09-11 10:36:53 +10001694 set headids($name) $id
1695 lappend idheads($id) $name
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10001696 }
Paul Mackerras62d3ea62006-09-11 10:36:53 +10001697 } elseif {[string match "heads/*" $name]} {
1698 set name [string range $name 6 end]
Junio C Hamano36a7cad2005-11-18 23:54:17 -08001699 set headids($name) $id
1700 lappend idheads($id) $name
Paul Mackerras62d3ea62006-09-11 10:36:53 +10001701 } elseif {[string match "tags/*" $name]} {
1702 # this lets refs/tags/foo^{} overwrite refs/tags/foo,
1703 # which is what we want since the former is the commit ID
1704 set name [string range $name 5 end]
1705 if {[string match "*^{}" $name]} {
1706 set name [string range $name 0 end-3]
1707 } else {
1708 set tagobjid($name) $id
1709 }
1710 set tagids($name) $id
1711 lappend idtags($id) $name
Junio C Hamano36a7cad2005-11-18 23:54:17 -08001712 } else {
1713 set otherrefids($name) $id
1714 lappend idotherrefs($id) $name
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10001715 }
1716 }
Alex Riesen062d6712007-07-29 22:28:40 +02001717 catch {close $refd}
Paul Mackerras8a485712006-07-06 10:21:23 +10001718 set mainhead {}
Paul Mackerras219ea3a2006-09-07 10:21:39 +10001719 set mainheadid {}
Paul Mackerras8a485712006-07-06 10:21:23 +10001720 catch {
Paul Mackerrasc11ff122008-05-26 10:11:33 +10001721 set mainheadid [exec git rev-parse HEAD]
Paul Mackerras8a485712006-07-06 10:21:23 +10001722 set thehead [exec git symbolic-ref HEAD]
1723 if {[string match "refs/heads/*" $thehead]} {
1724 set mainhead [string range $thehead 11 end]
1725 }
1726 }
Alexander Gavrilov39816d62008-08-23 12:27:44 +04001727 set selectheadid {}
1728 if {$selecthead ne {}} {
1729 catch {
1730 set selectheadid [exec git rev-parse --verify $selecthead]
1731 }
1732 }
Paul Mackerras887fe3c2005-05-21 07:35:37 +00001733}
1734
Paul Mackerras8f489362007-07-13 19:49:37 +10001735# skip over fake commits
1736proc first_real_row {} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001737 global nullid nullid2 numcommits
Paul Mackerras8f489362007-07-13 19:49:37 +10001738
1739 for {set row 0} {$row < $numcommits} {incr row} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001740 set id [commitonrow $row]
Paul Mackerras8f489362007-07-13 19:49:37 +10001741 if {$id ne $nullid && $id ne $nullid2} {
1742 break
1743 }
1744 }
1745 return $row
1746}
1747
Paul Mackerrase11f1232007-06-16 20:29:25 +10001748# update things for a head moved to a child of its previous location
1749proc movehead {id name} {
1750 global headids idheads
1751
1752 removehead $headids($name) $name
1753 set headids($name) $id
1754 lappend idheads($id) $name
1755}
1756
1757# update things when a head has been removed
1758proc removehead {id name} {
1759 global headids idheads
1760
1761 if {$idheads($id) eq $name} {
1762 unset idheads($id)
1763 } else {
1764 set i [lsearch -exact $idheads($id) $name]
1765 if {$i >= 0} {
1766 set idheads($id) [lreplace $idheads($id) $i $i]
1767 }
1768 }
1769 unset headids($name)
1770}
1771
Alexander Gavrilove7d64002008-11-11 23:55:42 +03001772proc make_transient {window origin} {
1773 global have_tk85
1774
1775 # In MacOS Tk 8.4 transient appears to work by setting
1776 # overrideredirect, which is utterly useless, since the
1777 # windows get no border, and are not even kept above
1778 # the parent.
1779 if {!$have_tk85 && [tk windowingsystem] eq {aqua}} return
1780
1781 wm transient $window $origin
1782
1783 # Windows fails to place transient windows normally, so
1784 # schedule a callback to center them on the parent.
1785 if {[tk windowingsystem] eq {win32}} {
1786 after idle [list tk::PlaceWindow $window widget $origin]
1787 }
1788}
1789
Paul Mackerrase54be9e2006-05-26 22:34:30 +10001790proc show_error {w top msg} {
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00001791 message $w.m -text $msg -justify center -aspect 400
1792 pack $w.m -side top -fill x -padx 20 -pady 20
Christian Stimmingd990ced2007-11-07 18:42:55 +01001793 button $w.ok -text [mc OK] -command "destroy $top"
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00001794 pack $w.ok -side bottom -fill x
Paul Mackerrase54be9e2006-05-26 22:34:30 +10001795 bind $top <Visibility> "grab $top; focus $top"
1796 bind $top <Key-Return> "destroy $top"
Alexander Gavrilov76f15942008-11-02 21:59:44 +03001797 bind $top <Key-space> "destroy $top"
1798 bind $top <Key-Escape> "destroy $top"
Paul Mackerrase54be9e2006-05-26 22:34:30 +10001799 tkwait window $top
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00001800}
1801
Alexander Gavrilov84a76f12008-11-02 21:59:45 +03001802proc error_popup {msg {owner .}} {
Paul Mackerras098dd8a2006-05-03 09:32:53 +10001803 set w .error
1804 toplevel $w
Alexander Gavrilove7d64002008-11-11 23:55:42 +03001805 make_transient $w $owner
Paul Mackerrase54be9e2006-05-26 22:34:30 +10001806 show_error $w $w $msg
Paul Mackerras098dd8a2006-05-03 09:32:53 +10001807}
1808
Alexander Gavrilov84a76f12008-11-02 21:59:45 +03001809proc confirm_popup {msg {owner .}} {
Paul Mackerras10299152006-08-02 09:52:01 +10001810 global confirm_ok
1811 set confirm_ok 0
1812 set w .confirm
1813 toplevel $w
Alexander Gavrilove7d64002008-11-11 23:55:42 +03001814 make_transient $w $owner
Paul Mackerras10299152006-08-02 09:52:01 +10001815 message $w.m -text $msg -justify center -aspect 400
1816 pack $w.m -side top -fill x -padx 20 -pady 20
Christian Stimmingd990ced2007-11-07 18:42:55 +01001817 button $w.ok -text [mc OK] -command "set confirm_ok 1; destroy $w"
Paul Mackerras10299152006-08-02 09:52:01 +10001818 pack $w.ok -side left -fill x
Christian Stimmingd990ced2007-11-07 18:42:55 +01001819 button $w.cancel -text [mc Cancel] -command "destroy $w"
Paul Mackerras10299152006-08-02 09:52:01 +10001820 pack $w.cancel -side right -fill x
1821 bind $w <Visibility> "grab $w; focus $w"
Alexander Gavrilov76f15942008-11-02 21:59:44 +03001822 bind $w <Key-Return> "set confirm_ok 1; destroy $w"
1823 bind $w <Key-space> "set confirm_ok 1; destroy $w"
1824 bind $w <Key-Escape> "destroy $w"
Paul Mackerras10299152006-08-02 09:52:01 +10001825 tkwait window $w
1826 return $confirm_ok
1827}
1828
Paul Mackerrasb039f0a2008-01-06 15:54:46 +11001829proc setoptions {} {
1830 option add *Panedwindow.showHandle 1 startupFile
1831 option add *Panedwindow.sashRelief raised startupFile
1832 option add *Button.font uifont startupFile
1833 option add *Checkbutton.font uifont startupFile
1834 option add *Radiobutton.font uifont startupFile
Daniel A. Steffen5fdcbb12009-03-23 12:17:38 +01001835 if {[tk windowingsystem] ne "aqua"} {
1836 option add *Menu.font uifont startupFile
1837 }
Paul Mackerrasb039f0a2008-01-06 15:54:46 +11001838 option add *Menubutton.font uifont startupFile
1839 option add *Label.font uifont startupFile
1840 option add *Message.font uifont startupFile
1841 option add *Entry.font uifont startupFile
1842}
1843
Paul Mackerras79056032008-10-18 16:24:46 +11001844# Make a menu and submenus.
1845# m is the window name for the menu, items is the list of menu items to add.
1846# Each item is a list {mc label type description options...}
1847# mc is ignored; it's so we can put mc there to alert xgettext
1848# label is the string that appears in the menu
1849# type is cascade, command or radiobutton (should add checkbutton)
1850# description depends on type; it's the sublist for cascade, the
1851# command to invoke for command, or {variable value} for radiobutton
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11001852proc makemenu {m items} {
1853 menu $m
Alexander Gavrilovcea07cf2008-11-09 13:00:45 +03001854 if {[tk windowingsystem] eq {aqua}} {
1855 set Meta1 Cmd
1856 } else {
1857 set Meta1 Ctrl
1858 }
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11001859 foreach i $items {
Paul Mackerras79056032008-10-18 16:24:46 +11001860 set name [mc [lindex $i 1]]
1861 set type [lindex $i 2]
1862 set thing [lindex $i 3]
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11001863 set params [list $type]
1864 if {$name ne {}} {
1865 set u [string first "&" [string map {&& x} $name]]
1866 lappend params -label [string map {&& & & {}} $name]
1867 if {$u >= 0} {
1868 lappend params -underline $u
1869 }
1870 }
1871 switch -- $type {
1872 "cascade" {
Paul Mackerras79056032008-10-18 16:24:46 +11001873 set submenu [string tolower [string map {& ""} [lindex $i 1]]]
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11001874 lappend params -menu $m.$submenu
1875 }
1876 "command" {
1877 lappend params -command $thing
1878 }
1879 "radiobutton" {
1880 lappend params -variable [lindex $thing 0] \
1881 -value [lindex $thing 1]
1882 }
1883 }
Alexander Gavrilovcea07cf2008-11-09 13:00:45 +03001884 set tail [lrange $i 4 end]
1885 regsub -all {\yMeta1\y} $tail $Meta1 tail
1886 eval $m add $params $tail
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11001887 if {$type eq "cascade"} {
1888 makemenu $m.$submenu $thing
1889 }
1890 }
1891}
1892
1893# translate string and remove ampersands
1894proc mca {str} {
1895 return [string map {&& & & {}} [mc $str]]
1896}
1897
Paul Mackerrasd94f8cd2006-04-06 10:18:23 +10001898proc makewindow {} {
Paul Mackerras31c0eaa2007-12-30 22:41:14 +11001899 global canv canv2 canv3 linespc charspc ctext cflist cscroll
Paul Mackerras9c311b32007-10-04 22:27:13 +10001900 global tabstop
Paul Mackerrasb74fd572005-07-16 07:46:13 -04001901 global findtype findtypemenu findloc findstring fstring geometry
Paul Mackerras887fe3c2005-05-21 07:35:37 +00001902 global entries sha1entry sha1string sha1but
Steffen Prohaska890fae72007-08-12 12:05:46 +02001903 global diffcontextstring diffcontext
Steffen Prohaskab9b86002008-01-17 23:42:55 +01001904 global ignorespace
Paul Mackerras94a2eed2005-08-07 15:27:57 +10001905 global maincursor textcursor curtextcursor
Paul Mackerras219ea3a2006-09-07 10:21:39 +10001906 global rowctxmenu fakerowmenu mergemax wrapcomment
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10001907 global highlight_files gdttype
Paul Mackerras3ea06f92006-05-24 10:16:03 +10001908 global searchstring sstring
Mark Levedahl60378c02007-05-20 12:12:48 -04001909 global bgcolor fgcolor bglist fglist diffcolors selectbgcolor
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10001910 global headctxmenu progresscanv progressitem progresscoords statusw
1911 global fprogitem fprogcoord lastprogupdate progupdatepending
Paul Mackerras6df74032008-05-11 22:13:02 +10001912 global rprogitem rprogcoord rownumsel numcommits
Paul Mackerras32f1b3e2007-09-28 21:27:39 +10001913 global have_tk85
Paul Mackerras9a40c502005-05-12 23:46:16 +00001914
Paul Mackerras79056032008-10-18 16:24:46 +11001915 # The "mc" arguments here are purely so that xgettext
1916 # sees the following string as needing to be translated
Daniel A. Steffen5fdcbb12009-03-23 12:17:38 +01001917 set file {
1918 mc "File" cascade {
Paul Mackerras79056032008-10-18 16:24:46 +11001919 {mc "Update" command updatecommits -accelerator F5}
Alexander Gavrilovcea07cf2008-11-09 13:00:45 +03001920 {mc "Reload" command reloadcommits -accelerator Meta1-F5}
Paul Mackerras79056032008-10-18 16:24:46 +11001921 {mc "Reread references" command rereadrefs}
Alexander Gavrilovcea07cf2008-11-09 13:00:45 +03001922 {mc "List references" command showrefs -accelerator F2}
Alexander Gavrilov7fb0abb2008-11-13 23:12:42 +03001923 {xx "" separator}
1924 {mc "Start git gui" command {exec git gui &}}
1925 {xx "" separator}
Alexander Gavrilovcea07cf2008-11-09 13:00:45 +03001926 {mc "Quit" command doquit -accelerator Meta1-Q}
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11001927 }}
Daniel A. Steffen5fdcbb12009-03-23 12:17:38 +01001928 set edit {
1929 mc "Edit" cascade {
Paul Mackerras79056032008-10-18 16:24:46 +11001930 {mc "Preferences" command doprefs}
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11001931 }}
Daniel A. Steffen5fdcbb12009-03-23 12:17:38 +01001932 set view {
1933 mc "View" cascade {
Alexander Gavrilovcea07cf2008-11-09 13:00:45 +03001934 {mc "New view..." command {newview 0} -accelerator Shift-F4}
1935 {mc "Edit view..." command editview -state disabled -accelerator F4}
Paul Mackerras79056032008-10-18 16:24:46 +11001936 {mc "Delete view" command delview -state disabled}
1937 {xx "" separator}
1938 {mc "All files" radiobutton {selectedview 0} -command {showview 0}}
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11001939 }}
Daniel A. Steffen5fdcbb12009-03-23 12:17:38 +01001940 if {[tk windowingsystem] ne "aqua"} {
1941 set help {
1942 mc "Help" cascade {
Paul Mackerras79056032008-10-18 16:24:46 +11001943 {mc "About gitk" command about}
1944 {mc "Key bindings" command keys}
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11001945 }}
Daniel A. Steffen5fdcbb12009-03-23 12:17:38 +01001946 set bar [list $file $edit $view $help]
1947 } else {
1948 proc ::tk::mac::ShowPreferences {} {doprefs}
1949 proc ::tk::mac::Quit {} {doquit}
1950 lset file end [lreplace [lindex $file end] end-1 end]
1951 set apple {
1952 xx "Apple" cascade {
1953 {mc "About gitk" command about}
1954 {xx "" separator}
1955 }}
1956 set help {
1957 mc "Help" cascade {
1958 {mc "Key bindings" command keys}
1959 }}
1960 set bar [list $apple $file $view $help]
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11001961 }
Daniel A. Steffen5fdcbb12009-03-23 12:17:38 +01001962 makemenu .bar $bar
Paul Mackerras9a40c502005-05-12 23:46:16 +00001963 . configure -menu .bar
1964
Junio C Hamanoe9937d22007-02-01 08:46:38 -05001965 # the gui has upper and lower half, parts of a paned window.
Paul Mackerras0327d272005-05-10 00:23:42 +00001966 panedwindow .ctop -orient vertical
Junio C Hamanoe9937d22007-02-01 08:46:38 -05001967
1968 # possibly use assumed geometry
Mark Levedahl9ca72f42007-02-12 19:19:34 -05001969 if {![info exists geometry(pwsash0)]} {
Junio C Hamanoe9937d22007-02-01 08:46:38 -05001970 set geometry(topheight) [expr {15 * $linespc}]
1971 set geometry(topwidth) [expr {80 * $charspc}]
1972 set geometry(botheight) [expr {15 * $linespc}]
1973 set geometry(botwidth) [expr {50 * $charspc}]
Mark Levedahl9ca72f42007-02-12 19:19:34 -05001974 set geometry(pwsash0) "[expr {40 * $charspc}] 2"
1975 set geometry(pwsash1) "[expr {60 * $charspc}] 2"
Paul Mackerras0fba86b2005-05-16 23:54:58 +00001976 }
Junio C Hamanoe9937d22007-02-01 08:46:38 -05001977
1978 # the upper half will have a paned window, a scroll bar to the right, and some stuff below
1979 frame .tf -height $geometry(topheight) -width $geometry(topwidth)
1980 frame .tf.histframe
1981 panedwindow .tf.histframe.pwclist -orient horizontal -sashpad 0 -handlesize 4
1982
1983 # create three canvases
1984 set cscroll .tf.histframe.csb
1985 set canv .tf.histframe.pwclist.canv
Mark Levedahl9ca72f42007-02-12 19:19:34 -05001986 canvas $canv \
Mark Levedahl60378c02007-05-20 12:12:48 -04001987 -selectbackground $selectbgcolor \
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10001988 -background $bgcolor -bd 0 \
Paul Mackerras9f1afe02006-02-19 22:44:47 +11001989 -yscrollincr $linespc -yscrollcommand "scrollcanv $cscroll"
Junio C Hamanoe9937d22007-02-01 08:46:38 -05001990 .tf.histframe.pwclist add $canv
1991 set canv2 .tf.histframe.pwclist.canv2
Mark Levedahl9ca72f42007-02-12 19:19:34 -05001992 canvas $canv2 \
Mark Levedahl60378c02007-05-20 12:12:48 -04001993 -selectbackground $selectbgcolor \
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10001994 -background $bgcolor -bd 0 -yscrollincr $linespc
Junio C Hamanoe9937d22007-02-01 08:46:38 -05001995 .tf.histframe.pwclist add $canv2
1996 set canv3 .tf.histframe.pwclist.canv3
Mark Levedahl9ca72f42007-02-12 19:19:34 -05001997 canvas $canv3 \
Mark Levedahl60378c02007-05-20 12:12:48 -04001998 -selectbackground $selectbgcolor \
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10001999 -background $bgcolor -bd 0 -yscrollincr $linespc
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002000 .tf.histframe.pwclist add $canv3
Mark Levedahl9ca72f42007-02-12 19:19:34 -05002001 eval .tf.histframe.pwclist sash place 0 $geometry(pwsash0)
2002 eval .tf.histframe.pwclist sash place 1 $geometry(pwsash1)
Paul Mackerras98f350e2005-05-15 05:56:51 +00002003
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002004 # a scroll bar to rule them
2005 scrollbar $cscroll -command {allcanvs yview} -highlightthickness 0
2006 pack $cscroll -side right -fill y
2007 bind .tf.histframe.pwclist <Configure> {resizeclistpanes %W %w}
2008 lappend bglist $canv $canv2 $canv3
2009 pack .tf.histframe.pwclist -fill both -expand 1 -side left
2010
2011 # we have two button bars at bottom of top frame. Bar 1
2012 frame .tf.bar
2013 frame .tf.lbar -height 15
2014
2015 set sha1entry .tf.bar.sha1
Paul Mackerras887fe3c2005-05-21 07:35:37 +00002016 set entries $sha1entry
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002017 set sha1but .tf.bar.sha1label
Christian Stimmingd990ced2007-11-07 18:42:55 +01002018 button $sha1but -text [mc "SHA1 ID: "] -state disabled -relief flat \
Paul Mackerrasb039f0a2008-01-06 15:54:46 +11002019 -command gotocommit -width 8
Paul Mackerras887fe3c2005-05-21 07:35:37 +00002020 $sha1but conf -disabledforeground [$sha1but cget -foreground]
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002021 pack .tf.bar.sha1label -side left
Paul Mackerras9c311b32007-10-04 22:27:13 +10002022 entry $sha1entry -width 40 -font textfont -textvariable sha1string
Paul Mackerras887fe3c2005-05-21 07:35:37 +00002023 trace add variable sha1string write sha1change
Paul Mackerras98f350e2005-05-15 05:56:51 +00002024 pack $sha1entry -side left -pady 2
Paul Mackerrasd6982062005-08-06 22:06:06 +10002025
2026 image create bitmap bm-left -data {
2027 #define left_width 16
2028 #define left_height 16
2029 static unsigned char left_bits[] = {
2030 0x00, 0x00, 0xc0, 0x01, 0xe0, 0x00, 0x70, 0x00, 0x38, 0x00, 0x1c, 0x00,
2031 0x0e, 0x00, 0xff, 0x7f, 0xff, 0x7f, 0xff, 0x7f, 0x0e, 0x00, 0x1c, 0x00,
2032 0x38, 0x00, 0x70, 0x00, 0xe0, 0x00, 0xc0, 0x01};
2033 }
2034 image create bitmap bm-right -data {
2035 #define right_width 16
2036 #define right_height 16
2037 static unsigned char right_bits[] = {
2038 0x00, 0x00, 0xc0, 0x01, 0x80, 0x03, 0x00, 0x07, 0x00, 0x0e, 0x00, 0x1c,
2039 0x00, 0x38, 0xff, 0x7f, 0xff, 0x7f, 0xff, 0x7f, 0x00, 0x38, 0x00, 0x1c,
2040 0x00, 0x0e, 0x00, 0x07, 0x80, 0x03, 0xc0, 0x01};
2041 }
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002042 button .tf.bar.leftbut -image bm-left -command goback \
Paul Mackerrasd6982062005-08-06 22:06:06 +10002043 -state disabled -width 26
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002044 pack .tf.bar.leftbut -side left -fill y
2045 button .tf.bar.rightbut -image bm-right -command goforw \
Paul Mackerrasd6982062005-08-06 22:06:06 +10002046 -state disabled -width 26
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002047 pack .tf.bar.rightbut -side left -fill y
Paul Mackerrasd6982062005-08-06 22:06:06 +10002048
Paul Mackerras6df74032008-05-11 22:13:02 +10002049 label .tf.bar.rowlabel -text [mc "Row"]
2050 set rownumsel {}
2051 label .tf.bar.rownum -width 7 -font textfont -textvariable rownumsel \
2052 -relief sunken -anchor e
2053 label .tf.bar.rowlabel2 -text "/"
2054 label .tf.bar.numcommits -width 7 -font textfont -textvariable numcommits \
2055 -relief sunken -anchor e
2056 pack .tf.bar.rowlabel .tf.bar.rownum .tf.bar.rowlabel2 .tf.bar.numcommits \
2057 -side left
2058 global selectedline
Paul Mackerras94b4a692008-05-20 20:51:06 +10002059 trace add variable selectedline write selectedline_change
Paul Mackerras6df74032008-05-11 22:13:02 +10002060
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10002061 # Status label and progress bar
2062 set statusw .tf.bar.status
Paul Mackerrasb039f0a2008-01-06 15:54:46 +11002063 label $statusw -width 15 -relief sunken
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10002064 pack $statusw -side left -padx 5
Paul Mackerras9c311b32007-10-04 22:27:13 +10002065 set h [expr {[font metrics uifont -linespace] + 2}]
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10002066 set progresscanv .tf.bar.progress
2067 canvas $progresscanv -relief sunken -height $h -borderwidth 2
2068 set progressitem [$progresscanv create rect -1 0 0 $h -fill green]
2069 set fprogitem [$progresscanv create rect -1 0 0 $h -fill yellow]
Paul Mackerrasa137a902007-10-23 21:12:49 +10002070 set rprogitem [$progresscanv create rect -1 0 0 $h -fill red]
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10002071 pack $progresscanv -side right -expand 1 -fill x
2072 set progresscoords {0 0}
2073 set fprogcoord 0
Paul Mackerrasa137a902007-10-23 21:12:49 +10002074 set rprogcoord 0
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10002075 bind $progresscanv <Configure> adjustprogress
2076 set lastprogupdate [clock clicks -milliseconds]
2077 set progupdatepending 0
Paul Mackerrasb5721c72005-05-10 12:08:22 +00002078
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002079 # build up the bottom bar of upper window
Paul Mackerrasb039f0a2008-01-06 15:54:46 +11002080 label .tf.lbar.flabel -text "[mc "Find"] "
2081 button .tf.lbar.fnext -text [mc "next"] -command {dofind 1 1}
2082 button .tf.lbar.fprev -text [mc "prev"] -command {dofind -1 1}
2083 label .tf.lbar.flab2 -text " [mc "commit"] "
Paul Mackerras687c8762007-09-22 12:49:33 +10002084 pack .tf.lbar.flabel .tf.lbar.fnext .tf.lbar.fprev .tf.lbar.flab2 \
2085 -side left -fill y
Christian Stimmingb007ee22007-11-07 18:44:35 +01002086 set gdttype [mc "containing:"]
Paul Mackerras687c8762007-09-22 12:49:33 +10002087 set gm [tk_optionMenu .tf.lbar.gdttype gdttype \
Christian Stimmingb007ee22007-11-07 18:44:35 +01002088 [mc "containing:"] \
2089 [mc "touching paths:"] \
2090 [mc "adding/removing string:"]]
Paul Mackerras687c8762007-09-22 12:49:33 +10002091 trace add variable gdttype write gdttype_change
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002092 pack .tf.lbar.gdttype -side left -fill y
Paul Mackerras687c8762007-09-22 12:49:33 +10002093
2094 set findstring {}
2095 set fstring .tf.lbar.findstring
2096 lappend entries $fstring
Paul Mackerras9c311b32007-10-04 22:27:13 +10002097 entry $fstring -width 30 -font textfont -textvariable findstring
Paul Mackerras687c8762007-09-22 12:49:33 +10002098 trace add variable findstring write find_change
Christian Stimmingb007ee22007-11-07 18:44:35 +01002099 set findtype [mc "Exact"]
Paul Mackerras687c8762007-09-22 12:49:33 +10002100 set findtypemenu [tk_optionMenu .tf.lbar.findtype \
Christian Stimmingb007ee22007-11-07 18:44:35 +01002101 findtype [mc "Exact"] [mc "IgnCase"] [mc "Regexp"]]
Paul Mackerras687c8762007-09-22 12:49:33 +10002102 trace add variable findtype write findcom_change
Christian Stimmingb007ee22007-11-07 18:44:35 +01002103 set findloc [mc "All fields"]
2104 tk_optionMenu .tf.lbar.findloc findloc [mc "All fields"] [mc "Headline"] \
2105 [mc "Comments"] [mc "Author"] [mc "Committer"]
Paul Mackerras687c8762007-09-22 12:49:33 +10002106 trace add variable findloc write find_change
Paul Mackerras687c8762007-09-22 12:49:33 +10002107 pack .tf.lbar.findloc -side right
2108 pack .tf.lbar.findtype -side right
2109 pack $fstring -side left -expand 1 -fill x
Paul Mackerras908c3582006-05-20 09:38:11 +10002110
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002111 # Finish putting the upper half of the viewer together
2112 pack .tf.lbar -in .tf -side bottom -fill x
2113 pack .tf.bar -in .tf -side bottom -fill x
2114 pack .tf.histframe -fill both -side top -expand 1
2115 .ctop add .tf
Mark Levedahl9ca72f42007-02-12 19:19:34 -05002116 .ctop paneconfigure .tf -height $geometry(topheight)
2117 .ctop paneconfigure .tf -width $geometry(topwidth)
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002118
2119 # now build up the bottom
2120 panedwindow .pwbottom -orient horizontal
2121
2122 # lower left, a text box over search bar, scroll bar to the right
2123 # if we know window height, then that will set the lower text height, otherwise
2124 # we set lower text height which will drive window height
2125 if {[info exists geometry(main)]} {
2126 frame .bleft -width $geometry(botwidth)
2127 } else {
2128 frame .bleft -width $geometry(botwidth) -height $geometry(botheight)
2129 }
2130 frame .bleft.top
Paul Mackerrasa8d610a2007-04-19 11:39:12 +10002131 frame .bleft.mid
Pekka Kaitaniemi8809d692008-03-08 14:27:23 +02002132 frame .bleft.bottom
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002133
Paul Mackerrasb039f0a2008-01-06 15:54:46 +11002134 button .bleft.top.search -text [mc "Search"] -command dosearch
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002135 pack .bleft.top.search -side left -padx 5
2136 set sstring .bleft.top.sstring
Paul Mackerras9c311b32007-10-04 22:27:13 +10002137 entry $sstring -width 20 -font textfont -textvariable searchstring
Paul Mackerras3ea06f92006-05-24 10:16:03 +10002138 lappend entries $sstring
2139 trace add variable searchstring write incrsearch
2140 pack $sstring -side left -expand 1 -fill x
Paul Mackerrasb039f0a2008-01-06 15:54:46 +11002141 radiobutton .bleft.mid.diff -text [mc "Diff"] \
Paul Mackerrasa8d610a2007-04-19 11:39:12 +10002142 -command changediffdisp -variable diffelide -value {0 0}
Paul Mackerrasb039f0a2008-01-06 15:54:46 +11002143 radiobutton .bleft.mid.old -text [mc "Old version"] \
Paul Mackerrasa8d610a2007-04-19 11:39:12 +10002144 -command changediffdisp -variable diffelide -value {0 1}
Paul Mackerrasb039f0a2008-01-06 15:54:46 +11002145 radiobutton .bleft.mid.new -text [mc "New version"] \
Paul Mackerrasa8d610a2007-04-19 11:39:12 +10002146 -command changediffdisp -variable diffelide -value {1 0}
Paul Mackerrasb039f0a2008-01-06 15:54:46 +11002147 label .bleft.mid.labeldiffcontext -text " [mc "Lines of context"]: "
Paul Mackerrasa8d610a2007-04-19 11:39:12 +10002148 pack .bleft.mid.diff .bleft.mid.old .bleft.mid.new -side left
Paul Mackerras9c311b32007-10-04 22:27:13 +10002149 spinbox .bleft.mid.diffcontext -width 5 -font textfont \
Markus Heidelberga41ddbb2009-05-23 19:31:37 +02002150 -from 0 -increment 1 -to 10000000 \
Steffen Prohaska890fae72007-08-12 12:05:46 +02002151 -validate all -validatecommand "diffcontextvalidate %P" \
2152 -textvariable diffcontextstring
2153 .bleft.mid.diffcontext set $diffcontext
2154 trace add variable diffcontextstring write diffcontextchange
2155 lappend entries .bleft.mid.diffcontext
2156 pack .bleft.mid.labeldiffcontext .bleft.mid.diffcontext -side left
Steffen Prohaskab9b86002008-01-17 23:42:55 +01002157 checkbutton .bleft.mid.ignspace -text [mc "Ignore space change"] \
2158 -command changeignorespace -variable ignorespace
2159 pack .bleft.mid.ignspace -side left -padx 5
Pekka Kaitaniemi8809d692008-03-08 14:27:23 +02002160 set ctext .bleft.bottom.ctext
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10002161 text $ctext -background $bgcolor -foreground $fgcolor \
Paul Mackerras9c311b32007-10-04 22:27:13 +10002162 -state disabled -font textfont \
Pekka Kaitaniemi8809d692008-03-08 14:27:23 +02002163 -yscrollcommand scrolltext -wrap none \
2164 -xscrollcommand ".bleft.bottom.sbhorizontal set"
Paul Mackerras32f1b3e2007-09-28 21:27:39 +10002165 if {$have_tk85} {
2166 $ctext conf -tabstyle wordprocessor
2167 }
Pekka Kaitaniemi8809d692008-03-08 14:27:23 +02002168 scrollbar .bleft.bottom.sb -command "$ctext yview"
2169 scrollbar .bleft.bottom.sbhorizontal -command "$ctext xview" -orient h \
2170 -width 10
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002171 pack .bleft.top -side top -fill x
Paul Mackerrasa8d610a2007-04-19 11:39:12 +10002172 pack .bleft.mid -side top -fill x
Pekka Kaitaniemi8809d692008-03-08 14:27:23 +02002173 grid $ctext .bleft.bottom.sb -sticky nsew
2174 grid .bleft.bottom.sbhorizontal -sticky ew
2175 grid columnconfigure .bleft.bottom 0 -weight 1
2176 grid rowconfigure .bleft.bottom 0 -weight 1
2177 grid rowconfigure .bleft.bottom 1 -weight 0
2178 pack .bleft.bottom -side top -fill both -expand 1
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10002179 lappend bglist $ctext
2180 lappend fglist $ctext
Paul Mackerrasd2610d12005-05-11 00:45:38 +00002181
Sergey Vlasovf1b86292006-05-15 19:13:14 +04002182 $ctext tag conf comment -wrap $wrapcomment
Paul Mackerras9c311b32007-10-04 22:27:13 +10002183 $ctext tag conf filesep -font textfontbold -back "#aaaaaa"
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10002184 $ctext tag conf hunksep -fore [lindex $diffcolors 2]
2185 $ctext tag conf d0 -fore [lindex $diffcolors 0]
Paul Mackerras8b07dca2008-11-02 22:34:47 +11002186 $ctext tag conf dresult -fore [lindex $diffcolors 1]
Paul Mackerras712fcc02005-11-30 09:28:16 +11002187 $ctext tag conf m0 -fore red
2188 $ctext tag conf m1 -fore blue
2189 $ctext tag conf m2 -fore green
2190 $ctext tag conf m3 -fore purple
2191 $ctext tag conf m4 -fore brown
Paul Mackerrasb77b0272006-02-07 09:13:52 +11002192 $ctext tag conf m5 -fore "#009090"
2193 $ctext tag conf m6 -fore magenta
2194 $ctext tag conf m7 -fore "#808000"
2195 $ctext tag conf m8 -fore "#009000"
2196 $ctext tag conf m9 -fore "#ff0080"
2197 $ctext tag conf m10 -fore cyan
2198 $ctext tag conf m11 -fore "#b07070"
2199 $ctext tag conf m12 -fore "#70b0f0"
2200 $ctext tag conf m13 -fore "#70f0b0"
2201 $ctext tag conf m14 -fore "#f0b070"
2202 $ctext tag conf m15 -fore "#ff70b0"
Paul Mackerras712fcc02005-11-30 09:28:16 +11002203 $ctext tag conf mmax -fore darkgrey
Paul Mackerrasb77b0272006-02-07 09:13:52 +11002204 set mergemax 16
Paul Mackerras9c311b32007-10-04 22:27:13 +10002205 $ctext tag conf mresult -font textfontbold
2206 $ctext tag conf msep -font textfontbold
Paul Mackerras712fcc02005-11-30 09:28:16 +11002207 $ctext tag conf found -back yellow
Paul Mackerrase5c2d852005-05-11 23:44:54 +00002208
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002209 .pwbottom add .bleft
Mark Levedahl9ca72f42007-02-12 19:19:34 -05002210 .pwbottom paneconfigure .bleft -width $geometry(botwidth)
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002211
2212 # lower right
2213 frame .bright
2214 frame .bright.mode
Christian Stimmingd990ced2007-11-07 18:42:55 +01002215 radiobutton .bright.mode.patch -text [mc "Patch"] \
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10002216 -command reselectline -variable cmitmode -value "patch"
Christian Stimmingd990ced2007-11-07 18:42:55 +01002217 radiobutton .bright.mode.tree -text [mc "Tree"] \
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10002218 -command reselectline -variable cmitmode -value "tree"
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002219 grid .bright.mode.patch .bright.mode.tree -sticky ew
2220 pack .bright.mode -side top -fill x
2221 set cflist .bright.cfiles
Paul Mackerras9c311b32007-10-04 22:27:13 +10002222 set indent [font measure mainfont "nn"]
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002223 text $cflist \
Mark Levedahl60378c02007-05-20 12:12:48 -04002224 -selectbackground $selectbgcolor \
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10002225 -background $bgcolor -foreground $fgcolor \
Paul Mackerras9c311b32007-10-04 22:27:13 +10002226 -font mainfont \
Paul Mackerras7fcceed2006-04-27 19:21:49 +10002227 -tabs [list $indent [expr {2 * $indent}]] \
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002228 -yscrollcommand ".bright.sb set" \
Paul Mackerras7fcceed2006-04-27 19:21:49 +10002229 -cursor [. cget -cursor] \
2230 -spacing1 1 -spacing3 1
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10002231 lappend bglist $cflist
2232 lappend fglist $cflist
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002233 scrollbar .bright.sb -command "$cflist yview"
2234 pack .bright.sb -side right -fill y
Paul Mackerrasd2610d12005-05-11 00:45:38 +00002235 pack $cflist -side left -fill both -expand 1
Paul Mackerras89b11d32006-05-02 19:55:31 +10002236 $cflist tag configure highlight \
2237 -background [$cflist cget -selectbackground]
Paul Mackerras9c311b32007-10-04 22:27:13 +10002238 $cflist tag configure bold -font mainfontbold
Paul Mackerrasd2610d12005-05-11 00:45:38 +00002239
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002240 .pwbottom add .bright
2241 .ctop add .pwbottom
Paul Mackerras1db95b02005-05-09 04:08:39 +00002242
Paul Mackerrasb9bee112008-03-10 16:50:34 +11002243 # restore window width & height if known
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002244 if {[info exists geometry(main)]} {
Paul Mackerrasb9bee112008-03-10 16:50:34 +11002245 if {[scan $geometry(main) "%dx%d" w h] >= 2} {
2246 if {$w > [winfo screenwidth .]} {
2247 set w [winfo screenwidth .]
2248 }
2249 if {$h > [winfo screenheight .]} {
2250 set h [winfo screenheight .]
2251 }
2252 wm geometry . "${w}x$h"
2253 }
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002254 }
2255
Pat Thoytsc876dba2009-04-14 22:09:53 +01002256 if {[info exists geometry(state)] && $geometry(state) eq "zoomed"} {
2257 wm state . $geometry(state)
2258 }
2259
Shawn O. Pearced23d98d2007-07-19 00:37:58 -04002260 if {[tk windowingsystem] eq {aqua}} {
2261 set M1B M1
Daniel A. Steffen5fdcbb12009-03-23 12:17:38 +01002262 set ::BM "3"
Shawn O. Pearced23d98d2007-07-19 00:37:58 -04002263 } else {
2264 set M1B Control
Daniel A. Steffen5fdcbb12009-03-23 12:17:38 +01002265 set ::BM "2"
Shawn O. Pearced23d98d2007-07-19 00:37:58 -04002266 }
2267
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002268 bind .pwbottom <Configure> {resizecdetpanes %W %w}
2269 pack .ctop -fill both -expand 1
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10002270 bindall <1> {selcanvline %W %x %y}
2271 #bindall <B1-Motion> {selcanvline %W %x %y}
Mark Levedahl314c3092007-08-07 21:40:35 -04002272 if {[tk windowingsystem] == "win32"} {
2273 bind . <MouseWheel> { windows_mousewheel_redirector %W %X %Y %D }
2274 bind $ctext <MouseWheel> { windows_mousewheel_redirector %W %X %Y %D ; break }
2275 } else {
2276 bindall <ButtonRelease-4> "allcanvs yview scroll -5 units"
2277 bindall <ButtonRelease-5> "allcanvs yview scroll 5 units"
Jonathan del Strother5dd57d52007-10-15 10:33:07 +01002278 if {[tk windowingsystem] eq "aqua"} {
2279 bindall <MouseWheel> {
2280 set delta [expr {- (%D)}]
2281 allcanvs yview scroll $delta units
2282 }
Daniel A. Steffen5fdcbb12009-03-23 12:17:38 +01002283 bindall <Shift-MouseWheel> {
2284 set delta [expr {- (%D)}]
2285 $canv xview scroll $delta units
2286 }
Jonathan del Strother5dd57d52007-10-15 10:33:07 +01002287 }
Mark Levedahl314c3092007-08-07 21:40:35 -04002288 }
Daniel A. Steffen5fdcbb12009-03-23 12:17:38 +01002289 bindall <$::BM> "canvscan mark %W %x %y"
2290 bindall <B$::BM-Motion> "canvscan dragto %W %x %y"
Rutger Nijlunsing6e5f7202006-04-05 10:24:03 +10002291 bindkey <Home> selfirstline
2292 bindkey <End> sellastline
Paul Mackerras17386062005-05-18 22:51:00 +00002293 bind . <Key-Up> "selnextline -1"
2294 bind . <Key-Down> "selnextline 1"
Paul Mackerrascca5d942007-10-27 21:16:56 +10002295 bind . <Shift-Key-Up> "dofind -1 0"
2296 bind . <Shift-Key-Down> "dofind 1 0"
Rutger Nijlunsing6e5f7202006-04-05 10:24:03 +10002297 bindkey <Key-Right> "goforw"
2298 bindkey <Key-Left> "goback"
2299 bind . <Key-Prior> "selnextpage -1"
2300 bind . <Key-Next> "selnextpage 1"
Shawn O. Pearced23d98d2007-07-19 00:37:58 -04002301 bind . <$M1B-Home> "allcanvs yview moveto 0.0"
2302 bind . <$M1B-End> "allcanvs yview moveto 1.0"
2303 bind . <$M1B-Key-Up> "allcanvs yview scroll -1 units"
2304 bind . <$M1B-Key-Down> "allcanvs yview scroll 1 units"
2305 bind . <$M1B-Key-Prior> "allcanvs yview scroll -1 pages"
2306 bind . <$M1B-Key-Next> "allcanvs yview scroll 1 pages"
Paul Mackerrascfb45632005-05-31 12:14:42 +00002307 bindkey <Key-Delete> "$ctext yview scroll -1 pages"
2308 bindkey <Key-BackSpace> "$ctext yview scroll -1 pages"
2309 bindkey <Key-space> "$ctext yview scroll 1 pages"
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00002310 bindkey p "selnextline -1"
2311 bindkey n "selnextline 1"
Robert Suetterlin6e2dda32005-09-22 10:07:36 +10002312 bindkey z "goback"
2313 bindkey x "goforw"
2314 bindkey i "selnextline -1"
2315 bindkey k "selnextline 1"
2316 bindkey j "goback"
2317 bindkey l "goforw"
Paul Mackerrasf4c54b32008-05-10 13:15:36 +10002318 bindkey b prevfile
Paul Mackerrascfb45632005-05-31 12:14:42 +00002319 bindkey d "$ctext yview scroll 18 units"
2320 bindkey u "$ctext yview scroll -18 units"
Giuseppe Bilotta97bed032008-12-02 02:19:22 +01002321 bindkey / {focus $fstring}
Michele Ballabiob6e192d2009-03-30 14:55:21 +02002322 bindkey <Key-KP_Divide> {focus $fstring}
Paul Mackerrascca5d942007-10-27 21:16:56 +10002323 bindkey <Key-Return> {dofind 1 1}
2324 bindkey ? {dofind -1 1}
Paul Mackerras39ad8572005-05-19 12:35:53 +00002325 bindkey f nextfile
Alexander Gavrilovcea07cf2008-11-09 13:00:45 +03002326 bind . <F5> updatecommits
2327 bind . <$M1B-F5> reloadcommits
2328 bind . <F2> showrefs
2329 bind . <Shift-F4> {newview 0}
2330 catch { bind . <Shift-Key-XF86_Switch_VT_4> {newview 0} }
2331 bind . <F4> edit_or_newview
Shawn O. Pearced23d98d2007-07-19 00:37:58 -04002332 bind . <$M1B-q> doquit
Paul Mackerrascca5d942007-10-27 21:16:56 +10002333 bind . <$M1B-f> {dofind 1 1}
2334 bind . <$M1B-g> {dofind 1 0}
Shawn O. Pearced23d98d2007-07-19 00:37:58 -04002335 bind . <$M1B-r> dosearchback
2336 bind . <$M1B-s> dosearch
2337 bind . <$M1B-equal> {incrfont 1}
Johannes Schindelin646f3a12008-01-11 12:39:33 +00002338 bind . <$M1B-plus> {incrfont 1}
Shawn O. Pearced23d98d2007-07-19 00:37:58 -04002339 bind . <$M1B-KP_Add> {incrfont 1}
2340 bind . <$M1B-minus> {incrfont -1}
2341 bind . <$M1B-KP_Subtract> {incrfont -1}
Mark Levedahlb6047c52007-02-08 22:22:24 -05002342 wm protocol . WM_DELETE_WINDOW doquit
Alexander Gavrilove2f90ee2008-07-12 16:09:28 +04002343 bind . <Destroy> {stop_backends}
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00002344 bind . <Button-1> "click %W"
Paul Mackerrascca5d942007-10-27 21:16:56 +10002345 bind $fstring <Key-Return> {dofind 1 1}
Paul Mackerras968ce452008-10-16 09:57:02 +11002346 bind $sha1entry <Key-Return> {gotocommit; break}
Paul Mackerrasee3dc722005-06-25 16:37:13 +10002347 bind $sha1entry <<PasteSelection>> clearsha1
Paul Mackerras7fcceed2006-04-27 19:21:49 +10002348 bind $cflist <1> {sel_flist %W %x %y; break}
2349 bind $cflist <B1-Motion> {sel_flist %W %x %y; break}
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10002350 bind $cflist <ButtonRelease-1> {treeclick %W %x %y}
Paul Mackerrasd277e892008-09-21 18:11:37 -05002351 global ctxbut
2352 bind $cflist $ctxbut {pop_flist_menu %W %X %Y %x %y}
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04002353 bind $ctext $ctxbut {pop_diff_menu %W %X %Y %x %y}
Paul Mackerrasea13cba2005-06-16 10:54:04 +00002354
2355 set maincursor [. cget -cursor]
2356 set textcursor [$ctext cget -cursor]
Paul Mackerras94a2eed2005-08-07 15:27:57 +10002357 set curtextcursor $textcursor
Paul Mackerras84ba7342005-06-17 00:12:26 +00002358
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10002359 set rowctxmenu .rowctxmenu
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11002360 makemenu $rowctxmenu {
Paul Mackerras79056032008-10-18 16:24:46 +11002361 {mc "Diff this -> selected" command {diffvssel 0}}
2362 {mc "Diff selected -> this" command {diffvssel 1}}
2363 {mc "Make patch" command mkpatch}
2364 {mc "Create tag" command mktag}
2365 {mc "Write commit to file" command writecommit}
2366 {mc "Create new branch" command mkbranch}
2367 {mc "Cherry-pick this commit" command cherrypick}
2368 {mc "Reset HEAD branch to here" command resethead}
Paul Mackerrasb9fdba72009-04-09 09:34:46 +10002369 {mc "Mark this commit" command markhere}
2370 {mc "Return to mark" command gotomark}
2371 {mc "Find descendant of this and mark" command find_common_desc}
Paul Mackerras010509f2009-04-09 22:10:20 +10002372 {mc "Compare with marked commit" command compare_commits}
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11002373 }
2374 $rowctxmenu configure -tearoff 0
Paul Mackerras10299152006-08-02 09:52:01 +10002375
Paul Mackerras219ea3a2006-09-07 10:21:39 +10002376 set fakerowmenu .fakerowmenu
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11002377 makemenu $fakerowmenu {
Paul Mackerras79056032008-10-18 16:24:46 +11002378 {mc "Diff this -> selected" command {diffvssel 0}}
2379 {mc "Diff selected -> this" command {diffvssel 1}}
2380 {mc "Make patch" command mkpatch}
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11002381 }
2382 $fakerowmenu configure -tearoff 0
Paul Mackerras219ea3a2006-09-07 10:21:39 +10002383
Paul Mackerras10299152006-08-02 09:52:01 +10002384 set headctxmenu .headctxmenu
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11002385 makemenu $headctxmenu {
Paul Mackerras79056032008-10-18 16:24:46 +11002386 {mc "Check out this branch" command cobranch}
2387 {mc "Remove this branch" command rmbranch}
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11002388 }
2389 $headctxmenu configure -tearoff 0
Paul Mackerras32447292007-07-27 22:30:15 +10002390
2391 global flist_menu
2392 set flist_menu .flistctxmenu
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11002393 makemenu $flist_menu {
Paul Mackerras79056032008-10-18 16:24:46 +11002394 {mc "Highlight this too" command {flist_hl 0}}
2395 {mc "Highlight this only" command {flist_hl 1}}
2396 {mc "External diff" command {external_diff}}
2397 {mc "Blame parent commit" command {external_blame 1}}
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11002398 }
2399 $flist_menu configure -tearoff 0
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04002400
2401 global diff_menu
2402 set diff_menu .diffctxmenu
2403 makemenu $diff_menu {
Paul Mackerras8a897742008-10-27 21:36:25 +11002404 {mc "Show origin of this line" command show_line_source}
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04002405 {mc "Run git gui blame on this line" command {external_blame_diff}}
2406 }
2407 $diff_menu configure -tearoff 0
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00002408}
2409
Mark Levedahl314c3092007-08-07 21:40:35 -04002410# Windows sends all mouse wheel events to the current focused window, not
2411# the one where the mouse hovers, so bind those events here and redirect
2412# to the correct window
2413proc windows_mousewheel_redirector {W X Y D} {
2414 global canv canv2 canv3
2415 set w [winfo containing -displayof $W $X $Y]
2416 if {$w ne ""} {
2417 set u [expr {$D < 0 ? 5 : -5}]
2418 if {$w == $canv || $w == $canv2 || $w == $canv3} {
2419 allcanvs yview scroll $u units
2420 } else {
2421 catch {
2422 $w yview scroll $u units
2423 }
2424 }
2425 }
2426}
2427
Paul Mackerras6df74032008-05-11 22:13:02 +10002428# Update row number label when selectedline changes
2429proc selectedline_change {n1 n2 op} {
2430 global selectedline rownumsel
2431
Paul Mackerras94b4a692008-05-20 20:51:06 +10002432 if {$selectedline eq {}} {
Paul Mackerras6df74032008-05-11 22:13:02 +10002433 set rownumsel {}
2434 } else {
2435 set rownumsel [expr {$selectedline + 1}]
2436 }
2437}
2438
Paul Mackerrasbe0cd092006-03-31 09:55:11 +11002439# mouse-2 makes all windows scan vertically, but only the one
2440# the cursor is in scans horizontally
2441proc canvscan {op w x y} {
2442 global canv canv2 canv3
2443 foreach c [list $canv $canv2 $canv3] {
2444 if {$c == $w} {
2445 $c scan $op $x $y
2446 } else {
2447 $c scan $op 0 $y
2448 }
2449 }
2450}
2451
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002452proc scrollcanv {cscroll f0 f1} {
2453 $cscroll set $f0 $f1
Paul Mackerras31c0eaa2007-12-30 22:41:14 +11002454 drawvisible
Paul Mackerras908c3582006-05-20 09:38:11 +10002455 flushhighlights
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002456}
2457
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00002458# when we make a key binding for the toplevel, make sure
2459# it doesn't get triggered when that key is pressed in the
2460# find string entry widget.
2461proc bindkey {ev script} {
Paul Mackerras887fe3c2005-05-21 07:35:37 +00002462 global entries
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00002463 bind . $ev $script
2464 set escript [bind Entry $ev]
2465 if {$escript == {}} {
2466 set escript [bind Entry <Key>]
2467 }
Paul Mackerras887fe3c2005-05-21 07:35:37 +00002468 foreach e $entries {
2469 bind $e $ev "$escript; break"
2470 }
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00002471}
2472
2473# set the focus back to the toplevel for any click outside
Paul Mackerras887fe3c2005-05-21 07:35:37 +00002474# the entry widgets
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00002475proc click {w} {
Mark Levedahlbd441de2007-08-07 21:40:34 -04002476 global ctext entries
2477 foreach e [concat $entries $ctext] {
Paul Mackerras887fe3c2005-05-21 07:35:37 +00002478 if {$w == $e} return
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00002479 }
Paul Mackerras887fe3c2005-05-21 07:35:37 +00002480 focus .
Paul Mackerras0fba86b2005-05-16 23:54:58 +00002481}
2482
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10002483# Adjust the progress bar for a change in requested extent or canvas size
2484proc adjustprogress {} {
2485 global progresscanv progressitem progresscoords
2486 global fprogitem fprogcoord lastprogupdate progupdatepending
Paul Mackerrasa137a902007-10-23 21:12:49 +10002487 global rprogitem rprogcoord
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10002488
2489 set w [expr {[winfo width $progresscanv] - 4}]
2490 set x0 [expr {$w * [lindex $progresscoords 0]}]
2491 set x1 [expr {$w * [lindex $progresscoords 1]}]
2492 set h [winfo height $progresscanv]
2493 $progresscanv coords $progressitem $x0 0 $x1 $h
2494 $progresscanv coords $fprogitem 0 0 [expr {$w * $fprogcoord}] $h
Paul Mackerrasa137a902007-10-23 21:12:49 +10002495 $progresscanv coords $rprogitem 0 0 [expr {$w * $rprogcoord}] $h
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10002496 set now [clock clicks -milliseconds]
2497 if {$now >= $lastprogupdate + 100} {
2498 set progupdatepending 0
2499 update
2500 } elseif {!$progupdatepending} {
2501 set progupdatepending 1
2502 after [expr {$lastprogupdate + 100 - $now}] doprogupdate
2503 }
2504}
2505
2506proc doprogupdate {} {
2507 global lastprogupdate progupdatepending
2508
2509 if {$progupdatepending} {
2510 set progupdatepending 0
2511 set lastprogupdate [clock clicks -milliseconds]
2512 update
2513 }
2514}
2515
Paul Mackerras0fba86b2005-05-16 23:54:58 +00002516proc savestuff {w} {
Paul Mackerras32f1b3e2007-09-28 21:27:39 +10002517 global canv canv2 canv3 mainfont textfont uifont tabstop
Paul Mackerras712fcc02005-11-30 09:28:16 +11002518 global stuffsaved findmergefiles maxgraphpct
Paul Mackerras219ea3a2006-09-07 10:21:39 +10002519 global maxwidth showneartags showlocalchanges
Yann Dirson2d480852008-02-21 21:23:31 +01002520 global viewname viewfiles viewargs viewargscmd viewperm nextviewnum
Paul Mackerras7a39a172007-10-23 10:15:11 +10002521 global cmitmode wrapcomment datetimeformat limitdiffs
Steffen Prohaska890fae72007-08-12 12:05:46 +02002522 global colors bgcolor fgcolor diffcolors diffcontext selectbgcolor
Paul Mackerrase3e901b2008-10-27 22:37:21 +11002523 global autoselect extdifftool perfile_attrs markbgcolor
Thomas Rastffe15292009-08-03 23:53:36 +02002524 global hideremotes
Paul Mackerras4ef17532005-07-27 22:16:51 -05002525
Paul Mackerras0fba86b2005-05-16 23:54:58 +00002526 if {$stuffsaved} return
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00002527 if {![winfo viewable .]} return
Paul Mackerras0fba86b2005-05-16 23:54:58 +00002528 catch {
Pat Thoyts9bedb0e2009-09-15 10:26:30 +01002529 if {[file exists ~/.gitk-new]} {file delete -force ~/.gitk-new}
Paul Mackerras0fba86b2005-05-16 23:54:58 +00002530 set f [open "~/.gitk-new" w]
Paul Mackerras9832e4f2009-03-23 21:37:51 +11002531 if {$::tcl_platform(platform) eq {windows}} {
2532 file attributes "~/.gitk-new" -hidden true
2533 }
Paul Mackerrasf0654862005-07-18 14:29:03 -04002534 puts $f [list set mainfont $mainfont]
2535 puts $f [list set textfont $textfont]
Keith Packard4840be62006-04-04 00:19:45 -07002536 puts $f [list set uifont $uifont]
Mark Levedahl7e12f1a2007-05-20 11:45:50 -04002537 puts $f [list set tabstop $tabstop]
Paul Mackerrasf0654862005-07-18 14:29:03 -04002538 puts $f [list set findmergefiles $findmergefiles]
Paul Mackerras8d858d12005-08-05 09:52:16 +10002539 puts $f [list set maxgraphpct $maxgraphpct]
Paul Mackerras04c13d32005-08-19 10:22:24 +10002540 puts $f [list set maxwidth $maxwidth]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10002541 puts $f [list set cmitmode $cmitmode]
Sergey Vlasovf1b86292006-05-15 19:13:14 +04002542 puts $f [list set wrapcomment $wrapcomment]
Jeff King95293b52008-03-06 06:49:25 -05002543 puts $f [list set autoselect $autoselect]
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10002544 puts $f [list set showneartags $showneartags]
Thomas Rastffe15292009-08-03 23:53:36 +02002545 puts $f [list set hideremotes $hideremotes]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10002546 puts $f [list set showlocalchanges $showlocalchanges]
Arjen Laarhovene8b5f4b2007-08-14 22:02:04 +02002547 puts $f [list set datetimeformat $datetimeformat]
Paul Mackerras7a39a172007-10-23 10:15:11 +10002548 puts $f [list set limitdiffs $limitdiffs]
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10002549 puts $f [list set bgcolor $bgcolor]
2550 puts $f [list set fgcolor $fgcolor]
2551 puts $f [list set colors $colors]
2552 puts $f [list set diffcolors $diffcolors]
Paul Mackerrase3e901b2008-10-27 22:37:21 +11002553 puts $f [list set markbgcolor $markbgcolor]
Steffen Prohaska890fae72007-08-12 12:05:46 +02002554 puts $f [list set diffcontext $diffcontext]
Mark Levedahl60378c02007-05-20 12:12:48 -04002555 puts $f [list set selectbgcolor $selectbgcolor]
Thomas Arcila314f5de2008-03-24 12:55:36 +01002556 puts $f [list set extdifftool $extdifftool]
Paul Mackerras39ee47e2008-10-15 22:23:03 +11002557 puts $f [list set perfile_attrs $perfile_attrs]
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002558
Mark Levedahlb6047c52007-02-08 22:22:24 -05002559 puts $f "set geometry(main) [wm geometry .]"
Pat Thoytsc876dba2009-04-14 22:09:53 +01002560 puts $f "set geometry(state) [wm state .]"
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002561 puts $f "set geometry(topwidth) [winfo width .tf]"
2562 puts $f "set geometry(topheight) [winfo height .tf]"
Mark Levedahl9ca72f42007-02-12 19:19:34 -05002563 puts $f "set geometry(pwsash0) \"[.tf.histframe.pwclist sash coord 0]\""
2564 puts $f "set geometry(pwsash1) \"[.tf.histframe.pwclist sash coord 1]\""
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002565 puts $f "set geometry(botwidth) [winfo width .bleft]"
2566 puts $f "set geometry(botheight) [winfo height .bleft]"
2567
Paul Mackerrasa90a6d22006-04-25 17:12:46 +10002568 puts -nonewline $f "set permviews {"
2569 for {set v 0} {$v < $nextviewnum} {incr v} {
2570 if {$viewperm($v)} {
Yann Dirson2d480852008-02-21 21:23:31 +01002571 puts $f "{[list $viewname($v) $viewfiles($v) $viewargs($v) $viewargscmd($v)]}"
Paul Mackerrasa90a6d22006-04-25 17:12:46 +10002572 }
2573 }
2574 puts $f "}"
Paul Mackerras0fba86b2005-05-16 23:54:58 +00002575 close $f
2576 file rename -force "~/.gitk-new" "~/.gitk"
2577 }
2578 set stuffsaved 1
Paul Mackerras1db95b02005-05-09 04:08:39 +00002579}
2580
Paul Mackerras43bddeb2005-05-15 23:19:18 +00002581proc resizeclistpanes {win w} {
2582 global oldwidth
Paul Mackerras418c4c72006-02-07 09:10:18 +11002583 if {[info exists oldwidth($win)]} {
Paul Mackerras43bddeb2005-05-15 23:19:18 +00002584 set s0 [$win sash coord 0]
2585 set s1 [$win sash coord 1]
2586 if {$w < 60} {
2587 set sash0 [expr {int($w/2 - 2)}]
2588 set sash1 [expr {int($w*5/6 - 2)}]
2589 } else {
2590 set factor [expr {1.0 * $w / $oldwidth($win)}]
2591 set sash0 [expr {int($factor * [lindex $s0 0])}]
2592 set sash1 [expr {int($factor * [lindex $s1 0])}]
2593 if {$sash0 < 30} {
2594 set sash0 30
2595 }
2596 if {$sash1 < $sash0 + 20} {
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08002597 set sash1 [expr {$sash0 + 20}]
Paul Mackerras43bddeb2005-05-15 23:19:18 +00002598 }
2599 if {$sash1 > $w - 10} {
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08002600 set sash1 [expr {$w - 10}]
Paul Mackerras43bddeb2005-05-15 23:19:18 +00002601 if {$sash0 > $sash1 - 20} {
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08002602 set sash0 [expr {$sash1 - 20}]
Paul Mackerras43bddeb2005-05-15 23:19:18 +00002603 }
2604 }
2605 }
2606 $win sash place 0 $sash0 [lindex $s0 1]
2607 $win sash place 1 $sash1 [lindex $s1 1]
2608 }
2609 set oldwidth($win) $w
2610}
2611
2612proc resizecdetpanes {win w} {
2613 global oldwidth
Paul Mackerras418c4c72006-02-07 09:10:18 +11002614 if {[info exists oldwidth($win)]} {
Paul Mackerras43bddeb2005-05-15 23:19:18 +00002615 set s0 [$win sash coord 0]
2616 if {$w < 60} {
2617 set sash0 [expr {int($w*3/4 - 2)}]
2618 } else {
2619 set factor [expr {1.0 * $w / $oldwidth($win)}]
2620 set sash0 [expr {int($factor * [lindex $s0 0])}]
2621 if {$sash0 < 45} {
2622 set sash0 45
2623 }
2624 if {$sash0 > $w - 15} {
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08002625 set sash0 [expr {$w - 15}]
Paul Mackerras43bddeb2005-05-15 23:19:18 +00002626 }
2627 }
2628 $win sash place 0 $sash0 [lindex $s0 1]
2629 }
2630 set oldwidth($win) $w
2631}
2632
Paul Mackerrasb5721c72005-05-10 12:08:22 +00002633proc allcanvs args {
2634 global canv canv2 canv3
2635 eval $canv $args
2636 eval $canv2 $args
2637 eval $canv3 $args
2638}
2639
2640proc bindall {event action} {
2641 global canv canv2 canv3
2642 bind $canv $event $action
2643 bind $canv2 $event $action
2644 bind $canv3 $event $action
2645}
2646
Paul Mackerras9a40c502005-05-12 23:46:16 +00002647proc about {} {
Eygene Ryabinkind59c4b62007-03-27 14:36:12 +04002648 global uifont
Paul Mackerras9a40c502005-05-12 23:46:16 +00002649 set w .about
2650 if {[winfo exists $w]} {
2651 raise $w
2652 return
2653 }
2654 toplevel $w
Christian Stimmingd990ced2007-11-07 18:42:55 +01002655 wm title $w [mc "About gitk"]
Alexander Gavrilove7d64002008-11-11 23:55:42 +03002656 make_transient $w .
Christian Stimmingd990ced2007-11-07 18:42:55 +01002657 message $w.m -text [mc "
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002658Gitk - a commit viewer for git
Paul Mackerras9a40c502005-05-12 23:46:16 +00002659
Paul Mackerrasee66e082008-05-09 10:14:07 +10002660Copyright © 2005-2008 Paul Mackerras
Paul Mackerras9a40c502005-05-12 23:46:16 +00002661
Christian Stimmingd990ced2007-11-07 18:42:55 +01002662Use and redistribute under the terms of the GNU General Public License"] \
Eygene Ryabinkin3a950e92007-03-27 14:36:59 +04002663 -justify center -aspect 400 -border 2 -bg white -relief groove
2664 pack $w.m -side top -fill x -padx 2 -pady 2
Christian Stimmingd990ced2007-11-07 18:42:55 +01002665 button $w.ok -text [mc "Close"] -command "destroy $w" -default active
Paul Mackerras9a40c502005-05-12 23:46:16 +00002666 pack $w.ok -side bottom
Eygene Ryabinkin3a950e92007-03-27 14:36:59 +04002667 bind $w <Visibility> "focus $w.ok"
2668 bind $w <Key-Escape> "destroy $w"
2669 bind $w <Key-Return> "destroy $w"
Paul Mackerras9a40c502005-05-12 23:46:16 +00002670}
2671
Paul Mackerras4e95e1f2006-04-05 09:39:51 +10002672proc keys {} {
2673 set w .keys
2674 if {[winfo exists $w]} {
2675 raise $w
2676 return
2677 }
Shawn O. Pearced23d98d2007-07-19 00:37:58 -04002678 if {[tk windowingsystem] eq {aqua}} {
2679 set M1T Cmd
2680 } else {
2681 set M1T Ctrl
2682 }
Paul Mackerras4e95e1f2006-04-05 09:39:51 +10002683 toplevel $w
Christian Stimmingd990ced2007-11-07 18:42:55 +01002684 wm title $w [mc "Gitk key bindings"]
Alexander Gavrilove7d64002008-11-11 23:55:42 +03002685 make_transient $w .
Michele Ballabio3d2c9982008-01-15 23:31:49 +01002686 message $w.m -text "
2687[mc "Gitk key bindings:"]
Paul Mackerras4e95e1f2006-04-05 09:39:51 +10002688
Michele Ballabio3d2c9982008-01-15 23:31:49 +01002689[mc "<%s-Q> Quit" $M1T]
2690[mc "<Home> Move to first commit"]
2691[mc "<End> Move to last commit"]
2692[mc "<Up>, p, i Move up one commit"]
2693[mc "<Down>, n, k Move down one commit"]
2694[mc "<Left>, z, j Go back in history list"]
2695[mc "<Right>, x, l Go forward in history list"]
2696[mc "<PageUp> Move up one page in commit list"]
2697[mc "<PageDown> Move down one page in commit list"]
2698[mc "<%s-Home> Scroll to top of commit list" $M1T]
2699[mc "<%s-End> Scroll to bottom of commit list" $M1T]
2700[mc "<%s-Up> Scroll commit list up one line" $M1T]
2701[mc "<%s-Down> Scroll commit list down one line" $M1T]
2702[mc "<%s-PageUp> Scroll commit list up one page" $M1T]
2703[mc "<%s-PageDown> Scroll commit list down one page" $M1T]
2704[mc "<Shift-Up> Find backwards (upwards, later commits)"]
2705[mc "<Shift-Down> Find forwards (downwards, earlier commits)"]
2706[mc "<Delete>, b Scroll diff view up one page"]
2707[mc "<Backspace> Scroll diff view up one page"]
2708[mc "<Space> Scroll diff view down one page"]
2709[mc "u Scroll diff view up 18 lines"]
2710[mc "d Scroll diff view down 18 lines"]
2711[mc "<%s-F> Find" $M1T]
2712[mc "<%s-G> Move to next find hit" $M1T]
2713[mc "<Return> Move to next find hit"]
Giuseppe Bilotta97bed032008-12-02 02:19:22 +01002714[mc "/ Focus the search box"]
Michele Ballabio3d2c9982008-01-15 23:31:49 +01002715[mc "? Move to previous find hit"]
2716[mc "f Scroll diff view to next file"]
2717[mc "<%s-S> Search for next hit in diff view" $M1T]
2718[mc "<%s-R> Search for previous hit in diff view" $M1T]
2719[mc "<%s-KP+> Increase font size" $M1T]
2720[mc "<%s-plus> Increase font size" $M1T]
2721[mc "<%s-KP-> Decrease font size" $M1T]
2722[mc "<%s-minus> Decrease font size" $M1T]
2723[mc "<F5> Update"]
2724" \
Eygene Ryabinkin3a950e92007-03-27 14:36:59 +04002725 -justify left -bg white -border 2 -relief groove
2726 pack $w.m -side top -fill both -padx 2 -pady 2
Christian Stimmingd990ced2007-11-07 18:42:55 +01002727 button $w.ok -text [mc "Close"] -command "destroy $w" -default active
Alexander Gavrilov76f15942008-11-02 21:59:44 +03002728 bind $w <Key-Escape> [list destroy $w]
Paul Mackerras4e95e1f2006-04-05 09:39:51 +10002729 pack $w.ok -side bottom
Eygene Ryabinkin3a950e92007-03-27 14:36:59 +04002730 bind $w <Visibility> "focus $w.ok"
2731 bind $w <Key-Escape> "destroy $w"
2732 bind $w <Key-Return> "destroy $w"
Paul Mackerras4e95e1f2006-04-05 09:39:51 +10002733}
2734
Paul Mackerras7fcceed2006-04-27 19:21:49 +10002735# Procedures for manipulating the file list window at the
2736# bottom right of the overall window.
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10002737
2738proc treeview {w l openlevs} {
2739 global treecontents treediropen treeheight treeparent treeindex
2740
2741 set ix 0
2742 set treeindex() 0
2743 set lev 0
2744 set prefix {}
2745 set prefixend -1
2746 set prefendstack {}
2747 set htstack {}
2748 set ht 0
2749 set treecontents() {}
2750 $w conf -state normal
2751 foreach f $l {
2752 while {[string range $f 0 $prefixend] ne $prefix} {
2753 if {$lev <= $openlevs} {
2754 $w mark set e:$treeindex($prefix) "end -1c"
2755 $w mark gravity e:$treeindex($prefix) left
2756 }
2757 set treeheight($prefix) $ht
2758 incr ht [lindex $htstack end]
2759 set htstack [lreplace $htstack end end]
2760 set prefixend [lindex $prefendstack end]
2761 set prefendstack [lreplace $prefendstack end end]
2762 set prefix [string range $prefix 0 $prefixend]
2763 incr lev -1
2764 }
2765 set tail [string range $f [expr {$prefixend+1}] end]
2766 while {[set slash [string first "/" $tail]] >= 0} {
2767 lappend htstack $ht
2768 set ht 0
2769 lappend prefendstack $prefixend
2770 incr prefixend [expr {$slash + 1}]
2771 set d [string range $tail 0 $slash]
2772 lappend treecontents($prefix) $d
2773 set oldprefix $prefix
2774 append prefix $d
2775 set treecontents($prefix) {}
2776 set treeindex($prefix) [incr ix]
2777 set treeparent($prefix) $oldprefix
2778 set tail [string range $tail [expr {$slash+1}] end]
2779 if {$lev <= $openlevs} {
2780 set ht 1
2781 set treediropen($prefix) [expr {$lev < $openlevs}]
2782 set bm [expr {$lev == $openlevs? "tri-rt": "tri-dn"}]
2783 $w mark set d:$ix "end -1c"
2784 $w mark gravity d:$ix left
2785 set str "\n"
2786 for {set i 0} {$i < $lev} {incr i} {append str "\t"}
2787 $w insert end $str
2788 $w image create end -align center -image $bm -padx 1 \
2789 -name a:$ix
Paul Mackerras45a9d502006-05-20 22:56:27 +10002790 $w insert end $d [highlight_tag $prefix]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10002791 $w mark set s:$ix "end -1c"
2792 $w mark gravity s:$ix left
2793 }
2794 incr lev
2795 }
2796 if {$tail ne {}} {
2797 if {$lev <= $openlevs} {
2798 incr ht
2799 set str "\n"
2800 for {set i 0} {$i < $lev} {incr i} {append str "\t"}
2801 $w insert end $str
Paul Mackerras45a9d502006-05-20 22:56:27 +10002802 $w insert end $tail [highlight_tag $f]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10002803 }
2804 lappend treecontents($prefix) $tail
2805 }
2806 }
2807 while {$htstack ne {}} {
2808 set treeheight($prefix) $ht
2809 incr ht [lindex $htstack end]
2810 set htstack [lreplace $htstack end end]
Brian Downing096e96b2007-07-05 06:33:02 -05002811 set prefixend [lindex $prefendstack end]
2812 set prefendstack [lreplace $prefendstack end end]
2813 set prefix [string range $prefix 0 $prefixend]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10002814 }
2815 $w conf -state disabled
2816}
2817
2818proc linetoelt {l} {
2819 global treeheight treecontents
2820
2821 set y 2
2822 set prefix {}
2823 while {1} {
2824 foreach e $treecontents($prefix) {
2825 if {$y == $l} {
2826 return "$prefix$e"
2827 }
2828 set n 1
2829 if {[string index $e end] eq "/"} {
2830 set n $treeheight($prefix$e)
2831 if {$y + $n > $l} {
2832 append prefix $e
2833 incr y
2834 break
2835 }
2836 }
2837 incr y $n
2838 }
2839 }
2840}
2841
Paul Mackerras45a9d502006-05-20 22:56:27 +10002842proc highlight_tree {y prefix} {
2843 global treeheight treecontents cflist
2844
2845 foreach e $treecontents($prefix) {
2846 set path $prefix$e
2847 if {[highlight_tag $path] ne {}} {
2848 $cflist tag add bold $y.0 "$y.0 lineend"
2849 }
2850 incr y
2851 if {[string index $e end] eq "/" && $treeheight($path) > 1} {
2852 set y [highlight_tree $y $path]
2853 }
2854 }
2855 return $y
2856}
2857
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10002858proc treeclosedir {w dir} {
2859 global treediropen treeheight treeparent treeindex
2860
2861 set ix $treeindex($dir)
2862 $w conf -state normal
2863 $w delete s:$ix e:$ix
2864 set treediropen($dir) 0
2865 $w image configure a:$ix -image tri-rt
2866 $w conf -state disabled
2867 set n [expr {1 - $treeheight($dir)}]
2868 while {$dir ne {}} {
2869 incr treeheight($dir) $n
2870 set dir $treeparent($dir)
2871 }
2872}
2873
2874proc treeopendir {w dir} {
2875 global treediropen treeheight treeparent treecontents treeindex
2876
2877 set ix $treeindex($dir)
2878 $w conf -state normal
2879 $w image configure a:$ix -image tri-dn
2880 $w mark set e:$ix s:$ix
2881 $w mark gravity e:$ix right
2882 set lev 0
2883 set str "\n"
2884 set n [llength $treecontents($dir)]
2885 for {set x $dir} {$x ne {}} {set x $treeparent($x)} {
2886 incr lev
2887 append str "\t"
2888 incr treeheight($x) $n
2889 }
2890 foreach e $treecontents($dir) {
Paul Mackerras45a9d502006-05-20 22:56:27 +10002891 set de $dir$e
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10002892 if {[string index $e end] eq "/"} {
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10002893 set iy $treeindex($de)
2894 $w mark set d:$iy e:$ix
2895 $w mark gravity d:$iy left
2896 $w insert e:$ix $str
2897 set treediropen($de) 0
2898 $w image create e:$ix -align center -image tri-rt -padx 1 \
2899 -name a:$iy
Paul Mackerras45a9d502006-05-20 22:56:27 +10002900 $w insert e:$ix $e [highlight_tag $de]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10002901 $w mark set s:$iy e:$ix
2902 $w mark gravity s:$iy left
2903 set treeheight($de) 1
2904 } else {
2905 $w insert e:$ix $str
Paul Mackerras45a9d502006-05-20 22:56:27 +10002906 $w insert e:$ix $e [highlight_tag $de]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10002907 }
2908 }
Alexander Gavrilovb8a640e2008-09-08 11:28:16 +04002909 $w mark gravity e:$ix right
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10002910 $w conf -state disabled
2911 set treediropen($dir) 1
2912 set top [lindex [split [$w index @0,0] .] 0]
2913 set ht [$w cget -height]
2914 set l [lindex [split [$w index s:$ix] .] 0]
2915 if {$l < $top} {
2916 $w yview $l.0
2917 } elseif {$l + $n + 1 > $top + $ht} {
2918 set top [expr {$l + $n + 2 - $ht}]
2919 if {$l < $top} {
2920 set top $l
2921 }
2922 $w yview $top.0
2923 }
2924}
2925
2926proc treeclick {w x y} {
2927 global treediropen cmitmode ctext cflist cflist_top
2928
2929 if {$cmitmode ne "tree"} return
2930 if {![info exists cflist_top]} return
2931 set l [lindex [split [$w index "@$x,$y"] "."] 0]
2932 $cflist tag remove highlight $cflist_top.0 "$cflist_top.0 lineend"
2933 $cflist tag add highlight $l.0 "$l.0 lineend"
2934 set cflist_top $l
2935 if {$l == 1} {
2936 $ctext yview 1.0
2937 return
2938 }
2939 set e [linetoelt $l]
2940 if {[string index $e end] ne "/"} {
2941 showfile $e
2942 } elseif {$treediropen($e)} {
2943 treeclosedir $w $e
2944 } else {
2945 treeopendir $w $e
2946 }
2947}
2948
2949proc setfilelist {id} {
Paul Mackerras8a897742008-10-27 21:36:25 +11002950 global treefilelist cflist jump_to_here
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10002951
2952 treeview $cflist $treefilelist($id) 0
Paul Mackerras8a897742008-10-27 21:36:25 +11002953 if {$jump_to_here ne {}} {
2954 set f [lindex $jump_to_here 0]
2955 if {[lsearch -exact $treefilelist($id) $f] >= 0} {
2956 showfile $f
2957 }
2958 }
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10002959}
2960
2961image create bitmap tri-rt -background black -foreground blue -data {
2962 #define tri-rt_width 13
2963 #define tri-rt_height 13
2964 static unsigned char tri-rt_bits[] = {
2965 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x30, 0x00, 0x70, 0x00, 0xf0, 0x00,
2966 0xf0, 0x01, 0xf0, 0x00, 0x70, 0x00, 0x30, 0x00, 0x10, 0x00, 0x00, 0x00,
2967 0x00, 0x00};
2968} -maskdata {
2969 #define tri-rt-mask_width 13
2970 #define tri-rt-mask_height 13
2971 static unsigned char tri-rt-mask_bits[] = {
2972 0x08, 0x00, 0x18, 0x00, 0x38, 0x00, 0x78, 0x00, 0xf8, 0x00, 0xf8, 0x01,
2973 0xf8, 0x03, 0xf8, 0x01, 0xf8, 0x00, 0x78, 0x00, 0x38, 0x00, 0x18, 0x00,
2974 0x08, 0x00};
2975}
2976image create bitmap tri-dn -background black -foreground blue -data {
2977 #define tri-dn_width 13
2978 #define tri-dn_height 13
2979 static unsigned char tri-dn_bits[] = {
2980 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x07, 0xf8, 0x03,
2981 0xf0, 0x01, 0xe0, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2982 0x00, 0x00};
2983} -maskdata {
2984 #define tri-dn-mask_width 13
2985 #define tri-dn-mask_height 13
2986 static unsigned char tri-dn-mask_bits[] = {
2987 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x1f, 0xfe, 0x0f, 0xfc, 0x07,
2988 0xf8, 0x03, 0xf0, 0x01, 0xe0, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00,
2989 0x00, 0x00};
2990}
2991
Paul Mackerras887c9962007-08-20 19:36:20 +10002992image create bitmap reficon-T -background black -foreground yellow -data {
2993 #define tagicon_width 13
2994 #define tagicon_height 9
2995 static unsigned char tagicon_bits[] = {
2996 0x00, 0x00, 0x00, 0x00, 0xf0, 0x07, 0xf8, 0x07,
2997 0xfc, 0x07, 0xf8, 0x07, 0xf0, 0x07, 0x00, 0x00, 0x00, 0x00};
2998} -maskdata {
2999 #define tagicon-mask_width 13
3000 #define tagicon-mask_height 9
3001 static unsigned char tagicon-mask_bits[] = {
3002 0x00, 0x00, 0xf0, 0x0f, 0xf8, 0x0f, 0xfc, 0x0f,
3003 0xfe, 0x0f, 0xfc, 0x0f, 0xf8, 0x0f, 0xf0, 0x0f, 0x00, 0x00};
3004}
3005set rectdata {
3006 #define headicon_width 13
3007 #define headicon_height 9
3008 static unsigned char headicon_bits[] = {
3009 0x00, 0x00, 0x00, 0x00, 0xf8, 0x07, 0xf8, 0x07,
3010 0xf8, 0x07, 0xf8, 0x07, 0xf8, 0x07, 0x00, 0x00, 0x00, 0x00};
3011}
3012set rectmask {
3013 #define headicon-mask_width 13
3014 #define headicon-mask_height 9
3015 static unsigned char headicon-mask_bits[] = {
3016 0x00, 0x00, 0xfc, 0x0f, 0xfc, 0x0f, 0xfc, 0x0f,
3017 0xfc, 0x0f, 0xfc, 0x0f, 0xfc, 0x0f, 0xfc, 0x0f, 0x00, 0x00};
3018}
3019image create bitmap reficon-H -background black -foreground green \
3020 -data $rectdata -maskdata $rectmask
3021image create bitmap reficon-o -background black -foreground "#ddddff" \
3022 -data $rectdata -maskdata $rectmask
3023
Paul Mackerras7fcceed2006-04-27 19:21:49 +10003024proc init_flist {first} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11003025 global cflist cflist_top difffilestart
Paul Mackerras7fcceed2006-04-27 19:21:49 +10003026
3027 $cflist conf -state normal
3028 $cflist delete 0.0 end
3029 if {$first ne {}} {
3030 $cflist insert end $first
3031 set cflist_top 1
Paul Mackerras7fcceed2006-04-27 19:21:49 +10003032 $cflist tag add highlight 1.0 "1.0 lineend"
3033 } else {
3034 catch {unset cflist_top}
3035 }
3036 $cflist conf -state disabled
3037 set difffilestart {}
3038}
3039
Paul Mackerras63b79192006-05-20 21:31:52 +10003040proc highlight_tag {f} {
3041 global highlight_paths
3042
3043 foreach p $highlight_paths {
3044 if {[string match $p $f]} {
3045 return "bold"
3046 }
3047 }
3048 return {}
3049}
3050
3051proc highlight_filelist {} {
Paul Mackerras45a9d502006-05-20 22:56:27 +10003052 global cmitmode cflist
Paul Mackerras63b79192006-05-20 21:31:52 +10003053
Paul Mackerras45a9d502006-05-20 22:56:27 +10003054 $cflist conf -state normal
3055 if {$cmitmode ne "tree"} {
Paul Mackerras63b79192006-05-20 21:31:52 +10003056 set end [lindex [split [$cflist index end] .] 0]
3057 for {set l 2} {$l < $end} {incr l} {
3058 set line [$cflist get $l.0 "$l.0 lineend"]
3059 if {[highlight_tag $line] ne {}} {
3060 $cflist tag add bold $l.0 "$l.0 lineend"
3061 }
3062 }
Paul Mackerras45a9d502006-05-20 22:56:27 +10003063 } else {
3064 highlight_tree 2 {}
Paul Mackerras63b79192006-05-20 21:31:52 +10003065 }
Paul Mackerras45a9d502006-05-20 22:56:27 +10003066 $cflist conf -state disabled
Paul Mackerras63b79192006-05-20 21:31:52 +10003067}
3068
3069proc unhighlight_filelist {} {
Paul Mackerras45a9d502006-05-20 22:56:27 +10003070 global cflist
Paul Mackerras63b79192006-05-20 21:31:52 +10003071
Paul Mackerras45a9d502006-05-20 22:56:27 +10003072 $cflist conf -state normal
3073 $cflist tag remove bold 1.0 end
3074 $cflist conf -state disabled
Paul Mackerras63b79192006-05-20 21:31:52 +10003075}
3076
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10003077proc add_flist {fl} {
Paul Mackerras45a9d502006-05-20 22:56:27 +10003078 global cflist
Paul Mackerras7fcceed2006-04-27 19:21:49 +10003079
Paul Mackerras45a9d502006-05-20 22:56:27 +10003080 $cflist conf -state normal
3081 foreach f $fl {
3082 $cflist insert end "\n"
3083 $cflist insert end $f [highlight_tag $f]
Paul Mackerras7fcceed2006-04-27 19:21:49 +10003084 }
Paul Mackerras45a9d502006-05-20 22:56:27 +10003085 $cflist conf -state disabled
Paul Mackerras7fcceed2006-04-27 19:21:49 +10003086}
3087
3088proc sel_flist {w x y} {
Paul Mackerras45a9d502006-05-20 22:56:27 +10003089 global ctext difffilestart cflist cflist_top cmitmode
Paul Mackerras7fcceed2006-04-27 19:21:49 +10003090
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10003091 if {$cmitmode eq "tree"} return
Paul Mackerras7fcceed2006-04-27 19:21:49 +10003092 if {![info exists cflist_top]} return
3093 set l [lindex [split [$w index "@$x,$y"] "."] 0]
Paul Mackerras89b11d32006-05-02 19:55:31 +10003094 $cflist tag remove highlight $cflist_top.0 "$cflist_top.0 lineend"
3095 $cflist tag add highlight $l.0 "$l.0 lineend"
3096 set cflist_top $l
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10003097 if {$l == 1} {
3098 $ctext yview 1.0
3099 } else {
3100 catch {$ctext yview [lindex $difffilestart [expr {$l - 2}]]}
Paul Mackerras7fcceed2006-04-27 19:21:49 +10003101 }
Paul Mackerras7fcceed2006-04-27 19:21:49 +10003102}
3103
Paul Mackerras32447292007-07-27 22:30:15 +10003104proc pop_flist_menu {w X Y x y} {
3105 global ctext cflist cmitmode flist_menu flist_menu_file
3106 global treediffs diffids
3107
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10003108 stopfinding
Paul Mackerras32447292007-07-27 22:30:15 +10003109 set l [lindex [split [$w index "@$x,$y"] "."] 0]
3110 if {$l <= 1} return
3111 if {$cmitmode eq "tree"} {
3112 set e [linetoelt $l]
3113 if {[string index $e end] eq "/"} return
3114 } else {
3115 set e [lindex $treediffs($diffids) [expr {$l-2}]]
3116 }
3117 set flist_menu_file $e
Thomas Arcila314f5de2008-03-24 12:55:36 +01003118 set xdiffstate "normal"
3119 if {$cmitmode eq "tree"} {
3120 set xdiffstate "disabled"
3121 }
3122 # Disable "External diff" item in tree mode
3123 $flist_menu entryconf 2 -state $xdiffstate
Paul Mackerras32447292007-07-27 22:30:15 +10003124 tk_popup $flist_menu $X $Y
3125}
3126
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003127proc find_ctext_fileinfo {line} {
3128 global ctext_file_names ctext_file_lines
3129
3130 set ok [bsearch $ctext_file_lines $line]
3131 set tline [lindex $ctext_file_lines $ok]
3132
3133 if {$ok >= [llength $ctext_file_lines] || $line < $tline} {
3134 return {}
3135 } else {
3136 return [list [lindex $ctext_file_names $ok] $tline]
3137 }
3138}
3139
3140proc pop_diff_menu {w X Y x y} {
3141 global ctext diff_menu flist_menu_file
3142 global diff_menu_txtpos diff_menu_line
3143 global diff_menu_filebase
3144
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003145 set diff_menu_txtpos [split [$w index "@$x,$y"] "."]
3146 set diff_menu_line [lindex $diff_menu_txtpos 0]
Paul Mackerras190ec522008-10-27 21:13:37 +11003147 # don't pop up the menu on hunk-separator or file-separator lines
3148 if {[lsearch -glob [$ctext tag names $diff_menu_line.0] "*sep"] >= 0} {
3149 return
3150 }
3151 stopfinding
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003152 set f [find_ctext_fileinfo $diff_menu_line]
3153 if {$f eq {}} return
3154 set flist_menu_file [lindex $f 0]
3155 set diff_menu_filebase [lindex $f 1]
3156 tk_popup $diff_menu $X $Y
3157}
3158
Paul Mackerras32447292007-07-27 22:30:15 +10003159proc flist_hl {only} {
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10003160 global flist_menu_file findstring gdttype
Paul Mackerras32447292007-07-27 22:30:15 +10003161
3162 set x [shellquote $flist_menu_file]
Christian Stimmingb007ee22007-11-07 18:44:35 +01003163 if {$only || $findstring eq {} || $gdttype ne [mc "touching paths:"]} {
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10003164 set findstring $x
Paul Mackerras32447292007-07-27 22:30:15 +10003165 } else {
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10003166 append findstring " " $x
Paul Mackerras32447292007-07-27 22:30:15 +10003167 }
Christian Stimmingb007ee22007-11-07 18:44:35 +01003168 set gdttype [mc "touching paths:"]
Paul Mackerras32447292007-07-27 22:30:15 +10003169}
3170
Paul Mackerrasc21398b2009-09-07 10:08:21 +10003171proc gitknewtmpdir {} {
3172 global diffnum gitktmpdir gitdir
3173
3174 if {![info exists gitktmpdir]} {
3175 set gitktmpdir [file join [file dirname $gitdir] \
3176 [format ".gitk-tmp.%s" [pid]]]
3177 if {[catch {file mkdir $gitktmpdir} err]} {
3178 error_popup "[mc "Error creating temporary directory %s:" $gitktmpdir] $err"
3179 unset gitktmpdir
3180 return {}
3181 }
3182 set diffnum 0
3183 }
3184 incr diffnum
3185 set diffdir [file join $gitktmpdir $diffnum]
3186 if {[catch {file mkdir $diffdir} err]} {
3187 error_popup "[mc "Error creating temporary directory %s:" $diffdir] $err"
3188 return {}
3189 }
3190 return $diffdir
3191}
3192
Thomas Arcila314f5de2008-03-24 12:55:36 +01003193proc save_file_from_commit {filename output what} {
3194 global nullfile
3195
3196 if {[catch {exec git show $filename -- > $output} err]} {
3197 if {[string match "fatal: bad revision *" $err]} {
3198 return $nullfile
3199 }
Christian Stimming3945d2c2008-09-12 11:39:43 +02003200 error_popup "[mc "Error getting \"%s\" from %s:" $filename $what] $err"
Thomas Arcila314f5de2008-03-24 12:55:36 +01003201 return {}
3202 }
3203 return $output
3204}
3205
3206proc external_diff_get_one_file {diffid filename diffdir} {
3207 global nullid nullid2 nullfile
3208 global gitdir
3209
3210 if {$diffid == $nullid} {
3211 set difffile [file join [file dirname $gitdir] $filename]
3212 if {[file exists $difffile]} {
3213 return $difffile
3214 }
3215 return $nullfile
3216 }
3217 if {$diffid == $nullid2} {
3218 set difffile [file join $diffdir "\[index\] [file tail $filename]"]
3219 return [save_file_from_commit :$filename $difffile index]
3220 }
3221 set difffile [file join $diffdir "\[$diffid\] [file tail $filename]"]
3222 return [save_file_from_commit $diffid:$filename $difffile \
3223 "revision $diffid"]
3224}
3225
3226proc external_diff {} {
Paul Mackerrasc21398b2009-09-07 10:08:21 +10003227 global nullid nullid2
Thomas Arcila314f5de2008-03-24 12:55:36 +01003228 global flist_menu_file
3229 global diffids
Paul Mackerrasc21398b2009-09-07 10:08:21 +10003230 global extdifftool
Thomas Arcila314f5de2008-03-24 12:55:36 +01003231
3232 if {[llength $diffids] == 1} {
3233 # no reference commit given
3234 set diffidto [lindex $diffids 0]
3235 if {$diffidto eq $nullid} {
3236 # diffing working copy with index
3237 set diffidfrom $nullid2
3238 } elseif {$diffidto eq $nullid2} {
3239 # diffing index with HEAD
3240 set diffidfrom "HEAD"
3241 } else {
3242 # use first parent commit
3243 global parentlist selectedline
3244 set diffidfrom [lindex $parentlist $selectedline 0]
3245 }
3246 } else {
3247 set diffidfrom [lindex $diffids 0]
3248 set diffidto [lindex $diffids 1]
3249 }
3250
3251 # make sure that several diffs wont collide
Paul Mackerrasc21398b2009-09-07 10:08:21 +10003252 set diffdir [gitknewtmpdir]
3253 if {$diffdir eq {}} return
Thomas Arcila314f5de2008-03-24 12:55:36 +01003254
3255 # gather files to diff
3256 set difffromfile [external_diff_get_one_file $diffidfrom $flist_menu_file $diffdir]
3257 set difftofile [external_diff_get_one_file $diffidto $flist_menu_file $diffdir]
3258
3259 if {$difffromfile ne {} && $difftofile ne {}} {
Pat Thoytsb575b2f2009-04-15 16:54:19 +01003260 set cmd [list [shellsplit $extdifftool] $difffromfile $difftofile]
3261 if {[catch {set fl [open |$cmd r]} err]} {
Thomas Arcila314f5de2008-03-24 12:55:36 +01003262 file delete -force $diffdir
Christian Stimming3945d2c2008-09-12 11:39:43 +02003263 error_popup "$extdifftool: [mc "command failed:"] $err"
Thomas Arcila314f5de2008-03-24 12:55:36 +01003264 } else {
3265 fconfigure $fl -blocking 0
3266 filerun $fl [list delete_at_eof $fl $diffdir]
3267 }
3268 }
3269}
3270
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003271proc find_hunk_blamespec {base line} {
3272 global ctext
3273
3274 # Find and parse the hunk header
3275 set s_lix [$ctext search -backwards -regexp ^@@ "$line.0 lineend" $base.0]
3276 if {$s_lix eq {}} return
3277
3278 set s_line [$ctext get $s_lix "$s_lix + 1 lines"]
3279 if {![regexp {^@@@*(( -\d+(,\d+)?)+) \+(\d+)(,\d+)? @@} $s_line \
3280 s_line old_specs osz osz1 new_line nsz]} {
3281 return
3282 }
3283
3284 # base lines for the parents
3285 set base_lines [list $new_line]
3286 foreach old_spec [lrange [split $old_specs " "] 1 end] {
3287 if {![regexp -- {-(\d+)(,\d+)?} $old_spec \
3288 old_spec old_line osz]} {
3289 return
3290 }
3291 lappend base_lines $old_line
3292 }
3293
3294 # Now scan the lines to determine offset within the hunk
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003295 set max_parent [expr {[llength $base_lines]-2}]
3296 set dline 0
3297 set s_lno [lindex [split $s_lix "."] 0]
3298
Paul Mackerras190ec522008-10-27 21:13:37 +11003299 # Determine if the line is removed
3300 set chunk [$ctext get $line.0 "$line.1 + $max_parent chars"]
3301 if {[string match {[-+ ]*} $chunk]} {
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003302 set removed_idx [string first "-" $chunk]
3303 # Choose a parent index
Paul Mackerras190ec522008-10-27 21:13:37 +11003304 if {$removed_idx >= 0} {
3305 set parent $removed_idx
3306 } else {
3307 set unchanged_idx [string first " " $chunk]
3308 if {$unchanged_idx >= 0} {
3309 set parent $unchanged_idx
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003310 } else {
Paul Mackerras190ec522008-10-27 21:13:37 +11003311 # blame the current commit
3312 set parent -1
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003313 }
3314 }
3315 # then count other lines that belong to it
Paul Mackerras190ec522008-10-27 21:13:37 +11003316 for {set i $line} {[incr i -1] > $s_lno} {} {
3317 set chunk [$ctext get $i.0 "$i.1 + $max_parent chars"]
3318 # Determine if the line is removed
3319 set removed_idx [string first "-" $chunk]
3320 if {$parent >= 0} {
3321 set code [string index $chunk $parent]
3322 if {$code eq "-" || ($removed_idx < 0 && $code ne "+")} {
3323 incr dline
3324 }
3325 } else {
3326 if {$removed_idx < 0} {
3327 incr dline
3328 }
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003329 }
3330 }
Paul Mackerras190ec522008-10-27 21:13:37 +11003331 incr parent
3332 } else {
3333 set parent 0
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003334 }
3335
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003336 incr dline [lindex $base_lines $parent]
3337 return [list $parent $dline]
3338}
3339
3340proc external_blame_diff {} {
Paul Mackerras8b07dca2008-11-02 22:34:47 +11003341 global currentid cmitmode
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003342 global diff_menu_txtpos diff_menu_line
3343 global diff_menu_filebase flist_menu_file
3344
3345 if {$cmitmode eq "tree"} {
3346 set parent_idx 0
Paul Mackerras190ec522008-10-27 21:13:37 +11003347 set line [expr {$diff_menu_line - $diff_menu_filebase}]
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003348 } else {
3349 set hinfo [find_hunk_blamespec $diff_menu_filebase $diff_menu_line]
3350 if {$hinfo ne {}} {
3351 set parent_idx [lindex $hinfo 0]
3352 set line [lindex $hinfo 1]
3353 } else {
3354 set parent_idx 0
3355 set line 0
3356 }
3357 }
3358
3359 external_blame $parent_idx $line
3360}
3361
Paul Mackerrasfc4977e2008-11-04 12:57:44 +11003362# Find the SHA1 ID of the blob for file $fname in the index
3363# at stage 0 or 2
3364proc index_sha1 {fname} {
3365 set f [open [list | git ls-files -s $fname] r]
3366 while {[gets $f line] >= 0} {
3367 set info [lindex [split $line "\t"] 0]
3368 set stage [lindex $info 2]
3369 if {$stage eq "0" || $stage eq "2"} {
3370 close $f
3371 return [lindex $info 1]
3372 }
3373 }
3374 close $f
3375 return {}
3376}
3377
Paul Mackerras9712b812008-12-06 21:44:05 +11003378# Turn an absolute path into one relative to the current directory
3379proc make_relative {f} {
3380 set elts [file split $f]
3381 set here [file split [pwd]]
3382 set ei 0
3383 set hi 0
3384 set res {}
3385 foreach d $here {
3386 if {$ei < $hi || $ei >= [llength $elts] || [lindex $elts $ei] ne $d} {
3387 lappend res ".."
3388 } else {
3389 incr ei
3390 }
3391 incr hi
3392 }
3393 set elts [concat $res [lrange $elts $ei end]]
3394 return [eval file join $elts]
3395}
3396
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003397proc external_blame {parent_idx {line {}}} {
Paul Mackerras9712b812008-12-06 21:44:05 +11003398 global flist_menu_file gitdir
Alexander Gavrilov77aa0ae2008-08-23 12:29:08 +04003399 global nullid nullid2
3400 global parentlist selectedline currentid
3401
3402 if {$parent_idx > 0} {
3403 set base_commit [lindex $parentlist $selectedline [expr {$parent_idx-1}]]
3404 } else {
3405 set base_commit $currentid
3406 }
3407
3408 if {$base_commit eq {} || $base_commit eq $nullid || $base_commit eq $nullid2} {
3409 error_popup [mc "No such commit"]
3410 return
3411 }
3412
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003413 set cmdline [list git gui blame]
3414 if {$line ne {} && $line > 1} {
3415 lappend cmdline "--line=$line"
3416 }
Paul Mackerras9712b812008-12-06 21:44:05 +11003417 set f [file join [file dirname $gitdir] $flist_menu_file]
3418 # Unfortunately it seems git gui blame doesn't like
3419 # being given an absolute path...
3420 set f [make_relative $f]
3421 lappend cmdline $base_commit $f
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003422 if {[catch {eval exec $cmdline &} err]} {
Christian Stimming3945d2c2008-09-12 11:39:43 +02003423 error_popup "[mc "git gui blame: command failed:"] $err"
Alexander Gavrilov77aa0ae2008-08-23 12:29:08 +04003424 }
3425}
3426
Paul Mackerras8a897742008-10-27 21:36:25 +11003427proc show_line_source {} {
3428 global cmitmode currentid parents curview blamestuff blameinst
3429 global diff_menu_line diff_menu_filebase flist_menu_file
Paul Mackerrasfc4977e2008-11-04 12:57:44 +11003430 global nullid nullid2 gitdir
Paul Mackerras8a897742008-10-27 21:36:25 +11003431
Paul Mackerrasfc4977e2008-11-04 12:57:44 +11003432 set from_index {}
Paul Mackerras8a897742008-10-27 21:36:25 +11003433 if {$cmitmode eq "tree"} {
3434 set id $currentid
3435 set line [expr {$diff_menu_line - $diff_menu_filebase}]
3436 } else {
3437 set h [find_hunk_blamespec $diff_menu_filebase $diff_menu_line]
3438 if {$h eq {}} return
3439 set pi [lindex $h 0]
3440 if {$pi == 0} {
3441 mark_ctext_line $diff_menu_line
3442 return
3443 }
Paul Mackerrasfc4977e2008-11-04 12:57:44 +11003444 incr pi -1
3445 if {$currentid eq $nullid} {
3446 if {$pi > 0} {
3447 # must be a merge in progress...
3448 if {[catch {
3449 # get the last line from .git/MERGE_HEAD
3450 set f [open [file join $gitdir MERGE_HEAD] r]
3451 set id [lindex [split [read $f] "\n"] end-1]
3452 close $f
3453 } err]} {
3454 error_popup [mc "Couldn't read merge head: %s" $err]
3455 return
3456 }
3457 } elseif {$parents($curview,$currentid) eq $nullid2} {
3458 # need to do the blame from the index
3459 if {[catch {
3460 set from_index [index_sha1 $flist_menu_file]
3461 } err]} {
3462 error_popup [mc "Error reading index: %s" $err]
3463 return
3464 }
Paul Mackerras9712b812008-12-06 21:44:05 +11003465 } else {
3466 set id $parents($curview,$currentid)
Paul Mackerrasfc4977e2008-11-04 12:57:44 +11003467 }
3468 } else {
3469 set id [lindex $parents($curview,$currentid) $pi]
3470 }
Paul Mackerras8a897742008-10-27 21:36:25 +11003471 set line [lindex $h 1]
3472 }
Paul Mackerrasfc4977e2008-11-04 12:57:44 +11003473 set blameargs {}
3474 if {$from_index ne {}} {
3475 lappend blameargs | git cat-file blob $from_index
3476 }
3477 lappend blameargs | git blame -p -L$line,+1
3478 if {$from_index ne {}} {
3479 lappend blameargs --contents -
3480 } else {
3481 lappend blameargs $id
3482 }
Paul Mackerras9712b812008-12-06 21:44:05 +11003483 lappend blameargs -- [file join [file dirname $gitdir] $flist_menu_file]
Paul Mackerras8a897742008-10-27 21:36:25 +11003484 if {[catch {
Paul Mackerrasfc4977e2008-11-04 12:57:44 +11003485 set f [open $blameargs r]
Paul Mackerras8a897742008-10-27 21:36:25 +11003486 } err]} {
3487 error_popup [mc "Couldn't start git blame: %s" $err]
3488 return
3489 }
Alexander Gavrilovf3413072008-12-01 20:30:09 +03003490 nowbusy blaming [mc "Searching"]
Paul Mackerras8a897742008-10-27 21:36:25 +11003491 fconfigure $f -blocking 0
3492 set i [reg_instance $f]
3493 set blamestuff($i) {}
3494 set blameinst $i
3495 filerun $f [list read_line_source $f $i]
3496}
3497
3498proc stopblaming {} {
3499 global blameinst
3500
3501 if {[info exists blameinst]} {
3502 stop_instance $blameinst
3503 unset blameinst
Alexander Gavrilovf3413072008-12-01 20:30:09 +03003504 notbusy blaming
Paul Mackerras8a897742008-10-27 21:36:25 +11003505 }
3506}
3507
3508proc read_line_source {fd inst} {
Paul Mackerrasfc4977e2008-11-04 12:57:44 +11003509 global blamestuff curview commfd blameinst nullid nullid2
Paul Mackerras8a897742008-10-27 21:36:25 +11003510
3511 while {[gets $fd line] >= 0} {
3512 lappend blamestuff($inst) $line
3513 }
3514 if {![eof $fd]} {
3515 return 1
3516 }
3517 unset commfd($inst)
3518 unset blameinst
Alexander Gavrilovf3413072008-12-01 20:30:09 +03003519 notbusy blaming
Paul Mackerras8a897742008-10-27 21:36:25 +11003520 fconfigure $fd -blocking 1
3521 if {[catch {close $fd} err]} {
3522 error_popup [mc "Error running git blame: %s" $err]
3523 return 0
3524 }
3525
3526 set fname {}
3527 set line [split [lindex $blamestuff($inst) 0] " "]
3528 set id [lindex $line 0]
3529 set lnum [lindex $line 1]
3530 if {[string length $id] == 40 && [string is xdigit $id] &&
3531 [string is digit -strict $lnum]} {
3532 # look for "filename" line
3533 foreach l $blamestuff($inst) {
3534 if {[string match "filename *" $l]} {
3535 set fname [string range $l 9 end]
3536 break
3537 }
3538 }
3539 }
3540 if {$fname ne {}} {
3541 # all looks good, select it
Paul Mackerrasfc4977e2008-11-04 12:57:44 +11003542 if {$id eq $nullid} {
3543 # blame uses all-zeroes to mean not committed,
3544 # which would mean a change in the index
3545 set id $nullid2
3546 }
Paul Mackerras8a897742008-10-27 21:36:25 +11003547 if {[commitinview $id $curview]} {
3548 selectline [rowofcommit $id] 1 [list $fname $lnum]
3549 } else {
3550 error_popup [mc "That line comes from commit %s, \
3551 which is not in this view" [shortids $id]]
3552 }
3553 } else {
3554 puts "oops couldn't parse git blame output"
3555 }
3556 return 0
3557}
3558
Thomas Arcila314f5de2008-03-24 12:55:36 +01003559# delete $dir when we see eof on $f (presumably because the child has exited)
3560proc delete_at_eof {f dir} {
3561 while {[gets $f line] >= 0} {}
3562 if {[eof $f]} {
3563 if {[catch {close $f} err]} {
Christian Stimming3945d2c2008-09-12 11:39:43 +02003564 error_popup "[mc "External diff viewer failed:"] $err"
Thomas Arcila314f5de2008-03-24 12:55:36 +01003565 }
3566 file delete -force $dir
3567 return 0
3568 }
3569 return 1
3570}
3571
Paul Mackerras098dd8a2006-05-03 09:32:53 +10003572# Functions for adding and removing shell-type quoting
3573
3574proc shellquote {str} {
3575 if {![string match "*\['\"\\ \t]*" $str]} {
3576 return $str
3577 }
3578 if {![string match "*\['\"\\]*" $str]} {
3579 return "\"$str\""
3580 }
3581 if {![string match "*'*" $str]} {
3582 return "'$str'"
3583 }
3584 return "\"[string map {\" \\\" \\ \\\\} $str]\""
3585}
3586
3587proc shellarglist {l} {
3588 set str {}
3589 foreach a $l {
3590 if {$str ne {}} {
3591 append str " "
3592 }
3593 append str [shellquote $a]
3594 }
3595 return $str
3596}
3597
3598proc shelldequote {str} {
3599 set ret {}
3600 set used -1
3601 while {1} {
3602 incr used
3603 if {![regexp -start $used -indices "\['\"\\\\ \t]" $str first]} {
3604 append ret [string range $str $used end]
3605 set used [string length $str]
3606 break
3607 }
3608 set first [lindex $first 0]
3609 set ch [string index $str $first]
3610 if {$first > $used} {
3611 append ret [string range $str $used [expr {$first - 1}]]
3612 set used $first
3613 }
3614 if {$ch eq " " || $ch eq "\t"} break
3615 incr used
3616 if {$ch eq "'"} {
3617 set first [string first "'" $str $used]
3618 if {$first < 0} {
3619 error "unmatched single-quote"
3620 }
3621 append ret [string range $str $used [expr {$first - 1}]]
3622 set used $first
3623 continue
3624 }
3625 if {$ch eq "\\"} {
3626 if {$used >= [string length $str]} {
3627 error "trailing backslash"
3628 }
3629 append ret [string index $str $used]
3630 continue
3631 }
3632 # here ch == "\""
3633 while {1} {
3634 if {![regexp -start $used -indices "\[\"\\\\]" $str first]} {
3635 error "unmatched double-quote"
3636 }
3637 set first [lindex $first 0]
3638 set ch [string index $str $first]
3639 if {$first > $used} {
3640 append ret [string range $str $used [expr {$first - 1}]]
3641 set used $first
3642 }
3643 if {$ch eq "\""} break
3644 incr used
3645 append ret [string index $str $used]
3646 incr used
3647 }
3648 }
3649 return [list $used $ret]
3650}
3651
3652proc shellsplit {str} {
3653 set l {}
3654 while {1} {
3655 set str [string trimleft $str]
3656 if {$str eq {}} break
3657 set dq [shelldequote $str]
3658 set n [lindex $dq 0]
3659 set word [lindex $dq 1]
3660 set str [string range $str $n end]
3661 lappend l $word
3662 }
3663 return $l
3664}
3665
Paul Mackerras7fcceed2006-04-27 19:21:49 +10003666# Code to implement multiple views
3667
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10003668proc newview {ishighlight} {
Alexander Gavrilov218a9002008-11-02 21:59:48 +03003669 global nextviewnum newviewname newishighlight
3670 global revtreeargs viewargscmd newviewopts curview
Paul Mackerras50b44ec2006-04-04 10:16:22 +10003671
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10003672 set newishighlight $ishighlight
Paul Mackerras50b44ec2006-04-04 10:16:22 +10003673 set top .gitkview
3674 if {[winfo exists $top]} {
3675 raise $top
3676 return
3677 }
Michele Ballabioa3a1f572008-03-03 21:12:47 +01003678 set newviewname($nextviewnum) "[mc "View"] $nextviewnum"
Alexander Gavrilov218a9002008-11-02 21:59:48 +03003679 set newviewopts($nextviewnum,perm) 0
3680 set newviewopts($nextviewnum,cmd) $viewargscmd($curview)
3681 decode_view_opts $nextviewnum $revtreeargs
Christian Stimmingd990ced2007-11-07 18:42:55 +01003682 vieweditor $top $nextviewnum [mc "Gitk view definition"]
Paul Mackerrasd16c0812006-04-25 21:21:10 +10003683}
3684
Alexander Gavrilov218a9002008-11-02 21:59:48 +03003685set known_view_options {
Elijah Newren13d40b62009-03-23 11:57:46 -06003686 {perm b . {} {mc "Remember this view"}}
3687 {reflabel l + {} {mc "References (space separated list):"}}
3688 {refs t15 .. {} {mc "Branches & tags:"}}
3689 {allrefs b *. "--all" {mc "All refs"}}
3690 {branches b . "--branches" {mc "All (local) branches"}}
3691 {tags b . "--tags" {mc "All tags"}}
3692 {remotes b . "--remotes" {mc "All remote-tracking branches"}}
3693 {commitlbl l + {} {mc "Commit Info (regular expressions):"}}
3694 {author t15 .. "--author=*" {mc "Author:"}}
3695 {committer t15 . "--committer=*" {mc "Committer:"}}
3696 {loginfo t15 .. "--grep=*" {mc "Commit Message:"}}
3697 {allmatch b .. "--all-match" {mc "Matches all Commit Info criteria"}}
3698 {changes_l l + {} {mc "Changes to Files:"}}
3699 {pickaxe_s r0 . {} {mc "Fixed String"}}
3700 {pickaxe_t r1 . "--pickaxe-regex" {mc "Regular Expression"}}
3701 {pickaxe t15 .. "-S*" {mc "Search string:"}}
3702 {datelabel l + {} {mc "Commit Dates (\"2 weeks ago\", \"2009-03-17 15:27:38\", \"March 17, 2009 15:27:38\"):"}}
3703 {since t15 .. {"--since=*" "--after=*"} {mc "Since:"}}
3704 {until t15 . {"--until=*" "--before=*"} {mc "Until:"}}
3705 {limit_lbl l + {} {mc "Limit and/or skip a number of revisions (positive integer):"}}
3706 {limit t10 *. "--max-count=*" {mc "Number to show:"}}
3707 {skip t10 . "--skip=*" {mc "Number to skip:"}}
3708 {misc_lbl l + {} {mc "Miscellaneous options:"}}
3709 {dorder b *. {"--date-order" "-d"} {mc "Strictly sort by date"}}
3710 {lright b . "--left-right" {mc "Mark branch sides"}}
3711 {first b . "--first-parent" {mc "Limit to first parent"}}
Dirk Suesserottf687aaa2009-05-21 15:35:40 +02003712 {smplhst b . "--simplify-by-decoration" {mc "Simple history"}}
Elijah Newren13d40b62009-03-23 11:57:46 -06003713 {args t50 *. {} {mc "Additional arguments to git log:"}}
3714 {allpaths path + {} {mc "Enter files and directories to include, one per line:"}}
3715 {cmd t50= + {} {mc "Command to generate more commits to include:"}}
Alexander Gavrilov218a9002008-11-02 21:59:48 +03003716 }
3717
3718proc encode_view_opts {n} {
3719 global known_view_options newviewopts
3720
3721 set rargs [list]
3722 foreach opt $known_view_options {
3723 set patterns [lindex $opt 3]
3724 if {$patterns eq {}} continue
3725 set pattern [lindex $patterns 0]
3726
Alexander Gavrilov218a9002008-11-02 21:59:48 +03003727 if {[lindex $opt 1] eq "b"} {
Elijah Newren13d40b62009-03-23 11:57:46 -06003728 set val $newviewopts($n,[lindex $opt 0])
Alexander Gavrilov218a9002008-11-02 21:59:48 +03003729 if {$val} {
3730 lappend rargs $pattern
3731 }
Elijah Newren13d40b62009-03-23 11:57:46 -06003732 } elseif {[regexp {^r(\d+)$} [lindex $opt 1] type value]} {
3733 regexp {^(.*_)} [lindex $opt 0] uselessvar button_id
3734 set val $newviewopts($n,$button_id)
3735 if {$val eq $value} {
3736 lappend rargs $pattern
3737 }
Alexander Gavrilov218a9002008-11-02 21:59:48 +03003738 } else {
Elijah Newren13d40b62009-03-23 11:57:46 -06003739 set val $newviewopts($n,[lindex $opt 0])
Alexander Gavrilov218a9002008-11-02 21:59:48 +03003740 set val [string trim $val]
3741 if {$val ne {}} {
3742 set pfix [string range $pattern 0 end-1]
3743 lappend rargs $pfix$val
3744 }
3745 }
3746 }
Elijah Newren13d40b62009-03-23 11:57:46 -06003747 set rargs [concat $rargs [shellsplit $newviewopts($n,refs)]]
Alexander Gavrilov218a9002008-11-02 21:59:48 +03003748 return [concat $rargs [shellsplit $newviewopts($n,args)]]
3749}
3750
3751proc decode_view_opts {n view_args} {
3752 global known_view_options newviewopts
3753
3754 foreach opt $known_view_options {
Elijah Newren13d40b62009-03-23 11:57:46 -06003755 set id [lindex $opt 0]
Alexander Gavrilov218a9002008-11-02 21:59:48 +03003756 if {[lindex $opt 1] eq "b"} {
Elijah Newren13d40b62009-03-23 11:57:46 -06003757 # Checkboxes
3758 set val 0
3759 } elseif {[regexp {^r(\d+)$} [lindex $opt 1]]} {
3760 # Radiobuttons
3761 regexp {^(.*_)} $id uselessvar id
Alexander Gavrilov218a9002008-11-02 21:59:48 +03003762 set val 0
3763 } else {
Elijah Newren13d40b62009-03-23 11:57:46 -06003764 # Text fields
Alexander Gavrilov218a9002008-11-02 21:59:48 +03003765 set val {}
3766 }
Elijah Newren13d40b62009-03-23 11:57:46 -06003767 set newviewopts($n,$id) $val
Alexander Gavrilov218a9002008-11-02 21:59:48 +03003768 }
3769 set oargs [list]
Elijah Newren13d40b62009-03-23 11:57:46 -06003770 set refargs [list]
Alexander Gavrilov218a9002008-11-02 21:59:48 +03003771 foreach arg $view_args {
3772 if {[regexp -- {^-([0-9]+)$} $arg arg cnt]
3773 && ![info exists found(limit)]} {
3774 set newviewopts($n,limit) $cnt
3775 set found(limit) 1
3776 continue
3777 }
3778 catch { unset val }
3779 foreach opt $known_view_options {
3780 set id [lindex $opt 0]
3781 if {[info exists found($id)]} continue
3782 foreach pattern [lindex $opt 3] {
3783 if {![string match $pattern $arg]} continue
Elijah Newren13d40b62009-03-23 11:57:46 -06003784 if {[lindex $opt 1] eq "b"} {
3785 # Check buttons
3786 set val 1
3787 } elseif {[regexp {^r(\d+)$} [lindex $opt 1] match num]} {
3788 # Radio buttons
3789 regexp {^(.*_)} $id uselessvar id
3790 set val $num
3791 } else {
3792 # Text input fields
Alexander Gavrilov218a9002008-11-02 21:59:48 +03003793 set size [string length $pattern]
3794 set val [string range $arg [expr {$size-1}] end]
Alexander Gavrilov218a9002008-11-02 21:59:48 +03003795 }
3796 set newviewopts($n,$id) $val
3797 set found($id) 1
3798 break
3799 }
3800 if {[info exists val]} break
3801 }
3802 if {[info exists val]} continue
Elijah Newren13d40b62009-03-23 11:57:46 -06003803 if {[regexp {^-} $arg]} {
3804 lappend oargs $arg
3805 } else {
3806 lappend refargs $arg
3807 }
Alexander Gavrilov218a9002008-11-02 21:59:48 +03003808 }
Elijah Newren13d40b62009-03-23 11:57:46 -06003809 set newviewopts($n,refs) [shellarglist $refargs]
Alexander Gavrilov218a9002008-11-02 21:59:48 +03003810 set newviewopts($n,args) [shellarglist $oargs]
3811}
3812
Alexander Gavrilovcea07cf2008-11-09 13:00:45 +03003813proc edit_or_newview {} {
3814 global curview
3815
3816 if {$curview > 0} {
3817 editview
3818 } else {
3819 newview 0
3820 }
3821}
3822
Paul Mackerrasd16c0812006-04-25 21:21:10 +10003823proc editview {} {
3824 global curview
Alexander Gavrilov218a9002008-11-02 21:59:48 +03003825 global viewname viewperm newviewname newviewopts
3826 global viewargs viewargscmd
Paul Mackerrasd16c0812006-04-25 21:21:10 +10003827
3828 set top .gitkvedit-$curview
3829 if {[winfo exists $top]} {
3830 raise $top
3831 return
3832 }
Alexander Gavrilov218a9002008-11-02 21:59:48 +03003833 set newviewname($curview) $viewname($curview)
3834 set newviewopts($curview,perm) $viewperm($curview)
3835 set newviewopts($curview,cmd) $viewargscmd($curview)
3836 decode_view_opts $curview $viewargs($curview)
Michele Ballabiob56e0a92009-03-30 21:17:25 +02003837 vieweditor $top $curview "[mc "Gitk: edit view"] $viewname($curview)"
Paul Mackerrasd16c0812006-04-25 21:21:10 +10003838}
3839
3840proc vieweditor {top n title} {
Alexander Gavrilov218a9002008-11-02 21:59:48 +03003841 global newviewname newviewopts viewfiles bgcolor
3842 global known_view_options
Paul Mackerrasd16c0812006-04-25 21:21:10 +10003843
Paul Mackerras50b44ec2006-04-04 10:16:22 +10003844 toplevel $top
Michele Ballabioe0a01992009-05-23 11:48:25 +02003845 wm title $top [concat $title [mc "-- criteria for selecting revisions"]]
Alexander Gavrilove7d64002008-11-11 23:55:42 +03003846 make_transient $top .
Alexander Gavrilov218a9002008-11-02 21:59:48 +03003847
3848 # View name
3849 frame $top.nfr
Elijah Newren13d40b62009-03-23 11:57:46 -06003850 label $top.nl -text [mc "View Name:"]
Paul Mackerrasb039f0a2008-01-06 15:54:46 +11003851 entry $top.name -width 20 -textvariable newviewname($n)
Alexander Gavrilov218a9002008-11-02 21:59:48 +03003852 pack $top.nfr -in $top -fill x -pady 5 -padx 3
Elijah Newren13d40b62009-03-23 11:57:46 -06003853 pack $top.nl -in $top.nfr -side left -padx {0 5}
3854 pack $top.name -in $top.nfr -side left -padx {0 25}
Yann Dirson2d480852008-02-21 21:23:31 +01003855
Alexander Gavrilov218a9002008-11-02 21:59:48 +03003856 # View options
3857 set cframe $top.nfr
3858 set cexpand 0
3859 set cnt 0
3860 foreach opt $known_view_options {
3861 set id [lindex $opt 0]
3862 set type [lindex $opt 1]
3863 set flags [lindex $opt 2]
3864 set title [eval [lindex $opt 4]]
3865 set lxpad 0
Yann Dirson2d480852008-02-21 21:23:31 +01003866
Alexander Gavrilov218a9002008-11-02 21:59:48 +03003867 if {$flags eq "+" || $flags eq "*"} {
3868 set cframe $top.fr$cnt
3869 incr cnt
3870 frame $cframe
3871 pack $cframe -in $top -fill x -pady 3 -padx 3
3872 set cexpand [expr {$flags eq "*"}]
Elijah Newren13d40b62009-03-23 11:57:46 -06003873 } elseif {$flags eq ".." || $flags eq "*."} {
3874 set cframe $top.fr$cnt
3875 incr cnt
3876 frame $cframe
3877 pack $cframe -in $top -fill x -pady 3 -padx [list 15 3]
3878 set cexpand [expr {$flags eq "*."}]
Alexander Gavrilov218a9002008-11-02 21:59:48 +03003879 } else {
3880 set lxpad 5
3881 }
3882
Elijah Newren13d40b62009-03-23 11:57:46 -06003883 if {$type eq "l"} {
3884 label $cframe.l_$id -text $title
3885 pack $cframe.l_$id -in $cframe -side left -pady [list 3 0] -anchor w
3886 } elseif {$type eq "b"} {
Alexander Gavrilov218a9002008-11-02 21:59:48 +03003887 checkbutton $cframe.c_$id -text $title -variable newviewopts($n,$id)
3888 pack $cframe.c_$id -in $cframe -side left \
3889 -padx [list $lxpad 0] -expand $cexpand -anchor w
Elijah Newren13d40b62009-03-23 11:57:46 -06003890 } elseif {[regexp {^r(\d+)$} $type type sz]} {
3891 regexp {^(.*_)} $id uselessvar button_id
3892 radiobutton $cframe.c_$id -text $title -variable newviewopts($n,$button_id) -value $sz
3893 pack $cframe.c_$id -in $cframe -side left \
3894 -padx [list $lxpad 0] -expand $cexpand -anchor w
Alexander Gavrilov218a9002008-11-02 21:59:48 +03003895 } elseif {[regexp {^t(\d+)$} $type type sz]} {
3896 message $cframe.l_$id -aspect 1500 -text $title
3897 entry $cframe.e_$id -width $sz -background $bgcolor \
3898 -textvariable newviewopts($n,$id)
3899 pack $cframe.l_$id -in $cframe -side left -padx [list $lxpad 0]
3900 pack $cframe.e_$id -in $cframe -side left -expand 1 -fill x
3901 } elseif {[regexp {^t(\d+)=$} $type type sz]} {
3902 message $cframe.l_$id -aspect 1500 -text $title
3903 entry $cframe.e_$id -width $sz -background $bgcolor \
3904 -textvariable newviewopts($n,$id)
3905 pack $cframe.l_$id -in $cframe -side top -pady [list 3 0] -anchor w
3906 pack $cframe.e_$id -in $cframe -side top -fill x
Elijah Newren13d40b62009-03-23 11:57:46 -06003907 } elseif {$type eq "path"} {
3908 message $top.l -aspect 1500 -text $title
3909 pack $top.l -in $top -side top -pady [list 3 0] -anchor w -padx 3
3910 text $top.t -width 40 -height 5 -background $bgcolor -font uifont
3911 if {[info exists viewfiles($n)]} {
3912 foreach f $viewfiles($n) {
3913 $top.t insert end $f
3914 $top.t insert end "\n"
3915 }
3916 $top.t delete {end - 1c} end
3917 $top.t mark set insert 0.0
3918 }
3919 pack $top.t -in $top -side top -pady [list 0 5] -fill both -expand 1 -padx 3
Alexander Gavrilov218a9002008-11-02 21:59:48 +03003920 }
3921 }
3922
Paul Mackerras50b44ec2006-04-04 10:16:22 +10003923 frame $top.buts
Paul Mackerrasb039f0a2008-01-06 15:54:46 +11003924 button $top.buts.ok -text [mc "OK"] -command [list newviewok $top $n]
Alexander Gavrilov218a9002008-11-02 21:59:48 +03003925 button $top.buts.apply -text [mc "Apply (F5)"] -command [list newviewok $top $n 1]
Paul Mackerrasb039f0a2008-01-06 15:54:46 +11003926 button $top.buts.can -text [mc "Cancel"] -command [list destroy $top]
Alexander Gavrilov218a9002008-11-02 21:59:48 +03003927 bind $top <Control-Return> [list newviewok $top $n]
3928 bind $top <F5> [list newviewok $top $n 1]
Alexander Gavrilov76f15942008-11-02 21:59:44 +03003929 bind $top <Escape> [list destroy $top]
Alexander Gavrilov218a9002008-11-02 21:59:48 +03003930 grid $top.buts.ok $top.buts.apply $top.buts.can
Paul Mackerras50b44ec2006-04-04 10:16:22 +10003931 grid columnconfigure $top.buts 0 -weight 1 -uniform a
3932 grid columnconfigure $top.buts 1 -weight 1 -uniform a
Alexander Gavrilov218a9002008-11-02 21:59:48 +03003933 grid columnconfigure $top.buts 2 -weight 1 -uniform a
3934 pack $top.buts -in $top -side top -fill x
Paul Mackerras50b44ec2006-04-04 10:16:22 +10003935 focus $top.t
3936}
3937
Paul Mackerras908c3582006-05-20 09:38:11 +10003938proc doviewmenu {m first cmd op argv} {
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10003939 set nmenu [$m index end]
3940 for {set i $first} {$i <= $nmenu} {incr i} {
3941 if {[$m entrycget $i -command] eq $cmd} {
Paul Mackerras908c3582006-05-20 09:38:11 +10003942 eval $m $op $i $argv
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10003943 break
Paul Mackerrasd16c0812006-04-25 21:21:10 +10003944 }
3945 }
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10003946}
3947
3948proc allviewmenus {n op args} {
Paul Mackerras687c8762007-09-22 12:49:33 +10003949 # global viewhlmenu
Paul Mackerras908c3582006-05-20 09:38:11 +10003950
Paul Mackerras3cd204e2006-11-23 21:06:16 +11003951 doviewmenu .bar.view 5 [list showview $n] $op $args
Paul Mackerras687c8762007-09-22 12:49:33 +10003952 # doviewmenu $viewhlmenu 1 [list addvhighlight $n] $op $args
Paul Mackerrasd16c0812006-04-25 21:21:10 +10003953}
Paul Mackerras50b44ec2006-04-04 10:16:22 +10003954
Alexander Gavrilov218a9002008-11-02 21:59:48 +03003955proc newviewok {top n {apply 0}} {
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10003956 global nextviewnum newviewperm newviewname newishighlight
Paul Mackerrasd16c0812006-04-25 21:21:10 +10003957 global viewname viewfiles viewperm selectedview curview
Alexander Gavrilov218a9002008-11-02 21:59:48 +03003958 global viewargs viewargscmd newviewopts viewhlmenu
Paul Mackerrasd16c0812006-04-25 21:21:10 +10003959
Paul Mackerras098dd8a2006-05-03 09:32:53 +10003960 if {[catch {
Alexander Gavrilov218a9002008-11-02 21:59:48 +03003961 set newargs [encode_view_opts $n]
Paul Mackerras098dd8a2006-05-03 09:32:53 +10003962 } err]} {
Alexander Gavrilov84a76f12008-11-02 21:59:45 +03003963 error_popup "[mc "Error in commit selection arguments:"] $err" $top
Paul Mackerras098dd8a2006-05-03 09:32:53 +10003964 return
3965 }
Paul Mackerras50b44ec2006-04-04 10:16:22 +10003966 set files {}
Paul Mackerrasd16c0812006-04-25 21:21:10 +10003967 foreach f [split [$top.t get 0.0 end] "\n"] {
Paul Mackerras50b44ec2006-04-04 10:16:22 +10003968 set ft [string trim $f]
3969 if {$ft ne {}} {
3970 lappend files $ft
3971 }
3972 }
Paul Mackerrasd16c0812006-04-25 21:21:10 +10003973 if {![info exists viewfiles($n)]} {
3974 # creating a new view
3975 incr nextviewnum
3976 set viewname($n) $newviewname($n)
Alexander Gavrilov218a9002008-11-02 21:59:48 +03003977 set viewperm($n) $newviewopts($n,perm)
Paul Mackerrasd16c0812006-04-25 21:21:10 +10003978 set viewfiles($n) $files
Paul Mackerras098dd8a2006-05-03 09:32:53 +10003979 set viewargs($n) $newargs
Alexander Gavrilov218a9002008-11-02 21:59:48 +03003980 set viewargscmd($n) $newviewopts($n,cmd)
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10003981 addviewmenu $n
3982 if {!$newishighlight} {
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10003983 run showview $n
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10003984 } else {
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10003985 run addvhighlight $n
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10003986 }
Paul Mackerrasd16c0812006-04-25 21:21:10 +10003987 } else {
3988 # editing an existing view
Alexander Gavrilov218a9002008-11-02 21:59:48 +03003989 set viewperm($n) $newviewopts($n,perm)
Paul Mackerrasd16c0812006-04-25 21:21:10 +10003990 if {$newviewname($n) ne $viewname($n)} {
3991 set viewname($n) $newviewname($n)
Paul Mackerras3cd204e2006-11-23 21:06:16 +11003992 doviewmenu .bar.view 5 [list showview $n] \
Paul Mackerras908c3582006-05-20 09:38:11 +10003993 entryconf [list -label $viewname($n)]
Paul Mackerras687c8762007-09-22 12:49:33 +10003994 # doviewmenu $viewhlmenu 1 [list addvhighlight $n] \
3995 # entryconf [list -label $viewname($n) -value $viewname($n)]
Paul Mackerrasd16c0812006-04-25 21:21:10 +10003996 }
Yann Dirson2d480852008-02-21 21:23:31 +01003997 if {$files ne $viewfiles($n) || $newargs ne $viewargs($n) || \
Alexander Gavrilov218a9002008-11-02 21:59:48 +03003998 $newviewopts($n,cmd) ne $viewargscmd($n)} {
Paul Mackerrasd16c0812006-04-25 21:21:10 +10003999 set viewfiles($n) $files
Paul Mackerras098dd8a2006-05-03 09:32:53 +10004000 set viewargs($n) $newargs
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004001 set viewargscmd($n) $newviewopts($n,cmd)
Paul Mackerrasd16c0812006-04-25 21:21:10 +10004002 if {$curview == $n} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004003 run reloadcommits
Paul Mackerrasd16c0812006-04-25 21:21:10 +10004004 }
4005 }
4006 }
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004007 if {$apply} return
Paul Mackerrasd16c0812006-04-25 21:21:10 +10004008 catch {destroy $top}
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004009}
4010
4011proc delview {} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004012 global curview viewperm hlview selectedhlview
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004013
4014 if {$curview == 0} return
Paul Mackerras908c3582006-05-20 09:38:11 +10004015 if {[info exists hlview] && $hlview == $curview} {
Christian Stimmingb007ee22007-11-07 18:44:35 +01004016 set selectedhlview [mc "None"]
Paul Mackerras908c3582006-05-20 09:38:11 +10004017 unset hlview
4018 }
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004019 allviewmenus $curview delete
Paul Mackerrasa90a6d22006-04-25 17:12:46 +10004020 set viewperm($curview) 0
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004021 showview 0
4022}
4023
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004024proc addviewmenu {n} {
Paul Mackerras908c3582006-05-20 09:38:11 +10004025 global viewname viewhlmenu
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004026
4027 .bar.view add radiobutton -label $viewname($n) \
4028 -command [list showview $n] -variable selectedview -value $n
Paul Mackerras687c8762007-09-22 12:49:33 +10004029 #$viewhlmenu add radiobutton -label $viewname($n) \
4030 # -command [list addvhighlight $n] -variable selectedhlview
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004031}
4032
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004033proc showview {n} {
Paul Mackerras3ed31a82008-04-26 16:00:00 +10004034 global curview cached_commitrow ordertok
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10004035 global displayorder parentlist rowidlist rowisopt rowfinal
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004036 global colormap rowtextx nextcolor canvxmax
4037 global numcommits viewcomplete
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004038 global selectedline currentid canv canvy0
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004039 global treediffs
Paul Mackerras3e766082008-01-13 17:26:30 +11004040 global pending_select mainheadid
Paul Mackerras03800812007-08-29 21:45:21 +10004041 global commitidx
Paul Mackerras3e766082008-01-13 17:26:30 +11004042 global selectedview
Paul Mackerras97645682007-08-23 22:24:38 +10004043 global hlview selectedhlview commitinterest
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004044
4045 if {$n == $curview} return
4046 set selid {}
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004047 set ymax [lindex [$canv cget -scrollregion] 3]
4048 set span [$canv yview]
4049 set ytop [expr {[lindex $span 0] * $ymax}]
4050 set ybot [expr {[lindex $span 1] * $ymax}]
4051 set yscreen [expr {($ybot - $ytop) / 2}]
Paul Mackerras94b4a692008-05-20 20:51:06 +10004052 if {$selectedline ne {}} {
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004053 set selid $currentid
4054 set y [yc $selectedline]
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004055 if {$ytop < $y && $y < $ybot} {
4056 set yscreen [expr {$y - $ytop}]
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004057 }
Paul Mackerrase507fd42007-06-16 21:51:08 +10004058 } elseif {[info exists pending_select]} {
4059 set selid $pending_select
4060 unset pending_select
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004061 }
4062 unselectline
Paul Mackerrasfdedbcf2006-04-06 21:22:52 +10004063 normalline
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004064 catch {unset treediffs}
4065 clear_display
Paul Mackerras908c3582006-05-20 09:38:11 +10004066 if {[info exists hlview] && $hlview == $n} {
4067 unset hlview
Christian Stimmingb007ee22007-11-07 18:44:35 +01004068 set selectedhlview [mc "None"]
Paul Mackerras908c3582006-05-20 09:38:11 +10004069 }
Paul Mackerras97645682007-08-23 22:24:38 +10004070 catch {unset commitinterest}
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004071 catch {unset cached_commitrow}
Paul Mackerras9257d8f2007-12-11 10:45:38 +11004072 catch {unset ordertok}
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004073
4074 set curview $n
Paul Mackerrasa90a6d22006-04-25 17:12:46 +10004075 set selectedview $n
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11004076 .bar.view entryconf [mca "Edit view..."] -state [expr {$n == 0? "disabled": "normal"}]
4077 .bar.view entryconf [mca "Delete view"] -state [expr {$n == 0? "disabled": "normal"}]
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004078
Paul Mackerrasdf904492007-08-29 22:03:07 +10004079 run refill_reflist
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004080 if {![info exists viewcomplete($n)]} {
Alexander Gavrilov567c34e2008-07-26 20:13:45 +04004081 getcommits $selid
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004082 return
4083 }
4084
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004085 set displayorder {}
4086 set parentlist {}
4087 set rowidlist {}
4088 set rowisopt {}
4089 set rowfinal {}
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10004090 set numcommits $commitidx($n)
Paul Mackerras22626ef2006-04-17 09:56:02 +10004091
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004092 catch {unset colormap}
4093 catch {unset rowtextx}
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004094 set nextcolor 0
4095 set canvxmax [$canv cget -width]
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004096 set curview $n
4097 set row 0
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004098 setcanvscroll
4099 set yf 0
Paul Mackerrase507fd42007-06-16 21:51:08 +10004100 set row {}
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004101 if {$selid ne {} && [commitinview $selid $n]} {
4102 set row [rowofcommit $selid]
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004103 # try to get the selected row in the same position on the screen
4104 set ymax [lindex [$canv cget -scrollregion] 3]
4105 set ytop [expr {[yc $row] - $yscreen}]
4106 if {$ytop < 0} {
4107 set ytop 0
4108 }
4109 set yf [expr {$ytop * 1.0 / $ymax}]
4110 }
4111 allcanvs yview moveto $yf
4112 drawvisible
Paul Mackerrase507fd42007-06-16 21:51:08 +10004113 if {$row ne {}} {
4114 selectline $row 0
Paul Mackerras3e766082008-01-13 17:26:30 +11004115 } elseif {!$viewcomplete($n)} {
Alexander Gavrilov567c34e2008-07-26 20:13:45 +04004116 reset_pending_select $selid
Paul Mackerrase507fd42007-06-16 21:51:08 +10004117 } else {
Alexander Gavrilov835e62a2008-07-26 20:15:54 +04004118 reset_pending_select {}
4119
4120 if {[commitinview $pending_select $curview]} {
4121 selectline [rowofcommit $pending_select] 1
4122 } else {
4123 set row [first_real_row]
4124 if {$row < $numcommits} {
4125 selectline $row 0
4126 }
Paul Mackerrase507fd42007-06-16 21:51:08 +10004127 }
4128 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004129 if {!$viewcomplete($n)} {
4130 if {$numcommits == 0} {
Christian Stimmingd990ced2007-11-07 18:42:55 +01004131 show_status [mc "Reading commits..."]
Paul Mackerrasd16c0812006-04-25 21:21:10 +10004132 }
Paul Mackerras098dd8a2006-05-03 09:32:53 +10004133 } elseif {$numcommits == 0} {
Christian Stimmingd990ced2007-11-07 18:42:55 +01004134 show_status [mc "No commits selected"]
Paul Mackerras2516dae2006-04-21 10:35:31 +10004135 }
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004136}
4137
Paul Mackerras908c3582006-05-20 09:38:11 +10004138# Stuff relating to the highlighting facility
4139
Paul Mackerras476ca632008-01-07 22:16:31 +11004140proc ishighlighted {id} {
Paul Mackerras164ff272006-05-29 19:50:02 +10004141 global vhighlights fhighlights nhighlights rhighlights
Paul Mackerras908c3582006-05-20 09:38:11 +10004142
Paul Mackerras476ca632008-01-07 22:16:31 +11004143 if {[info exists nhighlights($id)] && $nhighlights($id) > 0} {
4144 return $nhighlights($id)
Paul Mackerras908c3582006-05-20 09:38:11 +10004145 }
Paul Mackerras476ca632008-01-07 22:16:31 +11004146 if {[info exists vhighlights($id)] && $vhighlights($id) > 0} {
4147 return $vhighlights($id)
Paul Mackerras908c3582006-05-20 09:38:11 +10004148 }
Paul Mackerras476ca632008-01-07 22:16:31 +11004149 if {[info exists fhighlights($id)] && $fhighlights($id) > 0} {
4150 return $fhighlights($id)
Paul Mackerras908c3582006-05-20 09:38:11 +10004151 }
Paul Mackerras476ca632008-01-07 22:16:31 +11004152 if {[info exists rhighlights($id)] && $rhighlights($id) > 0} {
4153 return $rhighlights($id)
Paul Mackerras164ff272006-05-29 19:50:02 +10004154 }
Paul Mackerras908c3582006-05-20 09:38:11 +10004155 return 0
4156}
4157
Paul Mackerras28593d32008-11-13 23:01:46 +11004158proc bolden {id font} {
Paul Mackerrasb9fdba72009-04-09 09:34:46 +10004159 global canv linehtag currentid boldids need_redisplay markedid
Paul Mackerras908c3582006-05-20 09:38:11 +10004160
Paul Mackerrasd98d50e2008-11-13 22:39:00 +11004161 # need_redisplay = 1 means the display is stale and about to be redrawn
4162 if {$need_redisplay} return
Paul Mackerras28593d32008-11-13 23:01:46 +11004163 lappend boldids $id
4164 $canv itemconf $linehtag($id) -font $font
4165 if {[info exists currentid] && $id eq $currentid} {
Paul Mackerras908c3582006-05-20 09:38:11 +10004166 $canv delete secsel
Paul Mackerras28593d32008-11-13 23:01:46 +11004167 set t [eval $canv create rect [$canv bbox $linehtag($id)] \
Paul Mackerras908c3582006-05-20 09:38:11 +10004168 -outline {{}} -tags secsel \
4169 -fill [$canv cget -selectbackground]]
4170 $canv lower $t
4171 }
Paul Mackerrasb9fdba72009-04-09 09:34:46 +10004172 if {[info exists markedid] && $id eq $markedid} {
4173 make_idmark $id
4174 }
Paul Mackerras908c3582006-05-20 09:38:11 +10004175}
4176
Paul Mackerras28593d32008-11-13 23:01:46 +11004177proc bolden_name {id font} {
4178 global canv2 linentag currentid boldnameids need_redisplay
Paul Mackerras908c3582006-05-20 09:38:11 +10004179
Paul Mackerrasd98d50e2008-11-13 22:39:00 +11004180 if {$need_redisplay} return
Paul Mackerras28593d32008-11-13 23:01:46 +11004181 lappend boldnameids $id
4182 $canv2 itemconf $linentag($id) -font $font
4183 if {[info exists currentid] && $id eq $currentid} {
Paul Mackerras908c3582006-05-20 09:38:11 +10004184 $canv2 delete secsel
Paul Mackerras28593d32008-11-13 23:01:46 +11004185 set t [eval $canv2 create rect [$canv2 bbox $linentag($id)] \
Paul Mackerras908c3582006-05-20 09:38:11 +10004186 -outline {{}} -tags secsel \
4187 -fill [$canv2 cget -selectbackground]]
4188 $canv2 lower $t
4189 }
4190}
4191
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004192proc unbolden {} {
Paul Mackerras28593d32008-11-13 23:01:46 +11004193 global boldids
Paul Mackerras908c3582006-05-20 09:38:11 +10004194
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004195 set stillbold {}
Paul Mackerras28593d32008-11-13 23:01:46 +11004196 foreach id $boldids {
4197 if {![ishighlighted $id]} {
4198 bolden $id mainfont
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004199 } else {
Paul Mackerras28593d32008-11-13 23:01:46 +11004200 lappend stillbold $id
Paul Mackerras908c3582006-05-20 09:38:11 +10004201 }
4202 }
Paul Mackerras28593d32008-11-13 23:01:46 +11004203 set boldids $stillbold
Paul Mackerras908c3582006-05-20 09:38:11 +10004204}
4205
4206proc addvhighlight {n} {
Paul Mackerras476ca632008-01-07 22:16:31 +11004207 global hlview viewcomplete curview vhl_done commitidx
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004208
4209 if {[info exists hlview]} {
Paul Mackerras908c3582006-05-20 09:38:11 +10004210 delvhighlight
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004211 }
4212 set hlview $n
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004213 if {$n != $curview && ![info exists viewcomplete($n)]} {
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004214 start_rev_list $n
Paul Mackerras908c3582006-05-20 09:38:11 +10004215 }
4216 set vhl_done $commitidx($hlview)
4217 if {$vhl_done > 0} {
4218 drawvisible
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004219 }
4220}
4221
Paul Mackerras908c3582006-05-20 09:38:11 +10004222proc delvhighlight {} {
4223 global hlview vhighlights
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004224
4225 if {![info exists hlview]} return
4226 unset hlview
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004227 catch {unset vhighlights}
4228 unbolden
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004229}
4230
Paul Mackerras908c3582006-05-20 09:38:11 +10004231proc vhighlightmore {} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004232 global hlview vhl_done commitidx vhighlights curview
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004233
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004234 set max $commitidx($hlview)
Paul Mackerras908c3582006-05-20 09:38:11 +10004235 set vr [visiblerows]
4236 set r0 [lindex $vr 0]
4237 set r1 [lindex $vr 1]
4238 for {set i $vhl_done} {$i < $max} {incr i} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004239 set id [commitonrow $i $hlview]
4240 if {[commitinview $id $curview]} {
4241 set row [rowofcommit $id]
Paul Mackerras908c3582006-05-20 09:38:11 +10004242 if {$r0 <= $row && $row <= $r1} {
4243 if {![highlighted $row]} {
Paul Mackerras28593d32008-11-13 23:01:46 +11004244 bolden $id mainfontbold
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004245 }
Paul Mackerras476ca632008-01-07 22:16:31 +11004246 set vhighlights($id) 1
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004247 }
4248 }
4249 }
Paul Mackerras908c3582006-05-20 09:38:11 +10004250 set vhl_done $max
Paul Mackerrasac1276a2008-03-03 10:11:08 +11004251 return 0
Paul Mackerras908c3582006-05-20 09:38:11 +10004252}
4253
4254proc askvhighlight {row id} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004255 global hlview vhighlights iddrawn
Paul Mackerras908c3582006-05-20 09:38:11 +10004256
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004257 if {[commitinview $id $hlview]} {
Paul Mackerras476ca632008-01-07 22:16:31 +11004258 if {[info exists iddrawn($id)] && ![ishighlighted $id]} {
Paul Mackerras28593d32008-11-13 23:01:46 +11004259 bolden $id mainfontbold
Paul Mackerras908c3582006-05-20 09:38:11 +10004260 }
Paul Mackerras476ca632008-01-07 22:16:31 +11004261 set vhighlights($id) 1
Paul Mackerras908c3582006-05-20 09:38:11 +10004262 } else {
Paul Mackerras476ca632008-01-07 22:16:31 +11004263 set vhighlights($id) 0
Paul Mackerras908c3582006-05-20 09:38:11 +10004264 }
4265}
4266
Paul Mackerras687c8762007-09-22 12:49:33 +10004267proc hfiles_change {} {
Paul Mackerras908c3582006-05-20 09:38:11 +10004268 global highlight_files filehighlight fhighlights fh_serial
Paul Mackerras8b39e042008-12-02 09:02:46 +11004269 global highlight_paths
Paul Mackerras908c3582006-05-20 09:38:11 +10004270
4271 if {[info exists filehighlight]} {
4272 # delete previous highlights
4273 catch {close $filehighlight}
4274 unset filehighlight
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004275 catch {unset fhighlights}
4276 unbolden
Paul Mackerras63b79192006-05-20 21:31:52 +10004277 unhighlight_filelist
Paul Mackerras908c3582006-05-20 09:38:11 +10004278 }
Paul Mackerras63b79192006-05-20 21:31:52 +10004279 set highlight_paths {}
Paul Mackerras908c3582006-05-20 09:38:11 +10004280 after cancel do_file_hl $fh_serial
4281 incr fh_serial
4282 if {$highlight_files ne {}} {
4283 after 300 do_file_hl $fh_serial
4284 }
4285}
4286
Paul Mackerras687c8762007-09-22 12:49:33 +10004287proc gdttype_change {name ix op} {
4288 global gdttype highlight_files findstring findpattern
4289
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10004290 stopfinding
Paul Mackerras687c8762007-09-22 12:49:33 +10004291 if {$findstring ne {}} {
Christian Stimmingb007ee22007-11-07 18:44:35 +01004292 if {$gdttype eq [mc "containing:"]} {
Paul Mackerras687c8762007-09-22 12:49:33 +10004293 if {$highlight_files ne {}} {
4294 set highlight_files {}
4295 hfiles_change
4296 }
4297 findcom_change
4298 } else {
4299 if {$findpattern ne {}} {
4300 set findpattern {}
4301 findcom_change
4302 }
4303 set highlight_files $findstring
4304 hfiles_change
4305 }
4306 drawvisible
4307 }
4308 # enable/disable findtype/findloc menus too
4309}
4310
4311proc find_change {name ix op} {
4312 global gdttype findstring highlight_files
4313
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10004314 stopfinding
Christian Stimmingb007ee22007-11-07 18:44:35 +01004315 if {$gdttype eq [mc "containing:"]} {
Paul Mackerras687c8762007-09-22 12:49:33 +10004316 findcom_change
4317 } else {
4318 if {$highlight_files ne $findstring} {
4319 set highlight_files $findstring
4320 hfiles_change
4321 }
4322 }
4323 drawvisible
4324}
4325
Paul Mackerras64b5f142007-10-04 22:19:24 +10004326proc findcom_change args {
Paul Mackerras28593d32008-11-13 23:01:46 +11004327 global nhighlights boldnameids
Paul Mackerras687c8762007-09-22 12:49:33 +10004328 global findpattern findtype findstring gdttype
4329
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10004330 stopfinding
Paul Mackerras687c8762007-09-22 12:49:33 +10004331 # delete previous highlights, if any
Paul Mackerras28593d32008-11-13 23:01:46 +11004332 foreach id $boldnameids {
4333 bolden_name $id mainfont
Paul Mackerras687c8762007-09-22 12:49:33 +10004334 }
Paul Mackerras28593d32008-11-13 23:01:46 +11004335 set boldnameids {}
Paul Mackerras687c8762007-09-22 12:49:33 +10004336 catch {unset nhighlights}
4337 unbolden
4338 unmarkmatches
Christian Stimmingb007ee22007-11-07 18:44:35 +01004339 if {$gdttype ne [mc "containing:"] || $findstring eq {}} {
Paul Mackerras687c8762007-09-22 12:49:33 +10004340 set findpattern {}
Christian Stimmingb007ee22007-11-07 18:44:35 +01004341 } elseif {$findtype eq [mc "Regexp"]} {
Paul Mackerras687c8762007-09-22 12:49:33 +10004342 set findpattern $findstring
4343 } else {
4344 set e [string map {"*" "\\*" "?" "\\?" "\[" "\\\[" "\\" "\\\\"} \
4345 $findstring]
4346 set findpattern "*$e*"
4347 }
4348}
4349
Paul Mackerras63b79192006-05-20 21:31:52 +10004350proc makepatterns {l} {
4351 set ret {}
4352 foreach e $l {
4353 set ee [string map {"*" "\\*" "?" "\\?" "\[" "\\\[" "\\" "\\\\"} $e]
4354 if {[string index $ee end] eq "/"} {
4355 lappend ret "$ee*"
4356 } else {
4357 lappend ret $ee
4358 lappend ret "$ee/*"
4359 }
4360 }
4361 return $ret
4362}
4363
Paul Mackerras908c3582006-05-20 09:38:11 +10004364proc do_file_hl {serial} {
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004365 global highlight_files filehighlight highlight_paths gdttype fhl_list
Paul Mackerras908c3582006-05-20 09:38:11 +10004366
Christian Stimmingb007ee22007-11-07 18:44:35 +01004367 if {$gdttype eq [mc "touching paths:"]} {
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10004368 if {[catch {set paths [shellsplit $highlight_files]}]} return
4369 set highlight_paths [makepatterns $paths]
4370 highlight_filelist
4371 set gdtargs [concat -- $paths]
Christian Stimmingb007ee22007-11-07 18:44:35 +01004372 } elseif {$gdttype eq [mc "adding/removing string:"]} {
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10004373 set gdtargs [list "-S$highlight_files"]
Paul Mackerras687c8762007-09-22 12:49:33 +10004374 } else {
4375 # must be "containing:", i.e. we're searching commit info
4376 return
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10004377 }
Brandon Casey1ce09dd2007-03-19 18:00:37 -05004378 set cmd [concat | git diff-tree -r -s --stdin $gdtargs]
Paul Mackerras908c3582006-05-20 09:38:11 +10004379 set filehighlight [open $cmd r+]
4380 fconfigure $filehighlight -blocking 0
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004381 filerun $filehighlight readfhighlight
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004382 set fhl_list {}
Paul Mackerras908c3582006-05-20 09:38:11 +10004383 drawvisible
4384 flushhighlights
4385}
4386
4387proc flushhighlights {} {
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004388 global filehighlight fhl_list
Paul Mackerras908c3582006-05-20 09:38:11 +10004389
4390 if {[info exists filehighlight]} {
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004391 lappend fhl_list {}
Paul Mackerras908c3582006-05-20 09:38:11 +10004392 puts $filehighlight ""
4393 flush $filehighlight
4394 }
4395}
4396
4397proc askfilehighlight {row id} {
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004398 global filehighlight fhighlights fhl_list
Paul Mackerras908c3582006-05-20 09:38:11 +10004399
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004400 lappend fhl_list $id
Paul Mackerras476ca632008-01-07 22:16:31 +11004401 set fhighlights($id) -1
Paul Mackerras908c3582006-05-20 09:38:11 +10004402 puts $filehighlight $id
4403}
4404
4405proc readfhighlight {} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004406 global filehighlight fhighlights curview iddrawn
Paul Mackerras687c8762007-09-22 12:49:33 +10004407 global fhl_list find_dirn
Paul Mackerras908c3582006-05-20 09:38:11 +10004408
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004409 if {![info exists filehighlight]} {
4410 return 0
4411 }
4412 set nr 0
4413 while {[incr nr] <= 100 && [gets $filehighlight line] >= 0} {
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004414 set line [string trim $line]
4415 set i [lsearch -exact $fhl_list $line]
4416 if {$i < 0} continue
4417 for {set j 0} {$j < $i} {incr j} {
4418 set id [lindex $fhl_list $j]
Paul Mackerras476ca632008-01-07 22:16:31 +11004419 set fhighlights($id) 0
Paul Mackerras908c3582006-05-20 09:38:11 +10004420 }
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004421 set fhl_list [lrange $fhl_list [expr {$i+1}] end]
4422 if {$line eq {}} continue
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004423 if {![commitinview $line $curview]} continue
Paul Mackerras476ca632008-01-07 22:16:31 +11004424 if {[info exists iddrawn($line)] && ![ishighlighted $line]} {
Paul Mackerras28593d32008-11-13 23:01:46 +11004425 bolden $line mainfontbold
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004426 }
Paul Mackerras476ca632008-01-07 22:16:31 +11004427 set fhighlights($line) 1
Paul Mackerras908c3582006-05-20 09:38:11 +10004428 }
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004429 if {[eof $filehighlight]} {
4430 # strange...
Brandon Casey1ce09dd2007-03-19 18:00:37 -05004431 puts "oops, git diff-tree died"
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004432 catch {close $filehighlight}
4433 unset filehighlight
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004434 return 0
Paul Mackerras908c3582006-05-20 09:38:11 +10004435 }
Paul Mackerras687c8762007-09-22 12:49:33 +10004436 if {[info exists find_dirn]} {
Paul Mackerrascca5d942007-10-27 21:16:56 +10004437 run findmore
Paul Mackerras687c8762007-09-22 12:49:33 +10004438 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004439 return 1
Paul Mackerras908c3582006-05-20 09:38:11 +10004440}
4441
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004442proc doesmatch {f} {
Paul Mackerras687c8762007-09-22 12:49:33 +10004443 global findtype findpattern
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004444
Christian Stimmingb007ee22007-11-07 18:44:35 +01004445 if {$findtype eq [mc "Regexp"]} {
Paul Mackerras687c8762007-09-22 12:49:33 +10004446 return [regexp $findpattern $f]
Christian Stimmingb007ee22007-11-07 18:44:35 +01004447 } elseif {$findtype eq [mc "IgnCase"]} {
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004448 return [string match -nocase $findpattern $f]
4449 } else {
4450 return [string match $findpattern $f]
4451 }
4452}
4453
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10004454proc askfindhighlight {row id} {
Paul Mackerras9c311b32007-10-04 22:27:13 +10004455 global nhighlights commitinfo iddrawn
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004456 global findloc
4457 global markingmatches
Paul Mackerras908c3582006-05-20 09:38:11 +10004458
4459 if {![info exists commitinfo($id)]} {
4460 getcommit $id
4461 }
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10004462 set info $commitinfo($id)
Paul Mackerras908c3582006-05-20 09:38:11 +10004463 set isbold 0
Christian Stimmingb007ee22007-11-07 18:44:35 +01004464 set fldtypes [list [mc Headline] [mc Author] [mc Date] [mc Committer] [mc CDate] [mc Comments]]
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10004465 foreach f $info ty $fldtypes {
Christian Stimmingb007ee22007-11-07 18:44:35 +01004466 if {($findloc eq [mc "All fields"] || $findloc eq $ty) &&
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004467 [doesmatch $f]} {
Christian Stimmingb007ee22007-11-07 18:44:35 +01004468 if {$ty eq [mc "Author"]} {
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10004469 set isbold 2
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004470 break
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10004471 }
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004472 set isbold 1
Paul Mackerras908c3582006-05-20 09:38:11 +10004473 }
4474 }
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004475 if {$isbold && [info exists iddrawn($id)]} {
Paul Mackerras476ca632008-01-07 22:16:31 +11004476 if {![ishighlighted $id]} {
Paul Mackerras28593d32008-11-13 23:01:46 +11004477 bolden $id mainfontbold
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004478 if {$isbold > 1} {
Paul Mackerras28593d32008-11-13 23:01:46 +11004479 bolden_name $id mainfontbold
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004480 }
Paul Mackerras908c3582006-05-20 09:38:11 +10004481 }
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004482 if {$markingmatches} {
Paul Mackerras005a2f42007-07-26 22:36:39 +10004483 markrowmatches $row $id
Paul Mackerras908c3582006-05-20 09:38:11 +10004484 }
4485 }
Paul Mackerras476ca632008-01-07 22:16:31 +11004486 set nhighlights($id) $isbold
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004487}
4488
Paul Mackerras005a2f42007-07-26 22:36:39 +10004489proc markrowmatches {row id} {
4490 global canv canv2 linehtag linentag commitinfo findloc
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004491
Paul Mackerras005a2f42007-07-26 22:36:39 +10004492 set headline [lindex $commitinfo($id) 0]
4493 set author [lindex $commitinfo($id) 1]
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004494 $canv delete match$row
4495 $canv2 delete match$row
Christian Stimmingb007ee22007-11-07 18:44:35 +01004496 if {$findloc eq [mc "All fields"] || $findloc eq [mc "Headline"]} {
Paul Mackerras005a2f42007-07-26 22:36:39 +10004497 set m [findmatches $headline]
4498 if {$m ne {}} {
Paul Mackerras28593d32008-11-13 23:01:46 +11004499 markmatches $canv $row $headline $linehtag($id) $m \
4500 [$canv itemcget $linehtag($id) -font] $row
Paul Mackerras005a2f42007-07-26 22:36:39 +10004501 }
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004502 }
Christian Stimmingb007ee22007-11-07 18:44:35 +01004503 if {$findloc eq [mc "All fields"] || $findloc eq [mc "Author"]} {
Paul Mackerras005a2f42007-07-26 22:36:39 +10004504 set m [findmatches $author]
4505 if {$m ne {}} {
Paul Mackerras28593d32008-11-13 23:01:46 +11004506 markmatches $canv2 $row $author $linentag($id) $m \
4507 [$canv2 itemcget $linentag($id) -font] $row
Paul Mackerras005a2f42007-07-26 22:36:39 +10004508 }
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004509 }
4510}
4511
Paul Mackerras164ff272006-05-29 19:50:02 +10004512proc vrel_change {name ix op} {
4513 global highlight_related
4514
4515 rhighlight_none
Christian Stimmingb007ee22007-11-07 18:44:35 +01004516 if {$highlight_related ne [mc "None"]} {
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004517 run drawvisible
Paul Mackerras164ff272006-05-29 19:50:02 +10004518 }
4519}
4520
4521# prepare for testing whether commits are descendents or ancestors of a
4522proc rhighlight_sel {a} {
4523 global descendent desc_todo ancestor anc_todo
Paul Mackerras476ca632008-01-07 22:16:31 +11004524 global highlight_related
Paul Mackerras164ff272006-05-29 19:50:02 +10004525
4526 catch {unset descendent}
4527 set desc_todo [list $a]
4528 catch {unset ancestor}
4529 set anc_todo [list $a]
Christian Stimmingb007ee22007-11-07 18:44:35 +01004530 if {$highlight_related ne [mc "None"]} {
Paul Mackerras164ff272006-05-29 19:50:02 +10004531 rhighlight_none
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004532 run drawvisible
Paul Mackerras164ff272006-05-29 19:50:02 +10004533 }
4534}
4535
4536proc rhighlight_none {} {
4537 global rhighlights
4538
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004539 catch {unset rhighlights}
4540 unbolden
Paul Mackerras164ff272006-05-29 19:50:02 +10004541}
4542
4543proc is_descendent {a} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004544 global curview children descendent desc_todo
Paul Mackerras164ff272006-05-29 19:50:02 +10004545
4546 set v $curview
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004547 set la [rowofcommit $a]
Paul Mackerras164ff272006-05-29 19:50:02 +10004548 set todo $desc_todo
4549 set leftover {}
4550 set done 0
4551 for {set i 0} {$i < [llength $todo]} {incr i} {
4552 set do [lindex $todo $i]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004553 if {[rowofcommit $do] < $la} {
Paul Mackerras164ff272006-05-29 19:50:02 +10004554 lappend leftover $do
4555 continue
4556 }
4557 foreach nk $children($v,$do) {
4558 if {![info exists descendent($nk)]} {
4559 set descendent($nk) 1
4560 lappend todo $nk
4561 if {$nk eq $a} {
4562 set done 1
4563 }
4564 }
4565 }
4566 if {$done} {
4567 set desc_todo [concat $leftover [lrange $todo [expr {$i+1}] end]]
4568 return
4569 }
4570 }
4571 set descendent($a) 0
4572 set desc_todo $leftover
4573}
4574
4575proc is_ancestor {a} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004576 global curview parents ancestor anc_todo
Paul Mackerras164ff272006-05-29 19:50:02 +10004577
4578 set v $curview
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004579 set la [rowofcommit $a]
Paul Mackerras164ff272006-05-29 19:50:02 +10004580 set todo $anc_todo
4581 set leftover {}
4582 set done 0
4583 for {set i 0} {$i < [llength $todo]} {incr i} {
4584 set do [lindex $todo $i]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004585 if {![commitinview $do $v] || [rowofcommit $do] > $la} {
Paul Mackerras164ff272006-05-29 19:50:02 +10004586 lappend leftover $do
4587 continue
4588 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004589 foreach np $parents($v,$do) {
Paul Mackerras164ff272006-05-29 19:50:02 +10004590 if {![info exists ancestor($np)]} {
4591 set ancestor($np) 1
4592 lappend todo $np
4593 if {$np eq $a} {
4594 set done 1
4595 }
4596 }
4597 }
4598 if {$done} {
4599 set anc_todo [concat $leftover [lrange $todo [expr {$i+1}] end]]
4600 return
4601 }
4602 }
4603 set ancestor($a) 0
4604 set anc_todo $leftover
4605}
4606
4607proc askrelhighlight {row id} {
Paul Mackerras9c311b32007-10-04 22:27:13 +10004608 global descendent highlight_related iddrawn rhighlights
Paul Mackerras164ff272006-05-29 19:50:02 +10004609 global selectedline ancestor
4610
Paul Mackerras94b4a692008-05-20 20:51:06 +10004611 if {$selectedline eq {}} return
Paul Mackerras164ff272006-05-29 19:50:02 +10004612 set isbold 0
Christian Stimming55e34432008-01-09 22:23:18 +01004613 if {$highlight_related eq [mc "Descendant"] ||
4614 $highlight_related eq [mc "Not descendant"]} {
Paul Mackerras164ff272006-05-29 19:50:02 +10004615 if {![info exists descendent($id)]} {
4616 is_descendent $id
4617 }
Christian Stimming55e34432008-01-09 22:23:18 +01004618 if {$descendent($id) == ($highlight_related eq [mc "Descendant"])} {
Paul Mackerras164ff272006-05-29 19:50:02 +10004619 set isbold 1
4620 }
Christian Stimmingb007ee22007-11-07 18:44:35 +01004621 } elseif {$highlight_related eq [mc "Ancestor"] ||
4622 $highlight_related eq [mc "Not ancestor"]} {
Paul Mackerras164ff272006-05-29 19:50:02 +10004623 if {![info exists ancestor($id)]} {
4624 is_ancestor $id
4625 }
Christian Stimmingb007ee22007-11-07 18:44:35 +01004626 if {$ancestor($id) == ($highlight_related eq [mc "Ancestor"])} {
Paul Mackerras164ff272006-05-29 19:50:02 +10004627 set isbold 1
4628 }
4629 }
4630 if {[info exists iddrawn($id)]} {
Paul Mackerras476ca632008-01-07 22:16:31 +11004631 if {$isbold && ![ishighlighted $id]} {
Paul Mackerras28593d32008-11-13 23:01:46 +11004632 bolden $id mainfontbold
Paul Mackerras164ff272006-05-29 19:50:02 +10004633 }
4634 }
Paul Mackerras476ca632008-01-07 22:16:31 +11004635 set rhighlights($id) $isbold
Paul Mackerras164ff272006-05-29 19:50:02 +10004636}
4637
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004638# Graph layout functions
4639
Paul Mackerras9f1afe02006-02-19 22:44:47 +11004640proc shortids {ids} {
4641 set res {}
4642 foreach id $ids {
4643 if {[llength $id] > 1} {
4644 lappend res [shortids $id]
4645 } elseif {[regexp {^[0-9a-f]{40}$} $id]} {
4646 lappend res [string range $id 0 7]
4647 } else {
4648 lappend res $id
4649 }
4650 }
4651 return $res
4652}
4653
Paul Mackerras9f1afe02006-02-19 22:44:47 +11004654proc ntimes {n o} {
4655 set ret {}
Paul Mackerras03800812007-08-29 21:45:21 +10004656 set o [list $o]
4657 for {set mask 1} {$mask <= $n} {incr mask $mask} {
4658 if {($n & $mask) != 0} {
4659 set ret [concat $ret $o]
4660 }
4661 set o [concat $o $o]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11004662 }
4663 return $ret
4664}
4665
Paul Mackerras9257d8f2007-12-11 10:45:38 +11004666proc ordertoken {id} {
4667 global ordertok curview varcid varcstart varctok curview parents children
4668 global nullid nullid2
4669
4670 if {[info exists ordertok($id)]} {
4671 return $ordertok($id)
4672 }
4673 set origid $id
4674 set todo {}
4675 while {1} {
4676 if {[info exists varcid($curview,$id)]} {
4677 set a $varcid($curview,$id)
4678 set p [lindex $varcstart($curview) $a]
4679 } else {
4680 set p [lindex $children($curview,$id) 0]
4681 }
4682 if {[info exists ordertok($p)]} {
4683 set tok $ordertok($p)
4684 break
4685 }
Paul Mackerrasc8c9f3d2008-01-06 13:54:58 +11004686 set id [first_real_child $curview,$p]
4687 if {$id eq {}} {
Paul Mackerras9257d8f2007-12-11 10:45:38 +11004688 # it's a root
Paul Mackerras46308ea2008-01-15 22:16:32 +11004689 set tok [lindex $varctok($curview) $varcid($curview,$p)]
Paul Mackerras9257d8f2007-12-11 10:45:38 +11004690 break
4691 }
Paul Mackerras9257d8f2007-12-11 10:45:38 +11004692 if {[llength $parents($curview,$id)] == 1} {
4693 lappend todo [list $p {}]
4694 } else {
4695 set j [lsearch -exact $parents($curview,$id) $p]
4696 if {$j < 0} {
4697 puts "oops didn't find [shortids $p] in parents of [shortids $id]"
4698 }
4699 lappend todo [list $p [strrep $j]]
4700 }
4701 }
4702 for {set i [llength $todo]} {[incr i -1] >= 0} {} {
4703 set p [lindex $todo $i 0]
4704 append tok [lindex $todo $i 1]
4705 set ordertok($p) $tok
4706 }
4707 set ordertok($origid) $tok
4708 return $tok
4709}
4710
Paul Mackerras6e8c8702007-07-31 21:03:06 +10004711# Work out where id should go in idlist so that order-token
4712# values increase from left to right
4713proc idcol {idlist id {i 0}} {
Paul Mackerras9257d8f2007-12-11 10:45:38 +11004714 set t [ordertoken $id]
Paul Mackerrase5b37ac2007-12-12 18:13:51 +11004715 if {$i < 0} {
4716 set i 0
4717 }
Paul Mackerras9257d8f2007-12-11 10:45:38 +11004718 if {$i >= [llength $idlist] || $t < [ordertoken [lindex $idlist $i]]} {
Paul Mackerras6e8c8702007-07-31 21:03:06 +10004719 if {$i > [llength $idlist]} {
4720 set i [llength $idlist]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11004721 }
Paul Mackerras9257d8f2007-12-11 10:45:38 +11004722 while {[incr i -1] >= 0 && $t < [ordertoken [lindex $idlist $i]]} {}
Paul Mackerras6e8c8702007-07-31 21:03:06 +10004723 incr i
4724 } else {
Paul Mackerras9257d8f2007-12-11 10:45:38 +11004725 if {$t > [ordertoken [lindex $idlist $i]]} {
Paul Mackerras6e8c8702007-07-31 21:03:06 +10004726 while {[incr i] < [llength $idlist] &&
Paul Mackerras9257d8f2007-12-11 10:45:38 +11004727 $t >= [ordertoken [lindex $idlist $i]]} {}
Paul Mackerras9f1afe02006-02-19 22:44:47 +11004728 }
4729 }
Paul Mackerras6e8c8702007-07-31 21:03:06 +10004730 return $i
Paul Mackerras9f1afe02006-02-19 22:44:47 +11004731}
4732
4733proc initlayout {} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004734 global rowidlist rowisopt rowfinal displayorder parentlist
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004735 global numcommits canvxmax canv
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11004736 global nextcolor
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004737 global colormap rowtextx
Paul Mackerras9f1afe02006-02-19 22:44:47 +11004738
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11004739 set numcommits 0
4740 set displayorder {}
Paul Mackerras79b2c752006-04-02 20:47:40 +10004741 set parentlist {}
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11004742 set nextcolor 0
Paul Mackerras03800812007-08-29 21:45:21 +10004743 set rowidlist {}
4744 set rowisopt {}
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10004745 set rowfinal {}
Paul Mackerrasbe0cd092006-03-31 09:55:11 +11004746 set canvxmax [$canv cget -width]
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004747 catch {unset colormap}
4748 catch {unset rowtextx}
Paul Mackerrasac1276a2008-03-03 10:11:08 +11004749 setcanvscroll
Paul Mackerrasbe0cd092006-03-31 09:55:11 +11004750}
4751
4752proc setcanvscroll {} {
4753 global canv canv2 canv3 numcommits linespc canvxmax canvy0
Paul Mackerrasac1276a2008-03-03 10:11:08 +11004754 global lastscrollset lastscrollrows
Paul Mackerrasbe0cd092006-03-31 09:55:11 +11004755
4756 set ymax [expr {$canvy0 + ($numcommits - 0.5) * $linespc + 2}]
4757 $canv conf -scrollregion [list 0 0 $canvxmax $ymax]
4758 $canv2 conf -scrollregion [list 0 0 0 $ymax]
4759 $canv3 conf -scrollregion [list 0 0 0 $ymax]
Paul Mackerrasac1276a2008-03-03 10:11:08 +11004760 set lastscrollset [clock clicks -milliseconds]
4761 set lastscrollrows $numcommits
Paul Mackerras9f1afe02006-02-19 22:44:47 +11004762}
4763
4764proc visiblerows {} {
4765 global canv numcommits linespc
4766
4767 set ymax [lindex [$canv cget -scrollregion] 3]
4768 if {$ymax eq {} || $ymax == 0} return
4769 set f [$canv yview]
4770 set y0 [expr {int([lindex $f 0] * $ymax)}]
4771 set r0 [expr {int(($y0 - 3) / $linespc) - 1}]
4772 if {$r0 < 0} {
4773 set r0 0
4774 }
4775 set y1 [expr {int([lindex $f 1] * $ymax)}]
4776 set r1 [expr {int(($y1 - 3) / $linespc) + 1}]
4777 if {$r1 >= $numcommits} {
4778 set r1 [expr {$numcommits - 1}]
4779 }
4780 return [list $r0 $r1]
4781}
4782
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10004783proc layoutmore {} {
Paul Mackerras38dfe932007-12-06 20:50:31 +11004784 global commitidx viewcomplete curview
Paul Mackerras94b4a692008-05-20 20:51:06 +10004785 global numcommits pending_select curview
Paul Mackerrasd375ef92008-10-21 10:18:12 +11004786 global lastscrollset lastscrollrows
Paul Mackerras9f1afe02006-02-19 22:44:47 +11004787
Paul Mackerrasac1276a2008-03-03 10:11:08 +11004788 if {$lastscrollrows < 100 || $viewcomplete($curview) ||
4789 [clock clicks -milliseconds] - $lastscrollset > 500} {
Paul Mackerrasa2c22362006-10-31 15:00:53 +11004790 setcanvscroll
4791 }
Paul Mackerrasd94f8cd2006-04-06 10:18:23 +10004792 if {[info exists pending_select] &&
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004793 [commitinview $pending_select $curview]} {
Alexander Gavrilov567c34e2008-07-26 20:13:45 +04004794 update
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004795 selectline [rowofcommit $pending_select] 1
Paul Mackerrasd94f8cd2006-04-06 10:18:23 +10004796 }
Paul Mackerrasac1276a2008-03-03 10:11:08 +11004797 drawvisible
Paul Mackerras219ea3a2006-09-07 10:21:39 +10004798}
4799
Paul Mackerrascdc84292008-11-18 19:54:14 +11004800# With path limiting, we mightn't get the actual HEAD commit,
4801# so ask git rev-list what is the first ancestor of HEAD that
4802# touches a file in the path limit.
4803proc get_viewmainhead {view} {
4804 global viewmainheadid vfilelimit viewinstances mainheadid
Paul Mackerras219ea3a2006-09-07 10:21:39 +10004805
Paul Mackerrascdc84292008-11-18 19:54:14 +11004806 catch {
4807 set rfd [open [concat | git rev-list -1 $mainheadid \
4808 -- $vfilelimit($view)] r]
4809 set j [reg_instance $rfd]
4810 lappend viewinstances($view) $j
4811 fconfigure $rfd -blocking 0
4812 filerun $rfd [list getviewhead $rfd $j $view]
4813 set viewmainheadid($curview) {}
4814 }
4815}
4816
4817# git rev-list should give us just 1 line to use as viewmainheadid($view)
4818proc getviewhead {fd inst view} {
4819 global viewmainheadid commfd curview viewinstances showlocalchanges
4820
4821 set id {}
4822 if {[gets $fd line] < 0} {
4823 if {![eof $fd]} {
4824 return 1
4825 }
4826 } elseif {[string length $line] == 40 && [string is xdigit $line]} {
4827 set id $line
4828 }
4829 set viewmainheadid($view) $id
4830 close $fd
4831 unset commfd($inst)
4832 set i [lsearch -exact $viewinstances($view) $inst]
4833 if {$i >= 0} {
4834 set viewinstances($view) [lreplace $viewinstances($view) $i $i]
4835 }
4836 if {$showlocalchanges && $id ne {} && $view == $curview} {
4837 doshowlocalchanges
4838 }
4839 return 0
4840}
4841
4842proc doshowlocalchanges {} {
4843 global curview viewmainheadid
4844
4845 if {$viewmainheadid($curview) eq {}} return
4846 if {[commitinview $viewmainheadid($curview) $curview]} {
Paul Mackerras219ea3a2006-09-07 10:21:39 +10004847 dodiffindex
Paul Mackerras38dfe932007-12-06 20:50:31 +11004848 } else {
Paul Mackerrascdc84292008-11-18 19:54:14 +11004849 interestedin $viewmainheadid($curview) dodiffindex
Paul Mackerras219ea3a2006-09-07 10:21:39 +10004850 }
4851}
4852
4853proc dohidelocalchanges {} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004854 global nullid nullid2 lserial curview
Paul Mackerras219ea3a2006-09-07 10:21:39 +10004855
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004856 if {[commitinview $nullid $curview]} {
Paul Mackerrasb8a938c2008-02-13 22:12:31 +11004857 removefakerow $nullid
Paul Mackerras8f489362007-07-13 19:49:37 +10004858 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004859 if {[commitinview $nullid2 $curview]} {
Paul Mackerrasb8a938c2008-02-13 22:12:31 +11004860 removefakerow $nullid2
Paul Mackerras219ea3a2006-09-07 10:21:39 +10004861 }
4862 incr lserial
4863}
4864
Paul Mackerras8f489362007-07-13 19:49:37 +10004865# spawn off a process to do git diff-index --cached HEAD
Paul Mackerras219ea3a2006-09-07 10:21:39 +10004866proc dodiffindex {} {
Paul Mackerrascdc84292008-11-18 19:54:14 +11004867 global lserial showlocalchanges vfilelimit curview
David Aguilarcb8329a2008-03-10 03:54:56 -07004868 global isworktree
Paul Mackerras219ea3a2006-09-07 10:21:39 +10004869
David Aguilarcb8329a2008-03-10 03:54:56 -07004870 if {!$showlocalchanges || !$isworktree} return
Paul Mackerras219ea3a2006-09-07 10:21:39 +10004871 incr lserial
Paul Mackerrascdc84292008-11-18 19:54:14 +11004872 set cmd "|git diff-index --cached HEAD"
4873 if {$vfilelimit($curview) ne {}} {
4874 set cmd [concat $cmd -- $vfilelimit($curview)]
4875 }
4876 set fd [open $cmd r]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10004877 fconfigure $fd -blocking 0
Alexander Gavrilove439e092008-07-13 16:40:47 +04004878 set i [reg_instance $fd]
4879 filerun $fd [list readdiffindex $fd $lserial $i]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10004880}
4881
Alexander Gavrilove439e092008-07-13 16:40:47 +04004882proc readdiffindex {fd serial inst} {
Paul Mackerrascdc84292008-11-18 19:54:14 +11004883 global viewmainheadid nullid nullid2 curview commitinfo commitdata lserial
4884 global vfilelimit
Paul Mackerras219ea3a2006-09-07 10:21:39 +10004885
Paul Mackerras8f489362007-07-13 19:49:37 +10004886 set isdiff 1
Paul Mackerras219ea3a2006-09-07 10:21:39 +10004887 if {[gets $fd line] < 0} {
Paul Mackerras8f489362007-07-13 19:49:37 +10004888 if {![eof $fd]} {
4889 return 1
Paul Mackerras219ea3a2006-09-07 10:21:39 +10004890 }
Paul Mackerras8f489362007-07-13 19:49:37 +10004891 set isdiff 0
Paul Mackerras219ea3a2006-09-07 10:21:39 +10004892 }
4893 # we only need to see one line and we don't really care what it says...
Alexander Gavrilove439e092008-07-13 16:40:47 +04004894 stop_instance $inst
Paul Mackerras219ea3a2006-09-07 10:21:39 +10004895
Paul Mackerras24f7a662007-12-19 09:35:33 +11004896 if {$serial != $lserial} {
4897 return 0
Paul Mackerras8f489362007-07-13 19:49:37 +10004898 }
4899
Paul Mackerras24f7a662007-12-19 09:35:33 +11004900 # now see if there are any local changes not checked in to the index
Paul Mackerrascdc84292008-11-18 19:54:14 +11004901 set cmd "|git diff-files"
4902 if {$vfilelimit($curview) ne {}} {
4903 set cmd [concat $cmd -- $vfilelimit($curview)]
4904 }
4905 set fd [open $cmd r]
Paul Mackerras24f7a662007-12-19 09:35:33 +11004906 fconfigure $fd -blocking 0
Alexander Gavrilove439e092008-07-13 16:40:47 +04004907 set i [reg_instance $fd]
4908 filerun $fd [list readdifffiles $fd $serial $i]
Paul Mackerras24f7a662007-12-19 09:35:33 +11004909
4910 if {$isdiff && ![commitinview $nullid2 $curview]} {
Paul Mackerras8f489362007-07-13 19:49:37 +10004911 # add the line for the changes in the index to the graph
Christian Stimmingd990ced2007-11-07 18:42:55 +01004912 set hl [mc "Local changes checked in to index but not committed"]
Paul Mackerras8f489362007-07-13 19:49:37 +10004913 set commitinfo($nullid2) [list $hl {} {} {} {} " $hl\n"]
4914 set commitdata($nullid2) "\n $hl\n"
Paul Mackerrasfc2a2562007-12-26 23:03:43 +11004915 if {[commitinview $nullid $curview]} {
Paul Mackerrasb8a938c2008-02-13 22:12:31 +11004916 removefakerow $nullid
Paul Mackerrasfc2a2562007-12-26 23:03:43 +11004917 }
Paul Mackerrascdc84292008-11-18 19:54:14 +11004918 insertfakerow $nullid2 $viewmainheadid($curview)
Paul Mackerras24f7a662007-12-19 09:35:33 +11004919 } elseif {!$isdiff && [commitinview $nullid2 $curview]} {
Paul Mackerrascdc84292008-11-18 19:54:14 +11004920 if {[commitinview $nullid $curview]} {
4921 removefakerow $nullid
4922 }
Paul Mackerrasb8a938c2008-02-13 22:12:31 +11004923 removefakerow $nullid2
Paul Mackerras8f489362007-07-13 19:49:37 +10004924 }
4925 return 0
4926}
4927
Alexander Gavrilove439e092008-07-13 16:40:47 +04004928proc readdifffiles {fd serial inst} {
Paul Mackerrascdc84292008-11-18 19:54:14 +11004929 global viewmainheadid nullid nullid2 curview
Paul Mackerras8f489362007-07-13 19:49:37 +10004930 global commitinfo commitdata lserial
4931
4932 set isdiff 1
4933 if {[gets $fd line] < 0} {
4934 if {![eof $fd]} {
4935 return 1
4936 }
4937 set isdiff 0
4938 }
4939 # we only need to see one line and we don't really care what it says...
Alexander Gavrilove439e092008-07-13 16:40:47 +04004940 stop_instance $inst
Paul Mackerras8f489362007-07-13 19:49:37 +10004941
Paul Mackerras24f7a662007-12-19 09:35:33 +11004942 if {$serial != $lserial} {
4943 return 0
4944 }
4945
4946 if {$isdiff && ![commitinview $nullid $curview]} {
Paul Mackerras219ea3a2006-09-07 10:21:39 +10004947 # add the line for the local diff to the graph
Christian Stimmingd990ced2007-11-07 18:42:55 +01004948 set hl [mc "Local uncommitted changes, not checked in to index"]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10004949 set commitinfo($nullid) [list $hl {} {} {} {} " $hl\n"]
4950 set commitdata($nullid) "\n $hl\n"
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004951 if {[commitinview $nullid2 $curview]} {
4952 set p $nullid2
4953 } else {
Paul Mackerrascdc84292008-11-18 19:54:14 +11004954 set p $viewmainheadid($curview)
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004955 }
Paul Mackerrasb8a938c2008-02-13 22:12:31 +11004956 insertfakerow $nullid $p
Paul Mackerras24f7a662007-12-19 09:35:33 +11004957 } elseif {!$isdiff && [commitinview $nullid $curview]} {
Paul Mackerrasb8a938c2008-02-13 22:12:31 +11004958 removefakerow $nullid
Paul Mackerras219ea3a2006-09-07 10:21:39 +10004959 }
4960 return 0
Paul Mackerras9f1afe02006-02-19 22:44:47 +11004961}
4962
Paul Mackerras8f0bc7e2007-08-24 22:16:42 +10004963proc nextuse {id row} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004964 global curview children
Paul Mackerras8f0bc7e2007-08-24 22:16:42 +10004965
4966 if {[info exists children($curview,$id)]} {
4967 foreach kid $children($curview,$id) {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004968 if {![commitinview $kid $curview]} {
Paul Mackerras03800812007-08-29 21:45:21 +10004969 return -1
4970 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004971 if {[rowofcommit $kid] > $row} {
4972 return [rowofcommit $kid]
Paul Mackerras8f0bc7e2007-08-24 22:16:42 +10004973 }
4974 }
4975 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004976 if {[commitinview $id $curview]} {
4977 return [rowofcommit $id]
Paul Mackerras8f0bc7e2007-08-24 22:16:42 +10004978 }
4979 return -1
4980}
4981
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10004982proc prevuse {id row} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004983 global curview children
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10004984
4985 set ret -1
4986 if {[info exists children($curview,$id)]} {
4987 foreach kid $children($curview,$id) {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004988 if {![commitinview $kid $curview]} break
4989 if {[rowofcommit $kid] < $row} {
4990 set ret [rowofcommit $kid]
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10004991 }
4992 }
4993 }
4994 return $ret
4995}
4996
Paul Mackerras03800812007-08-29 21:45:21 +10004997proc make_idlist {row} {
4998 global displayorder parentlist uparrowlen downarrowlen mingaplen
Paul Mackerras9257d8f2007-12-11 10:45:38 +11004999 global commitidx curview children
Paul Mackerras03800812007-08-29 21:45:21 +10005000
5001 set r [expr {$row - $mingaplen - $downarrowlen - 1}]
5002 if {$r < 0} {
5003 set r 0
5004 }
5005 set ra [expr {$row - $downarrowlen}]
5006 if {$ra < 0} {
5007 set ra 0
5008 }
5009 set rb [expr {$row + $uparrowlen}]
5010 if {$rb > $commitidx($curview)} {
5011 set rb $commitidx($curview)
5012 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005013 make_disporder $r [expr {$rb + 1}]
Paul Mackerras03800812007-08-29 21:45:21 +10005014 set ids {}
5015 for {} {$r < $ra} {incr r} {
5016 set nextid [lindex $displayorder [expr {$r + 1}]]
5017 foreach p [lindex $parentlist $r] {
5018 if {$p eq $nextid} continue
5019 set rn [nextuse $p $r]
5020 if {$rn >= $row &&
5021 $rn <= $r + $downarrowlen + $mingaplen + $uparrowlen} {
Paul Mackerras9257d8f2007-12-11 10:45:38 +11005022 lappend ids [list [ordertoken $p] $p]
Paul Mackerras03800812007-08-29 21:45:21 +10005023 }
5024 }
5025 }
5026 for {} {$r < $row} {incr r} {
5027 set nextid [lindex $displayorder [expr {$r + 1}]]
5028 foreach p [lindex $parentlist $r] {
5029 if {$p eq $nextid} continue
5030 set rn [nextuse $p $r]
5031 if {$rn < 0 || $rn >= $row} {
Paul Mackerras9257d8f2007-12-11 10:45:38 +11005032 lappend ids [list [ordertoken $p] $p]
Paul Mackerras03800812007-08-29 21:45:21 +10005033 }
5034 }
5035 }
5036 set id [lindex $displayorder $row]
Paul Mackerras9257d8f2007-12-11 10:45:38 +11005037 lappend ids [list [ordertoken $id] $id]
Paul Mackerras03800812007-08-29 21:45:21 +10005038 while {$r < $rb} {
5039 foreach p [lindex $parentlist $r] {
5040 set firstkid [lindex $children($curview,$p) 0]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005041 if {[rowofcommit $firstkid] < $row} {
Paul Mackerras9257d8f2007-12-11 10:45:38 +11005042 lappend ids [list [ordertoken $p] $p]
Paul Mackerras03800812007-08-29 21:45:21 +10005043 }
5044 }
5045 incr r
5046 set id [lindex $displayorder $r]
5047 if {$id ne {}} {
5048 set firstkid [lindex $children($curview,$id) 0]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005049 if {$firstkid ne {} && [rowofcommit $firstkid] < $row} {
Paul Mackerras9257d8f2007-12-11 10:45:38 +11005050 lappend ids [list [ordertoken $id] $id]
Paul Mackerras03800812007-08-29 21:45:21 +10005051 }
5052 }
5053 }
5054 set idlist {}
5055 foreach idx [lsort -unique $ids] {
5056 lappend idlist [lindex $idx 1]
5057 }
5058 return $idlist
5059}
5060
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10005061proc rowsequal {a b} {
5062 while {[set i [lsearch -exact $a {}]] >= 0} {
5063 set a [lreplace $a $i $i]
5064 }
5065 while {[set i [lsearch -exact $b {}]] >= 0} {
5066 set b [lreplace $b $i $i]
5067 }
5068 return [expr {$a eq $b}]
5069}
5070
5071proc makeupline {id row rend col} {
5072 global rowidlist uparrowlen downarrowlen mingaplen
5073
5074 for {set r $rend} {1} {set r $rstart} {
5075 set rstart [prevuse $id $r]
5076 if {$rstart < 0} return
5077 if {$rstart < $row} break
5078 }
5079 if {$rstart + $uparrowlen + $mingaplen + $downarrowlen < $rend} {
5080 set rstart [expr {$rend - $uparrowlen - 1}]
5081 }
5082 for {set r $rstart} {[incr r] <= $row} {} {
5083 set idlist [lindex $rowidlist $r]
5084 if {$idlist ne {} && [lsearch -exact $idlist $id] < 0} {
5085 set col [idcol $idlist $id $col]
5086 lset rowidlist $r [linsert $idlist $col $id]
5087 changedrow $r
5088 }
5089 }
5090}
5091
Paul Mackerras03800812007-08-29 21:45:21 +10005092proc layoutrows {row endrow} {
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10005093 global rowidlist rowisopt rowfinal displayorder
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005094 global uparrowlen downarrowlen maxwidth mingaplen
Paul Mackerras6a90bff2007-06-18 09:48:23 +10005095 global children parentlist
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005096 global commitidx viewcomplete curview
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005097
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005098 make_disporder [expr {$row - 1}] [expr {$endrow + $uparrowlen}]
Paul Mackerras03800812007-08-29 21:45:21 +10005099 set idlist {}
5100 if {$row > 0} {
Paul Mackerrasf56782a2007-09-15 09:04:11 +10005101 set rm1 [expr {$row - 1}]
5102 foreach id [lindex $rowidlist $rm1] {
Paul Mackerras03800812007-08-29 21:45:21 +10005103 if {$id ne {}} {
5104 lappend idlist $id
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005105 }
5106 }
Paul Mackerrasf56782a2007-09-15 09:04:11 +10005107 set final [lindex $rowfinal $rm1]
Paul Mackerras8f0bc7e2007-08-24 22:16:42 +10005108 }
Paul Mackerras03800812007-08-29 21:45:21 +10005109 for {} {$row < $endrow} {incr row} {
5110 set rm1 [expr {$row - 1}]
Paul Mackerrasf56782a2007-09-15 09:04:11 +10005111 if {$rm1 < 0 || $idlist eq {}} {
Paul Mackerras03800812007-08-29 21:45:21 +10005112 set idlist [make_idlist $row]
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10005113 set final 1
Paul Mackerras03800812007-08-29 21:45:21 +10005114 } else {
5115 set id [lindex $displayorder $rm1]
5116 set col [lsearch -exact $idlist $id]
5117 set idlist [lreplace $idlist $col $col]
5118 foreach p [lindex $parentlist $rm1] {
5119 if {[lsearch -exact $idlist $p] < 0} {
5120 set col [idcol $idlist $p $col]
5121 set idlist [linsert $idlist $col $p]
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10005122 # if not the first child, we have to insert a line going up
5123 if {$id ne [lindex $children($curview,$p) 0]} {
5124 makeupline $p $rm1 $row $col
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005125 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005126 }
5127 }
Paul Mackerras03800812007-08-29 21:45:21 +10005128 set id [lindex $displayorder $row]
5129 if {$row > $downarrowlen} {
5130 set termrow [expr {$row - $downarrowlen - 1}]
5131 foreach p [lindex $parentlist $termrow] {
5132 set i [lsearch -exact $idlist $p]
5133 if {$i < 0} continue
5134 set nr [nextuse $p $termrow]
5135 if {$nr < 0 || $nr >= $row + $mingaplen + $uparrowlen} {
5136 set idlist [lreplace $idlist $i $i]
5137 }
5138 }
5139 }
5140 set col [lsearch -exact $idlist $id]
5141 if {$col < 0} {
5142 set col [idcol $idlist $id]
5143 set idlist [linsert $idlist $col $id]
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10005144 if {$children($curview,$id) ne {}} {
5145 makeupline $id $rm1 $row $col
5146 }
Paul Mackerras03800812007-08-29 21:45:21 +10005147 }
5148 set r [expr {$row + $uparrowlen - 1}]
5149 if {$r < $commitidx($curview)} {
5150 set x $col
5151 foreach p [lindex $parentlist $r] {
5152 if {[lsearch -exact $idlist $p] >= 0} continue
5153 set fk [lindex $children($curview,$p) 0]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005154 if {[rowofcommit $fk] < $row} {
Paul Mackerras03800812007-08-29 21:45:21 +10005155 set x [idcol $idlist $p $x]
5156 set idlist [linsert $idlist $x $p]
5157 }
5158 }
5159 if {[incr r] < $commitidx($curview)} {
5160 set p [lindex $displayorder $r]
5161 if {[lsearch -exact $idlist $p] < 0} {
5162 set fk [lindex $children($curview,$p) 0]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005163 if {$fk ne {} && [rowofcommit $fk] < $row} {
Paul Mackerras03800812007-08-29 21:45:21 +10005164 set x [idcol $idlist $p $x]
5165 set idlist [linsert $idlist $x $p]
5166 }
5167 }
5168 }
Paul Mackerras7b459a12007-08-13 14:52:00 +10005169 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005170 }
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10005171 if {$final && !$viewcomplete($curview) &&
5172 $row + $uparrowlen + $mingaplen + $downarrowlen
5173 >= $commitidx($curview)} {
5174 set final 0
Paul Mackerras7b459a12007-08-13 14:52:00 +10005175 }
Paul Mackerras03800812007-08-29 21:45:21 +10005176 set l [llength $rowidlist]
5177 if {$row == $l} {
5178 lappend rowidlist $idlist
5179 lappend rowisopt 0
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10005180 lappend rowfinal $final
Paul Mackerras03800812007-08-29 21:45:21 +10005181 } elseif {$row < $l} {
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10005182 if {![rowsequal $idlist [lindex $rowidlist $row]]} {
Paul Mackerras03800812007-08-29 21:45:21 +10005183 lset rowidlist $row $idlist
5184 changedrow $row
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005185 }
Paul Mackerrasf56782a2007-09-15 09:04:11 +10005186 lset rowfinal $row $final
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005187 } else {
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10005188 set pad [ntimes [expr {$row - $l}] {}]
5189 set rowidlist [concat $rowidlist $pad]
Paul Mackerras03800812007-08-29 21:45:21 +10005190 lappend rowidlist $idlist
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10005191 set rowfinal [concat $rowfinal $pad]
5192 lappend rowfinal $final
Paul Mackerras03800812007-08-29 21:45:21 +10005193 set rowisopt [concat $rowisopt [ntimes [expr {$row - $l + 1}] 0]]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005194 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005195 }
5196 return $row
5197}
5198
Paul Mackerras03800812007-08-29 21:45:21 +10005199proc changedrow {row} {
5200 global displayorder iddrawn rowisopt need_redisplay
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005201
Paul Mackerras03800812007-08-29 21:45:21 +10005202 set l [llength $rowisopt]
5203 if {$row < $l} {
5204 lset rowisopt $row 0
5205 if {$row + 1 < $l} {
5206 lset rowisopt [expr {$row + 1}] 0
5207 if {$row + 2 < $l} {
5208 lset rowisopt [expr {$row + 2}] 0
5209 }
5210 }
Paul Mackerras79b2c752006-04-02 20:47:40 +10005211 }
Paul Mackerras03800812007-08-29 21:45:21 +10005212 set id [lindex $displayorder $row]
5213 if {[info exists iddrawn($id)]} {
5214 set need_redisplay 1
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005215 }
5216}
5217
5218proc insert_pad {row col npad} {
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005219 global rowidlist
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005220
5221 set pad [ntimes $npad {}]
Paul Mackerrase341c062007-08-12 12:42:57 +10005222 set idlist [lindex $rowidlist $row]
5223 set bef [lrange $idlist 0 [expr {$col - 1}]]
5224 set aft [lrange $idlist $col end]
5225 set i [lsearch -exact $aft {}]
5226 if {$i > 0} {
5227 set aft [lreplace $aft $i $i]
5228 }
5229 lset rowidlist $row [concat $bef $pad $aft]
Paul Mackerras03800812007-08-29 21:45:21 +10005230 changedrow $row
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005231}
5232
5233proc optimize_rows {row col endrow} {
Paul Mackerras03800812007-08-29 21:45:21 +10005234 global rowidlist rowisopt displayorder curview children
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005235
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005236 if {$row < 1} {
5237 set row 1
5238 }
Paul Mackerras03800812007-08-29 21:45:21 +10005239 for {} {$row < $endrow} {incr row; set col 0} {
5240 if {[lindex $rowisopt $row]} continue
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005241 set haspad 0
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005242 set y0 [expr {$row - 1}]
5243 set ym [expr {$row - 2}]
Paul Mackerras03800812007-08-29 21:45:21 +10005244 set idlist [lindex $rowidlist $row]
5245 set previdlist [lindex $rowidlist $y0]
5246 if {$idlist eq {} || $previdlist eq {}} continue
5247 if {$ym >= 0} {
5248 set pprevidlist [lindex $rowidlist $ym]
5249 if {$pprevidlist eq {}} continue
5250 } else {
5251 set pprevidlist {}
5252 }
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005253 set x0 -1
5254 set xm -1
5255 for {} {$col < [llength $idlist]} {incr col} {
5256 set id [lindex $idlist $col]
5257 if {[lindex $previdlist $col] eq $id} continue
5258 if {$id eq {}} {
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005259 set haspad 1
5260 continue
5261 }
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005262 set x0 [lsearch -exact $previdlist $id]
5263 if {$x0 < 0} continue
5264 set z [expr {$x0 - $col}]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005265 set isarrow 0
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005266 set z0 {}
5267 if {$ym >= 0} {
5268 set xm [lsearch -exact $pprevidlist $id]
5269 if {$xm >= 0} {
5270 set z0 [expr {$xm - $x0}]
5271 }
5272 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005273 if {$z0 eq {}} {
Paul Mackerras92ed6662007-08-22 22:35:28 +10005274 # if row y0 is the first child of $id then it's not an arrow
5275 if {[lindex $children($curview,$id) 0] ne
5276 [lindex $displayorder $y0]} {
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005277 set isarrow 1
5278 }
5279 }
Paul Mackerrase341c062007-08-12 12:42:57 +10005280 if {!$isarrow && $id ne [lindex $displayorder $row] &&
5281 [lsearch -exact [lindex $rowidlist [expr {$row+1}]] $id] < 0} {
5282 set isarrow 1
5283 }
Paul Mackerras3fc42792006-09-15 09:45:23 +10005284 # Looking at lines from this row to the previous row,
5285 # make them go straight up if they end in an arrow on
5286 # the previous row; otherwise make them go straight up
5287 # or at 45 degrees.
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005288 if {$z < -1 || ($z < 0 && $isarrow)} {
Paul Mackerras3fc42792006-09-15 09:45:23 +10005289 # Line currently goes left too much;
5290 # insert pads in the previous row, then optimize it
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005291 set npad [expr {-1 - $z + $isarrow}]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005292 insert_pad $y0 $x0 $npad
5293 if {$y0 > 0} {
5294 optimize_rows $y0 $x0 $row
5295 }
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005296 set previdlist [lindex $rowidlist $y0]
5297 set x0 [lsearch -exact $previdlist $id]
5298 set z [expr {$x0 - $col}]
5299 if {$z0 ne {}} {
5300 set pprevidlist [lindex $rowidlist $ym]
5301 set xm [lsearch -exact $pprevidlist $id]
5302 set z0 [expr {$xm - $x0}]
5303 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005304 } elseif {$z > 1 || ($z > 0 && $isarrow)} {
Paul Mackerras3fc42792006-09-15 09:45:23 +10005305 # Line currently goes right too much;
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005306 # insert pads in this line
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005307 set npad [expr {$z - 1 + $isarrow}]
Paul Mackerrase341c062007-08-12 12:42:57 +10005308 insert_pad $row $col $npad
5309 set idlist [lindex $rowidlist $row]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005310 incr col $npad
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005311 set z [expr {$x0 - $col}]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005312 set haspad 1
5313 }
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005314 if {$z0 eq {} && !$isarrow && $ym >= 0} {
Paul Mackerraseb447a12006-03-18 23:11:37 +11005315 # this line links to its first child on row $row-2
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005316 set id [lindex $displayorder $ym]
5317 set xc [lsearch -exact $pprevidlist $id]
Paul Mackerraseb447a12006-03-18 23:11:37 +11005318 if {$xc >= 0} {
5319 set z0 [expr {$xc - $x0}]
5320 }
5321 }
Paul Mackerras3fc42792006-09-15 09:45:23 +10005322 # avoid lines jigging left then immediately right
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005323 if {$z0 ne {} && $z < 0 && $z0 > 0} {
5324 insert_pad $y0 $x0 1
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005325 incr x0
5326 optimize_rows $y0 $x0 $row
5327 set previdlist [lindex $rowidlist $y0]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005328 }
5329 }
5330 if {!$haspad} {
Paul Mackerras3fc42792006-09-15 09:45:23 +10005331 # Find the first column that doesn't have a line going right
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005332 for {set col [llength $idlist]} {[incr col -1] >= 0} {} {
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005333 set id [lindex $idlist $col]
5334 if {$id eq {}} break
5335 set x0 [lsearch -exact $previdlist $id]
5336 if {$x0 < 0} {
Paul Mackerraseb447a12006-03-18 23:11:37 +11005337 # check if this is the link to the first child
Paul Mackerras92ed6662007-08-22 22:35:28 +10005338 set kid [lindex $displayorder $y0]
5339 if {[lindex $children($curview,$id) 0] eq $kid} {
Paul Mackerraseb447a12006-03-18 23:11:37 +11005340 # it is, work out offset to child
Paul Mackerras92ed6662007-08-22 22:35:28 +10005341 set x0 [lsearch -exact $previdlist $kid]
Paul Mackerraseb447a12006-03-18 23:11:37 +11005342 }
5343 }
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005344 if {$x0 <= $col} break
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005345 }
Paul Mackerras3fc42792006-09-15 09:45:23 +10005346 # Insert a pad at that column as long as it has a line and
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005347 # isn't the last column
5348 if {$x0 >= 0 && [incr col] < [llength $idlist]} {
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005349 set idlist [linsert $idlist $col {}]
Paul Mackerras03800812007-08-29 21:45:21 +10005350 lset rowidlist $row $idlist
5351 changedrow $row
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005352 }
5353 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005354 }
5355}
5356
5357proc xc {row col} {
5358 global canvx0 linespc
5359 return [expr {$canvx0 + $col * $linespc}]
5360}
5361
5362proc yc {row} {
5363 global canvy0 linespc
5364 return [expr {$canvy0 + $row * $linespc}]
5365}
5366
Paul Mackerrasc934a8a2006-03-02 23:00:44 +11005367proc linewidth {id} {
5368 global thickerline lthickness
5369
5370 set wid $lthickness
5371 if {[info exists thickerline] && $id eq $thickerline} {
5372 set wid [expr {2 * $lthickness}]
5373 }
5374 return $wid
5375}
5376
Paul Mackerras50b44ec2006-04-04 10:16:22 +10005377proc rowranges {id} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005378 global curview children uparrowlen downarrowlen
Paul Mackerras92ed6662007-08-22 22:35:28 +10005379 global rowidlist
Paul Mackerras50b44ec2006-04-04 10:16:22 +10005380
Paul Mackerras92ed6662007-08-22 22:35:28 +10005381 set kids $children($curview,$id)
5382 if {$kids eq {}} {
5383 return {}
Paul Mackerras50b44ec2006-04-04 10:16:22 +10005384 }
Paul Mackerras92ed6662007-08-22 22:35:28 +10005385 set ret {}
5386 lappend kids $id
5387 foreach child $kids {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005388 if {![commitinview $child $curview]} break
5389 set row [rowofcommit $child]
Paul Mackerras92ed6662007-08-22 22:35:28 +10005390 if {![info exists prev]} {
5391 lappend ret [expr {$row + 1}]
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005392 } else {
Paul Mackerras92ed6662007-08-22 22:35:28 +10005393 if {$row <= $prevrow} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005394 puts "oops children of [shortids $id] out of order [shortids $child] $row <= [shortids $prev] $prevrow"
Paul Mackerras92ed6662007-08-22 22:35:28 +10005395 }
5396 # see if the line extends the whole way from prevrow to row
5397 if {$row > $prevrow + $uparrowlen + $downarrowlen &&
5398 [lsearch -exact [lindex $rowidlist \
5399 [expr {int(($row + $prevrow) / 2)}]] $id] < 0} {
5400 # it doesn't, see where it ends
5401 set r [expr {$prevrow + $downarrowlen}]
5402 if {[lsearch -exact [lindex $rowidlist $r] $id] < 0} {
5403 while {[incr r -1] > $prevrow &&
5404 [lsearch -exact [lindex $rowidlist $r] $id] < 0} {}
5405 } else {
5406 while {[incr r] <= $row &&
5407 [lsearch -exact [lindex $rowidlist $r] $id] >= 0} {}
5408 incr r -1
5409 }
5410 lappend ret $r
5411 # see where it starts up again
5412 set r [expr {$row - $uparrowlen}]
5413 if {[lsearch -exact [lindex $rowidlist $r] $id] < 0} {
5414 while {[incr r] < $row &&
5415 [lsearch -exact [lindex $rowidlist $r] $id] < 0} {}
5416 } else {
5417 while {[incr r -1] >= $prevrow &&
5418 [lsearch -exact [lindex $rowidlist $r] $id] >= 0} {}
5419 incr r
5420 }
5421 lappend ret $r
5422 }
Paul Mackerraseb447a12006-03-18 23:11:37 +11005423 }
Paul Mackerras92ed6662007-08-22 22:35:28 +10005424 if {$child eq $id} {
5425 lappend ret $row
5426 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005427 set prev $child
Paul Mackerras92ed6662007-08-22 22:35:28 +10005428 set prevrow $row
Paul Mackerraseb447a12006-03-18 23:11:37 +11005429 }
Paul Mackerras92ed6662007-08-22 22:35:28 +10005430 return $ret
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005431}
5432
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005433proc drawlineseg {id row endrow arrowlow} {
5434 global rowidlist displayorder iddrawn linesegs
Paul Mackerrase341c062007-08-12 12:42:57 +10005435 global canv colormap linespc curview maxlinelen parentlist
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005436
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005437 set cols [list [lsearch -exact [lindex $rowidlist $row] $id]]
5438 set le [expr {$row + 1}]
5439 set arrowhigh 1
5440 while {1} {
5441 set c [lsearch -exact [lindex $rowidlist $le] $id]
5442 if {$c < 0} {
5443 incr le -1
5444 break
5445 }
5446 lappend cols $c
5447 set x [lindex $displayorder $le]
5448 if {$x eq $id} {
5449 set arrowhigh 0
5450 break
5451 }
5452 if {[info exists iddrawn($x)] || $le == $endrow} {
5453 set c [lsearch -exact [lindex $rowidlist [expr {$le+1}]] $id]
5454 if {$c >= 0} {
5455 lappend cols $c
5456 set arrowhigh 0
5457 }
5458 break
5459 }
5460 incr le
5461 }
5462 if {$le <= $row} {
5463 return $row
5464 }
5465
5466 set lines {}
5467 set i 0
5468 set joinhigh 0
5469 if {[info exists linesegs($id)]} {
5470 set lines $linesegs($id)
5471 foreach li $lines {
5472 set r0 [lindex $li 0]
5473 if {$r0 > $row} {
5474 if {$r0 == $le && [lindex $li 1] - $row <= $maxlinelen} {
5475 set joinhigh 1
5476 }
5477 break
5478 }
5479 incr i
5480 }
5481 }
5482 set joinlow 0
5483 if {$i > 0} {
5484 set li [lindex $lines [expr {$i-1}]]
5485 set r1 [lindex $li 1]
5486 if {$r1 == $row && $le - [lindex $li 0] <= $maxlinelen} {
5487 set joinlow 1
5488 }
5489 }
5490
5491 set x [lindex $cols [expr {$le - $row}]]
5492 set xp [lindex $cols [expr {$le - 1 - $row}]]
5493 set dir [expr {$xp - $x}]
5494 if {$joinhigh} {
5495 set ith [lindex $lines $i 2]
5496 set coords [$canv coords $ith]
5497 set ah [$canv itemcget $ith -arrow]
5498 set arrowhigh [expr {$ah eq "first" || $ah eq "both"}]
5499 set x2 [lindex $cols [expr {$le + 1 - $row}]]
5500 if {$x2 ne {} && $x - $x2 == $dir} {
5501 set coords [lrange $coords 0 end-2]
5502 }
5503 } else {
5504 set coords [list [xc $le $x] [yc $le]]
5505 }
5506 if {$joinlow} {
5507 set itl [lindex $lines [expr {$i-1}] 2]
5508 set al [$canv itemcget $itl -arrow]
5509 set arrowlow [expr {$al eq "last" || $al eq "both"}]
Paul Mackerrase341c062007-08-12 12:42:57 +10005510 } elseif {$arrowlow} {
5511 if {[lsearch -exact [lindex $rowidlist [expr {$row-1}]] $id] >= 0 ||
5512 [lsearch -exact [lindex $parentlist [expr {$row-1}]] $id] >= 0} {
5513 set arrowlow 0
5514 }
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005515 }
5516 set arrow [lindex {none first last both} [expr {$arrowhigh + 2*$arrowlow}]]
5517 for {set y $le} {[incr y -1] > $row} {} {
5518 set x $xp
5519 set xp [lindex $cols [expr {$y - 1 - $row}]]
5520 set ndir [expr {$xp - $x}]
5521 if {$dir != $ndir || $xp < 0} {
5522 lappend coords [xc $y $x] [yc $y]
5523 }
5524 set dir $ndir
5525 }
5526 if {!$joinlow} {
5527 if {$xp < 0} {
5528 # join parent line to first child
5529 set ch [lindex $displayorder $row]
5530 set xc [lsearch -exact [lindex $rowidlist $row] $ch]
5531 if {$xc < 0} {
5532 puts "oops: drawlineseg: child $ch not on row $row"
Paul Mackerrase341c062007-08-12 12:42:57 +10005533 } elseif {$xc != $x} {
5534 if {($arrowhigh && $le == $row + 1) || $dir == 0} {
5535 set d [expr {int(0.5 * $linespc)}]
5536 set x1 [xc $row $x]
5537 if {$xc < $x} {
5538 set x2 [expr {$x1 - $d}]
5539 } else {
5540 set x2 [expr {$x1 + $d}]
5541 }
5542 set y2 [yc $row]
5543 set y1 [expr {$y2 + $d}]
5544 lappend coords $x1 $y1 $x2 $y2
5545 } elseif {$xc < $x - 1} {
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005546 lappend coords [xc $row [expr {$x-1}]] [yc $row]
5547 } elseif {$xc > $x + 1} {
5548 lappend coords [xc $row [expr {$x+1}]] [yc $row]
5549 }
5550 set x $xc
5551 }
5552 lappend coords [xc $row $x] [yc $row]
5553 } else {
5554 set xn [xc $row $xp]
5555 set yn [yc $row]
Paul Mackerrase341c062007-08-12 12:42:57 +10005556 lappend coords $xn $yn
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005557 }
5558 if {!$joinhigh} {
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005559 assigncolor $id
5560 set t [$canv create line $coords -width [linewidth $id] \
5561 -fill $colormap($id) -tags lines.$id -arrow $arrow]
5562 $canv lower $t
5563 bindline $t $id
5564 set lines [linsert $lines $i [list $row $le $t]]
5565 } else {
5566 $canv coords $ith $coords
5567 if {$arrow ne $ah} {
5568 $canv itemconf $ith -arrow $arrow
5569 }
5570 lset lines $i 0 $row
5571 }
5572 } else {
5573 set xo [lsearch -exact [lindex $rowidlist [expr {$row - 1}]] $id]
5574 set ndir [expr {$xo - $xp}]
5575 set clow [$canv coords $itl]
5576 if {$dir == $ndir} {
5577 set clow [lrange $clow 2 end]
5578 }
5579 set coords [concat $coords $clow]
5580 if {!$joinhigh} {
5581 lset lines [expr {$i-1}] 1 $le
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005582 } else {
5583 # coalesce two pieces
5584 $canv delete $ith
5585 set b [lindex $lines [expr {$i-1}] 0]
5586 set e [lindex $lines $i 1]
5587 set lines [lreplace $lines [expr {$i-1}] $i [list $b $e $itl]]
5588 }
5589 $canv coords $itl $coords
5590 if {$arrow ne $al} {
5591 $canv itemconf $itl -arrow $arrow
5592 }
5593 }
5594
5595 set linesegs($id) $lines
5596 return $le
5597}
5598
5599proc drawparentlinks {id row} {
5600 global rowidlist canv colormap curview parentlist
Paul Mackerras513a54d2007-08-01 22:27:57 +10005601 global idpos linespc
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005602
5603 set rowids [lindex $rowidlist $row]
5604 set col [lsearch -exact $rowids $id]
5605 if {$col < 0} return
5606 set olds [lindex $parentlist $row]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005607 set row2 [expr {$row + 1}]
5608 set x [xc $row $col]
5609 set y [yc $row]
5610 set y2 [yc $row2]
Paul Mackerrase341c062007-08-12 12:42:57 +10005611 set d [expr {int(0.5 * $linespc)}]
Paul Mackerras513a54d2007-08-01 22:27:57 +10005612 set ymid [expr {$y + $d}]
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11005613 set ids [lindex $rowidlist $row2]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005614 # rmx = right-most X coord used
5615 set rmx 0
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005616 foreach p $olds {
Paul Mackerrasf3408442006-03-31 09:54:24 +11005617 set i [lsearch -exact $ids $p]
5618 if {$i < 0} {
5619 puts "oops, parent $p of $id not in list"
5620 continue
5621 }
5622 set x2 [xc $row2 $i]
5623 if {$x2 > $rmx} {
5624 set rmx $x2
5625 }
Paul Mackerras513a54d2007-08-01 22:27:57 +10005626 set j [lsearch -exact $rowids $p]
5627 if {$j < 0} {
Paul Mackerraseb447a12006-03-18 23:11:37 +11005628 # drawlineseg will do this one for us
5629 continue
5630 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005631 assigncolor $p
5632 # should handle duplicated parents here...
5633 set coords [list $x $y]
Paul Mackerras513a54d2007-08-01 22:27:57 +10005634 if {$i != $col} {
5635 # if attaching to a vertical segment, draw a smaller
5636 # slant for visual distinctness
5637 if {$i == $j} {
5638 if {$i < $col} {
5639 lappend coords [expr {$x2 + $d}] $y $x2 $ymid
5640 } else {
5641 lappend coords [expr {$x2 - $d}] $y $x2 $ymid
5642 }
5643 } elseif {$i < $col && $i < $j} {
5644 # segment slants towards us already
5645 lappend coords [xc $row $j] $y
5646 } else {
5647 if {$i < $col - 1} {
5648 lappend coords [expr {$x2 + $linespc}] $y
5649 } elseif {$i > $col + 1} {
5650 lappend coords [expr {$x2 - $linespc}] $y
5651 }
5652 lappend coords $x2 $y2
5653 }
5654 } else {
5655 lappend coords $x2 $y2
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005656 }
Paul Mackerrasc934a8a2006-03-02 23:00:44 +11005657 set t [$canv create line $coords -width [linewidth $p] \
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005658 -fill $colormap($p) -tags lines.$p]
5659 $canv lower $t
5660 bindline $t $p
5661 }
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005662 if {$rmx > [lindex $idpos($id) 1]} {
5663 lset idpos($id) 1 $rmx
5664 redrawtags $id
5665 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005666}
5667
Paul Mackerrasc934a8a2006-03-02 23:00:44 +11005668proc drawlines {id} {
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005669 global canv
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005670
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005671 $canv itemconf lines.$id -width [linewidth $id]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005672}
5673
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005674proc drawcmittext {id row col} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005675 global linespc canv canv2 canv3 fgcolor curview
5676 global cmitlisted commitinfo rowidlist parentlist
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005677 global rowtextx idpos idtags idheads idotherrefs
Paul Mackerras03800812007-08-29 21:45:21 +10005678 global linehtag linentag linedtag selectedline
Paul Mackerrasb9fdba72009-04-09 09:34:46 +10005679 global canvxmax boldids boldnameids fgcolor markedid
Paul Mackerrasd277e892008-09-21 18:11:37 -05005680 global mainheadid nullid nullid2 circleitem circlecolors ctxbut
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005681
Linus Torvalds1407ade2008-02-09 14:02:07 -08005682 # listed is 0 for boundary, 1 for normal, 2 for negative, 3 for left, 4 for right
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005683 set listed $cmitlisted($curview,$id)
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005684 if {$id eq $nullid} {
5685 set ofill red
Paul Mackerras8f489362007-07-13 19:49:37 +10005686 } elseif {$id eq $nullid2} {
Paul Mackerrasef3192b2007-07-22 22:05:30 +10005687 set ofill green
Paul Mackerrasc11ff122008-05-26 10:11:33 +10005688 } elseif {$id eq $mainheadid} {
5689 set ofill yellow
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005690 } else {
Paul Mackerrasc11ff122008-05-26 10:11:33 +10005691 set ofill [lindex $circlecolors $listed]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005692 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005693 set x [xc $row $col]
5694 set y [yc $row]
5695 set orad [expr {$linespc / 3}]
Linus Torvalds1407ade2008-02-09 14:02:07 -08005696 if {$listed <= 2} {
Paul Mackerrasc961b222007-07-09 22:45:47 +10005697 set t [$canv create oval [expr {$x - $orad}] [expr {$y - $orad}] \
5698 [expr {$x + $orad - 1}] [expr {$y + $orad - 1}] \
5699 -fill $ofill -outline $fgcolor -width 1 -tags circle]
Linus Torvalds1407ade2008-02-09 14:02:07 -08005700 } elseif {$listed == 3} {
Paul Mackerrasc961b222007-07-09 22:45:47 +10005701 # triangle pointing left for left-side commits
5702 set t [$canv create polygon \
5703 [expr {$x - $orad}] $y \
5704 [expr {$x + $orad - 1}] [expr {$y - $orad}] \
5705 [expr {$x + $orad - 1}] [expr {$y + $orad - 1}] \
5706 -fill $ofill -outline $fgcolor -width 1 -tags circle]
5707 } else {
5708 # triangle pointing right for right-side commits
5709 set t [$canv create polygon \
5710 [expr {$x + $orad - 1}] $y \
5711 [expr {$x - $orad}] [expr {$y - $orad}] \
5712 [expr {$x - $orad}] [expr {$y + $orad - 1}] \
5713 -fill $ofill -outline $fgcolor -width 1 -tags circle]
5714 }
Paul Mackerrasc11ff122008-05-26 10:11:33 +10005715 set circleitem($row) $t
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005716 $canv raise $t
5717 $canv bind $t <1> {selcanvline {} %x %y}
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005718 set rmx [llength [lindex $rowidlist $row]]
5719 set olds [lindex $parentlist $row]
5720 if {$olds ne {}} {
5721 set nextids [lindex $rowidlist [expr {$row + 1}]]
5722 foreach p $olds {
5723 set i [lsearch -exact $nextids $p]
5724 if {$i > $rmx} {
5725 set rmx $i
5726 }
5727 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005728 }
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005729 set xt [xc $row $rmx]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005730 set rowtextx($row) $xt
5731 set idpos($id) [list $x $xt $y]
5732 if {[info exists idtags($id)] || [info exists idheads($id)]
5733 || [info exists idotherrefs($id)]} {
5734 set xt [drawtags $id $x $xt $y]
5735 }
5736 set headline [lindex $commitinfo($id) 0]
5737 set name [lindex $commitinfo($id) 1]
5738 set date [lindex $commitinfo($id) 2]
5739 set date [formatdate $date]
Paul Mackerras9c311b32007-10-04 22:27:13 +10005740 set font mainfont
5741 set nfont mainfont
Paul Mackerras476ca632008-01-07 22:16:31 +11005742 set isbold [ishighlighted $id]
Paul Mackerras908c3582006-05-20 09:38:11 +10005743 if {$isbold > 0} {
Paul Mackerras28593d32008-11-13 23:01:46 +11005744 lappend boldids $id
Paul Mackerras9c311b32007-10-04 22:27:13 +10005745 set font mainfontbold
Paul Mackerras908c3582006-05-20 09:38:11 +10005746 if {$isbold > 1} {
Paul Mackerras28593d32008-11-13 23:01:46 +11005747 lappend boldnameids $id
Paul Mackerras9c311b32007-10-04 22:27:13 +10005748 set nfont mainfontbold
Paul Mackerras908c3582006-05-20 09:38:11 +10005749 }
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10005750 }
Paul Mackerras28593d32008-11-13 23:01:46 +11005751 set linehtag($id) [$canv create text $xt $y -anchor w -fill $fgcolor \
5752 -text $headline -font $font -tags text]
5753 $canv bind $linehtag($id) $ctxbut "rowmenu %X %Y $id"
5754 set linentag($id) [$canv2 create text 3 $y -anchor w -fill $fgcolor \
5755 -text $name -font $nfont -tags text]
5756 set linedtag($id) [$canv3 create text 3 $y -anchor w -fill $fgcolor \
5757 -text $date -font mainfont -tags text]
Paul Mackerras94b4a692008-05-20 20:51:06 +10005758 if {$selectedline == $row} {
Paul Mackerras28593d32008-11-13 23:01:46 +11005759 make_secsel $id
Paul Mackerras03800812007-08-29 21:45:21 +10005760 }
Paul Mackerrasb9fdba72009-04-09 09:34:46 +10005761 if {[info exists markedid] && $markedid eq $id} {
5762 make_idmark $id
5763 }
Paul Mackerras9c311b32007-10-04 22:27:13 +10005764 set xr [expr {$xt + [font measure $font $headline]}]
Paul Mackerrasbe0cd092006-03-31 09:55:11 +11005765 if {$xr > $canvxmax} {
5766 set canvxmax $xr
5767 setcanvscroll
5768 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005769}
5770
5771proc drawcmitrow {row} {
Paul Mackerras03800812007-08-29 21:45:21 +10005772 global displayorder rowidlist nrows_drawn
Paul Mackerras005a2f42007-07-26 22:36:39 +10005773 global iddrawn markingmatches
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005774 global commitinfo numcommits
Paul Mackerras687c8762007-09-22 12:49:33 +10005775 global filehighlight fhighlights findpattern nhighlights
Paul Mackerras908c3582006-05-20 09:38:11 +10005776 global hlview vhighlights
Paul Mackerras164ff272006-05-29 19:50:02 +10005777 global highlight_related rhighlights
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005778
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11005779 if {$row >= $numcommits} return
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005780
5781 set id [lindex $displayorder $row]
Paul Mackerras476ca632008-01-07 22:16:31 +11005782 if {[info exists hlview] && ![info exists vhighlights($id)]} {
Paul Mackerras908c3582006-05-20 09:38:11 +10005783 askvhighlight $row $id
5784 }
Paul Mackerras476ca632008-01-07 22:16:31 +11005785 if {[info exists filehighlight] && ![info exists fhighlights($id)]} {
Paul Mackerras908c3582006-05-20 09:38:11 +10005786 askfilehighlight $row $id
5787 }
Paul Mackerras476ca632008-01-07 22:16:31 +11005788 if {$findpattern ne {} && ![info exists nhighlights($id)]} {
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10005789 askfindhighlight $row $id
Paul Mackerras908c3582006-05-20 09:38:11 +10005790 }
Paul Mackerras476ca632008-01-07 22:16:31 +11005791 if {$highlight_related ne [mc "None"] && ![info exists rhighlights($id)]} {
Paul Mackerras164ff272006-05-29 19:50:02 +10005792 askrelhighlight $row $id
5793 }
Paul Mackerras005a2f42007-07-26 22:36:39 +10005794 if {![info exists iddrawn($id)]} {
5795 set col [lsearch -exact [lindex $rowidlist $row] $id]
5796 if {$col < 0} {
5797 puts "oops, row $row id $id not in list"
5798 return
5799 }
5800 if {![info exists commitinfo($id)]} {
5801 getcommit $id
5802 }
5803 assigncolor $id
5804 drawcmittext $id $row $col
5805 set iddrawn($id) 1
Paul Mackerras03800812007-08-29 21:45:21 +10005806 incr nrows_drawn
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005807 }
Paul Mackerras005a2f42007-07-26 22:36:39 +10005808 if {$markingmatches} {
5809 markrowmatches $row $id
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005810 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005811}
5812
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005813proc drawcommits {row {endrow {}}} {
Paul Mackerras03800812007-08-29 21:45:21 +10005814 global numcommits iddrawn displayorder curview need_redisplay
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10005815 global parentlist rowidlist rowfinal uparrowlen downarrowlen nrows_drawn
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005816
5817 if {$row < 0} {
5818 set row 0
5819 }
5820 if {$endrow eq {}} {
5821 set endrow $row
5822 }
5823 if {$endrow >= $numcommits} {
5824 set endrow [expr {$numcommits - 1}]
5825 }
5826
Paul Mackerras03800812007-08-29 21:45:21 +10005827 set rl1 [expr {$row - $downarrowlen - 3}]
5828 if {$rl1 < 0} {
5829 set rl1 0
5830 }
5831 set ro1 [expr {$row - 3}]
5832 if {$ro1 < 0} {
5833 set ro1 0
5834 }
5835 set r2 [expr {$endrow + $uparrowlen + 3}]
5836 if {$r2 > $numcommits} {
5837 set r2 $numcommits
5838 }
5839 for {set r $rl1} {$r < $r2} {incr r} {
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10005840 if {[lindex $rowidlist $r] ne {} && [lindex $rowfinal $r]} {
Paul Mackerras03800812007-08-29 21:45:21 +10005841 if {$rl1 < $r} {
5842 layoutrows $rl1 $r
5843 }
5844 set rl1 [expr {$r + 1}]
5845 }
5846 }
5847 if {$rl1 < $r} {
5848 layoutrows $rl1 $r
5849 }
5850 optimize_rows $ro1 0 $r2
5851 if {$need_redisplay || $nrows_drawn > 2000} {
5852 clear_display
Paul Mackerras03800812007-08-29 21:45:21 +10005853 }
5854
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005855 # make the lines join to already-drawn rows either side
5856 set r [expr {$row - 1}]
5857 if {$r < 0 || ![info exists iddrawn([lindex $displayorder $r])]} {
5858 set r $row
5859 }
5860 set er [expr {$endrow + 1}]
5861 if {$er >= $numcommits ||
5862 ![info exists iddrawn([lindex $displayorder $er])]} {
5863 set er $endrow
5864 }
5865 for {} {$r <= $er} {incr r} {
5866 set id [lindex $displayorder $r]
5867 set wasdrawn [info exists iddrawn($id)]
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10005868 drawcmitrow $r
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005869 if {$r == $er} break
5870 set nextid [lindex $displayorder [expr {$r + 1}]]
Paul Mackerrase5ef6f92007-10-21 12:58:42 +10005871 if {$wasdrawn && [info exists iddrawn($nextid)]} continue
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005872 drawparentlinks $id $r
5873
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005874 set rowids [lindex $rowidlist $r]
5875 foreach lid $rowids {
5876 if {$lid eq {}} continue
Paul Mackerrase5ef6f92007-10-21 12:58:42 +10005877 if {[info exists lineend($lid)] && $lineend($lid) > $r} continue
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005878 if {$lid eq $id} {
5879 # see if this is the first child of any of its parents
5880 foreach p [lindex $parentlist $r] {
5881 if {[lsearch -exact $rowids $p] < 0} {
5882 # make this line extend up to the child
Paul Mackerrase5ef6f92007-10-21 12:58:42 +10005883 set lineend($p) [drawlineseg $p $r $er 0]
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005884 }
5885 }
Paul Mackerrase5ef6f92007-10-21 12:58:42 +10005886 } else {
5887 set lineend($lid) [drawlineseg $lid $r $er 1]
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005888 }
5889 }
5890 }
5891}
5892
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005893proc undolayout {row} {
5894 global uparrowlen mingaplen downarrowlen
5895 global rowidlist rowisopt rowfinal need_redisplay
5896
5897 set r [expr {$row - ($uparrowlen + $mingaplen + $downarrowlen)}]
5898 if {$r < 0} {
5899 set r 0
5900 }
5901 if {[llength $rowidlist] > $r} {
5902 incr r -1
5903 set rowidlist [lrange $rowidlist 0 $r]
5904 set rowfinal [lrange $rowfinal 0 $r]
5905 set rowisopt [lrange $rowisopt 0 $r]
5906 set need_redisplay 1
5907 run drawvisible
5908 }
5909}
5910
Paul Mackerras31c0eaa2007-12-30 22:41:14 +11005911proc drawvisible {} {
5912 global canv linespc curview vrowmod selectedline targetrow targetid
Paul Mackerras42a671f2008-01-02 09:59:39 +11005913 global need_redisplay cscroll numcommits
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005914
Paul Mackerras31c0eaa2007-12-30 22:41:14 +11005915 set fs [$canv yview]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005916 set ymax [lindex [$canv cget -scrollregion] 3]
Paul Mackerras5a7f5772008-01-15 22:45:36 +11005917 if {$ymax eq {} || $ymax == 0 || $numcommits == 0} return
Paul Mackerras31c0eaa2007-12-30 22:41:14 +11005918 set f0 [lindex $fs 0]
5919 set f1 [lindex $fs 1]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005920 set y0 [expr {int($f0 * $ymax)}]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005921 set y1 [expr {int($f1 * $ymax)}]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005922
Paul Mackerras31c0eaa2007-12-30 22:41:14 +11005923 if {[info exists targetid]} {
Paul Mackerras42a671f2008-01-02 09:59:39 +11005924 if {[commitinview $targetid $curview]} {
5925 set r [rowofcommit $targetid]
5926 if {$r != $targetrow} {
5927 # Fix up the scrollregion and change the scrolling position
5928 # now that our target row has moved.
5929 set diff [expr {($r - $targetrow) * $linespc}]
5930 set targetrow $r
5931 setcanvscroll
5932 set ymax [lindex [$canv cget -scrollregion] 3]
5933 incr y0 $diff
5934 incr y1 $diff
5935 set f0 [expr {$y0 / $ymax}]
5936 set f1 [expr {$y1 / $ymax}]
5937 allcanvs yview moveto $f0
5938 $cscroll set $f0 $f1
5939 set need_redisplay 1
5940 }
5941 } else {
5942 unset targetid
Paul Mackerras31c0eaa2007-12-30 22:41:14 +11005943 }
5944 }
5945
5946 set row [expr {int(($y0 - 3) / $linespc) - 1}]
5947 set endrow [expr {int(($y1 - 3) / $linespc) + 1}]
5948 if {$endrow >= $vrowmod($curview)} {
5949 update_arcrows $curview
5950 }
Paul Mackerras94b4a692008-05-20 20:51:06 +10005951 if {$selectedline ne {} &&
Paul Mackerras31c0eaa2007-12-30 22:41:14 +11005952 $row <= $selectedline && $selectedline <= $endrow} {
5953 set targetrow $selectedline
Paul Mackerrasac1276a2008-03-03 10:11:08 +11005954 } elseif {[info exists targetid]} {
Paul Mackerras31c0eaa2007-12-30 22:41:14 +11005955 set targetrow [expr {int(($row + $endrow) / 2)}]
5956 }
Paul Mackerrasac1276a2008-03-03 10:11:08 +11005957 if {[info exists targetrow]} {
5958 if {$targetrow >= $numcommits} {
5959 set targetrow [expr {$numcommits - 1}]
5960 }
5961 set targetid [commitonrow $targetrow]
Paul Mackerras42a671f2008-01-02 09:59:39 +11005962 }
Paul Mackerras31c0eaa2007-12-30 22:41:14 +11005963 drawcommits $row $endrow
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005964}
5965
5966proc clear_display {} {
Paul Mackerras03800812007-08-29 21:45:21 +10005967 global iddrawn linesegs need_redisplay nrows_drawn
Paul Mackerras164ff272006-05-29 19:50:02 +10005968 global vhighlights fhighlights nhighlights rhighlights
Paul Mackerras28593d32008-11-13 23:01:46 +11005969 global linehtag linentag linedtag boldids boldnameids
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005970
5971 allcanvs delete all
5972 catch {unset iddrawn}
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005973 catch {unset linesegs}
Paul Mackerras94503a62008-05-19 09:48:45 +10005974 catch {unset linehtag}
5975 catch {unset linentag}
5976 catch {unset linedtag}
Paul Mackerras28593d32008-11-13 23:01:46 +11005977 set boldids {}
5978 set boldnameids {}
Paul Mackerras908c3582006-05-20 09:38:11 +10005979 catch {unset vhighlights}
5980 catch {unset fhighlights}
5981 catch {unset nhighlights}
Paul Mackerras164ff272006-05-29 19:50:02 +10005982 catch {unset rhighlights}
Paul Mackerras03800812007-08-29 21:45:21 +10005983 set need_redisplay 0
5984 set nrows_drawn 0
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005985}
5986
Paul Mackerras50b44ec2006-04-04 10:16:22 +10005987proc findcrossings {id} {
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005988 global rowidlist parentlist numcommits displayorder
Paul Mackerras50b44ec2006-04-04 10:16:22 +10005989
5990 set cross {}
5991 set ccross {}
5992 foreach {s e} [rowranges $id] {
5993 if {$e >= $numcommits} {
5994 set e [expr {$numcommits - 1}]
Paul Mackerras50b44ec2006-04-04 10:16:22 +10005995 }
Paul Mackerrasd94f8cd2006-04-06 10:18:23 +10005996 if {$e <= $s} continue
Paul Mackerras50b44ec2006-04-04 10:16:22 +10005997 for {set row $e} {[incr row -1] >= $s} {} {
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005998 set x [lsearch -exact [lindex $rowidlist $row] $id]
5999 if {$x < 0} break
Paul Mackerras50b44ec2006-04-04 10:16:22 +10006000 set olds [lindex $parentlist $row]
6001 set kid [lindex $displayorder $row]
6002 set kidx [lsearch -exact [lindex $rowidlist $row] $kid]
6003 if {$kidx < 0} continue
6004 set nextrow [lindex $rowidlist [expr {$row + 1}]]
6005 foreach p $olds {
6006 set px [lsearch -exact $nextrow $p]
6007 if {$px < 0} continue
6008 if {($kidx < $x && $x < $px) || ($px < $x && $x < $kidx)} {
6009 if {[lsearch -exact $ccross $p] >= 0} continue
6010 if {$x == $px + ($kidx < $px? -1: 1)} {
6011 lappend ccross $p
6012 } elseif {[lsearch -exact $cross $p] < 0} {
6013 lappend cross $p
6014 }
6015 }
6016 }
Paul Mackerras50b44ec2006-04-04 10:16:22 +10006017 }
6018 }
6019 return [concat $ccross {{}} $cross]
6020}
6021
Paul Mackerrase5c2d852005-05-11 23:44:54 +00006022proc assigncolor {id} {
Paul Mackerrasaa81d972006-02-28 11:27:12 +11006023 global colormap colors nextcolor
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11006024 global parents children children curview
Paul Mackerras6c20ff32005-06-22 19:53:32 +10006025
Paul Mackerras418c4c72006-02-07 09:10:18 +11006026 if {[info exists colormap($id)]} return
Paul Mackerrase5c2d852005-05-11 23:44:54 +00006027 set ncolors [llength $colors]
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10006028 if {[info exists children($curview,$id)]} {
6029 set kids $children($curview,$id)
Paul Mackerras79b2c752006-04-02 20:47:40 +10006030 } else {
6031 set kids {}
6032 }
6033 if {[llength $kids] == 1} {
6034 set child [lindex $kids 0]
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +00006035 if {[info exists colormap($child)]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11006036 && [llength $parents($curview,$child)] == 1} {
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +00006037 set colormap($id) $colormap($child)
6038 return
Paul Mackerrase5c2d852005-05-11 23:44:54 +00006039 }
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +00006040 }
6041 set badcolors {}
Paul Mackerras50b44ec2006-04-04 10:16:22 +10006042 set origbad {}
6043 foreach x [findcrossings $id] {
6044 if {$x eq {}} {
6045 # delimiter between corner crossings and other crossings
6046 if {[llength $badcolors] >= $ncolors - 1} break
6047 set origbad $badcolors
Paul Mackerrase5c2d852005-05-11 23:44:54 +00006048 }
Paul Mackerras50b44ec2006-04-04 10:16:22 +10006049 if {[info exists colormap($x)]
6050 && [lsearch -exact $badcolors $colormap($x)] < 0} {
6051 lappend badcolors $colormap($x)
Paul Mackerras6c20ff32005-06-22 19:53:32 +10006052 }
6053 }
Paul Mackerras50b44ec2006-04-04 10:16:22 +10006054 if {[llength $badcolors] >= $ncolors} {
6055 set badcolors $origbad
6056 }
Paul Mackerras6c20ff32005-06-22 19:53:32 +10006057 set origbad $badcolors
6058 if {[llength $badcolors] < $ncolors - 1} {
Paul Mackerras79b2c752006-04-02 20:47:40 +10006059 foreach child $kids {
Paul Mackerras6c20ff32005-06-22 19:53:32 +10006060 if {[info exists colormap($child)]
6061 && [lsearch -exact $badcolors $colormap($child)] < 0} {
6062 lappend badcolors $colormap($child)
6063 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11006064 foreach p $parents($curview,$child) {
Paul Mackerras79b2c752006-04-02 20:47:40 +10006065 if {[info exists colormap($p)]
6066 && [lsearch -exact $badcolors $colormap($p)] < 0} {
6067 lappend badcolors $colormap($p)
Paul Mackerrase5c2d852005-05-11 23:44:54 +00006068 }
6069 }
6070 }
Paul Mackerras6c20ff32005-06-22 19:53:32 +10006071 if {[llength $badcolors] >= $ncolors} {
6072 set badcolors $origbad
6073 }
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +00006074 }
6075 for {set i 0} {$i <= $ncolors} {incr i} {
6076 set c [lindex $colors $nextcolor]
6077 if {[incr nextcolor] >= $ncolors} {
6078 set nextcolor 0
Paul Mackerrase5c2d852005-05-11 23:44:54 +00006079 }
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +00006080 if {[lsearch -exact $badcolors $c]} break
6081 }
6082 set colormap($id) $c
6083}
6084
Paul Mackerrasa823a912005-06-21 10:01:38 +10006085proc bindline {t id} {
6086 global canv
6087
Paul Mackerrasa823a912005-06-21 10:01:38 +10006088 $canv bind $t <Enter> "lineenter %x %y $id"
6089 $canv bind $t <Motion> "linemotion %x %y $id"
6090 $canv bind $t <Leave> "lineleave $id"
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10006091 $canv bind $t <Button-1> "lineclick %x %y $id 1"
Paul Mackerrasa823a912005-06-21 10:01:38 +10006092}
6093
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006094proc drawtags {id x xt y1} {
Paul Mackerras8a485712006-07-06 10:21:23 +10006095 global idtags idheads idotherrefs mainhead
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006096 global linespc lthickness
Paul Mackerrasd277e892008-09-21 18:11:37 -05006097 global canv rowtextx curview fgcolor bgcolor ctxbut
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006098
6099 set marks {}
6100 set ntags 0
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10006101 set nheads 0
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006102 if {[info exists idtags($id)]} {
6103 set marks $idtags($id)
6104 set ntags [llength $marks]
6105 }
6106 if {[info exists idheads($id)]} {
6107 set marks [concat $marks $idheads($id)]
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10006108 set nheads [llength $idheads($id)]
6109 }
6110 if {[info exists idotherrefs($id)]} {
6111 set marks [concat $marks $idotherrefs($id)]
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006112 }
6113 if {$marks eq {}} {
6114 return $xt
6115 }
6116
6117 set delta [expr {int(0.5 * ($linespc - $lthickness))}]
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08006118 set yt [expr {$y1 - 0.5 * $linespc}]
6119 set yb [expr {$yt + $linespc - 1}]
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006120 set xvals {}
6121 set wvals {}
Paul Mackerras8a485712006-07-06 10:21:23 +10006122 set i -1
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006123 foreach tag $marks {
Paul Mackerras8a485712006-07-06 10:21:23 +10006124 incr i
6125 if {$i >= $ntags && $i < $ntags + $nheads && $tag eq $mainhead} {
Paul Mackerras9c311b32007-10-04 22:27:13 +10006126 set wid [font measure mainfontbold $tag]
Paul Mackerras8a485712006-07-06 10:21:23 +10006127 } else {
Paul Mackerras9c311b32007-10-04 22:27:13 +10006128 set wid [font measure mainfont $tag]
Paul Mackerras8a485712006-07-06 10:21:23 +10006129 }
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006130 lappend xvals $xt
6131 lappend wvals $wid
6132 set xt [expr {$xt + $delta + $wid + $lthickness + $linespc}]
6133 }
6134 set t [$canv create line $x $y1 [lindex $xvals end] $y1 \
6135 -width $lthickness -fill black -tags tag.$id]
6136 $canv lower $t
6137 foreach tag $marks x $xvals wid $wvals {
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08006138 set xl [expr {$x + $delta}]
6139 set xr [expr {$x + $delta + $wid + $lthickness}]
Paul Mackerras9c311b32007-10-04 22:27:13 +10006140 set font mainfont
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006141 if {[incr ntags -1] >= 0} {
6142 # draw a tag
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08006143 set t [$canv create polygon $x [expr {$yt + $delta}] $xl $yt \
6144 $xr $yt $xr $yb $xl $yb $x [expr {$yb - $delta}] \
Paul Mackerras106288c2005-08-19 23:11:39 +10006145 -width 1 -outline black -fill yellow -tags tag.$id]
6146 $canv bind $t <1> [list showtag $tag 1]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11006147 set rowtextx([rowofcommit $id]) [expr {$xr + $linespc}]
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006148 } else {
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10006149 # draw a head or other ref
6150 if {[incr nheads -1] >= 0} {
6151 set col green
Paul Mackerras8a485712006-07-06 10:21:23 +10006152 if {$tag eq $mainhead} {
Paul Mackerras9c311b32007-10-04 22:27:13 +10006153 set font mainfontbold
Paul Mackerras8a485712006-07-06 10:21:23 +10006154 }
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10006155 } else {
6156 set col "#ddddff"
6157 }
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08006158 set xl [expr {$xl - $delta/2}]
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006159 $canv create polygon $x $yt $xr $yt $xr $yb $x $yb \
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10006160 -width 1 -outline black -fill $col -tags tag.$id
Josef Weidendorfera970fcf2006-04-18 23:53:07 +02006161 if {[regexp {^(remotes/.*/|remotes/)} $tag match remoteprefix]} {
Paul Mackerras9c311b32007-10-04 22:27:13 +10006162 set rwid [font measure mainfont $remoteprefix]
Josef Weidendorfera970fcf2006-04-18 23:53:07 +02006163 set xi [expr {$x + 1}]
6164 set yti [expr {$yt + 1}]
6165 set xri [expr {$x + $rwid}]
6166 $canv create polygon $xi $yti $xri $yti $xri $yb $xi $yb \
6167 -width 0 -fill "#ffddaa" -tags tag.$id
6168 }
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006169 }
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10006170 set t [$canv create text $xl $y1 -anchor w -text $tag -fill $fgcolor \
Paul Mackerras8a485712006-07-06 10:21:23 +10006171 -font $font -tags [list tag.$id text]]
Paul Mackerras106288c2005-08-19 23:11:39 +10006172 if {$ntags >= 0} {
6173 $canv bind $t <1> [list showtag $tag 1]
Paul Mackerras10299152006-08-02 09:52:01 +10006174 } elseif {$nheads >= 0} {
Paul Mackerrasd277e892008-09-21 18:11:37 -05006175 $canv bind $t $ctxbut [list headmenu %X %Y $id $tag]
Paul Mackerras106288c2005-08-19 23:11:39 +10006176 }
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006177 }
6178 return $xt
6179}
6180
Paul Mackerras8d858d12005-08-05 09:52:16 +10006181proc xcoord {i level ln} {
6182 global canvx0 xspc1 xspc2
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +00006183
Paul Mackerras8d858d12005-08-05 09:52:16 +10006184 set x [expr {$canvx0 + $i * $xspc1($ln)}]
6185 if {$i > 0 && $i == $level} {
6186 set x [expr {$x + 0.5 * ($xspc2 - $xspc1($ln))}]
6187 } elseif {$i > $level} {
6188 set x [expr {$x + $xspc2 - $xspc1($ln)}]
6189 }
6190 return $x
6191}
6192
Paul Mackerras098dd8a2006-05-03 09:32:53 +10006193proc show_status {msg} {
Paul Mackerras9c311b32007-10-04 22:27:13 +10006194 global canv fgcolor
Paul Mackerras098dd8a2006-05-03 09:32:53 +10006195
6196 clear_display
Paul Mackerras9c311b32007-10-04 22:27:13 +10006197 $canv create text 3 3 -anchor nw -text $msg -font mainfont \
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10006198 -tags text -fill $fgcolor
Paul Mackerras098dd8a2006-05-03 09:32:53 +10006199}
6200
Paul Mackerras94a2eed2005-08-07 15:27:57 +10006201# Don't change the text pane cursor if it is currently the hand cursor,
6202# showing that we are over a sha1 ID link.
6203proc settextcursor {c} {
6204 global ctext curtextcursor
6205
6206 if {[$ctext cget -cursor] == $curtextcursor} {
6207 $ctext config -cursor $c
6208 }
6209 set curtextcursor $c
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +00006210}
6211
Paul Mackerrasa137a902007-10-23 21:12:49 +10006212proc nowbusy {what {name {}}} {
6213 global isbusy busyname statusw
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10006214
6215 if {[array names isbusy] eq {}} {
6216 . config -cursor watch
6217 settextcursor watch
6218 }
6219 set isbusy($what) 1
Paul Mackerrasa137a902007-10-23 21:12:49 +10006220 set busyname($what) $name
6221 if {$name ne {}} {
6222 $statusw conf -text $name
6223 }
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10006224}
6225
6226proc notbusy {what} {
Paul Mackerrasa137a902007-10-23 21:12:49 +10006227 global isbusy maincursor textcursor busyname statusw
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10006228
Paul Mackerrasa137a902007-10-23 21:12:49 +10006229 catch {
6230 unset isbusy($what)
6231 if {$busyname($what) ne {} &&
6232 [$statusw cget -text] eq $busyname($what)} {
6233 $statusw conf -text {}
6234 }
6235 }
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10006236 if {[array names isbusy] eq {}} {
6237 . config -cursor $maincursor
6238 settextcursor $textcursor
6239 }
6240}
6241
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00006242proc findmatches {f} {
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006243 global findtype findstring
Christian Stimmingb007ee22007-11-07 18:44:35 +01006244 if {$findtype == [mc "Regexp"]} {
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006245 set matches [regexp -indices -all -inline $findstring $f]
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00006246 } else {
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006247 set fs $findstring
Christian Stimmingb007ee22007-11-07 18:44:35 +01006248 if {$findtype == [mc "IgnCase"]} {
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006249 set f [string tolower $f]
6250 set fs [string tolower $fs]
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00006251 }
6252 set matches {}
6253 set i 0
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006254 set l [string length $fs]
6255 while {[set j [string first $fs $f $i]] >= 0} {
6256 lappend matches [list $j [expr {$j+$l-1}]]
6257 set i [expr {$j + $l}]
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00006258 }
6259 }
6260 return $matches
6261}
6262
Paul Mackerrascca5d942007-10-27 21:16:56 +10006263proc dofind {{dirn 1} {wrap 1}} {
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006264 global findstring findstartline findcurline selectedline numcommits
Paul Mackerrascca5d942007-10-27 21:16:56 +10006265 global gdttype filehighlight fh_serial find_dirn findallowwrap
Paul Mackerrasb74fd572005-07-16 07:46:13 -04006266
Paul Mackerrascca5d942007-10-27 21:16:56 +10006267 if {[info exists find_dirn]} {
6268 if {$find_dirn == $dirn} return
6269 stopfinding
6270 }
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00006271 focus .
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006272 if {$findstring eq {} || $numcommits == 0} return
Paul Mackerras94b4a692008-05-20 20:51:06 +10006273 if {$selectedline eq {}} {
Paul Mackerrascca5d942007-10-27 21:16:56 +10006274 set findstartline [lindex [visiblerows] [expr {$dirn < 0}]]
Paul Mackerras98f350e2005-05-15 05:56:51 +00006275 } else {
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006276 set findstartline $selectedline
Paul Mackerras98f350e2005-05-15 05:56:51 +00006277 }
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006278 set findcurline $findstartline
Christian Stimmingb007ee22007-11-07 18:44:35 +01006279 nowbusy finding [mc "Searching"]
6280 if {$gdttype ne [mc "containing:"] && ![info exists filehighlight]} {
Paul Mackerras687c8762007-09-22 12:49:33 +10006281 after cancel do_file_hl $fh_serial
6282 do_file_hl $fh_serial
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006283 }
Paul Mackerrascca5d942007-10-27 21:16:56 +10006284 set find_dirn $dirn
6285 set findallowwrap $wrap
6286 run findmore
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006287}
6288
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10006289proc stopfinding {} {
6290 global find_dirn findcurline fprogcoord
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006291
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10006292 if {[info exists find_dirn]} {
6293 unset find_dirn
6294 unset findcurline
6295 notbusy finding
6296 set fprogcoord 0
6297 adjustprogress
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006298 }
Paul Mackerras8a897742008-10-27 21:36:25 +11006299 stopblaming
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006300}
6301
6302proc findmore {} {
Paul Mackerras687c8762007-09-22 12:49:33 +10006303 global commitdata commitinfo numcommits findpattern findloc
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11006304 global findstartline findcurline findallowwrap
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10006305 global find_dirn gdttype fhighlights fprogcoord
Paul Mackerrascd2bcae2008-01-02 21:44:06 +11006306 global curview varcorder vrownum varccommits vrowmod
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006307
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10006308 if {![info exists find_dirn]} {
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006309 return 0
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00006310 }
Christian Stimmingb007ee22007-11-07 18:44:35 +01006311 set fldtypes [list [mc "Headline"] [mc "Author"] [mc "Date"] [mc "Committer"] [mc "CDate"] [mc "Comments"]]
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006312 set l $findcurline
Paul Mackerrascca5d942007-10-27 21:16:56 +10006313 set moretodo 0
6314 if {$find_dirn > 0} {
6315 incr l
6316 if {$l >= $numcommits} {
6317 set l 0
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006318 }
Paul Mackerrascca5d942007-10-27 21:16:56 +10006319 if {$l <= $findstartline} {
6320 set lim [expr {$findstartline + 1}]
6321 } else {
6322 set lim $numcommits
6323 set moretodo $findallowwrap
6324 }
Paul Mackerras98f350e2005-05-15 05:56:51 +00006325 } else {
Paul Mackerrascca5d942007-10-27 21:16:56 +10006326 if {$l == 0} {
6327 set l $numcommits
6328 }
6329 incr l -1
6330 if {$l >= $findstartline} {
6331 set lim [expr {$findstartline - 1}]
6332 } else {
6333 set lim -1
6334 set moretodo $findallowwrap
6335 }
Paul Mackerras98f350e2005-05-15 05:56:51 +00006336 }
Paul Mackerrascca5d942007-10-27 21:16:56 +10006337 set n [expr {($lim - $l) * $find_dirn}]
6338 if {$n > 500} {
6339 set n 500
6340 set moretodo 1
Paul Mackerras98f350e2005-05-15 05:56:51 +00006341 }
Paul Mackerrascd2bcae2008-01-02 21:44:06 +11006342 if {$l + ($find_dirn > 0? $n: 1) > $vrowmod($curview)} {
6343 update_arcrows $curview
6344 }
Paul Mackerras687c8762007-09-22 12:49:33 +10006345 set found 0
6346 set domore 1
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11006347 set ai [bsearch $vrownum($curview) $l]
6348 set a [lindex $varcorder($curview) $ai]
6349 set arow [lindex $vrownum($curview) $ai]
6350 set ids [lindex $varccommits($curview,$a)]
6351 set arowend [expr {$arow + [llength $ids]}]
Christian Stimmingb007ee22007-11-07 18:44:35 +01006352 if {$gdttype eq [mc "containing:"]} {
Paul Mackerrascca5d942007-10-27 21:16:56 +10006353 for {} {$n > 0} {incr n -1; incr l $find_dirn} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11006354 if {$l < $arow || $l >= $arowend} {
6355 incr ai $find_dirn
6356 set a [lindex $varcorder($curview) $ai]
6357 set arow [lindex $vrownum($curview) $ai]
6358 set ids [lindex $varccommits($curview,$a)]
6359 set arowend [expr {$arow + [llength $ids]}]
6360 }
6361 set id [lindex $ids [expr {$l - $arow}]]
Paul Mackerras687c8762007-09-22 12:49:33 +10006362 # shouldn't happen unless git log doesn't give all the commits...
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11006363 if {![info exists commitdata($id)] ||
6364 ![doesmatch $commitdata($id)]} {
6365 continue
6366 }
Paul Mackerras687c8762007-09-22 12:49:33 +10006367 if {![info exists commitinfo($id)]} {
6368 getcommit $id
6369 }
6370 set info $commitinfo($id)
6371 foreach f $info ty $fldtypes {
Christian Stimmingb007ee22007-11-07 18:44:35 +01006372 if {($findloc eq [mc "All fields"] || $findloc eq $ty) &&
Paul Mackerras687c8762007-09-22 12:49:33 +10006373 [doesmatch $f]} {
6374 set found 1
6375 break
6376 }
6377 }
6378 if {$found} break
Paul Mackerras98f350e2005-05-15 05:56:51 +00006379 }
Paul Mackerras687c8762007-09-22 12:49:33 +10006380 } else {
Paul Mackerrascca5d942007-10-27 21:16:56 +10006381 for {} {$n > 0} {incr n -1; incr l $find_dirn} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11006382 if {$l < $arow || $l >= $arowend} {
6383 incr ai $find_dirn
6384 set a [lindex $varcorder($curview) $ai]
6385 set arow [lindex $vrownum($curview) $ai]
6386 set ids [lindex $varccommits($curview,$a)]
6387 set arowend [expr {$arow + [llength $ids]}]
6388 }
6389 set id [lindex $ids [expr {$l - $arow}]]
Paul Mackerras476ca632008-01-07 22:16:31 +11006390 if {![info exists fhighlights($id)]} {
6391 # this sets fhighlights($id) to -1
Paul Mackerras687c8762007-09-22 12:49:33 +10006392 askfilehighlight $l $id
Paul Mackerrascd2bcae2008-01-02 21:44:06 +11006393 }
Paul Mackerras476ca632008-01-07 22:16:31 +11006394 if {$fhighlights($id) > 0} {
Paul Mackerrascd2bcae2008-01-02 21:44:06 +11006395 set found $domore
6396 break
6397 }
Paul Mackerras476ca632008-01-07 22:16:31 +11006398 if {$fhighlights($id) < 0} {
Paul Mackerras687c8762007-09-22 12:49:33 +10006399 if {$domore} {
6400 set domore 0
Paul Mackerrascca5d942007-10-27 21:16:56 +10006401 set findcurline [expr {$l - $find_dirn}]
Paul Mackerras687c8762007-09-22 12:49:33 +10006402 }
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006403 }
6404 }
6405 }
Paul Mackerrascca5d942007-10-27 21:16:56 +10006406 if {$found || ($domore && !$moretodo)} {
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006407 unset findcurline
Paul Mackerras687c8762007-09-22 12:49:33 +10006408 unset find_dirn
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006409 notbusy finding
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10006410 set fprogcoord 0
6411 adjustprogress
6412 if {$found} {
6413 findselectline $l
6414 } else {
6415 bell
6416 }
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006417 return 0
6418 }
Paul Mackerras687c8762007-09-22 12:49:33 +10006419 if {!$domore} {
6420 flushhighlights
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10006421 } else {
Paul Mackerrascca5d942007-10-27 21:16:56 +10006422 set findcurline [expr {$l - $find_dirn}]
Paul Mackerras687c8762007-09-22 12:49:33 +10006423 }
Paul Mackerrascca5d942007-10-27 21:16:56 +10006424 set n [expr {($findcurline - $findstartline) * $find_dirn - 1}]
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10006425 if {$n < 0} {
6426 incr n $numcommits
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006427 }
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10006428 set fprogcoord [expr {$n * 1.0 / $numcommits}]
6429 adjustprogress
6430 return $domore
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00006431}
6432
6433proc findselectline {l} {
Paul Mackerras687c8762007-09-22 12:49:33 +10006434 global findloc commentend ctext findcurline markingmatches gdttype
Paul Mackerras005a2f42007-07-26 22:36:39 +10006435
Paul Mackerras8b39e042008-12-02 09:02:46 +11006436 set markingmatches [expr {$gdttype eq [mc "containing:"]}]
Paul Mackerras005a2f42007-07-26 22:36:39 +10006437 set findcurline $l
Paul Mackerrasd6982062005-08-06 22:06:06 +10006438 selectline $l 1
Paul Mackerras8b39e042008-12-02 09:02:46 +11006439 if {$markingmatches &&
6440 ($findloc eq [mc "All fields"] || $findloc eq [mc "Comments"])} {
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00006441 # highlight the matches in the comments
6442 set f [$ctext get 1.0 $commentend]
6443 set matches [findmatches $f]
6444 foreach match $matches {
6445 set start [lindex $match 0]
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08006446 set end [expr {[lindex $match 1] + 1}]
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00006447 $ctext tag add found "1.0 + $start c" "1.0 + $end c"
6448 }
Paul Mackerras98f350e2005-05-15 05:56:51 +00006449 }
Paul Mackerras005a2f42007-07-26 22:36:39 +10006450 drawvisible
Paul Mackerras98f350e2005-05-15 05:56:51 +00006451}
6452
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006453# mark the bits of a headline or author that match a find string
Paul Mackerras005a2f42007-07-26 22:36:39 +10006454proc markmatches {canv l str tag matches font row} {
6455 global selectedline
6456
Paul Mackerras98f350e2005-05-15 05:56:51 +00006457 set bbox [$canv bbox $tag]
6458 set x0 [lindex $bbox 0]
6459 set y0 [lindex $bbox 1]
6460 set y1 [lindex $bbox 3]
6461 foreach match $matches {
6462 set start [lindex $match 0]
6463 set end [lindex $match 1]
6464 if {$start > $end} continue
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08006465 set xoff [font measure $font [string range $str 0 [expr {$start-1}]]]
6466 set xlen [font measure $font [string range $str 0 [expr {$end}]]]
6467 set t [$canv create rect [expr {$x0+$xoff}] $y0 \
6468 [expr {$x0+$xlen+2}] $y1 \
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006469 -outline {} -tags [list match$l matches] -fill yellow]
Paul Mackerras98f350e2005-05-15 05:56:51 +00006470 $canv lower $t
Paul Mackerras94b4a692008-05-20 20:51:06 +10006471 if {$row == $selectedline} {
Paul Mackerras005a2f42007-07-26 22:36:39 +10006472 $canv raise $t secsel
6473 }
Paul Mackerras98f350e2005-05-15 05:56:51 +00006474 }
6475}
6476
6477proc unmarkmatches {} {
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10006478 global markingmatches
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006479
Paul Mackerras98f350e2005-05-15 05:56:51 +00006480 allcanvs delete matches
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006481 set markingmatches 0
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10006482 stopfinding
Paul Mackerras98f350e2005-05-15 05:56:51 +00006483}
6484
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10006485proc selcanvline {w x y} {
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10006486 global canv canvy0 ctext linespc
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006487 global rowtextx
Paul Mackerras1db95b02005-05-09 04:08:39 +00006488 set ymax [lindex [$canv cget -scrollregion] 3]
Paul Mackerrascfb45632005-05-31 12:14:42 +00006489 if {$ymax == {}} return
Paul Mackerras1db95b02005-05-09 04:08:39 +00006490 set yfrac [lindex [$canv yview] 0]
6491 set y [expr {$y + $yfrac * $ymax}]
6492 set l [expr {int(($y - $canvy0) / $linespc + 0.5)}]
6493 if {$l < 0} {
6494 set l 0
6495 }
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10006496 if {$w eq $canv} {
Paul Mackerrasfc2a2562007-12-26 23:03:43 +11006497 set xmax [lindex [$canv cget -scrollregion] 2]
6498 set xleft [expr {[lindex [$canv xview] 0] * $xmax}]
6499 if {![info exists rowtextx($l)] || $xleft + $x < $rowtextx($l)} return
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10006500 }
Paul Mackerras98f350e2005-05-15 05:56:51 +00006501 unmarkmatches
Paul Mackerrasd6982062005-08-06 22:06:06 +10006502 selectline $l 1
Paul Mackerras5ad588d2005-05-10 01:02:55 +00006503}
6504
Linus Torvaldsb1ba39e2005-08-08 20:04:20 -07006505proc commit_descriptor {p} {
6506 global commitinfo
Paul Mackerrasb0934482006-05-15 09:56:08 +10006507 if {![info exists commitinfo($p)]} {
6508 getcommit $p
6509 }
Linus Torvaldsb1ba39e2005-08-08 20:04:20 -07006510 set l "..."
Paul Mackerrasb0934482006-05-15 09:56:08 +10006511 if {[llength $commitinfo($p)] > 1} {
Linus Torvaldsb1ba39e2005-08-08 20:04:20 -07006512 set l [lindex $commitinfo($p) 0]
6513 }
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10006514 return "$p ($l)\n"
Linus Torvaldsb1ba39e2005-08-08 20:04:20 -07006515}
6516
Paul Mackerras106288c2005-08-19 23:11:39 +10006517# append some text to the ctext widget, and make any SHA1 ID
6518# that we know about be a clickable link.
Sergey Vlasovf1b86292006-05-15 19:13:14 +04006519proc appendwithlinks {text tags} {
Paul Mackerrasd375ef92008-10-21 10:18:12 +11006520 global ctext linknum curview
Paul Mackerras106288c2005-08-19 23:11:39 +10006521
6522 set start [$ctext index "end - 1c"]
Sergey Vlasovf1b86292006-05-15 19:13:14 +04006523 $ctext insert end $text $tags
Paul Mackerrasd375ef92008-10-21 10:18:12 +11006524 set links [regexp -indices -all -inline {\m[0-9a-f]{6,40}\M} $text]
Paul Mackerras106288c2005-08-19 23:11:39 +10006525 foreach l $links {
6526 set s [lindex $l 0]
6527 set e [lindex $l 1]
6528 set linkid [string range $text $s $e]
Paul Mackerras106288c2005-08-19 23:11:39 +10006529 incr e
Paul Mackerrasc73adce2007-09-27 10:35:05 +10006530 $ctext tag delete link$linknum
Paul Mackerras106288c2005-08-19 23:11:39 +10006531 $ctext tag add link$linknum "$start + $s c" "$start + $e c"
Paul Mackerras97645682007-08-23 22:24:38 +10006532 setlink $linkid link$linknum
Paul Mackerras106288c2005-08-19 23:11:39 +10006533 incr linknum
6534 }
Paul Mackerras97645682007-08-23 22:24:38 +10006535}
6536
6537proc setlink {id lk} {
Paul Mackerrasd375ef92008-10-21 10:18:12 +11006538 global curview ctext pendinglinks
Paul Mackerras97645682007-08-23 22:24:38 +10006539
Paul Mackerrasd375ef92008-10-21 10:18:12 +11006540 set known 0
6541 if {[string length $id] < 40} {
6542 set matches [longid $id]
6543 if {[llength $matches] > 0} {
6544 if {[llength $matches] > 1} return
6545 set known 1
6546 set id [lindex $matches 0]
6547 }
6548 } else {
6549 set known [commitinview $id $curview]
6550 }
6551 if {$known} {
Paul Mackerras97645682007-08-23 22:24:38 +10006552 $ctext tag conf $lk -foreground blue -underline 1
Paul Mackerrasd375ef92008-10-21 10:18:12 +11006553 $ctext tag bind $lk <1> [list selbyid $id]
Paul Mackerras97645682007-08-23 22:24:38 +10006554 $ctext tag bind $lk <Enter> {linkcursor %W 1}
6555 $ctext tag bind $lk <Leave> {linkcursor %W -1}
6556 } else {
6557 lappend pendinglinks($id) $lk
Paul Mackerrasd375ef92008-10-21 10:18:12 +11006558 interestedin $id {makelink %P}
Paul Mackerras97645682007-08-23 22:24:38 +10006559 }
6560}
6561
Paul Mackerras6f63fc12009-04-21 22:22:31 +10006562proc appendshortlink {id {pre {}} {post {}}} {
6563 global ctext linknum
6564
6565 $ctext insert end $pre
6566 $ctext tag delete link$linknum
6567 $ctext insert end [string range $id 0 7] link$linknum
6568 $ctext insert end $post
6569 setlink $id link$linknum
6570 incr linknum
6571}
6572
Paul Mackerras97645682007-08-23 22:24:38 +10006573proc makelink {id} {
6574 global pendinglinks
6575
6576 if {![info exists pendinglinks($id)]} return
6577 foreach lk $pendinglinks($id) {
6578 setlink $id $lk
6579 }
6580 unset pendinglinks($id)
6581}
6582
6583proc linkcursor {w inc} {
6584 global linkentercount curtextcursor
6585
6586 if {[incr linkentercount $inc] > 0} {
6587 $w configure -cursor hand2
6588 } else {
6589 $w configure -cursor $curtextcursor
6590 if {$linkentercount < 0} {
6591 set linkentercount 0
6592 }
6593 }
Paul Mackerras106288c2005-08-19 23:11:39 +10006594}
6595
Rutger Nijlunsing6e5f7202006-04-05 10:24:03 +10006596proc viewnextline {dir} {
6597 global canv linespc
6598
6599 $canv delete hover
6600 set ymax [lindex [$canv cget -scrollregion] 3]
6601 set wnow [$canv yview]
6602 set wtop [expr {[lindex $wnow 0] * $ymax}]
6603 set newtop [expr {$wtop + $dir * $linespc}]
6604 if {$newtop < 0} {
6605 set newtop 0
6606 } elseif {$newtop > $ymax} {
6607 set newtop $ymax
6608 }
6609 allcanvs yview moveto [expr {$newtop * 1.0 / $ymax}]
6610}
6611
Paul Mackerrasef030b82006-06-04 11:50:38 +10006612# add a list of tag or branch names at position pos
6613# returns the number of names inserted
Paul Mackerrase11f1232007-06-16 20:29:25 +10006614proc appendrefs {pos ids var} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11006615 global ctext linknum curview $var maxrefs
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10006616
Paul Mackerrasef030b82006-06-04 11:50:38 +10006617 if {[catch {$ctext index $pos}]} {
6618 return 0
6619 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10006620 $ctext conf -state normal
6621 $ctext delete $pos "$pos lineend"
6622 set tags {}
6623 foreach id $ids {
6624 foreach tag [set $var\($id\)] {
6625 lappend tags [list $tag $id]
6626 }
6627 }
Paul Mackerras0a4dd8b2007-06-16 21:21:57 +10006628 if {[llength $tags] > $maxrefs} {
Christian Stimming84b4b832009-03-26 21:13:45 +01006629 $ctext insert $pos "[mc "many"] ([llength $tags])"
Paul Mackerras0a4dd8b2007-06-16 21:21:57 +10006630 } else {
6631 set tags [lsort -index 0 -decreasing $tags]
6632 set sep {}
6633 foreach ti $tags {
6634 set id [lindex $ti 1]
6635 set lk link$linknum
6636 incr linknum
6637 $ctext tag delete $lk
6638 $ctext insert $pos $sep
6639 $ctext insert $pos [lindex $ti 0] $lk
Paul Mackerras97645682007-08-23 22:24:38 +10006640 setlink $id $lk
Paul Mackerras0a4dd8b2007-06-16 21:21:57 +10006641 set sep ", "
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10006642 }
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10006643 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10006644 $ctext conf -state disabled
Paul Mackerrasef030b82006-06-04 11:50:38 +10006645 return [llength $tags]
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10006646}
6647
6648# called when we have finished computing the nearby tags
Paul Mackerrase11f1232007-06-16 20:29:25 +10006649proc dispneartags {delay} {
6650 global selectedline currentid showneartags tagphase
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10006651
Paul Mackerras94b4a692008-05-20 20:51:06 +10006652 if {$selectedline eq {} || !$showneartags} return
Paul Mackerrase11f1232007-06-16 20:29:25 +10006653 after cancel dispnexttag
6654 if {$delay} {
6655 after 200 dispnexttag
6656 set tagphase -1
6657 } else {
6658 after idle dispnexttag
6659 set tagphase 0
6660 }
6661}
6662
6663proc dispnexttag {} {
6664 global selectedline currentid showneartags tagphase ctext
6665
Paul Mackerras94b4a692008-05-20 20:51:06 +10006666 if {$selectedline eq {} || !$showneartags} return
Paul Mackerrase11f1232007-06-16 20:29:25 +10006667 switch -- $tagphase {
6668 0 {
6669 set dtags [desctags $currentid]
6670 if {$dtags ne {}} {
6671 appendrefs precedes $dtags idtags
6672 }
6673 }
6674 1 {
6675 set atags [anctags $currentid]
6676 if {$atags ne {}} {
6677 appendrefs follows $atags idtags
6678 }
6679 }
6680 2 {
6681 set dheads [descheads $currentid]
6682 if {$dheads ne {}} {
6683 if {[appendrefs branch $dheads idheads] > 1
6684 && [$ctext get "branch -3c"] eq "h"} {
6685 # turn "Branch" into "Branches"
6686 $ctext conf -state normal
6687 $ctext insert "branch -2c" "es"
6688 $ctext conf -state disabled
6689 }
6690 }
Paul Mackerrasef030b82006-06-04 11:50:38 +10006691 }
6692 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10006693 if {[incr tagphase] <= 2} {
6694 after idle dispnexttag
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10006695 }
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10006696}
6697
Paul Mackerras28593d32008-11-13 23:01:46 +11006698proc make_secsel {id} {
Paul Mackerras03800812007-08-29 21:45:21 +10006699 global linehtag linentag linedtag canv canv2 canv3
6700
Paul Mackerras28593d32008-11-13 23:01:46 +11006701 if {![info exists linehtag($id)]} return
Paul Mackerras03800812007-08-29 21:45:21 +10006702 $canv delete secsel
Paul Mackerras28593d32008-11-13 23:01:46 +11006703 set t [eval $canv create rect [$canv bbox $linehtag($id)] -outline {{}} \
Paul Mackerras03800812007-08-29 21:45:21 +10006704 -tags secsel -fill [$canv cget -selectbackground]]
6705 $canv lower $t
6706 $canv2 delete secsel
Paul Mackerras28593d32008-11-13 23:01:46 +11006707 set t [eval $canv2 create rect [$canv2 bbox $linentag($id)] -outline {{}} \
Paul Mackerras03800812007-08-29 21:45:21 +10006708 -tags secsel -fill [$canv2 cget -selectbackground]]
6709 $canv2 lower $t
6710 $canv3 delete secsel
Paul Mackerras28593d32008-11-13 23:01:46 +11006711 set t [eval $canv3 create rect [$canv3 bbox $linedtag($id)] -outline {{}} \
Paul Mackerras03800812007-08-29 21:45:21 +10006712 -tags secsel -fill [$canv3 cget -selectbackground]]
6713 $canv3 lower $t
6714}
6715
Paul Mackerrasb9fdba72009-04-09 09:34:46 +10006716proc make_idmark {id} {
6717 global linehtag canv fgcolor
6718
6719 if {![info exists linehtag($id)]} return
6720 $canv delete markid
6721 set t [eval $canv create rect [$canv bbox $linehtag($id)] \
6722 -tags markid -outline $fgcolor]
6723 $canv raise $t
6724}
6725
Paul Mackerras8a897742008-10-27 21:36:25 +11006726proc selectline {l isnew {desired_loc {}}} {
Paul Mackerras03800812007-08-29 21:45:21 +10006727 global canv ctext commitinfo selectedline
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11006728 global canvy0 linespc parents children curview
Paul Mackerras7fcceed2006-04-27 19:21:49 +10006729 global currentid sha1entry
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006730 global commentend idtags linknum
Paul Mackerrasd94f8cd2006-04-06 10:18:23 +10006731 global mergemax numcommits pending_select
Paul Mackerrase11f1232007-06-16 20:29:25 +10006732 global cmitmode showneartags allcommits
Paul Mackerrasc30acc72008-03-07 22:51:55 +11006733 global targetrow targetid lastscrollrows
Paul Mackerras8a897742008-10-27 21:36:25 +11006734 global autoselect jump_to_here
Paul Mackerrasd6982062005-08-06 22:06:06 +10006735
Paul Mackerrasd94f8cd2006-04-06 10:18:23 +10006736 catch {unset pending_select}
Paul Mackerras84ba7342005-06-17 00:12:26 +00006737 $canv delete hover
Paul Mackerras9843c302005-08-30 10:57:11 +10006738 normalline
Paul Mackerras887c9962007-08-20 19:36:20 +10006739 unsel_reflist
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10006740 stopfinding
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11006741 if {$l < 0 || $l >= $numcommits} return
Paul Mackerrasac1276a2008-03-03 10:11:08 +11006742 set id [commitonrow $l]
6743 set targetid $id
6744 set targetrow $l
Paul Mackerrasc30acc72008-03-07 22:51:55 +11006745 set selectedline $l
6746 set currentid $id
6747 if {$lastscrollrows < $numcommits} {
6748 setcanvscroll
6749 }
Paul Mackerrasac1276a2008-03-03 10:11:08 +11006750
Paul Mackerras5ad588d2005-05-10 01:02:55 +00006751 set y [expr {$canvy0 + $l * $linespc}]
Paul Mackerras17386062005-05-18 22:51:00 +00006752 set ymax [lindex [$canv cget -scrollregion] 3]
Paul Mackerras58422152005-05-19 10:56:42 +00006753 set ytop [expr {$y - $linespc - 1}]
6754 set ybot [expr {$y + $linespc + 1}]
Paul Mackerras5ad588d2005-05-10 01:02:55 +00006755 set wnow [$canv yview]
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08006756 set wtop [expr {[lindex $wnow 0] * $ymax}]
6757 set wbot [expr {[lindex $wnow 1] * $ymax}]
Paul Mackerras58422152005-05-19 10:56:42 +00006758 set wh [expr {$wbot - $wtop}]
6759 set newtop $wtop
Paul Mackerras17386062005-05-18 22:51:00 +00006760 if {$ytop < $wtop} {
Paul Mackerras58422152005-05-19 10:56:42 +00006761 if {$ybot < $wtop} {
6762 set newtop [expr {$y - $wh / 2.0}]
6763 } else {
6764 set newtop $ytop
6765 if {$newtop > $wtop - $linespc} {
6766 set newtop [expr {$wtop - $linespc}]
6767 }
Paul Mackerras17386062005-05-18 22:51:00 +00006768 }
Paul Mackerras58422152005-05-19 10:56:42 +00006769 } elseif {$ybot > $wbot} {
6770 if {$ytop > $wbot} {
6771 set newtop [expr {$y - $wh / 2.0}]
6772 } else {
6773 set newtop [expr {$ybot - $wh}]
6774 if {$newtop < $wtop + $linespc} {
6775 set newtop [expr {$wtop + $linespc}]
6776 }
Paul Mackerras17386062005-05-18 22:51:00 +00006777 }
Paul Mackerras58422152005-05-19 10:56:42 +00006778 }
6779 if {$newtop != $wtop} {
6780 if {$newtop < 0} {
6781 set newtop 0
6782 }
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08006783 allcanvs yview moveto [expr {$newtop * 1.0 / $ymax}]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006784 drawvisible
Paul Mackerras5ad588d2005-05-10 01:02:55 +00006785 }
Paul Mackerrasd6982062005-08-06 22:06:06 +10006786
Paul Mackerras28593d32008-11-13 23:01:46 +11006787 make_secsel $id
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006788
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10006789 if {$isnew} {
Paul Mackerrasfc2a2562007-12-26 23:03:43 +11006790 addtohistory [list selbyid $id]
Paul Mackerrasd6982062005-08-06 22:06:06 +10006791 }
6792
Paul Mackerras98f350e2005-05-15 05:56:51 +00006793 $sha1entry delete 0 end
6794 $sha1entry insert 0 $id
Jeff King95293b52008-03-06 06:49:25 -05006795 if {$autoselect} {
6796 $sha1entry selection from 0
6797 $sha1entry selection to end
6798 }
Paul Mackerras164ff272006-05-29 19:50:02 +10006799 rhighlight_sel $id
Paul Mackerras98f350e2005-05-15 05:56:51 +00006800
Paul Mackerras5ad588d2005-05-10 01:02:55 +00006801 $ctext conf -state normal
Paul Mackerras3ea06f92006-05-24 10:16:03 +10006802 clear_ctext
Paul Mackerras106288c2005-08-19 23:11:39 +10006803 set linknum 0
Paul Mackerrasd76afb12008-03-07 21:19:18 +11006804 if {![info exists commitinfo($id)]} {
6805 getcommit $id
6806 }
Paul Mackerras1db95b02005-05-09 04:08:39 +00006807 set info $commitinfo($id)
Paul Mackerras232475d2005-11-15 10:34:03 +11006808 set date [formatdate [lindex $info 2]]
Christian Stimmingd990ced2007-11-07 18:42:55 +01006809 $ctext insert end "[mc "Author"]: [lindex $info 1] $date\n"
Paul Mackerras232475d2005-11-15 10:34:03 +11006810 set date [formatdate [lindex $info 4]]
Christian Stimmingd990ced2007-11-07 18:42:55 +01006811 $ctext insert end "[mc "Committer"]: [lindex $info 3] $date\n"
Paul Mackerras887fe3c2005-05-21 07:35:37 +00006812 if {[info exists idtags($id)]} {
Christian Stimmingd990ced2007-11-07 18:42:55 +01006813 $ctext insert end [mc "Tags:"]
Paul Mackerras887fe3c2005-05-21 07:35:37 +00006814 foreach tag $idtags($id) {
6815 $ctext insert end " $tag"
6816 }
6817 $ctext insert end "\n"
6818 }
Mark Levedahl40b87ff2007-02-01 08:44:46 -05006819
Sergey Vlasovf1b86292006-05-15 19:13:14 +04006820 set headers {}
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11006821 set olds $parents($curview,$id)
Paul Mackerras79b2c752006-04-02 20:47:40 +10006822 if {[llength $olds] > 1} {
Paul Mackerrasb77b0272006-02-07 09:13:52 +11006823 set np 0
Paul Mackerras79b2c752006-04-02 20:47:40 +10006824 foreach p $olds {
Paul Mackerrasb77b0272006-02-07 09:13:52 +11006825 if {$np >= $mergemax} {
6826 set tag mmax
6827 } else {
6828 set tag m$np
6829 }
Christian Stimmingd990ced2007-11-07 18:42:55 +01006830 $ctext insert end "[mc "Parent"]: " $tag
Sergey Vlasovf1b86292006-05-15 19:13:14 +04006831 appendwithlinks [commit_descriptor $p] {}
Paul Mackerrasb77b0272006-02-07 09:13:52 +11006832 incr np
6833 }
6834 } else {
Paul Mackerras79b2c752006-04-02 20:47:40 +10006835 foreach p $olds {
Christian Stimmingd990ced2007-11-07 18:42:55 +01006836 append headers "[mc "Parent"]: [commit_descriptor $p]"
Linus Torvalds8b192802005-08-07 13:58:56 -07006837 }
Linus Torvaldsb1ba39e2005-08-08 20:04:20 -07006838 }
Paul Mackerrasb77b0272006-02-07 09:13:52 +11006839
Paul Mackerras6a90bff2007-06-18 09:48:23 +10006840 foreach c $children($curview,$id) {
Christian Stimmingd990ced2007-11-07 18:42:55 +01006841 append headers "[mc "Child"]: [commit_descriptor $c]"
Linus Torvalds8b192802005-08-07 13:58:56 -07006842 }
Paul Mackerrasd6982062005-08-06 22:06:06 +10006843
6844 # make anything that looks like a SHA1 ID be a clickable link
Sergey Vlasovf1b86292006-05-15 19:13:14 +04006845 appendwithlinks $headers {}
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10006846 if {$showneartags} {
6847 if {![info exists allcommits]} {
6848 getallcommits
6849 }
Christian Stimmingd990ced2007-11-07 18:42:55 +01006850 $ctext insert end "[mc "Branch"]: "
Paul Mackerrasef030b82006-06-04 11:50:38 +10006851 $ctext mark set branch "end -1c"
6852 $ctext mark gravity branch left
Christian Stimmingd990ced2007-11-07 18:42:55 +01006853 $ctext insert end "\n[mc "Follows"]: "
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10006854 $ctext mark set follows "end -1c"
6855 $ctext mark gravity follows left
Christian Stimmingd990ced2007-11-07 18:42:55 +01006856 $ctext insert end "\n[mc "Precedes"]: "
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10006857 $ctext mark set precedes "end -1c"
6858 $ctext mark gravity precedes left
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10006859 $ctext insert end "\n"
Paul Mackerrase11f1232007-06-16 20:29:25 +10006860 dispneartags 1
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10006861 }
6862 $ctext insert end "\n"
Paul Mackerras43c25072006-09-27 10:56:02 +10006863 set comment [lindex $info 5]
6864 if {[string first "\r" $comment] >= 0} {
6865 set comment [string map {"\r" "\n "} $comment]
6866 }
6867 appendwithlinks $comment {comment}
Paul Mackerrasd6982062005-08-06 22:06:06 +10006868
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00006869 $ctext tag remove found 1.0 end
Paul Mackerras5ad588d2005-05-10 01:02:55 +00006870 $ctext conf -state disabled
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00006871 set commentend [$ctext index "end - 1c"]
Paul Mackerras5ad588d2005-05-10 01:02:55 +00006872
Paul Mackerras8a897742008-10-27 21:36:25 +11006873 set jump_to_here $desired_loc
Christian Stimmingb007ee22007-11-07 18:44:35 +01006874 init_flist [mc "Comments"]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10006875 if {$cmitmode eq "tree"} {
6876 gettree $id
6877 } elseif {[llength $olds] <= 1} {
Paul Mackerrasd3272442005-11-28 20:41:56 +11006878 startdiff $id
Paul Mackerras7b5ff7e2006-03-30 20:50:40 +11006879 } else {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11006880 mergediff $id
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10006881 }
6882}
6883
Rutger Nijlunsing6e5f7202006-04-05 10:24:03 +10006884proc selfirstline {} {
6885 unmarkmatches
6886 selectline 0 1
6887}
6888
6889proc sellastline {} {
6890 global numcommits
6891 unmarkmatches
6892 set l [expr {$numcommits - 1}]
6893 selectline $l 1
6894}
6895
Paul Mackerrase5c2d852005-05-11 23:44:54 +00006896proc selnextline {dir} {
6897 global selectedline
Mark Levedahlbd441de2007-08-07 21:40:34 -04006898 focus .
Paul Mackerras94b4a692008-05-20 20:51:06 +10006899 if {$selectedline eq {}} return
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08006900 set l [expr {$selectedline + $dir}]
Paul Mackerras98f350e2005-05-15 05:56:51 +00006901 unmarkmatches
Paul Mackerrasd6982062005-08-06 22:06:06 +10006902 selectline $l 1
6903}
6904
Rutger Nijlunsing6e5f7202006-04-05 10:24:03 +10006905proc selnextpage {dir} {
6906 global canv linespc selectedline numcommits
6907
6908 set lpp [expr {([winfo height $canv] - 2) / $linespc}]
6909 if {$lpp < 1} {
6910 set lpp 1
6911 }
6912 allcanvs yview scroll [expr {$dir * $lpp}] units
Paul Mackerrase72ee5e2006-05-20 09:58:49 +10006913 drawvisible
Paul Mackerras94b4a692008-05-20 20:51:06 +10006914 if {$selectedline eq {}} return
Rutger Nijlunsing6e5f7202006-04-05 10:24:03 +10006915 set l [expr {$selectedline + $dir * $lpp}]
6916 if {$l < 0} {
6917 set l 0
6918 } elseif {$l >= $numcommits} {
6919 set l [expr $numcommits - 1]
6920 }
6921 unmarkmatches
Mark Levedahl40b87ff2007-02-01 08:44:46 -05006922 selectline $l 1
Rutger Nijlunsing6e5f7202006-04-05 10:24:03 +10006923}
6924
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10006925proc unselectline {} {
Paul Mackerras50b44ec2006-04-04 10:16:22 +10006926 global selectedline currentid
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10006927
Paul Mackerras94b4a692008-05-20 20:51:06 +10006928 set selectedline {}
Paul Mackerras50b44ec2006-04-04 10:16:22 +10006929 catch {unset currentid}
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10006930 allcanvs delete secsel
Paul Mackerras164ff272006-05-29 19:50:02 +10006931 rhighlight_none
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10006932}
6933
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10006934proc reselectline {} {
6935 global selectedline
6936
Paul Mackerras94b4a692008-05-20 20:51:06 +10006937 if {$selectedline ne {}} {
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10006938 selectline $selectedline 0
6939 }
6940}
6941
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10006942proc addtohistory {cmd} {
Paul Mackerras2516dae2006-04-21 10:35:31 +10006943 global history historyindex curview
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10006944
Paul Mackerras2516dae2006-04-21 10:35:31 +10006945 set elt [list $curview $cmd]
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10006946 if {$historyindex > 0
Paul Mackerras2516dae2006-04-21 10:35:31 +10006947 && [lindex $history [expr {$historyindex - 1}]] == $elt} {
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10006948 return
6949 }
6950
6951 if {$historyindex < [llength $history]} {
Paul Mackerras2516dae2006-04-21 10:35:31 +10006952 set history [lreplace $history $historyindex end $elt]
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10006953 } else {
Paul Mackerras2516dae2006-04-21 10:35:31 +10006954 lappend history $elt
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10006955 }
6956 incr historyindex
6957 if {$historyindex > 1} {
Junio C Hamanoe9937d22007-02-01 08:46:38 -05006958 .tf.bar.leftbut conf -state normal
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10006959 } else {
Junio C Hamanoe9937d22007-02-01 08:46:38 -05006960 .tf.bar.leftbut conf -state disabled
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10006961 }
Junio C Hamanoe9937d22007-02-01 08:46:38 -05006962 .tf.bar.rightbut conf -state disabled
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10006963}
6964
Paul Mackerras2516dae2006-04-21 10:35:31 +10006965proc godo {elt} {
6966 global curview
6967
6968 set view [lindex $elt 0]
6969 set cmd [lindex $elt 1]
6970 if {$curview != $view} {
6971 showview $view
6972 }
6973 eval $cmd
6974}
6975
Paul Mackerrasd6982062005-08-06 22:06:06 +10006976proc goback {} {
6977 global history historyindex
Mark Levedahlbd441de2007-08-07 21:40:34 -04006978 focus .
Paul Mackerrasd6982062005-08-06 22:06:06 +10006979
6980 if {$historyindex > 1} {
6981 incr historyindex -1
Paul Mackerras2516dae2006-04-21 10:35:31 +10006982 godo [lindex $history [expr {$historyindex - 1}]]
Junio C Hamanoe9937d22007-02-01 08:46:38 -05006983 .tf.bar.rightbut conf -state normal
Paul Mackerrasd6982062005-08-06 22:06:06 +10006984 }
6985 if {$historyindex <= 1} {
Junio C Hamanoe9937d22007-02-01 08:46:38 -05006986 .tf.bar.leftbut conf -state disabled
Paul Mackerrasd6982062005-08-06 22:06:06 +10006987 }
6988}
6989
6990proc goforw {} {
6991 global history historyindex
Mark Levedahlbd441de2007-08-07 21:40:34 -04006992 focus .
Paul Mackerrasd6982062005-08-06 22:06:06 +10006993
6994 if {$historyindex < [llength $history]} {
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10006995 set cmd [lindex $history $historyindex]
Paul Mackerrasd6982062005-08-06 22:06:06 +10006996 incr historyindex
Paul Mackerras2516dae2006-04-21 10:35:31 +10006997 godo $cmd
Junio C Hamanoe9937d22007-02-01 08:46:38 -05006998 .tf.bar.leftbut conf -state normal
Paul Mackerrasd6982062005-08-06 22:06:06 +10006999 }
7000 if {$historyindex >= [llength $history]} {
Junio C Hamanoe9937d22007-02-01 08:46:38 -05007001 .tf.bar.rightbut conf -state disabled
Paul Mackerrasd6982062005-08-06 22:06:06 +10007002 }
Paul Mackerras5ad588d2005-05-10 01:02:55 +00007003}
7004
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007005proc gettree {id} {
Paul Mackerras8f489362007-07-13 19:49:37 +10007006 global treefilelist treeidlist diffids diffmergeid treepending
7007 global nullid nullid2
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007008
7009 set diffids $id
7010 catch {unset diffmergeid}
7011 if {![info exists treefilelist($id)]} {
7012 if {![info exists treepending]} {
Paul Mackerras8f489362007-07-13 19:49:37 +10007013 if {$id eq $nullid} {
7014 set cmd [list | git ls-files]
7015 } elseif {$id eq $nullid2} {
7016 set cmd [list | git ls-files --stage -t]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007017 } else {
Paul Mackerras8f489362007-07-13 19:49:37 +10007018 set cmd [list | git ls-tree -r $id]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007019 }
7020 if {[catch {set gtf [open $cmd r]}]} {
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007021 return
7022 }
7023 set treepending $id
7024 set treefilelist($id) {}
7025 set treeidlist($id) {}
Alexander Gavrilov09c70292008-10-13 12:12:31 +04007026 fconfigure $gtf -blocking 0 -encoding binary
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007027 filerun $gtf [list gettreeline $gtf $id]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007028 }
7029 } else {
7030 setfilelist $id
7031 }
7032}
7033
7034proc gettreeline {gtf id} {
Paul Mackerras8f489362007-07-13 19:49:37 +10007035 global treefilelist treeidlist treepending cmitmode diffids nullid nullid2
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007036
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007037 set nl 0
7038 while {[incr nl] <= 1000 && [gets $gtf line] >= 0} {
Paul Mackerras8f489362007-07-13 19:49:37 +10007039 if {$diffids eq $nullid} {
7040 set fname $line
7041 } else {
Paul Mackerras9396cd32007-06-23 20:28:15 +10007042 set i [string first "\t" $line]
7043 if {$i < 0} continue
Paul Mackerras9396cd32007-06-23 20:28:15 +10007044 set fname [string range $line [expr {$i+1}] end]
Paul Mackerrasf31fa2c2008-04-28 09:40:50 +10007045 set line [string range $line 0 [expr {$i-1}]]
7046 if {$diffids ne $nullid2 && [lindex $line 1] ne "blob"} continue
7047 set sha1 [lindex $line 2]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007048 lappend treeidlist($id) $sha1
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007049 }
Alexander Gavrilov09c70292008-10-13 12:12:31 +04007050 if {[string index $fname 0] eq "\""} {
7051 set fname [lindex $fname 0]
7052 }
7053 set fname [encoding convertfrom $fname]
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007054 lappend treefilelist($id) $fname
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007055 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007056 if {![eof $gtf]} {
7057 return [expr {$nl >= 1000? 2: 1}]
7058 }
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007059 close $gtf
7060 unset treepending
7061 if {$cmitmode ne "tree"} {
7062 if {![info exists diffmergeid]} {
7063 gettreediffs $diffids
7064 }
7065 } elseif {$id ne $diffids} {
7066 gettree $diffids
7067 } else {
7068 setfilelist $id
7069 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007070 return 0
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007071}
7072
7073proc showfile {f} {
Paul Mackerras8f489362007-07-13 19:49:37 +10007074 global treefilelist treeidlist diffids nullid nullid2
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04007075 global ctext_file_names ctext_file_lines
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007076 global ctext commentend
7077
7078 set i [lsearch -exact $treefilelist($diffids) $f]
7079 if {$i < 0} {
7080 puts "oops, $f not in list for id $diffids"
7081 return
7082 }
Paul Mackerras8f489362007-07-13 19:49:37 +10007083 if {$diffids eq $nullid} {
7084 if {[catch {set bf [open $f r]} err]} {
7085 puts "oops, can't read $f: $err"
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007086 return
7087 }
7088 } else {
Paul Mackerras8f489362007-07-13 19:49:37 +10007089 set blob [lindex $treeidlist($diffids) $i]
7090 if {[catch {set bf [open [concat | git cat-file blob $blob] r]} err]} {
7091 puts "oops, error reading blob $blob: $err"
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007092 return
7093 }
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007094 }
Alexander Gavrilov09c70292008-10-13 12:12:31 +04007095 fconfigure $bf -blocking 0 -encoding [get_path_encoding $f]
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007096 filerun $bf [list getblobline $bf $diffids]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007097 $ctext config -state normal
Paul Mackerras3ea06f92006-05-24 10:16:03 +10007098 clear_ctext $commentend
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04007099 lappend ctext_file_names $f
7100 lappend ctext_file_lines [lindex [split $commentend "."] 0]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007101 $ctext insert end "\n"
7102 $ctext insert end "$f\n" filesep
7103 $ctext config -state disabled
7104 $ctext yview $commentend
Paul Mackerras32f1b3e2007-09-28 21:27:39 +10007105 settabs 0
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007106}
7107
7108proc getblobline {bf id} {
7109 global diffids cmitmode ctext
7110
7111 if {$id ne $diffids || $cmitmode ne "tree"} {
7112 catch {close $bf}
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007113 return 0
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007114 }
7115 $ctext config -state normal
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007116 set nl 0
7117 while {[incr nl] <= 1000 && [gets $bf line] >= 0} {
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007118 $ctext insert end "$line\n"
7119 }
7120 if {[eof $bf]} {
Paul Mackerras8a897742008-10-27 21:36:25 +11007121 global jump_to_here ctext_file_names commentend
7122
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007123 # delete last newline
7124 $ctext delete "end - 2c" "end - 1c"
7125 close $bf
Paul Mackerras8a897742008-10-27 21:36:25 +11007126 if {$jump_to_here ne {} &&
7127 [lindex $jump_to_here 0] eq [lindex $ctext_file_names 0]} {
7128 set lnum [expr {[lindex $jump_to_here 1] +
7129 [lindex [split $commentend .] 0]}]
7130 mark_ctext_line $lnum
7131 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007132 return 0
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007133 }
7134 $ctext config -state disabled
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007135 return [expr {$nl >= 1000? 2: 1}]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007136}
7137
Paul Mackerras8a897742008-10-27 21:36:25 +11007138proc mark_ctext_line {lnum} {
Paul Mackerrase3e901b2008-10-27 22:37:21 +11007139 global ctext markbgcolor
Paul Mackerras8a897742008-10-27 21:36:25 +11007140
7141 $ctext tag delete omark
7142 $ctext tag add omark $lnum.0 "$lnum.0 + 1 line"
Paul Mackerrase3e901b2008-10-27 22:37:21 +11007143 $ctext tag conf omark -background $markbgcolor
Paul Mackerras8a897742008-10-27 21:36:25 +11007144 $ctext see $lnum.0
7145}
7146
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11007147proc mergediff {id} {
Paul Mackerras8b07dca2008-11-02 22:34:47 +11007148 global diffmergeid
Alexander Gavrilov2df64422008-10-08 11:05:37 +04007149 global diffids treediffs
Paul Mackerras8b07dca2008-11-02 22:34:47 +11007150 global parents curview
Paul Mackerrase2ed4322005-07-17 03:39:44 -04007151
Paul Mackerras3c461ff2005-07-20 09:13:46 -04007152 set diffmergeid $id
Paul Mackerras7a1d9d12006-03-22 10:21:45 +11007153 set diffids $id
Alexander Gavrilov2df64422008-10-08 11:05:37 +04007154 set treediffs($id) {}
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11007155 set np [llength $parents($curview,$id)]
Paul Mackerras32f1b3e2007-09-28 21:27:39 +10007156 settabs $np
Paul Mackerras8b07dca2008-11-02 22:34:47 +11007157 getblobdiffs $id
Paul Mackerrasc8a4acb2005-07-29 09:23:03 -05007158}
7159
Paul Mackerras3c461ff2005-07-20 09:13:46 -04007160proc startdiff {ids} {
Paul Mackerras8f489362007-07-13 19:49:37 +10007161 global treediffs diffids treepending diffmergeid nullid nullid2
Paul Mackerras3c461ff2005-07-20 09:13:46 -04007162
Paul Mackerras32f1b3e2007-09-28 21:27:39 +10007163 settabs 1
Paul Mackerras3c461ff2005-07-20 09:13:46 -04007164 set diffids $ids
7165 catch {unset diffmergeid}
Paul Mackerras8f489362007-07-13 19:49:37 +10007166 if {![info exists treediffs($ids)] ||
7167 [lsearch -exact $ids $nullid] >= 0 ||
7168 [lsearch -exact $ids $nullid2] >= 0} {
Paul Mackerras3c461ff2005-07-20 09:13:46 -04007169 if {![info exists treepending]} {
7170 gettreediffs $ids
7171 }
7172 } else {
7173 addtocflist $ids
7174 }
7175}
7176
Paul Mackerras7a39a172007-10-23 10:15:11 +10007177proc path_filter {filter name} {
7178 foreach p $filter {
7179 set l [string length $p]
Paul Mackerras74a40c72007-10-24 10:16:56 +10007180 if {[string index $p end] eq "/"} {
7181 if {[string compare -length $l $p $name] == 0} {
7182 return 1
7183 }
7184 } else {
7185 if {[string compare -length $l $p $name] == 0 &&
7186 ([string length $name] == $l ||
7187 [string index $name $l] eq "/")} {
7188 return 1
7189 }
Paul Mackerras7a39a172007-10-23 10:15:11 +10007190 }
7191 }
7192 return 0
7193}
7194
Paul Mackerras3c461ff2005-07-20 09:13:46 -04007195proc addtocflist {ids} {
Paul Mackerras74a40c72007-10-24 10:16:56 +10007196 global treediffs
Paul Mackerras7a39a172007-10-23 10:15:11 +10007197
Paul Mackerras74a40c72007-10-24 10:16:56 +10007198 add_flist $treediffs($ids)
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10007199 getblobdiffs $ids
Paul Mackerrasd2610d12005-05-11 00:45:38 +00007200}
7201
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007202proc diffcmd {ids flags} {
Paul Mackerras8f489362007-07-13 19:49:37 +10007203 global nullid nullid2
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007204
7205 set i [lsearch -exact $ids $nullid]
Paul Mackerras8f489362007-07-13 19:49:37 +10007206 set j [lsearch -exact $ids $nullid2]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007207 if {$i >= 0} {
Paul Mackerras8f489362007-07-13 19:49:37 +10007208 if {[llength $ids] > 1 && $j < 0} {
7209 # comparing working directory with some specific revision
7210 set cmd [concat | git diff-index $flags]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007211 if {$i == 0} {
7212 lappend cmd -R [lindex $ids 1]
7213 } else {
7214 lappend cmd [lindex $ids 0]
7215 }
7216 } else {
Paul Mackerras8f489362007-07-13 19:49:37 +10007217 # comparing working directory with index
7218 set cmd [concat | git diff-files $flags]
7219 if {$j == 1} {
7220 lappend cmd -R
7221 }
7222 }
7223 } elseif {$j >= 0} {
7224 set cmd [concat | git diff-index --cached $flags]
7225 if {[llength $ids] > 1} {
7226 # comparing index with specific revision
7227 if {$i == 0} {
7228 lappend cmd -R [lindex $ids 1]
7229 } else {
7230 lappend cmd [lindex $ids 0]
7231 }
7232 } else {
7233 # comparing index with HEAD
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007234 lappend cmd HEAD
7235 }
7236 } else {
Paul Mackerras8f489362007-07-13 19:49:37 +10007237 set cmd [concat | git diff-tree -r $flags $ids]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007238 }
7239 return $cmd
7240}
7241
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10007242proc gettreediffs {ids} {
Paul Mackerras79b2c752006-04-02 20:47:40 +10007243 global treediff treepending
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007244
Alexander Gavrilov72721312008-07-26 18:48:41 +04007245 if {[catch {set gdtf [open [diffcmd $ids {--no-commit-id}] r]}]} return
7246
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10007247 set treepending $ids
Paul Mackerras3c461ff2005-07-20 09:13:46 -04007248 set treediff {}
Alexander Gavrilov09c70292008-10-13 12:12:31 +04007249 fconfigure $gdtf -blocking 0 -encoding binary
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007250 filerun $gdtf [list gettreediffline $gdtf $ids]
Paul Mackerrasd2610d12005-05-11 00:45:38 +00007251}
7252
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10007253proc gettreediffline {gdtf ids} {
Paul Mackerras3c461ff2005-07-20 09:13:46 -04007254 global treediff treediffs treepending diffids diffmergeid
Paul Mackerras39ee47e2008-10-15 22:23:03 +11007255 global cmitmode vfilelimit curview limitdiffs perfile_attrs
Paul Mackerras3c461ff2005-07-20 09:13:46 -04007256
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007257 set nr 0
Alexander Gavrilov4db09302008-10-13 12:12:33 +04007258 set sublist {}
Paul Mackerras39ee47e2008-10-15 22:23:03 +11007259 set max 1000
7260 if {$perfile_attrs} {
7261 # cache_gitattr is slow, and even slower on win32 where we
7262 # have to invoke it for only about 30 paths at a time
7263 set max 500
7264 if {[tk windowingsystem] == "win32"} {
7265 set max 120
7266 }
7267 }
7268 while {[incr nr] <= $max && [gets $gdtf line] >= 0} {
Paul Mackerras9396cd32007-06-23 20:28:15 +10007269 set i [string first "\t" $line]
7270 if {$i >= 0} {
7271 set file [string range $line [expr {$i+1}] end]
7272 if {[string index $file 0] eq "\""} {
7273 set file [lindex $file 0]
7274 }
Alexander Gavrilov09c70292008-10-13 12:12:31 +04007275 set file [encoding convertfrom $file]
Paul Mackerras48a81b72008-11-04 21:09:00 +11007276 if {$file ne [lindex $treediff end]} {
7277 lappend treediff $file
7278 lappend sublist $file
7279 }
Paul Mackerras9396cd32007-06-23 20:28:15 +10007280 }
Paul Mackerrasd2610d12005-05-11 00:45:38 +00007281 }
Paul Mackerras39ee47e2008-10-15 22:23:03 +11007282 if {$perfile_attrs} {
7283 cache_gitattr encoding $sublist
7284 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007285 if {![eof $gdtf]} {
Paul Mackerras39ee47e2008-10-15 22:23:03 +11007286 return [expr {$nr >= $max? 2: 1}]
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007287 }
7288 close $gdtf
Paul Mackerras3ed31a82008-04-26 16:00:00 +10007289 if {$limitdiffs && $vfilelimit($curview) ne {}} {
Paul Mackerras74a40c72007-10-24 10:16:56 +10007290 set flist {}
7291 foreach f $treediff {
Paul Mackerras3ed31a82008-04-26 16:00:00 +10007292 if {[path_filter $vfilelimit($curview) $f]} {
Paul Mackerras74a40c72007-10-24 10:16:56 +10007293 lappend flist $f
7294 }
7295 }
7296 set treediffs($ids) $flist
7297 } else {
7298 set treediffs($ids) $treediff
7299 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007300 unset treepending
Paul Mackerrase1160132008-11-18 21:40:32 +11007301 if {$cmitmode eq "tree" && [llength $diffids] == 1} {
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007302 gettree $diffids
7303 } elseif {$ids != $diffids} {
7304 if {![info exists diffmergeid]} {
7305 gettreediffs $diffids
7306 }
7307 } else {
7308 addtocflist $ids
7309 }
7310 return 0
Paul Mackerrasd2610d12005-05-11 00:45:38 +00007311}
7312
Steffen Prohaska890fae72007-08-12 12:05:46 +02007313# empty string or positive integer
7314proc diffcontextvalidate {v} {
7315 return [regexp {^(|[1-9][0-9]*)$} $v]
7316}
7317
7318proc diffcontextchange {n1 n2 op} {
7319 global diffcontextstring diffcontext
7320
7321 if {[string is integer -strict $diffcontextstring]} {
Markus Heidelberga41ddbb2009-05-23 19:31:37 +02007322 if {$diffcontextstring >= 0} {
Steffen Prohaska890fae72007-08-12 12:05:46 +02007323 set diffcontext $diffcontextstring
7324 reselectline
7325 }
7326 }
7327}
7328
Steffen Prohaskab9b86002008-01-17 23:42:55 +01007329proc changeignorespace {} {
7330 reselectline
7331}
7332
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10007333proc getblobdiffs {ids} {
Paul Mackerras8d73b242007-10-06 20:22:00 +10007334 global blobdifffd diffids env
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007335 global diffinhdr treediffs
Steffen Prohaska890fae72007-08-12 12:05:46 +02007336 global diffcontext
Steffen Prohaskab9b86002008-01-17 23:42:55 +01007337 global ignorespace
Paul Mackerras3ed31a82008-04-26 16:00:00 +10007338 global limitdiffs vfilelimit curview
Paul Mackerras8b07dca2008-11-02 22:34:47 +11007339 global diffencoding targetline diffnparents
Paul Mackerrasa8138732009-05-16 21:06:01 +10007340 global git_version
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10007341
Paul Mackerrasa8138732009-05-16 21:06:01 +10007342 set textconv {}
7343 if {[package vcompare $git_version "1.6.1"] >= 0} {
7344 set textconv "--textconv"
7345 }
7346 set cmd [diffcmd $ids "-p $textconv -C --cc --no-commit-id -U$diffcontext"]
Steffen Prohaskab9b86002008-01-17 23:42:55 +01007347 if {$ignorespace} {
7348 append cmd " -w"
7349 }
Paul Mackerras3ed31a82008-04-26 16:00:00 +10007350 if {$limitdiffs && $vfilelimit($curview) ne {}} {
7351 set cmd [concat $cmd -- $vfilelimit($curview)]
Paul Mackerras7a39a172007-10-23 10:15:11 +10007352 }
7353 if {[catch {set bdf [open $cmd r]} err]} {
Paul Mackerras8b07dca2008-11-02 22:34:47 +11007354 error_popup [mc "Error getting diffs: %s" $err]
Paul Mackerrase5c2d852005-05-11 23:44:54 +00007355 return
7356 }
Paul Mackerras8a897742008-10-27 21:36:25 +11007357 set targetline {}
Paul Mackerras8b07dca2008-11-02 22:34:47 +11007358 set diffnparents 0
Paul Mackerras4f2c2642005-07-17 11:11:44 -04007359 set diffinhdr 0
Alexander Gavrilov09c70292008-10-13 12:12:31 +04007360 set diffencoding [get_path_encoding {}]
Pat Thoyts681c3292009-03-16 10:24:40 +00007361 fconfigure $bdf -blocking 0 -encoding binary -eofchar {}
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10007362 set blobdifffd($ids) $bdf
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007363 filerun $bdf [list getblobdiffline $bdf $diffids]
Paul Mackerrase5c2d852005-05-11 23:44:54 +00007364}
7365
Paul Mackerras89b11d32006-05-02 19:55:31 +10007366proc setinlist {var i val} {
7367 global $var
7368
7369 while {[llength [set $var]] < $i} {
7370 lappend $var {}
7371 }
7372 if {[llength [set $var]] == $i} {
7373 lappend $var $val
7374 } else {
7375 lset $var $i $val
7376 }
7377}
7378
Paul Mackerras9396cd32007-06-23 20:28:15 +10007379proc makediffhdr {fname ids} {
Paul Mackerras8b07dca2008-11-02 22:34:47 +11007380 global ctext curdiffstart treediffs diffencoding
Paul Mackerras8a897742008-10-27 21:36:25 +11007381 global ctext_file_names jump_to_here targetline diffline
Paul Mackerras9396cd32007-06-23 20:28:15 +10007382
Paul Mackerras8b07dca2008-11-02 22:34:47 +11007383 set fname [encoding convertfrom $fname]
7384 set diffencoding [get_path_encoding $fname]
Paul Mackerras9396cd32007-06-23 20:28:15 +10007385 set i [lsearch -exact $treediffs($ids) $fname]
7386 if {$i >= 0} {
7387 setinlist difffilestart $i $curdiffstart
7388 }
Paul Mackerras48a81b72008-11-04 21:09:00 +11007389 lset ctext_file_names end $fname
Paul Mackerras9396cd32007-06-23 20:28:15 +10007390 set l [expr {(78 - [string length $fname]) / 2}]
7391 set pad [string range "----------------------------------------" 1 $l]
7392 $ctext insert $curdiffstart "$pad $fname $pad" filesep
Paul Mackerras8a897742008-10-27 21:36:25 +11007393 set targetline {}
7394 if {$jump_to_here ne {} && [lindex $jump_to_here 0] eq $fname} {
7395 set targetline [lindex $jump_to_here 1]
7396 }
7397 set diffline 0
Paul Mackerras9396cd32007-06-23 20:28:15 +10007398}
7399
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10007400proc getblobdiffline {bdf ids} {
Paul Mackerras9396cd32007-06-23 20:28:15 +10007401 global diffids blobdifffd ctext curdiffstart
Paul Mackerras7eab2932005-07-20 12:25:54 -04007402 global diffnexthead diffnextnote difffilestart
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04007403 global ctext_file_names ctext_file_lines
Paul Mackerras8b07dca2008-11-02 22:34:47 +11007404 global diffinhdr treediffs mergemax diffnparents
Paul Mackerras8a897742008-10-27 21:36:25 +11007405 global diffencoding jump_to_here targetline diffline
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10007406
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007407 set nr 0
Paul Mackerrase5c2d852005-05-11 23:44:54 +00007408 $ctext conf -state normal
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007409 while {[incr nr] <= 1000 && [gets $bdf line] >= 0} {
7410 if {$ids != $diffids || $bdf != $blobdifffd($ids)} {
Paul Mackerrasc21398b2009-09-07 10:08:21 +10007411 catch {close $bdf}
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007412 return 0
Paul Mackerras89b11d32006-05-02 19:55:31 +10007413 }
Paul Mackerras8b07dca2008-11-02 22:34:47 +11007414 if {![string compare -length 5 "diff " $line]} {
7415 if {![regexp {^diff (--cc|--git) } $line m type]} {
7416 set line [encoding convertfrom $line]
7417 $ctext insert end "$line\n" hunksep
7418 continue
7419 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007420 # start of a new file
Paul Mackerras8b07dca2008-11-02 22:34:47 +11007421 set diffinhdr 1
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007422 $ctext insert end "\n"
Paul Mackerras9396cd32007-06-23 20:28:15 +10007423 set curdiffstart [$ctext index "end - 1c"]
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04007424 lappend ctext_file_names ""
7425 lappend ctext_file_lines [lindex [split $curdiffstart "."] 0]
Paul Mackerras9396cd32007-06-23 20:28:15 +10007426 $ctext insert end "\n" filesep
Paul Mackerras8b07dca2008-11-02 22:34:47 +11007427
7428 if {$type eq "--cc"} {
7429 # start of a new file in a merge diff
7430 set fname [string range $line 10 end]
7431 if {[lsearch -exact $treediffs($ids) $fname] < 0} {
7432 lappend treediffs($ids) $fname
7433 add_flist [list $fname]
7434 }
7435
Paul Mackerras9396cd32007-06-23 20:28:15 +10007436 } else {
Paul Mackerras8b07dca2008-11-02 22:34:47 +11007437 set line [string range $line 11 end]
7438 # If the name hasn't changed the length will be odd,
7439 # the middle char will be a space, and the two bits either
7440 # side will be a/name and b/name, or "a/name" and "b/name".
7441 # If the name has changed we'll get "rename from" and
7442 # "rename to" or "copy from" and "copy to" lines following
7443 # this, and we'll use them to get the filenames.
7444 # This complexity is necessary because spaces in the
7445 # filename(s) don't get escaped.
7446 set l [string length $line]
7447 set i [expr {$l / 2}]
7448 if {!(($l & 1) && [string index $line $i] eq " " &&
7449 [string range $line 2 [expr {$i - 1}]] eq \
7450 [string range $line [expr {$i + 3}] end])} {
7451 continue
7452 }
7453 # unescape if quoted and chop off the a/ from the front
7454 if {[string index $line 0] eq "\""} {
7455 set fname [string range [lindex $line 0] 2 end]
7456 } else {
7457 set fname [string range $line 2 [expr {$i - 1}]]
7458 }
Paul Mackerrase5c2d852005-05-11 23:44:54 +00007459 }
Paul Mackerras9396cd32007-06-23 20:28:15 +10007460 makediffhdr $fname $ids
7461
Paul Mackerras48a81b72008-11-04 21:09:00 +11007462 } elseif {![string compare -length 16 "* Unmerged path " $line]} {
7463 set fname [encoding convertfrom [string range $line 16 end]]
7464 $ctext insert end "\n"
7465 set curdiffstart [$ctext index "end - 1c"]
7466 lappend ctext_file_names $fname
7467 lappend ctext_file_lines [lindex [split $curdiffstart "."] 0]
7468 $ctext insert end "$line\n" filesep
7469 set i [lsearch -exact $treediffs($ids) $fname]
7470 if {$i >= 0} {
7471 setinlist difffilestart $i $curdiffstart
7472 }
7473
Paul Mackerras8b07dca2008-11-02 22:34:47 +11007474 } elseif {![string compare -length 2 "@@" $line]} {
7475 regexp {^@@+} $line ats
Alexander Gavrilov09c70292008-10-13 12:12:31 +04007476 set line [encoding convertfrom $diffencoding $line]
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007477 $ctext insert end "$line\n" hunksep
Paul Mackerras8b07dca2008-11-02 22:34:47 +11007478 if {[regexp { \+(\d+),\d+ @@} $line m nl]} {
7479 set diffline $nl
7480 }
7481 set diffnparents [expr {[string length $ats] - 1}]
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007482 set diffinhdr 0
Paul Mackerras9396cd32007-06-23 20:28:15 +10007483
7484 } elseif {$diffinhdr} {
Johannes Sixt5e85ec42007-10-02 16:16:54 +02007485 if {![string compare -length 12 "rename from " $line]} {
Johannes Sixtd1cb2982007-08-16 14:32:29 +02007486 set fname [string range $line [expr 6 + [string first " from " $line] ] end]
Paul Mackerras9396cd32007-06-23 20:28:15 +10007487 if {[string index $fname 0] eq "\""} {
7488 set fname [lindex $fname 0]
7489 }
Alexander Gavrilov09c70292008-10-13 12:12:31 +04007490 set fname [encoding convertfrom $fname]
Paul Mackerras9396cd32007-06-23 20:28:15 +10007491 set i [lsearch -exact $treediffs($ids) $fname]
7492 if {$i >= 0} {
7493 setinlist difffilestart $i $curdiffstart
7494 }
Johannes Sixtd1cb2982007-08-16 14:32:29 +02007495 } elseif {![string compare -length 10 $line "rename to "] ||
7496 ![string compare -length 8 $line "copy to "]} {
7497 set fname [string range $line [expr 4 + [string first " to " $line] ] end]
Paul Mackerras9396cd32007-06-23 20:28:15 +10007498 if {[string index $fname 0] eq "\""} {
7499 set fname [lindex $fname 0]
7500 }
7501 makediffhdr $fname $ids
7502 } elseif {[string compare -length 3 $line "---"] == 0} {
7503 # do nothing
7504 continue
7505 } elseif {[string compare -length 3 $line "+++"] == 0} {
7506 set diffinhdr 0
7507 continue
7508 }
7509 $ctext insert end "$line\n" filesep
7510
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007511 } else {
Pat Thoyts681c3292009-03-16 10:24:40 +00007512 set line [string map {\x1A ^Z} \
7513 [encoding convertfrom $diffencoding $line]]
Paul Mackerras8b07dca2008-11-02 22:34:47 +11007514 # parse the prefix - one ' ', '-' or '+' for each parent
7515 set prefix [string range $line 0 [expr {$diffnparents - 1}]]
7516 set tag [expr {$diffnparents > 1? "m": "d"}]
7517 if {[string trim $prefix " -+"] eq {}} {
7518 # prefix only has " ", "-" and "+" in it: normal diff line
7519 set num [string first "-" $prefix]
7520 if {$num >= 0} {
7521 # removed line, first parent with line is $num
7522 if {$num >= $mergemax} {
7523 set num "max"
7524 }
7525 $ctext insert end "$line\n" $tag$num
7526 } else {
7527 set tags {}
7528 if {[string first "+" $prefix] >= 0} {
7529 # added line
7530 lappend tags ${tag}result
7531 if {$diffnparents > 1} {
7532 set num [string first " " $prefix]
7533 if {$num >= 0} {
7534 if {$num >= $mergemax} {
7535 set num "max"
7536 }
7537 lappend tags m$num
7538 }
7539 }
7540 }
7541 if {$targetline ne {}} {
7542 if {$diffline == $targetline} {
7543 set seehere [$ctext index "end - 1 chars"]
7544 set targetline {}
7545 } else {
7546 incr diffline
7547 }
7548 }
7549 $ctext insert end "$line\n" $tags
7550 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007551 } else {
Paul Mackerras9396cd32007-06-23 20:28:15 +10007552 # "\ No newline at end of file",
7553 # or something else we don't recognize
7554 $ctext insert end "$line\n" hunksep
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007555 }
Paul Mackerrase5c2d852005-05-11 23:44:54 +00007556 }
7557 }
Paul Mackerras8b07dca2008-11-02 22:34:47 +11007558 if {[info exists seehere]} {
7559 mark_ctext_line [lindex [split $seehere .] 0]
7560 }
Paul Mackerrase5c2d852005-05-11 23:44:54 +00007561 $ctext conf -state disabled
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007562 if {[eof $bdf]} {
Paul Mackerrasc21398b2009-09-07 10:08:21 +10007563 catch {close $bdf}
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007564 return 0
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10007565 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007566 return [expr {$nr >= 1000? 2: 1}]
Paul Mackerrase5c2d852005-05-11 23:44:54 +00007567}
7568
Paul Mackerrasa8d610a2007-04-19 11:39:12 +10007569proc changediffdisp {} {
7570 global ctext diffelide
7571
7572 $ctext tag conf d0 -elide [lindex $diffelide 0]
Paul Mackerras8b07dca2008-11-02 22:34:47 +11007573 $ctext tag conf dresult -elide [lindex $diffelide 1]
Paul Mackerrasa8d610a2007-04-19 11:39:12 +10007574}
7575
Paul Mackerrasf4c54b32008-05-10 13:15:36 +10007576proc highlightfile {loc cline} {
7577 global ctext cflist cflist_top
7578
7579 $ctext yview $loc
7580 $cflist tag remove highlight $cflist_top.0 "$cflist_top.0 lineend"
7581 $cflist tag add highlight $cline.0 "$cline.0 lineend"
7582 $cflist see $cline.0
7583 set cflist_top $cline
7584}
7585
OGAWA Hirofumi67c22872006-09-27 12:32:19 +09007586proc prevfile {} {
Paul Mackerrasf4c54b32008-05-10 13:15:36 +10007587 global difffilestart ctext cmitmode
7588
7589 if {$cmitmode eq "tree"} return
7590 set prev 0.0
7591 set prevline 1
OGAWA Hirofumi67c22872006-09-27 12:32:19 +09007592 set here [$ctext index @0,0]
7593 foreach loc $difffilestart {
7594 if {[$ctext compare $loc >= $here]} {
Paul Mackerrasf4c54b32008-05-10 13:15:36 +10007595 highlightfile $prev $prevline
OGAWA Hirofumi67c22872006-09-27 12:32:19 +09007596 return
7597 }
7598 set prev $loc
Paul Mackerrasf4c54b32008-05-10 13:15:36 +10007599 incr prevline
OGAWA Hirofumi67c22872006-09-27 12:32:19 +09007600 }
Paul Mackerrasf4c54b32008-05-10 13:15:36 +10007601 highlightfile $prev $prevline
OGAWA Hirofumi67c22872006-09-27 12:32:19 +09007602}
7603
Paul Mackerras39ad8572005-05-19 12:35:53 +00007604proc nextfile {} {
Paul Mackerrasf4c54b32008-05-10 13:15:36 +10007605 global difffilestart ctext cmitmode
7606
7607 if {$cmitmode eq "tree"} return
Paul Mackerras39ad8572005-05-19 12:35:53 +00007608 set here [$ctext index @0,0]
Paul Mackerrasf4c54b32008-05-10 13:15:36 +10007609 set line 1
Paul Mackerras7fcceed2006-04-27 19:21:49 +10007610 foreach loc $difffilestart {
Paul Mackerrasf4c54b32008-05-10 13:15:36 +10007611 incr line
Paul Mackerras7fcceed2006-04-27 19:21:49 +10007612 if {[$ctext compare $loc > $here]} {
Paul Mackerrasf4c54b32008-05-10 13:15:36 +10007613 highlightfile $loc $line
OGAWA Hirofumi67c22872006-09-27 12:32:19 +09007614 return
Paul Mackerras39ad8572005-05-19 12:35:53 +00007615 }
7616 }
Paul Mackerras1db95b02005-05-09 04:08:39 +00007617}
7618
Paul Mackerras3ea06f92006-05-24 10:16:03 +10007619proc clear_ctext {{first 1.0}} {
7620 global ctext smarktop smarkbot
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04007621 global ctext_file_names ctext_file_lines
Paul Mackerras97645682007-08-23 22:24:38 +10007622 global pendinglinks
Paul Mackerras3ea06f92006-05-24 10:16:03 +10007623
Paul Mackerras1902c272006-05-25 21:25:13 +10007624 set l [lindex [split $first .] 0]
7625 if {![info exists smarktop] || [$ctext compare $first < $smarktop.0]} {
7626 set smarktop $l
Paul Mackerras3ea06f92006-05-24 10:16:03 +10007627 }
Paul Mackerras1902c272006-05-25 21:25:13 +10007628 if {![info exists smarkbot] || [$ctext compare $first < $smarkbot.0]} {
7629 set smarkbot $l
Paul Mackerras3ea06f92006-05-24 10:16:03 +10007630 }
7631 $ctext delete $first end
Paul Mackerras97645682007-08-23 22:24:38 +10007632 if {$first eq "1.0"} {
7633 catch {unset pendinglinks}
7634 }
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04007635 set ctext_file_names {}
7636 set ctext_file_lines {}
Paul Mackerras3ea06f92006-05-24 10:16:03 +10007637}
7638
Paul Mackerras32f1b3e2007-09-28 21:27:39 +10007639proc settabs {{firstab {}}} {
Paul Mackerras9c311b32007-10-04 22:27:13 +10007640 global firsttabstop tabstop ctext have_tk85
Paul Mackerras32f1b3e2007-09-28 21:27:39 +10007641
7642 if {$firstab ne {} && $have_tk85} {
7643 set firsttabstop $firstab
7644 }
Paul Mackerras9c311b32007-10-04 22:27:13 +10007645 set w [font measure textfont "0"]
Paul Mackerras32f1b3e2007-09-28 21:27:39 +10007646 if {$firsttabstop != 0} {
Paul Mackerras64b5f142007-10-04 22:19:24 +10007647 $ctext conf -tabs [list [expr {($firsttabstop + $tabstop) * $w}] \
7648 [expr {($firsttabstop + 2 * $tabstop) * $w}]]
Paul Mackerras32f1b3e2007-09-28 21:27:39 +10007649 } elseif {$have_tk85 || $tabstop != 8} {
7650 $ctext conf -tabs [expr {$tabstop * $w}]
7651 } else {
7652 $ctext conf -tabs {}
7653 }
Paul Mackerras3ea06f92006-05-24 10:16:03 +10007654}
7655
7656proc incrsearch {name ix op} {
Paul Mackerras1902c272006-05-25 21:25:13 +10007657 global ctext searchstring searchdirn
Paul Mackerras3ea06f92006-05-24 10:16:03 +10007658
7659 $ctext tag remove found 1.0 end
Paul Mackerras1902c272006-05-25 21:25:13 +10007660 if {[catch {$ctext index anchor}]} {
7661 # no anchor set, use start of selection, or of visible area
7662 set sel [$ctext tag ranges sel]
7663 if {$sel ne {}} {
7664 $ctext mark set anchor [lindex $sel 0]
7665 } elseif {$searchdirn eq "-forwards"} {
7666 $ctext mark set anchor @0,0
7667 } else {
7668 $ctext mark set anchor @0,[winfo height $ctext]
7669 }
7670 }
Paul Mackerras3ea06f92006-05-24 10:16:03 +10007671 if {$searchstring ne {}} {
Paul Mackerras1902c272006-05-25 21:25:13 +10007672 set here [$ctext search $searchdirn -- $searchstring anchor]
7673 if {$here ne {}} {
7674 $ctext see $here
7675 }
Paul Mackerras3ea06f92006-05-24 10:16:03 +10007676 searchmarkvisible 1
7677 }
7678}
7679
7680proc dosearch {} {
Paul Mackerras1902c272006-05-25 21:25:13 +10007681 global sstring ctext searchstring searchdirn
Paul Mackerras3ea06f92006-05-24 10:16:03 +10007682
7683 focus $sstring
7684 $sstring icursor end
Paul Mackerras1902c272006-05-25 21:25:13 +10007685 set searchdirn -forwards
7686 if {$searchstring ne {}} {
7687 set sel [$ctext tag ranges sel]
7688 if {$sel ne {}} {
7689 set start "[lindex $sel 0] + 1c"
7690 } elseif {[catch {set start [$ctext index anchor]}]} {
7691 set start "@0,0"
7692 }
7693 set match [$ctext search -count mlen -- $searchstring $start]
7694 $ctext tag remove sel 1.0 end
7695 if {$match eq {}} {
7696 bell
7697 return
7698 }
7699 $ctext see $match
7700 set mend "$match + $mlen c"
7701 $ctext tag add sel $match $mend
7702 $ctext mark unset anchor
Paul Mackerras3ea06f92006-05-24 10:16:03 +10007703 }
Paul Mackerras1902c272006-05-25 21:25:13 +10007704}
7705
7706proc dosearchback {} {
7707 global sstring ctext searchstring searchdirn
7708
7709 focus $sstring
7710 $sstring icursor end
7711 set searchdirn -backwards
7712 if {$searchstring ne {}} {
7713 set sel [$ctext tag ranges sel]
7714 if {$sel ne {}} {
7715 set start [lindex $sel 0]
7716 } elseif {[catch {set start [$ctext index anchor]}]} {
7717 set start @0,[winfo height $ctext]
7718 }
7719 set match [$ctext search -backwards -count ml -- $searchstring $start]
7720 $ctext tag remove sel 1.0 end
7721 if {$match eq {}} {
7722 bell
7723 return
7724 }
7725 $ctext see $match
7726 set mend "$match + $ml c"
7727 $ctext tag add sel $match $mend
7728 $ctext mark unset anchor
7729 }
Paul Mackerras3ea06f92006-05-24 10:16:03 +10007730}
7731
7732proc searchmark {first last} {
7733 global ctext searchstring
7734
7735 set mend $first.0
7736 while {1} {
7737 set match [$ctext search -count mlen -- $searchstring $mend $last.end]
7738 if {$match eq {}} break
7739 set mend "$match + $mlen c"
7740 $ctext tag add found $match $mend
7741 }
7742}
7743
7744proc searchmarkvisible {doall} {
7745 global ctext smarktop smarkbot
7746
7747 set topline [lindex [split [$ctext index @0,0] .] 0]
7748 set botline [lindex [split [$ctext index @0,[winfo height $ctext]] .] 0]
7749 if {$doall || $botline < $smarktop || $topline > $smarkbot} {
7750 # no overlap with previous
7751 searchmark $topline $botline
7752 set smarktop $topline
7753 set smarkbot $botline
7754 } else {
7755 if {$topline < $smarktop} {
7756 searchmark $topline [expr {$smarktop-1}]
7757 set smarktop $topline
7758 }
7759 if {$botline > $smarkbot} {
7760 searchmark [expr {$smarkbot+1}] $botline
7761 set smarkbot $botline
7762 }
7763 }
7764}
7765
7766proc scrolltext {f0 f1} {
Paul Mackerras1902c272006-05-25 21:25:13 +10007767 global searchstring
Paul Mackerras3ea06f92006-05-24 10:16:03 +10007768
Pekka Kaitaniemi8809d692008-03-08 14:27:23 +02007769 .bleft.bottom.sb set $f0 $f1
Paul Mackerras3ea06f92006-05-24 10:16:03 +10007770 if {$searchstring ne {}} {
7771 searchmarkvisible 0
7772 }
7773}
7774
Paul Mackerras1d10f362005-05-15 12:55:47 +00007775proc setcoords {} {
Paul Mackerras9c311b32007-10-04 22:27:13 +10007776 global linespc charspc canvx0 canvy0
Paul Mackerrasf6075eb2005-08-18 09:30:10 +10007777 global xspc1 xspc2 lthickness
Paul Mackerras8d858d12005-08-05 09:52:16 +10007778
Paul Mackerras9c311b32007-10-04 22:27:13 +10007779 set linespc [font metrics mainfont -linespace]
7780 set charspc [font measure mainfont "m"]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11007781 set canvy0 [expr {int(3 + 0.5 * $linespc)}]
7782 set canvx0 [expr {int(3 + 0.5 * $linespc)}]
Paul Mackerrasf6075eb2005-08-18 09:30:10 +10007783 set lthickness [expr {int($linespc / 9) + 1}]
Paul Mackerras8d858d12005-08-05 09:52:16 +10007784 set xspc1(0) $linespc
7785 set xspc2 $linespc
Paul Mackerras9a40c502005-05-12 23:46:16 +00007786}
Paul Mackerras1db95b02005-05-09 04:08:39 +00007787
Paul Mackerras1d10f362005-05-15 12:55:47 +00007788proc redisplay {} {
Paul Mackerrasbe0cd092006-03-31 09:55:11 +11007789 global canv
Paul Mackerras9f1afe02006-02-19 22:44:47 +11007790 global selectedline
7791
7792 set ymax [lindex [$canv cget -scrollregion] 3]
7793 if {$ymax eq {} || $ymax == 0} return
7794 set span [$canv yview]
7795 clear_display
Paul Mackerrasbe0cd092006-03-31 09:55:11 +11007796 setcanvscroll
Paul Mackerras9f1afe02006-02-19 22:44:47 +11007797 allcanvs yview moveto [lindex $span 0]
7798 drawvisible
Paul Mackerras94b4a692008-05-20 20:51:06 +10007799 if {$selectedline ne {}} {
Paul Mackerras9f1afe02006-02-19 22:44:47 +11007800 selectline $selectedline 0
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10007801 allcanvs yview moveto [lindex $span 0]
Paul Mackerras1db95b02005-05-09 04:08:39 +00007802 }
7803}
Paul Mackerras1d10f362005-05-15 12:55:47 +00007804
Paul Mackerras0ed1dd32007-10-06 18:27:37 +10007805proc parsefont {f n} {
7806 global fontattr
7807
7808 set fontattr($f,family) [lindex $n 0]
7809 set s [lindex $n 1]
7810 if {$s eq {} || $s == 0} {
7811 set s 10
7812 } elseif {$s < 0} {
7813 set s [expr {int(-$s / [winfo fpixels . 1p] + 0.5)}]
Paul Mackerras9c311b32007-10-04 22:27:13 +10007814 }
Paul Mackerras0ed1dd32007-10-06 18:27:37 +10007815 set fontattr($f,size) $s
7816 set fontattr($f,weight) normal
7817 set fontattr($f,slant) roman
7818 foreach style [lrange $n 2 end] {
7819 switch -- $style {
7820 "normal" -
7821 "bold" {set fontattr($f,weight) $style}
7822 "roman" -
7823 "italic" {set fontattr($f,slant) $style}
7824 }
Paul Mackerras9c311b32007-10-04 22:27:13 +10007825 }
Paul Mackerras0ed1dd32007-10-06 18:27:37 +10007826}
7827
7828proc fontflags {f {isbold 0}} {
7829 global fontattr
7830
7831 return [list -family $fontattr($f,family) -size $fontattr($f,size) \
7832 -weight [expr {$isbold? "bold": $fontattr($f,weight)}] \
7833 -slant $fontattr($f,slant)]
7834}
7835
7836proc fontname {f} {
7837 global fontattr
7838
7839 set n [list $fontattr($f,family) $fontattr($f,size)]
7840 if {$fontattr($f,weight) eq "bold"} {
7841 lappend n "bold"
Paul Mackerras9c311b32007-10-04 22:27:13 +10007842 }
Paul Mackerras0ed1dd32007-10-06 18:27:37 +10007843 if {$fontattr($f,slant) eq "italic"} {
7844 lappend n "italic"
Paul Mackerras9c311b32007-10-04 22:27:13 +10007845 }
Paul Mackerras0ed1dd32007-10-06 18:27:37 +10007846 return $n
Paul Mackerras9c311b32007-10-04 22:27:13 +10007847}
7848
Paul Mackerras1d10f362005-05-15 12:55:47 +00007849proc incrfont {inc} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11007850 global mainfont textfont ctext canv cflist showrefstop
Paul Mackerras0ed1dd32007-10-06 18:27:37 +10007851 global stopped entries fontattr
7852
Paul Mackerras1d10f362005-05-15 12:55:47 +00007853 unmarkmatches
Paul Mackerras0ed1dd32007-10-06 18:27:37 +10007854 set s $fontattr(mainfont,size)
Paul Mackerras9c311b32007-10-04 22:27:13 +10007855 incr s $inc
7856 if {$s < 1} {
7857 set s 1
7858 }
Paul Mackerras0ed1dd32007-10-06 18:27:37 +10007859 set fontattr(mainfont,size) $s
Paul Mackerras9c311b32007-10-04 22:27:13 +10007860 font config mainfont -size $s
7861 font config mainfontbold -size $s
Paul Mackerras0ed1dd32007-10-06 18:27:37 +10007862 set mainfont [fontname mainfont]
7863 set s $fontattr(textfont,size)
Paul Mackerras9c311b32007-10-04 22:27:13 +10007864 incr s $inc
7865 if {$s < 1} {
7866 set s 1
7867 }
Paul Mackerras0ed1dd32007-10-06 18:27:37 +10007868 set fontattr(textfont,size) $s
Paul Mackerras9c311b32007-10-04 22:27:13 +10007869 font config textfont -size $s
7870 font config textfontbold -size $s
Paul Mackerras0ed1dd32007-10-06 18:27:37 +10007871 set textfont [fontname textfont]
Paul Mackerras1d10f362005-05-15 12:55:47 +00007872 setcoords
Paul Mackerras32f1b3e2007-09-28 21:27:39 +10007873 settabs
Paul Mackerras1d10f362005-05-15 12:55:47 +00007874 redisplay
Paul Mackerras1db95b02005-05-09 04:08:39 +00007875}
Paul Mackerras1d10f362005-05-15 12:55:47 +00007876
Paul Mackerrasee3dc722005-06-25 16:37:13 +10007877proc clearsha1 {} {
7878 global sha1entry sha1string
7879 if {[string length $sha1string] == 40} {
7880 $sha1entry delete 0 end
7881 }
7882}
7883
Paul Mackerras887fe3c2005-05-21 07:35:37 +00007884proc sha1change {n1 n2 op} {
7885 global sha1string currentid sha1but
7886 if {$sha1string == {}
7887 || ([info exists currentid] && $sha1string == $currentid)} {
7888 set state disabled
7889 } else {
7890 set state normal
7891 }
7892 if {[$sha1but cget -state] == $state} return
7893 if {$state == "normal"} {
Christian Stimmingd990ced2007-11-07 18:42:55 +01007894 $sha1but conf -state normal -relief raised -text "[mc "Goto:"] "
Paul Mackerras887fe3c2005-05-21 07:35:37 +00007895 } else {
Christian Stimmingd990ced2007-11-07 18:42:55 +01007896 $sha1but conf -state disabled -relief flat -text "[mc "SHA1 ID:"] "
Paul Mackerras887fe3c2005-05-21 07:35:37 +00007897 }
7898}
7899
7900proc gotocommit {} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11007901 global sha1string tagids headids curview varcid
Paul Mackerrasf3b8b3c2005-07-18 12:16:35 -04007902
Paul Mackerras887fe3c2005-05-21 07:35:37 +00007903 if {$sha1string == {}
7904 || ([info exists currentid] && $sha1string == $currentid)} return
7905 if {[info exists tagids($sha1string)]} {
7906 set id $tagids($sha1string)
Stephen Rothwelle1007122006-03-30 16:13:12 +11007907 } elseif {[info exists headids($sha1string)]} {
7908 set id $headids($sha1string)
Paul Mackerras887fe3c2005-05-21 07:35:37 +00007909 } else {
7910 set id [string tolower $sha1string]
Paul Mackerrasf3b8b3c2005-07-18 12:16:35 -04007911 if {[regexp {^[0-9a-f]{4,39}$} $id]} {
Paul Mackerrasd375ef92008-10-21 10:18:12 +11007912 set matches [longid $id]
Paul Mackerrasf3b8b3c2005-07-18 12:16:35 -04007913 if {$matches ne {}} {
7914 if {[llength $matches] > 1} {
Christian Stimmingd990ced2007-11-07 18:42:55 +01007915 error_popup [mc "Short SHA1 id %s is ambiguous" $id]
Paul Mackerrasf3b8b3c2005-07-18 12:16:35 -04007916 return
7917 }
Paul Mackerrasd375ef92008-10-21 10:18:12 +11007918 set id [lindex $matches 0]
Paul Mackerrasf3b8b3c2005-07-18 12:16:35 -04007919 }
Thomas Rast9bf3acf2009-08-13 09:25:03 +02007920 } else {
7921 if {[catch {set id [exec git rev-parse --verify $sha1string]}]} {
7922 error_popup [mc "Revision %s is not known" $sha1string]
7923 return
7924 }
Paul Mackerrasf3b8b3c2005-07-18 12:16:35 -04007925 }
Paul Mackerras887fe3c2005-05-21 07:35:37 +00007926 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11007927 if {[commitinview $id $curview]} {
7928 selectline [rowofcommit $id] 1
Paul Mackerras887fe3c2005-05-21 07:35:37 +00007929 return
7930 }
Paul Mackerrasf3b8b3c2005-07-18 12:16:35 -04007931 if {[regexp {^[0-9a-fA-F]{4,}$} $sha1string]} {
Christian Stimmingd990ced2007-11-07 18:42:55 +01007932 set msg [mc "SHA1 id %s is not known" $sha1string]
Paul Mackerras887fe3c2005-05-21 07:35:37 +00007933 } else {
Thomas Rast9bf3acf2009-08-13 09:25:03 +02007934 set msg [mc "Revision %s is not in the current view" $sha1string]
Paul Mackerras887fe3c2005-05-21 07:35:37 +00007935 }
Christian Stimmingd990ced2007-11-07 18:42:55 +01007936 error_popup $msg
Paul Mackerras887fe3c2005-05-21 07:35:37 +00007937}
7938
Paul Mackerras84ba7342005-06-17 00:12:26 +00007939proc lineenter {x y id} {
7940 global hoverx hovery hoverid hovertimer
7941 global commitinfo canv
7942
Paul Mackerras8ed16482006-03-02 22:56:44 +11007943 if {![info exists commitinfo($id)] && ![getcommit $id]} return
Paul Mackerras84ba7342005-06-17 00:12:26 +00007944 set hoverx $x
7945 set hovery $y
7946 set hoverid $id
7947 if {[info exists hovertimer]} {
7948 after cancel $hovertimer
7949 }
7950 set hovertimer [after 500 linehover]
7951 $canv delete hover
7952}
7953
7954proc linemotion {x y id} {
7955 global hoverx hovery hoverid hovertimer
7956
7957 if {[info exists hoverid] && $id == $hoverid} {
7958 set hoverx $x
7959 set hovery $y
7960 if {[info exists hovertimer]} {
7961 after cancel $hovertimer
7962 }
7963 set hovertimer [after 500 linehover]
7964 }
7965}
7966
7967proc lineleave {id} {
7968 global hoverid hovertimer canv
7969
7970 if {[info exists hoverid] && $id == $hoverid} {
7971 $canv delete hover
7972 if {[info exists hovertimer]} {
7973 after cancel $hovertimer
7974 unset hovertimer
7975 }
7976 unset hoverid
7977 }
7978}
7979
7980proc linehover {} {
7981 global hoverx hovery hoverid hovertimer
7982 global canv linespc lthickness
Paul Mackerras9c311b32007-10-04 22:27:13 +10007983 global commitinfo
Paul Mackerras84ba7342005-06-17 00:12:26 +00007984
7985 set text [lindex $commitinfo($hoverid) 0]
7986 set ymax [lindex [$canv cget -scrollregion] 3]
7987 if {$ymax == {}} return
7988 set yfrac [lindex [$canv yview] 0]
7989 set x [expr {$hoverx + 2 * $linespc}]
7990 set y [expr {$hovery + $yfrac * $ymax - $linespc / 2}]
7991 set x0 [expr {$x - 2 * $lthickness}]
7992 set y0 [expr {$y - 2 * $lthickness}]
Paul Mackerras9c311b32007-10-04 22:27:13 +10007993 set x1 [expr {$x + [font measure mainfont $text] + 2 * $lthickness}]
Paul Mackerras84ba7342005-06-17 00:12:26 +00007994 set y1 [expr {$y + $linespc + 2 * $lthickness}]
7995 set t [$canv create rectangle $x0 $y0 $x1 $y1 \
7996 -fill \#ffff80 -outline black -width 1 -tags hover]
7997 $canv raise $t
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10007998 set t [$canv create text $x $y -anchor nw -text $text -tags hover \
Paul Mackerras9c311b32007-10-04 22:27:13 +10007999 -font mainfont]
Paul Mackerras84ba7342005-06-17 00:12:26 +00008000 $canv raise $t
8001}
8002
Paul Mackerras9843c302005-08-30 10:57:11 +10008003proc clickisonarrow {id y} {
Paul Mackerras50b44ec2006-04-04 10:16:22 +10008004 global lthickness
Paul Mackerras9843c302005-08-30 10:57:11 +10008005
Paul Mackerras50b44ec2006-04-04 10:16:22 +10008006 set ranges [rowranges $id]
Paul Mackerras9843c302005-08-30 10:57:11 +10008007 set thresh [expr {2 * $lthickness + 6}]
Paul Mackerras50b44ec2006-04-04 10:16:22 +10008008 set n [expr {[llength $ranges] - 1}]
Paul Mackerrasf6342482006-02-28 10:02:03 +11008009 for {set i 1} {$i < $n} {incr i} {
Paul Mackerras50b44ec2006-04-04 10:16:22 +10008010 set row [lindex $ranges $i]
Paul Mackerrasf6342482006-02-28 10:02:03 +11008011 if {abs([yc $row] - $y) < $thresh} {
8012 return $i
Paul Mackerras9843c302005-08-30 10:57:11 +10008013 }
8014 }
8015 return {}
8016}
8017
Paul Mackerrasf6342482006-02-28 10:02:03 +11008018proc arrowjump {id n y} {
Paul Mackerras50b44ec2006-04-04 10:16:22 +10008019 global canv
Paul Mackerras9843c302005-08-30 10:57:11 +10008020
Paul Mackerrasf6342482006-02-28 10:02:03 +11008021 # 1 <-> 2, 3 <-> 4, etc...
8022 set n [expr {(($n - 1) ^ 1) + 1}]
Paul Mackerras50b44ec2006-04-04 10:16:22 +10008023 set row [lindex [rowranges $id] $n]
Paul Mackerrasf6342482006-02-28 10:02:03 +11008024 set yt [yc $row]
Paul Mackerras9843c302005-08-30 10:57:11 +10008025 set ymax [lindex [$canv cget -scrollregion] 3]
8026 if {$ymax eq {} || $ymax <= 0} return
8027 set view [$canv yview]
8028 set yspan [expr {[lindex $view 1] - [lindex $view 0]}]
8029 set yfrac [expr {$yt / $ymax - $yspan / 2}]
8030 if {$yfrac < 0} {
8031 set yfrac 0
8032 }
Paul Mackerrasf6342482006-02-28 10:02:03 +11008033 allcanvs yview moveto $yfrac
Paul Mackerras9843c302005-08-30 10:57:11 +10008034}
8035
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10008036proc lineclick {x y id isnew} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11008037 global ctext commitinfo children canv thickerline curview
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008038
Paul Mackerras8ed16482006-03-02 22:56:44 +11008039 if {![info exists commitinfo($id)] && ![getcommit $id]} return
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008040 unmarkmatches
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10008041 unselectline
Paul Mackerras9843c302005-08-30 10:57:11 +10008042 normalline
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008043 $canv delete hover
Paul Mackerras9843c302005-08-30 10:57:11 +10008044 # draw this line thicker than normal
Paul Mackerras9843c302005-08-30 10:57:11 +10008045 set thickerline $id
Paul Mackerrasc934a8a2006-03-02 23:00:44 +11008046 drawlines $id
Paul Mackerras9843c302005-08-30 10:57:11 +10008047 if {$isnew} {
8048 set ymax [lindex [$canv cget -scrollregion] 3]
8049 if {$ymax eq {}} return
8050 set yfrac [lindex [$canv yview] 0]
8051 set y [expr {$y + $yfrac * $ymax}]
8052 }
8053 set dirn [clickisonarrow $id $y]
8054 if {$dirn ne {}} {
8055 arrowjump $id $dirn $y
8056 return
8057 }
8058
8059 if {$isnew} {
8060 addtohistory [list lineclick $x $y $id 0]
8061 }
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008062 # fill the details pane with info about this line
8063 $ctext conf -state normal
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008064 clear_ctext
Paul Mackerras32f1b3e2007-09-28 21:27:39 +10008065 settabs 0
Christian Stimmingd990ced2007-11-07 18:42:55 +01008066 $ctext insert end "[mc "Parent"]:\t"
Paul Mackerras97645682007-08-23 22:24:38 +10008067 $ctext insert end $id link0
8068 setlink $id link0
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008069 set info $commitinfo($id)
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10008070 $ctext insert end "\n\t[lindex $info 0]\n"
Christian Stimmingd990ced2007-11-07 18:42:55 +01008071 $ctext insert end "\t[mc "Author"]:\t[lindex $info 1]\n"
Paul Mackerras232475d2005-11-15 10:34:03 +11008072 set date [formatdate [lindex $info 2]]
Christian Stimmingd990ced2007-11-07 18:42:55 +01008073 $ctext insert end "\t[mc "Date"]:\t$date\n"
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10008074 set kids $children($curview,$id)
Paul Mackerras79b2c752006-04-02 20:47:40 +10008075 if {$kids ne {}} {
Christian Stimmingd990ced2007-11-07 18:42:55 +01008076 $ctext insert end "\n[mc "Children"]:"
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10008077 set i 0
Paul Mackerras79b2c752006-04-02 20:47:40 +10008078 foreach child $kids {
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10008079 incr i
Paul Mackerras8ed16482006-03-02 22:56:44 +11008080 if {![info exists commitinfo($child)] && ![getcommit $child]} continue
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008081 set info $commitinfo($child)
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10008082 $ctext insert end "\n\t"
Paul Mackerras97645682007-08-23 22:24:38 +10008083 $ctext insert end $child link$i
8084 setlink $child link$i
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10008085 $ctext insert end "\n\t[lindex $info 0]"
Christian Stimmingd990ced2007-11-07 18:42:55 +01008086 $ctext insert end "\n\t[mc "Author"]:\t[lindex $info 1]"
Paul Mackerras232475d2005-11-15 10:34:03 +11008087 set date [formatdate [lindex $info 2]]
Christian Stimmingd990ced2007-11-07 18:42:55 +01008088 $ctext insert end "\n\t[mc "Date"]:\t$date\n"
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008089 }
8090 }
8091 $ctext conf -state disabled
Paul Mackerras7fcceed2006-04-27 19:21:49 +10008092 init_flist {}
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008093}
8094
Paul Mackerras9843c302005-08-30 10:57:11 +10008095proc normalline {} {
8096 global thickerline
8097 if {[info exists thickerline]} {
Paul Mackerrasc934a8a2006-03-02 23:00:44 +11008098 set id $thickerline
Paul Mackerras9843c302005-08-30 10:57:11 +10008099 unset thickerline
Paul Mackerrasc934a8a2006-03-02 23:00:44 +11008100 drawlines $id
Paul Mackerras9843c302005-08-30 10:57:11 +10008101 }
8102}
8103
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008104proc selbyid {id} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11008105 global curview
8106 if {[commitinview $id $curview]} {
8107 selectline [rowofcommit $id] 1
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008108 }
8109}
8110
8111proc mstime {} {
8112 global startmstime
8113 if {![info exists startmstime]} {
8114 set startmstime [clock clicks -milliseconds]
8115 }
8116 return [format "%.3f" [expr {([clock click -milliseconds] - $startmstime) / 1000.0}]]
8117}
8118
8119proc rowmenu {x y id} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11008120 global rowctxmenu selectedline rowmenuid curview
Paul Mackerrasb9fdba72009-04-09 09:34:46 +10008121 global nullid nullid2 fakerowmenu mainhead markedid
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008122
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10008123 stopfinding
Paul Mackerras219ea3a2006-09-07 10:21:39 +10008124 set rowmenuid $id
Paul Mackerras94b4a692008-05-20 20:51:06 +10008125 if {$selectedline eq {} || [rowofcommit $id] eq $selectedline} {
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008126 set state disabled
8127 } else {
8128 set state normal
8129 }
Paul Mackerras8f489362007-07-13 19:49:37 +10008130 if {$id ne $nullid && $id ne $nullid2} {
Paul Mackerras219ea3a2006-09-07 10:21:39 +10008131 set menu $rowctxmenu
Michele Ballabio5e3502d2008-05-02 17:46:20 +02008132 if {$mainhead ne {}} {
Johannes Sixtda12e592008-12-03 13:43:20 +01008133 $menu entryconfigure 7 -label [mc "Reset %s branch to here" $mainhead] -state normal
Michele Ballabio5e3502d2008-05-02 17:46:20 +02008134 } else {
8135 $menu entryconfigure 7 -label [mc "Detached head: can't reset" $mainhead] -state disabled
8136 }
Paul Mackerrasb9fdba72009-04-09 09:34:46 +10008137 if {[info exists markedid] && $markedid ne $id} {
8138 $menu entryconfigure 9 -state normal
8139 $menu entryconfigure 10 -state normal
Paul Mackerras010509f2009-04-09 22:10:20 +10008140 $menu entryconfigure 11 -state normal
Paul Mackerrasb9fdba72009-04-09 09:34:46 +10008141 } else {
8142 $menu entryconfigure 9 -state disabled
8143 $menu entryconfigure 10 -state disabled
Paul Mackerras010509f2009-04-09 22:10:20 +10008144 $menu entryconfigure 11 -state disabled
Paul Mackerrasb9fdba72009-04-09 09:34:46 +10008145 }
Paul Mackerras219ea3a2006-09-07 10:21:39 +10008146 } else {
8147 set menu $fakerowmenu
8148 }
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11008149 $menu entryconfigure [mca "Diff this -> selected"] -state $state
8150 $menu entryconfigure [mca "Diff selected -> this"] -state $state
8151 $menu entryconfigure [mca "Make patch"] -state $state
Paul Mackerras219ea3a2006-09-07 10:21:39 +10008152 tk_popup $menu $x $y
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008153}
8154
Paul Mackerrasb9fdba72009-04-09 09:34:46 +10008155proc markhere {} {
8156 global rowmenuid markedid canv
8157
8158 set markedid $rowmenuid
8159 make_idmark $markedid
8160}
8161
8162proc gotomark {} {
8163 global markedid
8164
8165 if {[info exists markedid]} {
8166 selbyid $markedid
8167 }
8168}
8169
8170proc replace_by_kids {l r} {
8171 global curview children
8172
8173 set id [commitonrow $r]
8174 set l [lreplace $l 0 0]
8175 foreach kid $children($curview,$id) {
8176 lappend l [rowofcommit $kid]
8177 }
8178 return [lsort -integer -decreasing -unique $l]
8179}
8180
8181proc find_common_desc {} {
8182 global markedid rowmenuid curview children
8183
8184 if {![info exists markedid]} return
8185 if {![commitinview $markedid $curview] ||
8186 ![commitinview $rowmenuid $curview]} return
8187 #set t1 [clock clicks -milliseconds]
8188 set l1 [list [rowofcommit $markedid]]
8189 set l2 [list [rowofcommit $rowmenuid]]
8190 while 1 {
8191 set r1 [lindex $l1 0]
8192 set r2 [lindex $l2 0]
8193 if {$r1 eq {} || $r2 eq {}} break
8194 if {$r1 == $r2} {
8195 selectline $r1 1
8196 break
8197 }
8198 if {$r1 > $r2} {
8199 set l1 [replace_by_kids $l1 $r1]
8200 } else {
8201 set l2 [replace_by_kids $l2 $r2]
8202 }
8203 }
8204 #set t2 [clock clicks -milliseconds]
8205 #puts "took [expr {$t2-$t1}]ms"
8206}
8207
Paul Mackerras010509f2009-04-09 22:10:20 +10008208proc compare_commits {} {
8209 global markedid rowmenuid curview children
8210
8211 if {![info exists markedid]} return
8212 if {![commitinview $markedid $curview]} return
8213 addtohistory [list do_cmp_commits $markedid $rowmenuid]
8214 do_cmp_commits $markedid $rowmenuid
8215}
8216
8217proc getpatchid {id} {
8218 global patchids
8219
8220 if {![info exists patchids($id)]} {
Paul Mackerras6f63fc12009-04-21 22:22:31 +10008221 set cmd [diffcmd [list $id] {-p --root}]
8222 # trim off the initial "|"
8223 set cmd [lrange $cmd 1 end]
8224 if {[catch {
8225 set x [eval exec $cmd | git patch-id]
8226 set patchids($id) [lindex $x 0]
8227 }]} {
8228 set patchids($id) "error"
8229 }
Paul Mackerras010509f2009-04-09 22:10:20 +10008230 }
8231 return $patchids($id)
8232}
8233
8234proc do_cmp_commits {a b} {
8235 global ctext curview parents children patchids commitinfo
8236
8237 $ctext conf -state normal
8238 clear_ctext
8239 init_flist {}
8240 for {set i 0} {$i < 100} {incr i} {
Paul Mackerras010509f2009-04-09 22:10:20 +10008241 set skipa 0
8242 set skipb 0
8243 if {[llength $parents($curview,$a)] > 1} {
Paul Mackerras6f63fc12009-04-21 22:22:31 +10008244 appendshortlink $a [mc "Skipping merge commit "] "\n"
Paul Mackerras010509f2009-04-09 22:10:20 +10008245 set skipa 1
8246 } else {
8247 set patcha [getpatchid $a]
8248 }
8249 if {[llength $parents($curview,$b)] > 1} {
Paul Mackerras6f63fc12009-04-21 22:22:31 +10008250 appendshortlink $b [mc "Skipping merge commit "] "\n"
Paul Mackerras010509f2009-04-09 22:10:20 +10008251 set skipb 1
8252 } else {
8253 set patchb [getpatchid $b]
8254 }
8255 if {!$skipa && !$skipb} {
8256 set heada [lindex $commitinfo($a) 0]
8257 set headb [lindex $commitinfo($b) 0]
Paul Mackerras6f63fc12009-04-21 22:22:31 +10008258 if {$patcha eq "error"} {
8259 appendshortlink $a [mc "Error getting patch ID for "] \
8260 [mc " - stopping\n"]
8261 break
8262 }
8263 if {$patchb eq "error"} {
8264 appendshortlink $b [mc "Error getting patch ID for "] \
8265 [mc " - stopping\n"]
8266 break
8267 }
Paul Mackerras010509f2009-04-09 22:10:20 +10008268 if {$patcha eq $patchb} {
8269 if {$heada eq $headb} {
Paul Mackerras6f63fc12009-04-21 22:22:31 +10008270 appendshortlink $a [mc "Commit "]
8271 appendshortlink $b " == " " $heada\n"
Paul Mackerras010509f2009-04-09 22:10:20 +10008272 } else {
Paul Mackerras6f63fc12009-04-21 22:22:31 +10008273 appendshortlink $a [mc "Commit "] " $heada\n"
8274 appendshortlink $b [mc " is the same patch as\n "] \
8275 " $headb\n"
Paul Mackerras010509f2009-04-09 22:10:20 +10008276 }
8277 set skipa 1
8278 set skipb 1
8279 } else {
8280 $ctext insert end "\n"
Paul Mackerras6f63fc12009-04-21 22:22:31 +10008281 appendshortlink $a [mc "Commit "] " $heada\n"
8282 appendshortlink $b [mc " differs from\n "] \
8283 " $headb\n"
Paul Mackerrasc21398b2009-09-07 10:08:21 +10008284 $ctext insert end [mc "Diff of commits:\n\n"]
8285 $ctext conf -state disabled
8286 update
8287 diffcommits $a $b
8288 return
Paul Mackerras010509f2009-04-09 22:10:20 +10008289 }
8290 }
8291 if {$skipa} {
8292 if {[llength $children($curview,$a)] != 1} {
8293 $ctext insert end "\n"
Paul Mackerras6f63fc12009-04-21 22:22:31 +10008294 appendshortlink $a [mc "Commit "] \
8295 [mc " has %s children - stopping\n" \
8296 [llength $children($curview,$a)]]
Paul Mackerras010509f2009-04-09 22:10:20 +10008297 break
8298 }
8299 set a [lindex $children($curview,$a) 0]
8300 }
8301 if {$skipb} {
8302 if {[llength $children($curview,$b)] != 1} {
Paul Mackerras6f63fc12009-04-21 22:22:31 +10008303 appendshortlink $b [mc "Commit "] \
8304 [mc " has %s children - stopping\n" \
8305 [llength $children($curview,$b)]]
Paul Mackerras010509f2009-04-09 22:10:20 +10008306 break
8307 }
8308 set b [lindex $children($curview,$b) 0]
8309 }
8310 }
8311 $ctext conf -state disabled
8312}
8313
Paul Mackerrasc21398b2009-09-07 10:08:21 +10008314proc diffcommits {a b} {
8315 global diffcontext diffids blobdifffd diffinhdr
8316
8317 set tmpdir [gitknewtmpdir]
8318 set fna [file join $tmpdir "commit-[string range $a 0 7]"]
8319 set fnb [file join $tmpdir "commit-[string range $b 0 7]"]
8320 if {[catch {
8321 exec git diff-tree -p --pretty $a >$fna
8322 exec git diff-tree -p --pretty $b >$fnb
8323 } err]} {
8324 error_popup [mc "Error writing commit to file: %s" $err]
8325 return
8326 }
8327 if {[catch {
8328 set fd [open "| diff -U$diffcontext $fna $fnb" r]
8329 } err]} {
8330 error_popup [mc "Error diffing commits: %s" $err]
8331 return
8332 }
8333 set diffids [list commits $a $b]
8334 set blobdifffd($diffids) $fd
8335 set diffinhdr 0
8336 filerun $fd [list getblobdiffline $fd $diffids]
8337}
8338
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008339proc diffvssel {dirn} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11008340 global rowmenuid selectedline
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008341
Paul Mackerras94b4a692008-05-20 20:51:06 +10008342 if {$selectedline eq {}} return
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008343 if {$dirn} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11008344 set oldid [commitonrow $selectedline]
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008345 set newid $rowmenuid
8346 } else {
8347 set oldid $rowmenuid
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11008348 set newid [commitonrow $selectedline]
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008349 }
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10008350 addtohistory [list doseldiff $oldid $newid]
8351 doseldiff $oldid $newid
8352}
8353
8354proc doseldiff {oldid newid} {
Paul Mackerras7fcceed2006-04-27 19:21:49 +10008355 global ctext
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10008356 global commitinfo
8357
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008358 $ctext conf -state normal
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008359 clear_ctext
Christian Stimmingd990ced2007-11-07 18:42:55 +01008360 init_flist [mc "Top"]
8361 $ctext insert end "[mc "From"] "
Paul Mackerras97645682007-08-23 22:24:38 +10008362 $ctext insert end $oldid link0
8363 setlink $oldid link0
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10008364 $ctext insert end "\n "
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008365 $ctext insert end [lindex $commitinfo($oldid) 0]
Christian Stimmingd990ced2007-11-07 18:42:55 +01008366 $ctext insert end "\n\n[mc "To"] "
Paul Mackerras97645682007-08-23 22:24:38 +10008367 $ctext insert end $newid link1
8368 setlink $newid link1
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10008369 $ctext insert end "\n "
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008370 $ctext insert end [lindex $commitinfo($newid) 0]
8371 $ctext insert end "\n"
8372 $ctext conf -state disabled
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008373 $ctext tag remove found 1.0 end
Paul Mackerrasd3272442005-11-28 20:41:56 +11008374 startdiff [list $oldid $newid]
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008375}
8376
Paul Mackerras74daedb2005-06-27 19:27:32 +10008377proc mkpatch {} {
8378 global rowmenuid currentid commitinfo patchtop patchnum
8379
8380 if {![info exists currentid]} return
8381 set oldid $currentid
8382 set oldhead [lindex $commitinfo($oldid) 0]
8383 set newid $rowmenuid
8384 set newhead [lindex $commitinfo($newid) 0]
8385 set top .patch
8386 set patchtop $top
8387 catch {destroy $top}
8388 toplevel $top
Alexander Gavrilove7d64002008-11-11 23:55:42 +03008389 make_transient $top .
Christian Stimmingd990ced2007-11-07 18:42:55 +01008390 label $top.title -text [mc "Generate patch"]
Paul Mackerras4a2139f2005-06-29 09:47:48 +10008391 grid $top.title - -pady 10
Christian Stimmingd990ced2007-11-07 18:42:55 +01008392 label $top.from -text [mc "From:"]
Paul Mackerras4a2139f2005-06-29 09:47:48 +10008393 entry $top.fromsha1 -width 40 -relief flat
Paul Mackerras74daedb2005-06-27 19:27:32 +10008394 $top.fromsha1 insert 0 $oldid
8395 $top.fromsha1 conf -state readonly
8396 grid $top.from $top.fromsha1 -sticky w
Paul Mackerras4a2139f2005-06-29 09:47:48 +10008397 entry $top.fromhead -width 60 -relief flat
Paul Mackerras74daedb2005-06-27 19:27:32 +10008398 $top.fromhead insert 0 $oldhead
8399 $top.fromhead conf -state readonly
8400 grid x $top.fromhead -sticky w
Christian Stimmingd990ced2007-11-07 18:42:55 +01008401 label $top.to -text [mc "To:"]
Paul Mackerras4a2139f2005-06-29 09:47:48 +10008402 entry $top.tosha1 -width 40 -relief flat
Paul Mackerras74daedb2005-06-27 19:27:32 +10008403 $top.tosha1 insert 0 $newid
8404 $top.tosha1 conf -state readonly
8405 grid $top.to $top.tosha1 -sticky w
Paul Mackerras4a2139f2005-06-29 09:47:48 +10008406 entry $top.tohead -width 60 -relief flat
Paul Mackerras74daedb2005-06-27 19:27:32 +10008407 $top.tohead insert 0 $newhead
8408 $top.tohead conf -state readonly
8409 grid x $top.tohead -sticky w
Christian Stimmingd990ced2007-11-07 18:42:55 +01008410 button $top.rev -text [mc "Reverse"] -command mkpatchrev -padx 5
Paul Mackerras74daedb2005-06-27 19:27:32 +10008411 grid $top.rev x -pady 10
Christian Stimmingd990ced2007-11-07 18:42:55 +01008412 label $top.flab -text [mc "Output file:"]
Paul Mackerras74daedb2005-06-27 19:27:32 +10008413 entry $top.fname -width 60
8414 $top.fname insert 0 [file normalize "patch$patchnum.patch"]
8415 incr patchnum
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10008416 grid $top.flab $top.fname -sticky w
Paul Mackerras74daedb2005-06-27 19:27:32 +10008417 frame $top.buts
Christian Stimmingd990ced2007-11-07 18:42:55 +01008418 button $top.buts.gen -text [mc "Generate"] -command mkpatchgo
8419 button $top.buts.can -text [mc "Cancel"] -command mkpatchcan
Alexander Gavrilov76f15942008-11-02 21:59:44 +03008420 bind $top <Key-Return> mkpatchgo
8421 bind $top <Key-Escape> mkpatchcan
Paul Mackerras74daedb2005-06-27 19:27:32 +10008422 grid $top.buts.gen $top.buts.can
8423 grid columnconfigure $top.buts 0 -weight 1 -uniform a
8424 grid columnconfigure $top.buts 1 -weight 1 -uniform a
8425 grid $top.buts - -pady 10 -sticky ew
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10008426 focus $top.fname
Paul Mackerras74daedb2005-06-27 19:27:32 +10008427}
8428
8429proc mkpatchrev {} {
8430 global patchtop
8431
8432 set oldid [$patchtop.fromsha1 get]
8433 set oldhead [$patchtop.fromhead get]
8434 set newid [$patchtop.tosha1 get]
8435 set newhead [$patchtop.tohead get]
8436 foreach e [list fromsha1 fromhead tosha1 tohead] \
8437 v [list $newid $newhead $oldid $oldhead] {
8438 $patchtop.$e conf -state normal
8439 $patchtop.$e delete 0 end
8440 $patchtop.$e insert 0 $v
8441 $patchtop.$e conf -state readonly
8442 }
8443}
8444
8445proc mkpatchgo {} {
Paul Mackerras8f489362007-07-13 19:49:37 +10008446 global patchtop nullid nullid2
Paul Mackerras74daedb2005-06-27 19:27:32 +10008447
8448 set oldid [$patchtop.fromsha1 get]
8449 set newid [$patchtop.tosha1 get]
8450 set fname [$patchtop.fname get]
Paul Mackerras8f489362007-07-13 19:49:37 +10008451 set cmd [diffcmd [list $oldid $newid] -p]
Paul Mackerrasd372e212007-09-15 12:08:38 +10008452 # trim off the initial "|"
8453 set cmd [lrange $cmd 1 end]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10008454 lappend cmd >$fname &
8455 if {[catch {eval exec $cmd} err]} {
Alexander Gavrilov84a76f12008-11-02 21:59:45 +03008456 error_popup "[mc "Error creating patch:"] $err" $patchtop
Paul Mackerras74daedb2005-06-27 19:27:32 +10008457 }
8458 catch {destroy $patchtop}
8459 unset patchtop
8460}
8461
8462proc mkpatchcan {} {
8463 global patchtop
8464
8465 catch {destroy $patchtop}
8466 unset patchtop
8467}
8468
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10008469proc mktag {} {
8470 global rowmenuid mktagtop commitinfo
8471
8472 set top .maketag
8473 set mktagtop $top
8474 catch {destroy $top}
8475 toplevel $top
Alexander Gavrilove7d64002008-11-11 23:55:42 +03008476 make_transient $top .
Christian Stimmingd990ced2007-11-07 18:42:55 +01008477 label $top.title -text [mc "Create tag"]
Paul Mackerras4a2139f2005-06-29 09:47:48 +10008478 grid $top.title - -pady 10
Christian Stimmingd990ced2007-11-07 18:42:55 +01008479 label $top.id -text [mc "ID:"]
Paul Mackerras4a2139f2005-06-29 09:47:48 +10008480 entry $top.sha1 -width 40 -relief flat
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10008481 $top.sha1 insert 0 $rowmenuid
8482 $top.sha1 conf -state readonly
8483 grid $top.id $top.sha1 -sticky w
Paul Mackerras4a2139f2005-06-29 09:47:48 +10008484 entry $top.head -width 60 -relief flat
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10008485 $top.head insert 0 [lindex $commitinfo($rowmenuid) 0]
8486 $top.head conf -state readonly
8487 grid x $top.head -sticky w
Christian Stimmingd990ced2007-11-07 18:42:55 +01008488 label $top.tlab -text [mc "Tag name:"]
Paul Mackerras4a2139f2005-06-29 09:47:48 +10008489 entry $top.tag -width 60
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10008490 grid $top.tlab $top.tag -sticky w
8491 frame $top.buts
Christian Stimmingd990ced2007-11-07 18:42:55 +01008492 button $top.buts.gen -text [mc "Create"] -command mktaggo
8493 button $top.buts.can -text [mc "Cancel"] -command mktagcan
Alexander Gavrilov76f15942008-11-02 21:59:44 +03008494 bind $top <Key-Return> mktaggo
8495 bind $top <Key-Escape> mktagcan
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10008496 grid $top.buts.gen $top.buts.can
8497 grid columnconfigure $top.buts 0 -weight 1 -uniform a
8498 grid columnconfigure $top.buts 1 -weight 1 -uniform a
8499 grid $top.buts - -pady 10 -sticky ew
8500 focus $top.tag
8501}
8502
8503proc domktag {} {
8504 global mktagtop env tagids idtags
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10008505
8506 set id [$mktagtop.sha1 get]
8507 set tag [$mktagtop.tag get]
8508 if {$tag == {}} {
Alexander Gavrilov84a76f12008-11-02 21:59:45 +03008509 error_popup [mc "No tag name specified"] $mktagtop
8510 return 0
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10008511 }
8512 if {[info exists tagids($tag)]} {
Alexander Gavrilov84a76f12008-11-02 21:59:45 +03008513 error_popup [mc "Tag \"%s\" already exists" $tag] $mktagtop
8514 return 0
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10008515 }
8516 if {[catch {
Gerrit Pape48750d62008-02-11 10:57:40 +00008517 exec git tag $tag $id
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10008518 } err]} {
Alexander Gavrilov84a76f12008-11-02 21:59:45 +03008519 error_popup "[mc "Error creating tag:"] $err" $mktagtop
8520 return 0
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10008521 }
8522
8523 set tagids($tag) $id
8524 lappend idtags($id) $tag
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10008525 redrawtags $id
Paul Mackerrasceadfe92006-08-08 20:55:36 +10008526 addedtag $id
Paul Mackerras887c9962007-08-20 19:36:20 +10008527 dispneartags 0
8528 run refill_reflist
Alexander Gavrilov84a76f12008-11-02 21:59:45 +03008529 return 1
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10008530}
8531
8532proc redrawtags {id} {
Paul Mackerrasb9fdba72009-04-09 09:34:46 +10008533 global canv linehtag idpos currentid curview cmitlisted markedid
Paul Mackerrasc11ff122008-05-26 10:11:33 +10008534 global canvxmax iddrawn circleitem mainheadid circlecolors
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10008535
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11008536 if {![commitinview $id $curview]} return
Paul Mackerras322a8cc2006-10-15 18:03:46 +10008537 if {![info exists iddrawn($id)]} return
Paul Mackerrasfc2a2562007-12-26 23:03:43 +11008538 set row [rowofcommit $id]
Paul Mackerrasc11ff122008-05-26 10:11:33 +10008539 if {$id eq $mainheadid} {
8540 set ofill yellow
8541 } else {
8542 set ofill [lindex $circlecolors $cmitlisted($curview,$id)]
8543 }
8544 $canv itemconf $circleitem($row) -fill $ofill
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10008545 $canv delete tag.$id
8546 set xt [eval drawtags $id $idpos($id)]
Paul Mackerras28593d32008-11-13 23:01:46 +11008547 $canv coords $linehtag($id) $xt [lindex $idpos($id) 2]
8548 set text [$canv itemcget $linehtag($id) -text]
8549 set font [$canv itemcget $linehtag($id) -font]
Paul Mackerrasfc2a2562007-12-26 23:03:43 +11008550 set xr [expr {$xt + [font measure $font $text]}]
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10008551 if {$xr > $canvxmax} {
8552 set canvxmax $xr
8553 setcanvscroll
8554 }
Paul Mackerrasfc2a2562007-12-26 23:03:43 +11008555 if {[info exists currentid] && $currentid == $id} {
Paul Mackerras28593d32008-11-13 23:01:46 +11008556 make_secsel $id
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10008557 }
Paul Mackerrasb9fdba72009-04-09 09:34:46 +10008558 if {[info exists markedid] && $markedid eq $id} {
8559 make_idmark $id
8560 }
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10008561}
8562
8563proc mktagcan {} {
8564 global mktagtop
8565
8566 catch {destroy $mktagtop}
8567 unset mktagtop
8568}
8569
8570proc mktaggo {} {
Alexander Gavrilov84a76f12008-11-02 21:59:45 +03008571 if {![domktag]} return
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10008572 mktagcan
8573}
8574
Paul Mackerras4a2139f2005-06-29 09:47:48 +10008575proc writecommit {} {
8576 global rowmenuid wrcomtop commitinfo wrcomcmd
8577
8578 set top .writecommit
8579 set wrcomtop $top
8580 catch {destroy $top}
8581 toplevel $top
Alexander Gavrilove7d64002008-11-11 23:55:42 +03008582 make_transient $top .
Christian Stimmingd990ced2007-11-07 18:42:55 +01008583 label $top.title -text [mc "Write commit to file"]
Paul Mackerras4a2139f2005-06-29 09:47:48 +10008584 grid $top.title - -pady 10
Christian Stimmingd990ced2007-11-07 18:42:55 +01008585 label $top.id -text [mc "ID:"]
Paul Mackerras4a2139f2005-06-29 09:47:48 +10008586 entry $top.sha1 -width 40 -relief flat
8587 $top.sha1 insert 0 $rowmenuid
8588 $top.sha1 conf -state readonly
8589 grid $top.id $top.sha1 -sticky w
8590 entry $top.head -width 60 -relief flat
8591 $top.head insert 0 [lindex $commitinfo($rowmenuid) 0]
8592 $top.head conf -state readonly
8593 grid x $top.head -sticky w
Christian Stimmingd990ced2007-11-07 18:42:55 +01008594 label $top.clab -text [mc "Command:"]
Paul Mackerras4a2139f2005-06-29 09:47:48 +10008595 entry $top.cmd -width 60 -textvariable wrcomcmd
8596 grid $top.clab $top.cmd -sticky w -pady 10
Christian Stimmingd990ced2007-11-07 18:42:55 +01008597 label $top.flab -text [mc "Output file:"]
Paul Mackerras4a2139f2005-06-29 09:47:48 +10008598 entry $top.fname -width 60
8599 $top.fname insert 0 [file normalize "commit-[string range $rowmenuid 0 6]"]
8600 grid $top.flab $top.fname -sticky w
8601 frame $top.buts
Christian Stimmingd990ced2007-11-07 18:42:55 +01008602 button $top.buts.gen -text [mc "Write"] -command wrcomgo
8603 button $top.buts.can -text [mc "Cancel"] -command wrcomcan
Alexander Gavrilov76f15942008-11-02 21:59:44 +03008604 bind $top <Key-Return> wrcomgo
8605 bind $top <Key-Escape> wrcomcan
Paul Mackerras4a2139f2005-06-29 09:47:48 +10008606 grid $top.buts.gen $top.buts.can
8607 grid columnconfigure $top.buts 0 -weight 1 -uniform a
8608 grid columnconfigure $top.buts 1 -weight 1 -uniform a
8609 grid $top.buts - -pady 10 -sticky ew
8610 focus $top.fname
8611}
8612
8613proc wrcomgo {} {
8614 global wrcomtop
8615
8616 set id [$wrcomtop.sha1 get]
8617 set cmd "echo $id | [$wrcomtop.cmd get]"
8618 set fname [$wrcomtop.fname get]
8619 if {[catch {exec sh -c $cmd >$fname &} err]} {
Alexander Gavrilov84a76f12008-11-02 21:59:45 +03008620 error_popup "[mc "Error writing commit:"] $err" $wrcomtop
Paul Mackerras4a2139f2005-06-29 09:47:48 +10008621 }
8622 catch {destroy $wrcomtop}
8623 unset wrcomtop
8624}
8625
8626proc wrcomcan {} {
8627 global wrcomtop
8628
8629 catch {destroy $wrcomtop}
8630 unset wrcomtop
8631}
8632
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10008633proc mkbranch {} {
8634 global rowmenuid mkbrtop
8635
8636 set top .makebranch
8637 catch {destroy $top}
8638 toplevel $top
Alexander Gavrilove7d64002008-11-11 23:55:42 +03008639 make_transient $top .
Christian Stimmingd990ced2007-11-07 18:42:55 +01008640 label $top.title -text [mc "Create new branch"]
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10008641 grid $top.title - -pady 10
Christian Stimmingd990ced2007-11-07 18:42:55 +01008642 label $top.id -text [mc "ID:"]
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10008643 entry $top.sha1 -width 40 -relief flat
8644 $top.sha1 insert 0 $rowmenuid
8645 $top.sha1 conf -state readonly
8646 grid $top.id $top.sha1 -sticky w
Christian Stimmingd990ced2007-11-07 18:42:55 +01008647 label $top.nlab -text [mc "Name:"]
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10008648 entry $top.name -width 40
8649 grid $top.nlab $top.name -sticky w
8650 frame $top.buts
Christian Stimmingd990ced2007-11-07 18:42:55 +01008651 button $top.buts.go -text [mc "Create"] -command [list mkbrgo $top]
8652 button $top.buts.can -text [mc "Cancel"] -command "catch {destroy $top}"
Alexander Gavrilov76f15942008-11-02 21:59:44 +03008653 bind $top <Key-Return> [list mkbrgo $top]
8654 bind $top <Key-Escape> "catch {destroy $top}"
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10008655 grid $top.buts.go $top.buts.can
8656 grid columnconfigure $top.buts 0 -weight 1 -uniform a
8657 grid columnconfigure $top.buts 1 -weight 1 -uniform a
8658 grid $top.buts - -pady 10 -sticky ew
8659 focus $top.name
8660}
8661
8662proc mkbrgo {top} {
8663 global headids idheads
8664
8665 set name [$top.name get]
8666 set id [$top.sha1 get]
Alexander Gavrilovbee866f2008-10-08 11:05:35 +04008667 set cmdargs {}
8668 set old_id {}
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10008669 if {$name eq {}} {
Alexander Gavrilov84a76f12008-11-02 21:59:45 +03008670 error_popup [mc "Please specify a name for the new branch"] $top
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10008671 return
8672 }
Alexander Gavrilovbee866f2008-10-08 11:05:35 +04008673 if {[info exists headids($name)]} {
8674 if {![confirm_popup [mc \
Alexander Gavrilov84a76f12008-11-02 21:59:45 +03008675 "Branch '%s' already exists. Overwrite?" $name] $top]} {
Alexander Gavrilovbee866f2008-10-08 11:05:35 +04008676 return
8677 }
8678 set old_id $headids($name)
8679 lappend cmdargs -f
8680 }
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10008681 catch {destroy $top}
Alexander Gavrilovbee866f2008-10-08 11:05:35 +04008682 lappend cmdargs $name $id
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10008683 nowbusy newbranch
8684 update
8685 if {[catch {
Alexander Gavrilovbee866f2008-10-08 11:05:35 +04008686 eval exec git branch $cmdargs
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10008687 } err]} {
8688 notbusy newbranch
8689 error_popup $err
8690 } else {
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10008691 notbusy newbranch
Alexander Gavrilovbee866f2008-10-08 11:05:35 +04008692 if {$old_id ne {}} {
8693 movehead $id $name
8694 movedhead $id $name
8695 redrawtags $old_id
8696 redrawtags $id
8697 } else {
8698 set headids($name) $id
8699 lappend idheads($id) $name
8700 addedhead $id $name
8701 redrawtags $id
8702 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10008703 dispneartags 0
Paul Mackerras887c9962007-08-20 19:36:20 +10008704 run refill_reflist
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10008705 }
8706}
8707
Alexander Gavrilov15e35052008-11-02 21:59:47 +03008708proc exec_citool {tool_args {baseid {}}} {
8709 global commitinfo env
8710
8711 set save_env [array get env GIT_AUTHOR_*]
8712
8713 if {$baseid ne {}} {
8714 if {![info exists commitinfo($baseid)]} {
8715 getcommit $baseid
8716 }
8717 set author [lindex $commitinfo($baseid) 1]
8718 set date [lindex $commitinfo($baseid) 2]
8719 if {[regexp {^\s*(\S.*\S|\S)\s*<(.*)>\s*$} \
8720 $author author name email]
8721 && $date ne {}} {
8722 set env(GIT_AUTHOR_NAME) $name
8723 set env(GIT_AUTHOR_EMAIL) $email
8724 set env(GIT_AUTHOR_DATE) $date
8725 }
8726 }
8727
8728 eval exec git citool $tool_args &
8729
8730 array unset env GIT_AUTHOR_*
8731 array set env $save_env
8732}
8733
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10008734proc cherrypick {} {
Paul Mackerras468bcae2008-03-03 10:19:35 +11008735 global rowmenuid curview
Paul Mackerrasb8a938c2008-02-13 22:12:31 +11008736 global mainhead mainheadid
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10008737
Paul Mackerrase11f1232007-06-16 20:29:25 +10008738 set oldhead [exec git rev-parse HEAD]
8739 set dheads [descheads $rowmenuid]
8740 if {$dheads ne {} && [lsearch -exact $dheads $oldhead] >= 0} {
Christian Stimmingd990ced2007-11-07 18:42:55 +01008741 set ok [confirm_popup [mc "Commit %s is already\
8742 included in branch %s -- really re-apply it?" \
8743 [string range $rowmenuid 0 7] $mainhead]]
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10008744 if {!$ok} return
8745 }
Christian Stimmingd990ced2007-11-07 18:42:55 +01008746 nowbusy cherrypick [mc "Cherry-picking"]
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10008747 update
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10008748 # Unfortunately git-cherry-pick writes stuff to stderr even when
8749 # no error occurs, and exec takes that as an indication of error...
8750 if {[catch {exec sh -c "git cherry-pick -r $rowmenuid 2>&1"} err]} {
8751 notbusy cherrypick
Alexander Gavrilov15e35052008-11-02 21:59:47 +03008752 if {[regexp -line \
Paul Mackerras887a7912008-11-08 21:37:09 +11008753 {Entry '(.*)' (would be overwritten by merge|not uptodate)} \
8754 $err msg fname]} {
8755 error_popup [mc "Cherry-pick failed because of local changes\
8756 to file '%s'.\nPlease commit, reset or stash\
8757 your changes and try again." $fname]
8758 } elseif {[regexp -line \
8759 {^(CONFLICT \(.*\):|Automatic cherry-pick failed)} \
8760 $err]} {
8761 if {[confirm_popup [mc "Cherry-pick failed because of merge\
8762 conflict.\nDo you wish to run git citool to\
8763 resolve it?"]]} {
8764 # Force citool to read MERGE_MSG
8765 file delete [file join [gitdir] "GITGUI_MSG"]
8766 exec_citool {} $rowmenuid
8767 }
Alexander Gavrilov15e35052008-11-02 21:59:47 +03008768 } else {
8769 error_popup $err
8770 }
Paul Mackerras887a7912008-11-08 21:37:09 +11008771 run updatecommits
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10008772 return
8773 }
8774 set newhead [exec git rev-parse HEAD]
8775 if {$newhead eq $oldhead} {
8776 notbusy cherrypick
Christian Stimmingd990ced2007-11-07 18:42:55 +01008777 error_popup [mc "No changes committed"]
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10008778 return
8779 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10008780 addnewchild $newhead $oldhead
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11008781 if {[commitinview $oldhead $curview]} {
Paul Mackerrascdc84292008-11-18 19:54:14 +11008782 # XXX this isn't right if we have a path limit...
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11008783 insertrow $newhead $oldhead $curview
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10008784 if {$mainhead ne {}} {
Paul Mackerrase11f1232007-06-16 20:29:25 +10008785 movehead $newhead $mainhead
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10008786 movedhead $newhead $mainhead
8787 }
Paul Mackerrasc11ff122008-05-26 10:11:33 +10008788 set mainheadid $newhead
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10008789 redrawtags $oldhead
8790 redrawtags $newhead
Paul Mackerras46308ea2008-01-15 22:16:32 +11008791 selbyid $newhead
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10008792 }
8793 notbusy cherrypick
8794}
8795
Paul Mackerras6fb735a2006-10-19 10:09:06 +10008796proc resethead {} {
Paul Mackerrasb8a938c2008-02-13 22:12:31 +11008797 global mainhead rowmenuid confirm_ok resettype
Paul Mackerras6fb735a2006-10-19 10:09:06 +10008798
8799 set confirm_ok 0
8800 set w ".confirmreset"
8801 toplevel $w
Alexander Gavrilove7d64002008-11-11 23:55:42 +03008802 make_transient $w .
Christian Stimmingd990ced2007-11-07 18:42:55 +01008803 wm title $w [mc "Confirm reset"]
Paul Mackerras6fb735a2006-10-19 10:09:06 +10008804 message $w.m -text \
Christian Stimmingd990ced2007-11-07 18:42:55 +01008805 [mc "Reset branch %s to %s?" $mainhead [string range $rowmenuid 0 7]] \
Paul Mackerras6fb735a2006-10-19 10:09:06 +10008806 -justify center -aspect 1000
8807 pack $w.m -side top -fill x -padx 20 -pady 20
8808 frame $w.f -relief sunken -border 2
Christian Stimmingd990ced2007-11-07 18:42:55 +01008809 message $w.f.rt -text [mc "Reset type:"] -aspect 1000
Paul Mackerras6fb735a2006-10-19 10:09:06 +10008810 grid $w.f.rt -sticky w
8811 set resettype mixed
8812 radiobutton $w.f.soft -value soft -variable resettype -justify left \
Christian Stimmingd990ced2007-11-07 18:42:55 +01008813 -text [mc "Soft: Leave working tree and index untouched"]
Paul Mackerras6fb735a2006-10-19 10:09:06 +10008814 grid $w.f.soft -sticky w
8815 radiobutton $w.f.mixed -value mixed -variable resettype -justify left \
Christian Stimmingd990ced2007-11-07 18:42:55 +01008816 -text [mc "Mixed: Leave working tree untouched, reset index"]
Paul Mackerras6fb735a2006-10-19 10:09:06 +10008817 grid $w.f.mixed -sticky w
8818 radiobutton $w.f.hard -value hard -variable resettype -justify left \
Christian Stimmingd990ced2007-11-07 18:42:55 +01008819 -text [mc "Hard: Reset working tree and index\n(discard ALL local changes)"]
Paul Mackerras6fb735a2006-10-19 10:09:06 +10008820 grid $w.f.hard -sticky w
8821 pack $w.f -side top -fill x
Christian Stimmingd990ced2007-11-07 18:42:55 +01008822 button $w.ok -text [mc OK] -command "set confirm_ok 1; destroy $w"
Paul Mackerras6fb735a2006-10-19 10:09:06 +10008823 pack $w.ok -side left -fill x -padx 20 -pady 20
Christian Stimmingd990ced2007-11-07 18:42:55 +01008824 button $w.cancel -text [mc Cancel] -command "destroy $w"
Alexander Gavrilov76f15942008-11-02 21:59:44 +03008825 bind $w <Key-Escape> [list destroy $w]
Paul Mackerras6fb735a2006-10-19 10:09:06 +10008826 pack $w.cancel -side right -fill x -padx 20 -pady 20
8827 bind $w <Visibility> "grab $w; focus $w"
8828 tkwait window $w
8829 if {!$confirm_ok} return
Paul Mackerras706d6c32007-06-26 11:09:49 +10008830 if {[catch {set fd [open \
Paul Mackerras08ba8202008-05-12 10:18:38 +10008831 [list | git reset --$resettype $rowmenuid 2>@1] r]} err]} {
Paul Mackerras6fb735a2006-10-19 10:09:06 +10008832 error_popup $err
8833 } else {
Paul Mackerras706d6c32007-06-26 11:09:49 +10008834 dohidelocalchanges
Paul Mackerrasa137a902007-10-23 21:12:49 +10008835 filerun $fd [list readresetstat $fd]
Christian Stimmingd990ced2007-11-07 18:42:55 +01008836 nowbusy reset [mc "Resetting"]
Paul Mackerras46308ea2008-01-15 22:16:32 +11008837 selbyid $rowmenuid
Paul Mackerras706d6c32007-06-26 11:09:49 +10008838 }
8839}
8840
Paul Mackerrasa137a902007-10-23 21:12:49 +10008841proc readresetstat {fd} {
8842 global mainhead mainheadid showlocalchanges rprogcoord
Paul Mackerras706d6c32007-06-26 11:09:49 +10008843
8844 if {[gets $fd line] >= 0} {
8845 if {[regexp {([0-9]+)% \(([0-9]+)/([0-9]+)\)} $line match p m n]} {
Paul Mackerrasa137a902007-10-23 21:12:49 +10008846 set rprogcoord [expr {1.0 * $m / $n}]
8847 adjustprogress
Paul Mackerras706d6c32007-06-26 11:09:49 +10008848 }
8849 return 1
8850 }
Paul Mackerrasa137a902007-10-23 21:12:49 +10008851 set rprogcoord 0
8852 adjustprogress
Paul Mackerras706d6c32007-06-26 11:09:49 +10008853 notbusy reset
8854 if {[catch {close $fd} err]} {
8855 error_popup $err
8856 }
8857 set oldhead $mainheadid
8858 set newhead [exec git rev-parse HEAD]
8859 if {$newhead ne $oldhead} {
8860 movehead $newhead $mainhead
8861 movedhead $newhead $mainhead
8862 set mainheadid $newhead
Paul Mackerras6fb735a2006-10-19 10:09:06 +10008863 redrawtags $oldhead
Paul Mackerras706d6c32007-06-26 11:09:49 +10008864 redrawtags $newhead
Paul Mackerras6fb735a2006-10-19 10:09:06 +10008865 }
8866 if {$showlocalchanges} {
8867 doshowlocalchanges
8868 }
Paul Mackerras706d6c32007-06-26 11:09:49 +10008869 return 0
Paul Mackerras6fb735a2006-10-19 10:09:06 +10008870}
8871
Paul Mackerras10299152006-08-02 09:52:01 +10008872# context menu for a head
8873proc headmenu {x y id head} {
Paul Mackerras00609462007-06-17 17:08:35 +10008874 global headmenuid headmenuhead headctxmenu mainhead
Paul Mackerras10299152006-08-02 09:52:01 +10008875
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10008876 stopfinding
Paul Mackerras10299152006-08-02 09:52:01 +10008877 set headmenuid $id
8878 set headmenuhead $head
Paul Mackerras00609462007-06-17 17:08:35 +10008879 set state normal
8880 if {$head eq $mainhead} {
8881 set state disabled
8882 }
8883 $headctxmenu entryconfigure 0 -state $state
8884 $headctxmenu entryconfigure 1 -state $state
Paul Mackerras10299152006-08-02 09:52:01 +10008885 tk_popup $headctxmenu $x $y
8886}
8887
8888proc cobranch {} {
Paul Mackerrasc11ff122008-05-26 10:11:33 +10008889 global headmenuid headmenuhead headids
Paul Mackerrascdc84292008-11-18 19:54:14 +11008890 global showlocalchanges
Paul Mackerras10299152006-08-02 09:52:01 +10008891
8892 # check the tree is clean first??
Christian Stimmingd990ced2007-11-07 18:42:55 +01008893 nowbusy checkout [mc "Checking out"]
Paul Mackerras10299152006-08-02 09:52:01 +10008894 update
Paul Mackerras219ea3a2006-09-07 10:21:39 +10008895 dohidelocalchanges
Paul Mackerras10299152006-08-02 09:52:01 +10008896 if {[catch {
Paul Mackerras08ba8202008-05-12 10:18:38 +10008897 set fd [open [list | git checkout $headmenuhead 2>@1] r]
Paul Mackerras10299152006-08-02 09:52:01 +10008898 } err]} {
8899 notbusy checkout
8900 error_popup $err
Paul Mackerras08ba8202008-05-12 10:18:38 +10008901 if {$showlocalchanges} {
8902 dodiffindex
Paul Mackerras10299152006-08-02 09:52:01 +10008903 }
Paul Mackerras08ba8202008-05-12 10:18:38 +10008904 } else {
8905 filerun $fd [list readcheckoutstat $fd $headmenuhead $headmenuid]
Paul Mackerras6fb735a2006-10-19 10:09:06 +10008906 }
Paul Mackerras08ba8202008-05-12 10:18:38 +10008907}
8908
8909proc readcheckoutstat {fd newhead newheadid} {
8910 global mainhead mainheadid headids showlocalchanges progresscoords
Paul Mackerrascdc84292008-11-18 19:54:14 +11008911 global viewmainheadid curview
Paul Mackerras08ba8202008-05-12 10:18:38 +10008912
8913 if {[gets $fd line] >= 0} {
8914 if {[regexp {([0-9]+)% \(([0-9]+)/([0-9]+)\)} $line match p m n]} {
8915 set progresscoords [list 0 [expr {1.0 * $m / $n}]]
8916 adjustprogress
8917 }
8918 return 1
8919 }
8920 set progresscoords {0 0}
8921 adjustprogress
8922 notbusy checkout
8923 if {[catch {close $fd} err]} {
8924 error_popup $err
8925 }
Paul Mackerrasc11ff122008-05-26 10:11:33 +10008926 set oldmainid $mainheadid
Paul Mackerras08ba8202008-05-12 10:18:38 +10008927 set mainhead $newhead
8928 set mainheadid $newheadid
Paul Mackerrascdc84292008-11-18 19:54:14 +11008929 set viewmainheadid($curview) $newheadid
Paul Mackerrasc11ff122008-05-26 10:11:33 +10008930 redrawtags $oldmainid
Paul Mackerras08ba8202008-05-12 10:18:38 +10008931 redrawtags $newheadid
8932 selbyid $newheadid
Paul Mackerras6fb735a2006-10-19 10:09:06 +10008933 if {$showlocalchanges} {
8934 dodiffindex
Paul Mackerras10299152006-08-02 09:52:01 +10008935 }
8936}
8937
8938proc rmbranch {} {
Paul Mackerrase11f1232007-06-16 20:29:25 +10008939 global headmenuid headmenuhead mainhead
Paul Mackerrasb1054ac2007-08-15 10:09:47 +10008940 global idheads
Paul Mackerras10299152006-08-02 09:52:01 +10008941
8942 set head $headmenuhead
8943 set id $headmenuid
Paul Mackerras00609462007-06-17 17:08:35 +10008944 # this check shouldn't be needed any more...
Paul Mackerras10299152006-08-02 09:52:01 +10008945 if {$head eq $mainhead} {
Christian Stimmingd990ced2007-11-07 18:42:55 +01008946 error_popup [mc "Cannot delete the currently checked-out branch"]
Paul Mackerras10299152006-08-02 09:52:01 +10008947 return
8948 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10008949 set dheads [descheads $id]
Paul Mackerrasd7b16112007-08-17 17:57:31 +10008950 if {[llength $dheads] == 1 && $idheads($dheads) eq $head} {
Paul Mackerras10299152006-08-02 09:52:01 +10008951 # the stuff on this branch isn't on any other branch
Christian Stimmingd990ced2007-11-07 18:42:55 +01008952 if {![confirm_popup [mc "The commits on branch %s aren't on any other\
8953 branch.\nReally delete branch %s?" $head $head]]} return
Paul Mackerras10299152006-08-02 09:52:01 +10008954 }
8955 nowbusy rmbranch
8956 update
8957 if {[catch {exec git branch -D $head} err]} {
8958 notbusy rmbranch
8959 error_popup $err
8960 return
8961 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10008962 removehead $id $head
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10008963 removedhead $id $head
Paul Mackerras10299152006-08-02 09:52:01 +10008964 redrawtags $id
8965 notbusy rmbranch
Paul Mackerrase11f1232007-06-16 20:29:25 +10008966 dispneartags 0
Paul Mackerras887c9962007-08-20 19:36:20 +10008967 run refill_reflist
8968}
8969
8970# Display a list of tags and heads
8971proc showrefs {} {
Paul Mackerras9c311b32007-10-04 22:27:13 +10008972 global showrefstop bgcolor fgcolor selectbgcolor
8973 global bglist fglist reflistfilter reflist maincursor
Paul Mackerras887c9962007-08-20 19:36:20 +10008974
8975 set top .showrefs
8976 set showrefstop $top
8977 if {[winfo exists $top]} {
8978 raise $top
8979 refill_reflist
8980 return
8981 }
8982 toplevel $top
Christian Stimmingd990ced2007-11-07 18:42:55 +01008983 wm title $top [mc "Tags and heads: %s" [file tail [pwd]]]
Alexander Gavrilove7d64002008-11-11 23:55:42 +03008984 make_transient $top .
Paul Mackerras887c9962007-08-20 19:36:20 +10008985 text $top.list -background $bgcolor -foreground $fgcolor \
Paul Mackerras9c311b32007-10-04 22:27:13 +10008986 -selectbackground $selectbgcolor -font mainfont \
Paul Mackerras887c9962007-08-20 19:36:20 +10008987 -xscrollcommand "$top.xsb set" -yscrollcommand "$top.ysb set" \
8988 -width 30 -height 20 -cursor $maincursor \
8989 -spacing1 1 -spacing3 1 -state disabled
8990 $top.list tag configure highlight -background $selectbgcolor
8991 lappend bglist $top.list
8992 lappend fglist $top.list
8993 scrollbar $top.ysb -command "$top.list yview" -orient vertical
8994 scrollbar $top.xsb -command "$top.list xview" -orient horizontal
8995 grid $top.list $top.ysb -sticky nsew
8996 grid $top.xsb x -sticky ew
8997 frame $top.f
Paul Mackerrasb039f0a2008-01-06 15:54:46 +11008998 label $top.f.l -text "[mc "Filter"]: "
8999 entry $top.f.e -width 20 -textvariable reflistfilter
Paul Mackerras887c9962007-08-20 19:36:20 +10009000 set reflistfilter "*"
9001 trace add variable reflistfilter write reflistfilter_change
9002 pack $top.f.e -side right -fill x -expand 1
9003 pack $top.f.l -side left
9004 grid $top.f - -sticky ew -pady 2
Paul Mackerrasb039f0a2008-01-06 15:54:46 +11009005 button $top.close -command [list destroy $top] -text [mc "Close"]
Alexander Gavrilov76f15942008-11-02 21:59:44 +03009006 bind $top <Key-Escape> [list destroy $top]
Paul Mackerras887c9962007-08-20 19:36:20 +10009007 grid $top.close -
9008 grid columnconfigure $top 0 -weight 1
9009 grid rowconfigure $top 0 -weight 1
9010 bind $top.list <1> {break}
9011 bind $top.list <B1-Motion> {break}
9012 bind $top.list <ButtonRelease-1> {sel_reflist %W %x %y; break}
9013 set reflist {}
9014 refill_reflist
9015}
9016
9017proc sel_reflist {w x y} {
9018 global showrefstop reflist headids tagids otherrefids
9019
9020 if {![winfo exists $showrefstop]} return
9021 set l [lindex [split [$w index "@$x,$y"] "."] 0]
9022 set ref [lindex $reflist [expr {$l-1}]]
9023 set n [lindex $ref 0]
9024 switch -- [lindex $ref 1] {
9025 "H" {selbyid $headids($n)}
9026 "T" {selbyid $tagids($n)}
9027 "o" {selbyid $otherrefids($n)}
9028 }
9029 $showrefstop.list tag add highlight $l.0 "$l.0 lineend"
9030}
9031
9032proc unsel_reflist {} {
9033 global showrefstop
9034
9035 if {![info exists showrefstop] || ![winfo exists $showrefstop]} return
9036 $showrefstop.list tag remove highlight 0.0 end
9037}
9038
9039proc reflistfilter_change {n1 n2 op} {
9040 global reflistfilter
9041
9042 after cancel refill_reflist
9043 after 200 refill_reflist
9044}
9045
9046proc refill_reflist {} {
9047 global reflist reflistfilter showrefstop headids tagids otherrefids
Paul Mackerrasd375ef92008-10-21 10:18:12 +11009048 global curview
Paul Mackerras887c9962007-08-20 19:36:20 +10009049
9050 if {![info exists showrefstop] || ![winfo exists $showrefstop]} return
9051 set refs {}
9052 foreach n [array names headids] {
9053 if {[string match $reflistfilter $n]} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11009054 if {[commitinview $headids($n) $curview]} {
Paul Mackerras887c9962007-08-20 19:36:20 +10009055 lappend refs [list $n H]
9056 } else {
Paul Mackerrasd375ef92008-10-21 10:18:12 +11009057 interestedin $headids($n) {run refill_reflist}
Paul Mackerras887c9962007-08-20 19:36:20 +10009058 }
9059 }
9060 }
9061 foreach n [array names tagids] {
9062 if {[string match $reflistfilter $n]} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11009063 if {[commitinview $tagids($n) $curview]} {
Paul Mackerras887c9962007-08-20 19:36:20 +10009064 lappend refs [list $n T]
9065 } else {
Paul Mackerrasd375ef92008-10-21 10:18:12 +11009066 interestedin $tagids($n) {run refill_reflist}
Paul Mackerras887c9962007-08-20 19:36:20 +10009067 }
9068 }
9069 }
9070 foreach n [array names otherrefids] {
9071 if {[string match $reflistfilter $n]} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11009072 if {[commitinview $otherrefids($n) $curview]} {
Paul Mackerras887c9962007-08-20 19:36:20 +10009073 lappend refs [list $n o]
9074 } else {
Paul Mackerrasd375ef92008-10-21 10:18:12 +11009075 interestedin $otherrefids($n) {run refill_reflist}
Paul Mackerras887c9962007-08-20 19:36:20 +10009076 }
9077 }
9078 }
9079 set refs [lsort -index 0 $refs]
9080 if {$refs eq $reflist} return
9081
9082 # Update the contents of $showrefstop.list according to the
9083 # differences between $reflist (old) and $refs (new)
9084 $showrefstop.list conf -state normal
9085 $showrefstop.list insert end "\n"
9086 set i 0
9087 set j 0
9088 while {$i < [llength $reflist] || $j < [llength $refs]} {
9089 if {$i < [llength $reflist]} {
9090 if {$j < [llength $refs]} {
9091 set cmp [string compare [lindex $reflist $i 0] \
9092 [lindex $refs $j 0]]
9093 if {$cmp == 0} {
9094 set cmp [string compare [lindex $reflist $i 1] \
9095 [lindex $refs $j 1]]
9096 }
9097 } else {
9098 set cmp -1
9099 }
9100 } else {
9101 set cmp 1
9102 }
9103 switch -- $cmp {
9104 -1 {
9105 $showrefstop.list delete "[expr {$j+1}].0" "[expr {$j+2}].0"
9106 incr i
9107 }
9108 0 {
9109 incr i
9110 incr j
9111 }
9112 1 {
9113 set l [expr {$j + 1}]
9114 $showrefstop.list image create $l.0 -align baseline \
9115 -image reficon-[lindex $refs $j 1] -padx 2
9116 $showrefstop.list insert $l.1 "[lindex $refs $j 0]\n"
9117 incr j
9118 }
9119 }
9120 }
9121 set reflist $refs
9122 # delete last newline
9123 $showrefstop.list delete end-2c end-1c
9124 $showrefstop.list conf -state disabled
Paul Mackerras10299152006-08-02 09:52:01 +10009125}
9126
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10009127# Stuff for finding nearby tags
9128proc getallcommits {} {
Paul Mackerras5cd15b62007-08-30 21:54:17 +10009129 global allcommits nextarc seeds allccache allcwait cachedarcs allcupdate
9130 global idheads idtags idotherrefs allparents tagobjid
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10009131
Paul Mackerrasa69b2d12007-08-13 15:02:02 +10009132 if {![info exists allcommits]} {
Paul Mackerrasa69b2d12007-08-13 15:02:02 +10009133 set nextarc 0
9134 set allcommits 0
9135 set seeds {}
Paul Mackerras5cd15b62007-08-30 21:54:17 +10009136 set allcwait 0
9137 set cachedarcs 0
9138 set allccache [file join [gitdir] "gitk.cache"]
9139 if {![catch {
9140 set f [open $allccache r]
9141 set allcwait 1
9142 getcache $f
9143 }]} return
Paul Mackerrasa69b2d12007-08-13 15:02:02 +10009144 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10009145
Paul Mackerras5cd15b62007-08-30 21:54:17 +10009146 if {$allcwait} {
9147 return
Paul Mackerrase11f1232007-06-16 20:29:25 +10009148 }
Paul Mackerras5cd15b62007-08-30 21:54:17 +10009149 set cmd [list | git rev-list --parents]
9150 set allcupdate [expr {$seeds ne {}}]
9151 if {!$allcupdate} {
9152 set ids "--all"
9153 } else {
9154 set refs [concat [array names idheads] [array names idtags] \
9155 [array names idotherrefs]]
9156 set ids {}
9157 set tagobjs {}
9158 foreach name [array names tagobjid] {
9159 lappend tagobjs $tagobjid($name)
9160 }
9161 foreach id [lsort -unique $refs] {
9162 if {![info exists allparents($id)] &&
9163 [lsearch -exact $tagobjs $id] < 0} {
9164 lappend ids $id
9165 }
9166 }
9167 if {$ids ne {}} {
9168 foreach id $seeds {
9169 lappend ids "^$id"
9170 }
9171 }
9172 }
9173 if {$ids ne {}} {
9174 set fd [open [concat $cmd $ids] r]
9175 fconfigure $fd -blocking 0
9176 incr allcommits
9177 nowbusy allcommits
9178 filerun $fd [list getallclines $fd]
9179 } else {
9180 dispneartags 0
9181 }
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10009182}
9183
Paul Mackerrase11f1232007-06-16 20:29:25 +10009184# Since most commits have 1 parent and 1 child, we group strings of
9185# such commits into "arcs" joining branch/merge points (BMPs), which
9186# are commits that either don't have 1 parent or don't have 1 child.
9187#
9188# arcnos(id) - incoming arcs for BMP, arc we're on for other nodes
9189# arcout(id) - outgoing arcs for BMP
9190# arcids(a) - list of IDs on arc including end but not start
9191# arcstart(a) - BMP ID at start of arc
9192# arcend(a) - BMP ID at end of arc
9193# growing(a) - arc a is still growing
9194# arctags(a) - IDs out of arcids (excluding end) that have tags
9195# archeads(a) - IDs out of arcids (excluding end) that have heads
9196# The start of an arc is at the descendent end, so "incoming" means
9197# coming from descendents, and "outgoing" means going towards ancestors.
Paul Mackerrascec7bec2006-08-02 09:38:10 +10009198
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10009199proc getallclines {fd} {
Paul Mackerras5cd15b62007-08-30 21:54:17 +10009200 global allparents allchildren idtags idheads nextarc
Paul Mackerrase11f1232007-06-16 20:29:25 +10009201 global arcnos arcids arctags arcout arcend arcstart archeads growing
Paul Mackerras5cd15b62007-08-30 21:54:17 +10009202 global seeds allcommits cachedarcs allcupdate
9203
Paul Mackerrase11f1232007-06-16 20:29:25 +10009204 set nid 0
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10009205 while {[incr nid] <= 1000 && [gets $fd line] >= 0} {
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10009206 set id [lindex $line 0]
Paul Mackerrase11f1232007-06-16 20:29:25 +10009207 if {[info exists allparents($id)]} {
9208 # seen it already
9209 continue
9210 }
Paul Mackerras5cd15b62007-08-30 21:54:17 +10009211 set cachedarcs 0
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10009212 set olds [lrange $line 1 end]
9213 set allparents($id) $olds
9214 if {![info exists allchildren($id)]} {
9215 set allchildren($id) {}
Paul Mackerrase11f1232007-06-16 20:29:25 +10009216 set arcnos($id) {}
9217 lappend seeds $id
9218 } else {
9219 set a $arcnos($id)
9220 if {[llength $olds] == 1 && [llength $a] == 1} {
9221 lappend arcids($a) $id
9222 if {[info exists idtags($id)]} {
9223 lappend arctags($a) $id
9224 }
9225 if {[info exists idheads($id)]} {
9226 lappend archeads($a) $id
9227 }
9228 if {[info exists allparents($olds)]} {
9229 # seen parent already
9230 if {![info exists arcout($olds)]} {
9231 splitarc $olds
9232 }
9233 lappend arcids($a) $olds
9234 set arcend($a) $olds
9235 unset growing($a)
9236 }
9237 lappend allchildren($olds) $id
9238 lappend arcnos($olds) $a
9239 continue
9240 }
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10009241 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10009242 foreach a $arcnos($id) {
9243 lappend arcids($a) $id
9244 set arcend($a) $id
9245 unset growing($a)
9246 }
9247
9248 set ao {}
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10009249 foreach p $olds {
9250 lappend allchildren($p) $id
Paul Mackerrase11f1232007-06-16 20:29:25 +10009251 set a [incr nextarc]
9252 set arcstart($a) $id
9253 set archeads($a) {}
9254 set arctags($a) {}
9255 set archeads($a) {}
9256 set arcids($a) {}
9257 lappend ao $a
9258 set growing($a) 1
9259 if {[info exists allparents($p)]} {
9260 # seen it already, may need to make a new branch
9261 if {![info exists arcout($p)]} {
9262 splitarc $p
9263 }
9264 lappend arcids($a) $p
9265 set arcend($a) $p
9266 unset growing($a)
9267 }
9268 lappend arcnos($p) $a
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10009269 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10009270 set arcout($id) $ao
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10009271 }
Paul Mackerrasf3326b62007-06-18 22:39:21 +10009272 if {$nid > 0} {
9273 global cached_dheads cached_dtags cached_atags
9274 catch {unset cached_dheads}
9275 catch {unset cached_dtags}
9276 catch {unset cached_atags}
9277 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10009278 if {![eof $fd]} {
9279 return [expr {$nid >= 1000? 2: 1}]
9280 }
Paul Mackerras5cd15b62007-08-30 21:54:17 +10009281 set cacheok 1
9282 if {[catch {
9283 fconfigure $fd -blocking 1
9284 close $fd
9285 } err]} {
9286 # got an error reading the list of commits
9287 # if we were updating, try rereading the whole thing again
9288 if {$allcupdate} {
9289 incr allcommits -1
9290 dropcache $err
9291 return
9292 }
Christian Stimmingd990ced2007-11-07 18:42:55 +01009293 error_popup "[mc "Error reading commit topology information;\
Paul Mackerras5cd15b62007-08-30 21:54:17 +10009294 branch and preceding/following tag information\
Christian Stimmingd990ced2007-11-07 18:42:55 +01009295 will be incomplete."]\n($err)"
Paul Mackerras5cd15b62007-08-30 21:54:17 +10009296 set cacheok 0
9297 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10009298 if {[incr allcommits -1] == 0} {
9299 notbusy allcommits
Paul Mackerras5cd15b62007-08-30 21:54:17 +10009300 if {$cacheok} {
9301 run savecache
9302 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10009303 }
9304 dispneartags 0
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10009305 return 0
Paul Mackerrase11f1232007-06-16 20:29:25 +10009306}
9307
9308proc recalcarc {a} {
9309 global arctags archeads arcids idtags idheads
9310
9311 set at {}
9312 set ah {}
9313 foreach id [lrange $arcids($a) 0 end-1] {
9314 if {[info exists idtags($id)]} {
9315 lappend at $id
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10009316 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10009317 if {[info exists idheads($id)]} {
9318 lappend ah $id
9319 }
9320 }
9321 set arctags($a) $at
9322 set archeads($a) $ah
9323}
9324
9325proc splitarc {p} {
Paul Mackerras5cd15b62007-08-30 21:54:17 +10009326 global arcnos arcids nextarc arctags archeads idtags idheads
Paul Mackerrase11f1232007-06-16 20:29:25 +10009327 global arcstart arcend arcout allparents growing
9328
9329 set a $arcnos($p)
9330 if {[llength $a] != 1} {
9331 puts "oops splitarc called but [llength $a] arcs already"
9332 return
9333 }
9334 set a [lindex $a 0]
9335 set i [lsearch -exact $arcids($a) $p]
9336 if {$i < 0} {
9337 puts "oops splitarc $p not in arc $a"
9338 return
9339 }
9340 set na [incr nextarc]
9341 if {[info exists arcend($a)]} {
9342 set arcend($na) $arcend($a)
9343 } else {
9344 set l [lindex $allparents([lindex $arcids($a) end]) 0]
9345 set j [lsearch -exact $arcnos($l) $a]
9346 set arcnos($l) [lreplace $arcnos($l) $j $j $na]
9347 }
9348 set tail [lrange $arcids($a) [expr {$i+1}] end]
9349 set arcids($a) [lrange $arcids($a) 0 $i]
9350 set arcend($a) $p
9351 set arcstart($na) $p
9352 set arcout($p) $na
9353 set arcids($na) $tail
9354 if {[info exists growing($a)]} {
9355 set growing($na) 1
9356 unset growing($a)
9357 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10009358
9359 foreach id $tail {
9360 if {[llength $arcnos($id)] == 1} {
9361 set arcnos($id) $na
9362 } else {
9363 set j [lsearch -exact $arcnos($id) $a]
9364 set arcnos($id) [lreplace $arcnos($id) $j $j $na]
9365 }
9366 }
9367
9368 # reconstruct tags and heads lists
9369 if {$arctags($a) ne {} || $archeads($a) ne {}} {
9370 recalcarc $a
9371 recalcarc $na
9372 } else {
9373 set arctags($na) {}
9374 set archeads($na) {}
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10009375 }
9376}
9377
Paul Mackerrase11f1232007-06-16 20:29:25 +10009378# Update things for a new commit added that is a child of one
9379# existing commit. Used when cherry-picking.
9380proc addnewchild {id p} {
Paul Mackerras5cd15b62007-08-30 21:54:17 +10009381 global allparents allchildren idtags nextarc
Paul Mackerrase11f1232007-06-16 20:29:25 +10009382 global arcnos arcids arctags arcout arcend arcstart archeads growing
Paul Mackerras719c2b92007-08-29 22:41:34 +10009383 global seeds allcommits
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10009384
Paul Mackerras3ebba3c2007-10-20 22:10:52 +10009385 if {![info exists allcommits] || ![info exists arcnos($p)]} return
Paul Mackerrase11f1232007-06-16 20:29:25 +10009386 set allparents($id) [list $p]
9387 set allchildren($id) {}
9388 set arcnos($id) {}
9389 lappend seeds $id
Paul Mackerrase11f1232007-06-16 20:29:25 +10009390 lappend allchildren($p) $id
9391 set a [incr nextarc]
9392 set arcstart($a) $id
9393 set archeads($a) {}
9394 set arctags($a) {}
9395 set arcids($a) [list $p]
9396 set arcend($a) $p
9397 if {![info exists arcout($p)]} {
9398 splitarc $p
9399 }
9400 lappend arcnos($p) $a
9401 set arcout($id) [list $a]
9402}
9403
Paul Mackerras5cd15b62007-08-30 21:54:17 +10009404# This implements a cache for the topology information.
9405# The cache saves, for each arc, the start and end of the arc,
9406# the ids on the arc, and the outgoing arcs from the end.
9407proc readcache {f} {
9408 global arcnos arcids arcout arcstart arcend arctags archeads nextarc
9409 global idtags idheads allparents cachedarcs possible_seeds seeds growing
9410 global allcwait
9411
9412 set a $nextarc
9413 set lim $cachedarcs
9414 if {$lim - $a > 500} {
9415 set lim [expr {$a + 500}]
9416 }
9417 if {[catch {
9418 if {$a == $lim} {
9419 # finish reading the cache and setting up arctags, etc.
9420 set line [gets $f]
9421 if {$line ne "1"} {error "bad final version"}
9422 close $f
9423 foreach id [array names idtags] {
9424 if {[info exists arcnos($id)] && [llength $arcnos($id)] == 1 &&
9425 [llength $allparents($id)] == 1} {
9426 set a [lindex $arcnos($id) 0]
9427 if {$arctags($a) eq {}} {
9428 recalcarc $a
9429 }
9430 }
9431 }
9432 foreach id [array names idheads] {
9433 if {[info exists arcnos($id)] && [llength $arcnos($id)] == 1 &&
9434 [llength $allparents($id)] == 1} {
9435 set a [lindex $arcnos($id) 0]
9436 if {$archeads($a) eq {}} {
9437 recalcarc $a
9438 }
9439 }
9440 }
9441 foreach id [lsort -unique $possible_seeds] {
9442 if {$arcnos($id) eq {}} {
9443 lappend seeds $id
9444 }
9445 }
9446 set allcwait 0
9447 } else {
9448 while {[incr a] <= $lim} {
9449 set line [gets $f]
9450 if {[llength $line] != 3} {error "bad line"}
9451 set s [lindex $line 0]
9452 set arcstart($a) $s
9453 lappend arcout($s) $a
9454 if {![info exists arcnos($s)]} {
9455 lappend possible_seeds $s
9456 set arcnos($s) {}
9457 }
9458 set e [lindex $line 1]
9459 if {$e eq {}} {
9460 set growing($a) 1
9461 } else {
9462 set arcend($a) $e
9463 if {![info exists arcout($e)]} {
9464 set arcout($e) {}
9465 }
9466 }
9467 set arcids($a) [lindex $line 2]
9468 foreach id $arcids($a) {
9469 lappend allparents($s) $id
9470 set s $id
9471 lappend arcnos($id) $a
9472 }
9473 if {![info exists allparents($s)]} {
9474 set allparents($s) {}
9475 }
9476 set arctags($a) {}
9477 set archeads($a) {}
9478 }
9479 set nextarc [expr {$a - 1}]
9480 }
9481 } err]} {
9482 dropcache $err
9483 return 0
9484 }
9485 if {!$allcwait} {
9486 getallcommits
9487 }
9488 return $allcwait
9489}
9490
9491proc getcache {f} {
9492 global nextarc cachedarcs possible_seeds
9493
9494 if {[catch {
9495 set line [gets $f]
9496 if {[llength $line] != 2 || [lindex $line 0] ne "1"} {error "bad version"}
9497 # make sure it's an integer
9498 set cachedarcs [expr {int([lindex $line 1])}]
9499 if {$cachedarcs < 0} {error "bad number of arcs"}
9500 set nextarc 0
9501 set possible_seeds {}
9502 run readcache $f
9503 } err]} {
9504 dropcache $err
9505 }
9506 return 0
9507}
9508
9509proc dropcache {err} {
9510 global allcwait nextarc cachedarcs seeds
9511
9512 #puts "dropping cache ($err)"
9513 foreach v {arcnos arcout arcids arcstart arcend growing \
9514 arctags archeads allparents allchildren} {
9515 global $v
9516 catch {unset $v}
9517 }
9518 set allcwait 0
9519 set nextarc 0
9520 set cachedarcs 0
9521 set seeds {}
9522 getallcommits
9523}
9524
9525proc writecache {f} {
9526 global cachearc cachedarcs allccache
9527 global arcstart arcend arcnos arcids arcout
9528
9529 set a $cachearc
9530 set lim $cachedarcs
9531 if {$lim - $a > 1000} {
9532 set lim [expr {$a + 1000}]
9533 }
9534 if {[catch {
9535 while {[incr a] <= $lim} {
9536 if {[info exists arcend($a)]} {
9537 puts $f [list $arcstart($a) $arcend($a) $arcids($a)]
9538 } else {
9539 puts $f [list $arcstart($a) {} $arcids($a)]
9540 }
9541 }
9542 } err]} {
9543 catch {close $f}
9544 catch {file delete $allccache}
9545 #puts "writing cache failed ($err)"
9546 return 0
9547 }
9548 set cachearc [expr {$a - 1}]
9549 if {$a > $cachedarcs} {
9550 puts $f "1"
9551 close $f
9552 return 0
9553 }
9554 return 1
9555}
9556
9557proc savecache {} {
9558 global nextarc cachedarcs cachearc allccache
9559
9560 if {$nextarc == $cachedarcs} return
9561 set cachearc 0
9562 set cachedarcs $nextarc
9563 catch {
9564 set f [open $allccache w]
9565 puts $f [list 1 $cachedarcs]
9566 run writecache $f
9567 }
9568}
9569
Paul Mackerrase11f1232007-06-16 20:29:25 +10009570# Returns 1 if a is an ancestor of b, -1 if b is an ancestor of a,
9571# or 0 if neither is true.
9572proc anc_or_desc {a b} {
9573 global arcout arcstart arcend arcnos cached_isanc
9574
9575 if {$arcnos($a) eq $arcnos($b)} {
9576 # Both are on the same arc(s); either both are the same BMP,
9577 # or if one is not a BMP, the other is also not a BMP or is
9578 # the BMP at end of the arc (and it only has 1 incoming arc).
Paul Mackerras69c0b5d2007-07-04 21:57:04 +10009579 # Or both can be BMPs with no incoming arcs.
9580 if {$a eq $b || $arcnos($a) eq {}} {
Paul Mackerrase11f1232007-06-16 20:29:25 +10009581 return 0
9582 }
9583 # assert {[llength $arcnos($a)] == 1}
9584 set arc [lindex $arcnos($a) 0]
9585 set i [lsearch -exact $arcids($arc) $a]
9586 set j [lsearch -exact $arcids($arc) $b]
9587 if {$i < 0 || $i > $j} {
9588 return 1
9589 } else {
9590 return -1
9591 }
9592 }
9593
9594 if {![info exists arcout($a)]} {
9595 set arc [lindex $arcnos($a) 0]
9596 if {[info exists arcend($arc)]} {
9597 set aend $arcend($arc)
9598 } else {
9599 set aend {}
9600 }
9601 set a $arcstart($arc)
9602 } else {
9603 set aend $a
9604 }
9605 if {![info exists arcout($b)]} {
9606 set arc [lindex $arcnos($b) 0]
9607 if {[info exists arcend($arc)]} {
9608 set bend $arcend($arc)
9609 } else {
9610 set bend {}
9611 }
9612 set b $arcstart($arc)
9613 } else {
9614 set bend $b
9615 }
9616 if {$a eq $bend} {
9617 return 1
9618 }
9619 if {$b eq $aend} {
9620 return -1
9621 }
9622 if {[info exists cached_isanc($a,$bend)]} {
9623 if {$cached_isanc($a,$bend)} {
9624 return 1
9625 }
9626 }
9627 if {[info exists cached_isanc($b,$aend)]} {
9628 if {$cached_isanc($b,$aend)} {
9629 return -1
9630 }
9631 if {[info exists cached_isanc($a,$bend)]} {
9632 return 0
9633 }
9634 }
9635
9636 set todo [list $a $b]
9637 set anc($a) a
9638 set anc($b) b
9639 for {set i 0} {$i < [llength $todo]} {incr i} {
9640 set x [lindex $todo $i]
9641 if {$anc($x) eq {}} {
9642 continue
9643 }
9644 foreach arc $arcnos($x) {
9645 set xd $arcstart($arc)
9646 if {$xd eq $bend} {
9647 set cached_isanc($a,$bend) 1
9648 set cached_isanc($b,$aend) 0
9649 return 1
9650 } elseif {$xd eq $aend} {
9651 set cached_isanc($b,$aend) 1
9652 set cached_isanc($a,$bend) 0
9653 return -1
9654 }
9655 if {![info exists anc($xd)]} {
9656 set anc($xd) $anc($x)
9657 lappend todo $xd
9658 } elseif {$anc($xd) ne $anc($x)} {
9659 set anc($xd) {}
9660 }
9661 }
9662 }
9663 set cached_isanc($a,$bend) 0
9664 set cached_isanc($b,$aend) 0
9665 return 0
9666}
9667
9668# This identifies whether $desc has an ancestor that is
9669# a growing tip of the graph and which is not an ancestor of $anc
9670# and returns 0 if so and 1 if not.
9671# If we subsequently discover a tag on such a growing tip, and that
9672# turns out to be a descendent of $anc (which it could, since we
9673# don't necessarily see children before parents), then $desc
9674# isn't a good choice to display as a descendent tag of
9675# $anc (since it is the descendent of another tag which is
9676# a descendent of $anc). Similarly, $anc isn't a good choice to
9677# display as a ancestor tag of $desc.
9678#
9679proc is_certain {desc anc} {
9680 global arcnos arcout arcstart arcend growing problems
9681
9682 set certain {}
9683 if {[llength $arcnos($anc)] == 1} {
9684 # tags on the same arc are certain
9685 if {$arcnos($desc) eq $arcnos($anc)} {
9686 return 1
9687 }
9688 if {![info exists arcout($anc)]} {
9689 # if $anc is partway along an arc, use the start of the arc instead
9690 set a [lindex $arcnos($anc) 0]
9691 set anc $arcstart($a)
9692 }
9693 }
9694 if {[llength $arcnos($desc)] > 1 || [info exists arcout($desc)]} {
9695 set x $desc
9696 } else {
9697 set a [lindex $arcnos($desc) 0]
9698 set x $arcend($a)
9699 }
9700 if {$x == $anc} {
9701 return 1
9702 }
9703 set anclist [list $x]
9704 set dl($x) 1
9705 set nnh 1
9706 set ngrowanc 0
9707 for {set i 0} {$i < [llength $anclist] && ($nnh > 0 || $ngrowanc > 0)} {incr i} {
9708 set x [lindex $anclist $i]
9709 if {$dl($x)} {
9710 incr nnh -1
9711 }
9712 set done($x) 1
9713 foreach a $arcout($x) {
9714 if {[info exists growing($a)]} {
9715 if {![info exists growanc($x)] && $dl($x)} {
9716 set growanc($x) 1
9717 incr ngrowanc
9718 }
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10009719 } else {
Paul Mackerrase11f1232007-06-16 20:29:25 +10009720 set y $arcend($a)
9721 if {[info exists dl($y)]} {
9722 if {$dl($y)} {
9723 if {!$dl($x)} {
9724 set dl($y) 0
9725 if {![info exists done($y)]} {
9726 incr nnh -1
9727 }
9728 if {[info exists growanc($x)]} {
9729 incr ngrowanc -1
9730 }
9731 set xl [list $y]
9732 for {set k 0} {$k < [llength $xl]} {incr k} {
9733 set z [lindex $xl $k]
9734 foreach c $arcout($z) {
9735 if {[info exists arcend($c)]} {
9736 set v $arcend($c)
9737 if {[info exists dl($v)] && $dl($v)} {
9738 set dl($v) 0
9739 if {![info exists done($v)]} {
9740 incr nnh -1
9741 }
9742 if {[info exists growanc($v)]} {
9743 incr ngrowanc -1
9744 }
9745 lappend xl $v
9746 }
9747 }
9748 }
9749 }
9750 }
9751 }
9752 } elseif {$y eq $anc || !$dl($x)} {
9753 set dl($y) 0
9754 lappend anclist $y
9755 } else {
9756 set dl($y) 1
9757 lappend anclist $y
9758 incr nnh
9759 }
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10009760 }
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10009761 }
9762 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10009763 foreach x [array names growanc] {
9764 if {$dl($x)} {
9765 return 0
9766 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10009767 return 0
Paul Mackerrase11f1232007-06-16 20:29:25 +10009768 }
9769 return 1
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10009770}
9771
Paul Mackerrase11f1232007-06-16 20:29:25 +10009772proc validate_arctags {a} {
9773 global arctags idtags
9774
9775 set i -1
9776 set na $arctags($a)
9777 foreach id $arctags($a) {
9778 incr i
9779 if {![info exists idtags($id)]} {
9780 set na [lreplace $na $i $i]
9781 incr i -1
9782 }
9783 }
9784 set arctags($a) $na
9785}
9786
9787proc validate_archeads {a} {
9788 global archeads idheads
9789
9790 set i -1
9791 set na $archeads($a)
9792 foreach id $archeads($a) {
9793 incr i
9794 if {![info exists idheads($id)]} {
9795 set na [lreplace $na $i $i]
9796 incr i -1
9797 }
9798 }
9799 set archeads($a) $na
9800}
9801
9802# Return the list of IDs that have tags that are descendents of id,
9803# ignoring IDs that are descendents of IDs already reported.
9804proc desctags {id} {
9805 global arcnos arcstart arcids arctags idtags allparents
9806 global growing cached_dtags
9807
9808 if {![info exists allparents($id)]} {
9809 return {}
9810 }
9811 set t1 [clock clicks -milliseconds]
9812 set argid $id
9813 if {[llength $arcnos($id)] == 1 && [llength $allparents($id)] == 1} {
9814 # part-way along an arc; check that arc first
9815 set a [lindex $arcnos($id) 0]
9816 if {$arctags($a) ne {}} {
9817 validate_arctags $a
9818 set i [lsearch -exact $arcids($a) $id]
9819 set tid {}
9820 foreach t $arctags($a) {
9821 set j [lsearch -exact $arcids($a) $t]
9822 if {$j >= $i} break
9823 set tid $t
9824 }
9825 if {$tid ne {}} {
9826 return $tid
9827 }
9828 }
9829 set id $arcstart($a)
9830 if {[info exists idtags($id)]} {
9831 return $id
9832 }
9833 }
9834 if {[info exists cached_dtags($id)]} {
9835 return $cached_dtags($id)
9836 }
9837
9838 set origid $id
9839 set todo [list $id]
9840 set queued($id) 1
9841 set nc 1
9842 for {set i 0} {$i < [llength $todo] && $nc > 0} {incr i} {
9843 set id [lindex $todo $i]
9844 set done($id) 1
9845 set ta [info exists hastaggedancestor($id)]
9846 if {!$ta} {
9847 incr nc -1
9848 }
9849 # ignore tags on starting node
9850 if {!$ta && $i > 0} {
9851 if {[info exists idtags($id)]} {
9852 set tagloc($id) $id
9853 set ta 1
9854 } elseif {[info exists cached_dtags($id)]} {
9855 set tagloc($id) $cached_dtags($id)
9856 set ta 1
9857 }
9858 }
9859 foreach a $arcnos($id) {
9860 set d $arcstart($a)
9861 if {!$ta && $arctags($a) ne {}} {
9862 validate_arctags $a
9863 if {$arctags($a) ne {}} {
9864 lappend tagloc($id) [lindex $arctags($a) end]
9865 }
9866 }
9867 if {$ta || $arctags($a) ne {}} {
9868 set tomark [list $d]
9869 for {set j 0} {$j < [llength $tomark]} {incr j} {
9870 set dd [lindex $tomark $j]
9871 if {![info exists hastaggedancestor($dd)]} {
9872 if {[info exists done($dd)]} {
9873 foreach b $arcnos($dd) {
9874 lappend tomark $arcstart($b)
9875 }
9876 if {[info exists tagloc($dd)]} {
9877 unset tagloc($dd)
9878 }
9879 } elseif {[info exists queued($dd)]} {
9880 incr nc -1
9881 }
9882 set hastaggedancestor($dd) 1
9883 }
9884 }
9885 }
9886 if {![info exists queued($d)]} {
9887 lappend todo $d
9888 set queued($d) 1
9889 if {![info exists hastaggedancestor($d)]} {
9890 incr nc
9891 }
9892 }
9893 }
9894 }
9895 set tags {}
9896 foreach id [array names tagloc] {
9897 if {![info exists hastaggedancestor($id)]} {
9898 foreach t $tagloc($id) {
9899 if {[lsearch -exact $tags $t] < 0} {
9900 lappend tags $t
9901 }
9902 }
9903 }
9904 }
9905 set t2 [clock clicks -milliseconds]
9906 set loopix $i
9907
9908 # remove tags that are descendents of other tags
9909 for {set i 0} {$i < [llength $tags]} {incr i} {
9910 set a [lindex $tags $i]
9911 for {set j 0} {$j < $i} {incr j} {
9912 set b [lindex $tags $j]
9913 set r [anc_or_desc $a $b]
9914 if {$r == 1} {
9915 set tags [lreplace $tags $j $j]
9916 incr j -1
9917 incr i -1
9918 } elseif {$r == -1} {
9919 set tags [lreplace $tags $i $i]
9920 incr i -1
9921 break
9922 }
9923 }
9924 }
9925
9926 if {[array names growing] ne {}} {
9927 # graph isn't finished, need to check if any tag could get
9928 # eclipsed by another tag coming later. Simply ignore any
9929 # tags that could later get eclipsed.
9930 set ctags {}
9931 foreach t $tags {
9932 if {[is_certain $t $origid]} {
9933 lappend ctags $t
9934 }
9935 }
9936 if {$tags eq $ctags} {
9937 set cached_dtags($origid) $tags
9938 } else {
9939 set tags $ctags
9940 }
9941 } else {
9942 set cached_dtags($origid) $tags
9943 }
9944 set t3 [clock clicks -milliseconds]
9945 if {0 && $t3 - $t1 >= 100} {
9946 puts "iterating descendents ($loopix/[llength $todo] nodes) took\
9947 [expr {$t2-$t1}]+[expr {$t3-$t2}]ms, $nc candidates left"
9948 }
9949 return $tags
9950}
9951
9952proc anctags {id} {
9953 global arcnos arcids arcout arcend arctags idtags allparents
9954 global growing cached_atags
9955
9956 if {![info exists allparents($id)]} {
9957 return {}
9958 }
9959 set t1 [clock clicks -milliseconds]
9960 set argid $id
9961 if {[llength $arcnos($id)] == 1 && [llength $allparents($id)] == 1} {
9962 # part-way along an arc; check that arc first
9963 set a [lindex $arcnos($id) 0]
9964 if {$arctags($a) ne {}} {
9965 validate_arctags $a
9966 set i [lsearch -exact $arcids($a) $id]
9967 foreach t $arctags($a) {
9968 set j [lsearch -exact $arcids($a) $t]
9969 if {$j > $i} {
9970 return $t
9971 }
9972 }
9973 }
9974 if {![info exists arcend($a)]} {
9975 return {}
9976 }
9977 set id $arcend($a)
9978 if {[info exists idtags($id)]} {
9979 return $id
9980 }
9981 }
9982 if {[info exists cached_atags($id)]} {
9983 return $cached_atags($id)
9984 }
9985
9986 set origid $id
9987 set todo [list $id]
9988 set queued($id) 1
9989 set taglist {}
9990 set nc 1
9991 for {set i 0} {$i < [llength $todo] && $nc > 0} {incr i} {
9992 set id [lindex $todo $i]
9993 set done($id) 1
9994 set td [info exists hastaggeddescendent($id)]
9995 if {!$td} {
9996 incr nc -1
9997 }
9998 # ignore tags on starting node
9999 if {!$td && $i > 0} {
10000 if {[info exists idtags($id)]} {
10001 set tagloc($id) $id
10002 set td 1
10003 } elseif {[info exists cached_atags($id)]} {
10004 set tagloc($id) $cached_atags($id)
10005 set td 1
10006 }
10007 }
10008 foreach a $arcout($id) {
10009 if {!$td && $arctags($a) ne {}} {
10010 validate_arctags $a
10011 if {$arctags($a) ne {}} {
10012 lappend tagloc($id) [lindex $arctags($a) 0]
10013 }
10014 }
10015 if {![info exists arcend($a)]} continue
10016 set d $arcend($a)
10017 if {$td || $arctags($a) ne {}} {
10018 set tomark [list $d]
10019 for {set j 0} {$j < [llength $tomark]} {incr j} {
10020 set dd [lindex $tomark $j]
10021 if {![info exists hastaggeddescendent($dd)]} {
10022 if {[info exists done($dd)]} {
10023 foreach b $arcout($dd) {
10024 if {[info exists arcend($b)]} {
10025 lappend tomark $arcend($b)
10026 }
10027 }
10028 if {[info exists tagloc($dd)]} {
10029 unset tagloc($dd)
10030 }
10031 } elseif {[info exists queued($dd)]} {
10032 incr nc -1
10033 }
10034 set hastaggeddescendent($dd) 1
10035 }
10036 }
10037 }
10038 if {![info exists queued($d)]} {
10039 lappend todo $d
10040 set queued($d) 1
10041 if {![info exists hastaggeddescendent($d)]} {
10042 incr nc
10043 }
10044 }
10045 }
10046 }
10047 set t2 [clock clicks -milliseconds]
10048 set loopix $i
10049 set tags {}
10050 foreach id [array names tagloc] {
10051 if {![info exists hastaggeddescendent($id)]} {
10052 foreach t $tagloc($id) {
10053 if {[lsearch -exact $tags $t] < 0} {
10054 lappend tags $t
10055 }
10056 }
10057 }
10058 }
10059
10060 # remove tags that are ancestors of other tags
10061 for {set i 0} {$i < [llength $tags]} {incr i} {
10062 set a [lindex $tags $i]
10063 for {set j 0} {$j < $i} {incr j} {
10064 set b [lindex $tags $j]
10065 set r [anc_or_desc $a $b]
10066 if {$r == -1} {
10067 set tags [lreplace $tags $j $j]
10068 incr j -1
10069 incr i -1
10070 } elseif {$r == 1} {
10071 set tags [lreplace $tags $i $i]
10072 incr i -1
10073 break
10074 }
10075 }
10076 }
10077
10078 if {[array names growing] ne {}} {
10079 # graph isn't finished, need to check if any tag could get
10080 # eclipsed by another tag coming later. Simply ignore any
10081 # tags that could later get eclipsed.
10082 set ctags {}
10083 foreach t $tags {
10084 if {[is_certain $origid $t]} {
10085 lappend ctags $t
10086 }
10087 }
10088 if {$tags eq $ctags} {
10089 set cached_atags($origid) $tags
10090 } else {
10091 set tags $ctags
10092 }
10093 } else {
10094 set cached_atags($origid) $tags
10095 }
10096 set t3 [clock clicks -milliseconds]
10097 if {0 && $t3 - $t1 >= 100} {
10098 puts "iterating ancestors ($loopix/[llength $todo] nodes) took\
10099 [expr {$t2-$t1}]+[expr {$t3-$t2}]ms, $nc candidates left"
10100 }
10101 return $tags
10102}
10103
10104# Return the list of IDs that have heads that are descendents of id,
10105# including id itself if it has a head.
10106proc descheads {id} {
10107 global arcnos arcstart arcids archeads idheads cached_dheads
10108 global allparents
10109
10110 if {![info exists allparents($id)]} {
10111 return {}
10112 }
Paul Mackerrasf3326b62007-06-18 22:39:21 +100010113 set aret {}
Paul Mackerrase11f1232007-06-16 20:29:25 +100010114 if {[llength $arcnos($id)] == 1 && [llength $allparents($id)] == 1} {
10115 # part-way along an arc; check it first
10116 set a [lindex $arcnos($id) 0]
10117 if {$archeads($a) ne {}} {
10118 validate_archeads $a
10119 set i [lsearch -exact $arcids($a) $id]
10120 foreach t $archeads($a) {
10121 set j [lsearch -exact $arcids($a) $t]
10122 if {$j > $i} break
Paul Mackerrasf3326b62007-06-18 22:39:21 +100010123 lappend aret $t
Paul Mackerrase11f1232007-06-16 20:29:25 +100010124 }
10125 }
10126 set id $arcstart($a)
10127 }
10128 set origid $id
10129 set todo [list $id]
10130 set seen($id) 1
Paul Mackerrasf3326b62007-06-18 22:39:21 +100010131 set ret {}
Paul Mackerrase11f1232007-06-16 20:29:25 +100010132 for {set i 0} {$i < [llength $todo]} {incr i} {
10133 set id [lindex $todo $i]
10134 if {[info exists cached_dheads($id)]} {
10135 set ret [concat $ret $cached_dheads($id)]
10136 } else {
10137 if {[info exists idheads($id)]} {
10138 lappend ret $id
10139 }
10140 foreach a $arcnos($id) {
10141 if {$archeads($a) ne {}} {
Paul Mackerras706d6c32007-06-26 11:09:49 +100010142 validate_archeads $a
10143 if {$archeads($a) ne {}} {
10144 set ret [concat $ret $archeads($a)]
10145 }
Paul Mackerrase11f1232007-06-16 20:29:25 +100010146 }
10147 set d $arcstart($a)
10148 if {![info exists seen($d)]} {
10149 lappend todo $d
10150 set seen($d) 1
10151 }
10152 }
10153 }
10154 }
10155 set ret [lsort -unique $ret]
10156 set cached_dheads($origid) $ret
Paul Mackerrasf3326b62007-06-18 22:39:21 +100010157 return [concat $ret $aret]
Paul Mackerrase11f1232007-06-16 20:29:25 +100010158}
10159
Paul Mackerrasceadfe92006-08-08 20:55:36 +100010160proc addedtag {id} {
Paul Mackerrase11f1232007-06-16 20:29:25 +100010161 global arcnos arcout cached_dtags cached_atags
Paul Mackerrasceadfe92006-08-08 20:55:36 +100010162
Paul Mackerrase11f1232007-06-16 20:29:25 +100010163 if {![info exists arcnos($id)]} return
10164 if {![info exists arcout($id)]} {
10165 recalcarc [lindex $arcnos($id) 0]
Paul Mackerrasceadfe92006-08-08 20:55:36 +100010166 }
Paul Mackerrase11f1232007-06-16 20:29:25 +100010167 catch {unset cached_dtags}
10168 catch {unset cached_atags}
Paul Mackerrasceadfe92006-08-08 20:55:36 +100010169}
10170
Paul Mackerrasca6d8f52006-08-06 21:08:05 +100010171proc addedhead {hid head} {
Paul Mackerrase11f1232007-06-16 20:29:25 +100010172 global arcnos arcout cached_dheads
Paul Mackerrasca6d8f52006-08-06 21:08:05 +100010173
Paul Mackerrase11f1232007-06-16 20:29:25 +100010174 if {![info exists arcnos($hid)]} return
10175 if {![info exists arcout($hid)]} {
10176 recalcarc [lindex $arcnos($hid) 0]
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +100010177 }
Paul Mackerrase11f1232007-06-16 20:29:25 +100010178 catch {unset cached_dheads}
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +100010179}
10180
Paul Mackerrasca6d8f52006-08-06 21:08:05 +100010181proc removedhead {hid head} {
Paul Mackerrase11f1232007-06-16 20:29:25 +100010182 global cached_dheads
Paul Mackerrasca6d8f52006-08-06 21:08:05 +100010183
Paul Mackerrase11f1232007-06-16 20:29:25 +100010184 catch {unset cached_dheads}
Paul Mackerras10299152006-08-02 09:52:01 +100010185}
10186
Paul Mackerrase11f1232007-06-16 20:29:25 +100010187proc movedhead {hid head} {
10188 global arcnos arcout cached_dheads
Paul Mackerrasca6d8f52006-08-06 21:08:05 +100010189
Paul Mackerrase11f1232007-06-16 20:29:25 +100010190 if {![info exists arcnos($hid)]} return
10191 if {![info exists arcout($hid)]} {
10192 recalcarc [lindex $arcnos($hid) 0]
Paul Mackerrasca6d8f52006-08-06 21:08:05 +100010193 }
Paul Mackerrase11f1232007-06-16 20:29:25 +100010194 catch {unset cached_dheads}
Paul Mackerrasca6d8f52006-08-06 21:08:05 +100010195}
10196
Paul Mackerrascec7bec2006-08-02 09:38:10 +100010197proc changedrefs {} {
Paul Mackerrase11f1232007-06-16 20:29:25 +100010198 global cached_dheads cached_dtags cached_atags
10199 global arctags archeads arcnos arcout idheads idtags
Paul Mackerrascec7bec2006-08-02 09:38:10 +100010200
Paul Mackerrase11f1232007-06-16 20:29:25 +100010201 foreach id [concat [array names idheads] [array names idtags]] {
10202 if {[info exists arcnos($id)] && ![info exists arcout($id)]} {
10203 set a [lindex $arcnos($id) 0]
10204 if {![info exists donearc($a)]} {
10205 recalcarc $a
10206 set donearc($a) 1
10207 }
Paul Mackerrascec7bec2006-08-02 09:38:10 +100010208 }
10209 }
Paul Mackerrase11f1232007-06-16 20:29:25 +100010210 catch {unset cached_dtags}
10211 catch {unset cached_atags}
10212 catch {unset cached_dheads}
Paul Mackerrascec7bec2006-08-02 09:38:10 +100010213}
10214
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +100010215proc rereadrefs {} {
Paul Mackerrasfc2a2562007-12-26 23:03:43 +110010216 global idtags idheads idotherrefs mainheadid
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +100010217
10218 set refids [concat [array names idtags] \
10219 [array names idheads] [array names idotherrefs]]
10220 foreach id $refids {
10221 if {![info exists ref($id)]} {
10222 set ref($id) [listrefs $id]
10223 }
10224 }
Paul Mackerrasfc2a2562007-12-26 23:03:43 +110010225 set oldmainhead $mainheadid
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +100010226 readrefs
Paul Mackerrascec7bec2006-08-02 09:38:10 +100010227 changedrefs
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +100010228 set refids [lsort -unique [concat $refids [array names idtags] \
10229 [array names idheads] [array names idotherrefs]]]
10230 foreach id $refids {
10231 set v [listrefs $id]
Paul Mackerrasc11ff122008-05-26 10:11:33 +100010232 if {![info exists ref($id)] || $ref($id) != $v} {
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +100010233 redrawtags $id
10234 }
10235 }
Paul Mackerrasc11ff122008-05-26 10:11:33 +100010236 if {$oldmainhead ne $mainheadid} {
10237 redrawtags $oldmainhead
10238 redrawtags $mainheadid
10239 }
Paul Mackerras887c9962007-08-20 19:36:20 +100010240 run refill_reflist
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +100010241}
10242
Junio C Hamano2e1ded42006-06-11 09:50:47 -070010243proc listrefs {id} {
10244 global idtags idheads idotherrefs
10245
10246 set x {}
10247 if {[info exists idtags($id)]} {
10248 set x $idtags($id)
10249 }
10250 set y {}
10251 if {[info exists idheads($id)]} {
10252 set y $idheads($id)
10253 }
10254 set z {}
10255 if {[info exists idotherrefs($id)]} {
10256 set z $idotherrefs($id)
10257 }
10258 return [list $x $y $z]
10259}
10260
Paul Mackerras106288c2005-08-19 23:11:39 +100010261proc showtag {tag isnew} {
Paul Mackerras62d3ea62006-09-11 10:36:53 +100010262 global ctext tagcontents tagids linknum tagobjid
Paul Mackerras106288c2005-08-19 23:11:39 +100010263
10264 if {$isnew} {
10265 addtohistory [list showtag $tag 0]
10266 }
10267 $ctext conf -state normal
Paul Mackerras3ea06f92006-05-24 10:16:03 +100010268 clear_ctext
Paul Mackerras32f1b3e2007-09-28 21:27:39 +100010269 settabs 0
Paul Mackerras106288c2005-08-19 23:11:39 +100010270 set linknum 0
Paul Mackerras62d3ea62006-09-11 10:36:53 +100010271 if {![info exists tagcontents($tag)]} {
10272 catch {
10273 set tagcontents($tag) [exec git cat-file tag $tagobjid($tag)]
10274 }
10275 }
Paul Mackerras106288c2005-08-19 23:11:39 +100010276 if {[info exists tagcontents($tag)]} {
10277 set text $tagcontents($tag)
10278 } else {
Christian Stimmingd990ced2007-11-07 18:42:55 +010010279 set text "[mc "Tag"]: $tag\n[mc "Id"]: $tagids($tag)"
Paul Mackerras106288c2005-08-19 23:11:39 +100010280 }
Sergey Vlasovf1b86292006-05-15 19:13:14 +040010281 appendwithlinks $text {}
Paul Mackerras106288c2005-08-19 23:11:39 +100010282 $ctext conf -state disabled
Paul Mackerras7fcceed2006-04-27 19:21:49 +100010283 init_flist {}
Paul Mackerras106288c2005-08-19 23:11:39 +100010284}
10285
Paul Mackerras1d10f362005-05-15 12:55:47 +000010286proc doquit {} {
10287 global stopped
Thomas Arcila314f5de2008-03-24 12:55:36 +010010288 global gitktmpdir
10289
Paul Mackerras1d10f362005-05-15 12:55:47 +000010290 set stopped 100
Mark Levedahlb6047c52007-02-08 22:22:24 -050010291 savestuff .
Paul Mackerras1d10f362005-05-15 12:55:47 +000010292 destroy .
Thomas Arcila314f5de2008-03-24 12:55:36 +010010293
10294 if {[info exists gitktmpdir]} {
10295 catch {file delete -force $gitktmpdir}
10296 }
Paul Mackerras1d10f362005-05-15 12:55:47 +000010297}
10298
Paul Mackerras9a7558f2007-10-06 20:16:06 +100010299proc mkfontdisp {font top which} {
10300 global fontattr fontpref $font
10301
10302 set fontpref($font) [set $font]
10303 button $top.${font}but -text $which -font optionfont \
10304 -command [list choosefont $font $which]
10305 label $top.$font -relief flat -font $font \
10306 -text $fontattr($font,family) -justify left
10307 grid x $top.${font}but $top.$font -sticky w
10308}
10309
10310proc choosefont {font which} {
10311 global fontparam fontlist fonttop fontattr
Alexander Gavrilov84a76f12008-11-02 21:59:45 +030010312 global prefstop
Paul Mackerras9a7558f2007-10-06 20:16:06 +100010313
10314 set fontparam(which) $which
10315 set fontparam(font) $font
10316 set fontparam(family) [font actual $font -family]
10317 set fontparam(size) $fontattr($font,size)
10318 set fontparam(weight) $fontattr($font,weight)
10319 set fontparam(slant) $fontattr($font,slant)
10320 set top .gitkfont
10321 set fonttop $top
10322 if {![winfo exists $top]} {
10323 font create sample
10324 eval font config sample [font actual $font]
10325 toplevel $top
Alexander Gavrilove7d64002008-11-11 23:55:42 +030010326 make_transient $top $prefstop
Christian Stimmingd990ced2007-11-07 18:42:55 +010010327 wm title $top [mc "Gitk font chooser"]
Paul Mackerrasb039f0a2008-01-06 15:54:46 +110010328 label $top.l -textvariable fontparam(which)
Paul Mackerras9a7558f2007-10-06 20:16:06 +100010329 pack $top.l -side top
10330 set fontlist [lsort [font families]]
10331 frame $top.f
10332 listbox $top.f.fam -listvariable fontlist \
10333 -yscrollcommand [list $top.f.sb set]
10334 bind $top.f.fam <<ListboxSelect>> selfontfam
10335 scrollbar $top.f.sb -command [list $top.f.fam yview]
10336 pack $top.f.sb -side right -fill y
10337 pack $top.f.fam -side left -fill both -expand 1
10338 pack $top.f -side top -fill both -expand 1
10339 frame $top.g
10340 spinbox $top.g.size -from 4 -to 40 -width 4 \
10341 -textvariable fontparam(size) \
10342 -validatecommand {string is integer -strict %s}
10343 checkbutton $top.g.bold -padx 5 \
Christian Stimmingd990ced2007-11-07 18:42:55 +010010344 -font {{Times New Roman} 12 bold} -text [mc "B"] -indicatoron 0 \
Paul Mackerras9a7558f2007-10-06 20:16:06 +100010345 -variable fontparam(weight) -onvalue bold -offvalue normal
10346 checkbutton $top.g.ital -padx 5 \
Christian Stimmingd990ced2007-11-07 18:42:55 +010010347 -font {{Times New Roman} 12 italic} -text [mc "I"] -indicatoron 0 \
Paul Mackerras9a7558f2007-10-06 20:16:06 +100010348 -variable fontparam(slant) -onvalue italic -offvalue roman
10349 pack $top.g.size $top.g.bold $top.g.ital -side left
10350 pack $top.g -side top
10351 canvas $top.c -width 150 -height 50 -border 2 -relief sunk \
10352 -background white
10353 $top.c create text 100 25 -anchor center -text $which -font sample \
10354 -fill black -tags text
10355 bind $top.c <Configure> [list centertext $top.c]
10356 pack $top.c -side top -fill x
10357 frame $top.buts
Paul Mackerrasb039f0a2008-01-06 15:54:46 +110010358 button $top.buts.ok -text [mc "OK"] -command fontok -default active
10359 button $top.buts.can -text [mc "Cancel"] -command fontcan -default normal
Alexander Gavrilov76f15942008-11-02 21:59:44 +030010360 bind $top <Key-Return> fontok
10361 bind $top <Key-Escape> fontcan
Paul Mackerras9a7558f2007-10-06 20:16:06 +100010362 grid $top.buts.ok $top.buts.can
10363 grid columnconfigure $top.buts 0 -weight 1 -uniform a
10364 grid columnconfigure $top.buts 1 -weight 1 -uniform a
10365 pack $top.buts -side bottom -fill x
10366 trace add variable fontparam write chg_fontparam
10367 } else {
10368 raise $top
10369 $top.c itemconf text -text $which
10370 }
10371 set i [lsearch -exact $fontlist $fontparam(family)]
10372 if {$i >= 0} {
10373 $top.f.fam selection set $i
10374 $top.f.fam see $i
10375 }
10376}
10377
10378proc centertext {w} {
10379 $w coords text [expr {[winfo width $w] / 2}] [expr {[winfo height $w] / 2}]
10380}
10381
10382proc fontok {} {
10383 global fontparam fontpref prefstop
10384
10385 set f $fontparam(font)
10386 set fontpref($f) [list $fontparam(family) $fontparam(size)]
10387 if {$fontparam(weight) eq "bold"} {
10388 lappend fontpref($f) "bold"
10389 }
10390 if {$fontparam(slant) eq "italic"} {
10391 lappend fontpref($f) "italic"
10392 }
10393 set w $prefstop.$f
10394 $w conf -text $fontparam(family) -font $fontpref($f)
10395
10396 fontcan
10397}
10398
10399proc fontcan {} {
10400 global fonttop fontparam
10401
10402 if {[info exists fonttop]} {
10403 catch {destroy $fonttop}
10404 catch {font delete sample}
10405 unset fonttop
10406 unset fontparam
10407 }
10408}
10409
10410proc selfontfam {} {
10411 global fonttop fontparam
10412
10413 set i [$fonttop.f.fam curselection]
10414 if {$i ne {}} {
10415 set fontparam(family) [$fonttop.f.fam get $i]
10416 }
10417}
10418
10419proc chg_fontparam {v sub op} {
10420 global fontparam
10421
10422 font config sample -$sub $fontparam($sub)
10423}
10424
Paul Mackerras712fcc02005-11-30 09:28:16 +110010425proc doprefs {} {
Paul Mackerras8d73b242007-10-06 20:22:00 +100010426 global maxwidth maxgraphpct
Paul Mackerras219ea3a2006-09-07 10:21:39 +100010427 global oldprefs prefstop showneartags showlocalchanges
Paul Mackerrase3e901b2008-10-27 22:37:21 +110010428 global bgcolor fgcolor ctext diffcolors selectbgcolor markbgcolor
Paul Mackerras39ee47e2008-10-15 22:23:03 +110010429 global tabstop limitdiffs autoselect extdifftool perfile_attrs
Thomas Rastffe15292009-08-03 23:53:36 +020010430 global hideremotes
Paul Mackerras232475d2005-11-15 10:34:03 +110010431
Paul Mackerras712fcc02005-11-30 09:28:16 +110010432 set top .gitkprefs
10433 set prefstop $top
10434 if {[winfo exists $top]} {
10435 raise $top
10436 return
Paul Mackerras757f17b2005-11-21 09:56:07 +110010437 }
Paul Mackerras3de07112007-10-23 22:40:50 +100010438 foreach v {maxwidth maxgraphpct showneartags showlocalchanges \
Thomas Rastffe15292009-08-03 23:53:36 +020010439 limitdiffs tabstop perfile_attrs hideremotes} {
Paul Mackerras712fcc02005-11-30 09:28:16 +110010440 set oldprefs($v) [set $v]
Paul Mackerras232475d2005-11-15 10:34:03 +110010441 }
Paul Mackerras712fcc02005-11-30 09:28:16 +110010442 toplevel $top
Christian Stimmingd990ced2007-11-07 18:42:55 +010010443 wm title $top [mc "Gitk preferences"]
Alexander Gavrilove7d64002008-11-11 23:55:42 +030010444 make_transient $top .
Christian Stimmingd990ced2007-11-07 18:42:55 +010010445 label $top.ldisp -text [mc "Commit list display options"]
Paul Mackerras712fcc02005-11-30 09:28:16 +110010446 grid $top.ldisp - -sticky w -pady 10
10447 label $top.spacer -text " "
Christian Stimmingd990ced2007-11-07 18:42:55 +010010448 label $top.maxwidthl -text [mc "Maximum graph width (lines)"] \
Paul Mackerras712fcc02005-11-30 09:28:16 +110010449 -font optionfont
10450 spinbox $top.maxwidth -from 0 -to 100 -width 4 -textvariable maxwidth
10451 grid $top.spacer $top.maxwidthl $top.maxwidth -sticky w
Christian Stimmingd990ced2007-11-07 18:42:55 +010010452 label $top.maxpctl -text [mc "Maximum graph width (% of pane)"] \
Paul Mackerras712fcc02005-11-30 09:28:16 +110010453 -font optionfont
10454 spinbox $top.maxpct -from 1 -to 100 -width 4 -textvariable maxgraphpct
10455 grid x $top.maxpctl $top.maxpct -sticky w
Johannes Sixtadcbec12008-12-02 21:42:16 +010010456 checkbutton $top.showlocal -text [mc "Show local changes"] \
10457 -font optionfont -variable showlocalchanges
Paul Mackerras219ea3a2006-09-07 10:21:39 +100010458 grid x $top.showlocal -sticky w
Johannes Sixtadcbec12008-12-02 21:42:16 +010010459 checkbutton $top.autoselect -text [mc "Auto-select SHA1"] \
10460 -font optionfont -variable autoselect
Jeff King95293b52008-03-06 06:49:25 -050010461 grid x $top.autoselect -sticky w
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +100010462
Christian Stimmingd990ced2007-11-07 18:42:55 +010010463 label $top.ddisp -text [mc "Diff display options"]
Paul Mackerras712fcc02005-11-30 09:28:16 +110010464 grid $top.ddisp - -sticky w -pady 10
Christian Stimmingd990ced2007-11-07 18:42:55 +010010465 label $top.tabstopl -text [mc "Tab spacing"] -font optionfont
Paul Mackerras94503912007-10-23 10:33:38 +100010466 spinbox $top.tabstop -from 1 -to 20 -width 4 -textvariable tabstop
10467 grid x $top.tabstopl $top.tabstop -sticky w
Johannes Sixtadcbec12008-12-02 21:42:16 +010010468 checkbutton $top.ntag -text [mc "Display nearby tags"] \
10469 -font optionfont -variable showneartags
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +100010470 grid x $top.ntag -sticky w
Thomas Rastffe15292009-08-03 23:53:36 +020010471 checkbutton $top.hideremotes -text [mc "Hide remote refs"] \
10472 -font optionfont -variable hideremotes
10473 grid x $top.hideremotes -sticky w
Johannes Sixtadcbec12008-12-02 21:42:16 +010010474 checkbutton $top.ldiff -text [mc "Limit diffs to listed paths"] \
10475 -font optionfont -variable limitdiffs
Paul Mackerras7a39a172007-10-23 10:15:11 +100010476 grid x $top.ldiff -sticky w
Johannes Sixtadcbec12008-12-02 21:42:16 +010010477 checkbutton $top.lattr -text [mc "Support per-file encodings"] \
10478 -font optionfont -variable perfile_attrs
Paul Mackerras39ee47e2008-10-15 22:23:03 +110010479 grid x $top.lattr -sticky w
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +100010480
Thomas Arcila314f5de2008-03-24 12:55:36 +010010481 entry $top.extdifft -textvariable extdifftool
10482 frame $top.extdifff
10483 label $top.extdifff.l -text [mc "External diff tool" ] -font optionfont \
10484 -padx 10
10485 button $top.extdifff.b -text [mc "Choose..."] -font optionfont \
10486 -command choose_extdiff
10487 pack $top.extdifff.l $top.extdifff.b -side left
10488 grid x $top.extdifff $top.extdifft -sticky w
10489
Christian Stimmingd990ced2007-11-07 18:42:55 +010010490 label $top.cdisp -text [mc "Colors: press to choose"]
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +100010491 grid $top.cdisp - -sticky w -pady 10
10492 label $top.bg -padx 40 -relief sunk -background $bgcolor
Christian Stimmingd990ced2007-11-07 18:42:55 +010010493 button $top.bgbut -text [mc "Background"] -font optionfont \
Christian Stimming968b0162008-12-06 20:48:30 +010010494 -command [list choosecolor bgcolor {} $top.bg [mc "background"] setbg]
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +100010495 grid x $top.bgbut $top.bg -sticky w
10496 label $top.fg -padx 40 -relief sunk -background $fgcolor
Christian Stimmingd990ced2007-11-07 18:42:55 +010010497 button $top.fgbut -text [mc "Foreground"] -font optionfont \
Christian Stimming968b0162008-12-06 20:48:30 +010010498 -command [list choosecolor fgcolor {} $top.fg [mc "foreground"] setfg]
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +100010499 grid x $top.fgbut $top.fg -sticky w
10500 label $top.diffold -padx 40 -relief sunk -background [lindex $diffcolors 0]
Christian Stimmingd990ced2007-11-07 18:42:55 +010010501 button $top.diffoldbut -text [mc "Diff: old lines"] -font optionfont \
Christian Stimming968b0162008-12-06 20:48:30 +010010502 -command [list choosecolor diffcolors 0 $top.diffold [mc "diff old lines"] \
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +100010503 [list $ctext tag conf d0 -foreground]]
10504 grid x $top.diffoldbut $top.diffold -sticky w
10505 label $top.diffnew -padx 40 -relief sunk -background [lindex $diffcolors 1]
Christian Stimmingd990ced2007-11-07 18:42:55 +010010506 button $top.diffnewbut -text [mc "Diff: new lines"] -font optionfont \
Christian Stimming968b0162008-12-06 20:48:30 +010010507 -command [list choosecolor diffcolors 1 $top.diffnew [mc "diff new lines"] \
Paul Mackerras8b07dca2008-11-02 22:34:47 +110010508 [list $ctext tag conf dresult -foreground]]
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +100010509 grid x $top.diffnewbut $top.diffnew -sticky w
10510 label $top.hunksep -padx 40 -relief sunk -background [lindex $diffcolors 2]
Christian Stimmingd990ced2007-11-07 18:42:55 +010010511 button $top.hunksepbut -text [mc "Diff: hunk header"] -font optionfont \
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +100010512 -command [list choosecolor diffcolors 2 $top.hunksep \
Christian Stimming968b0162008-12-06 20:48:30 +010010513 [mc "diff hunk header"] \
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +100010514 [list $ctext tag conf hunksep -foreground]]
10515 grid x $top.hunksepbut $top.hunksep -sticky w
Paul Mackerrase3e901b2008-10-27 22:37:21 +110010516 label $top.markbgsep -padx 40 -relief sunk -background $markbgcolor
10517 button $top.markbgbut -text [mc "Marked line bg"] -font optionfont \
10518 -command [list choosecolor markbgcolor {} $top.markbgsep \
10519 [mc "marked line background"] \
10520 [list $ctext tag conf omark -background]]
10521 grid x $top.markbgbut $top.markbgsep -sticky w
Mark Levedahl60378c02007-05-20 12:12:48 -040010522 label $top.selbgsep -padx 40 -relief sunk -background $selectbgcolor
Christian Stimmingd990ced2007-11-07 18:42:55 +010010523 button $top.selbgbut -text [mc "Select bg"] -font optionfont \
Christian Stimming968b0162008-12-06 20:48:30 +010010524 -command [list choosecolor selectbgcolor {} $top.selbgsep [mc "background"] setselbg]
Mark Levedahl60378c02007-05-20 12:12:48 -040010525 grid x $top.selbgbut $top.selbgsep -sticky w
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +100010526
Christian Stimmingd990ced2007-11-07 18:42:55 +010010527 label $top.cfont -text [mc "Fonts: press to choose"]
Paul Mackerras9a7558f2007-10-06 20:16:06 +100010528 grid $top.cfont - -sticky w -pady 10
Christian Stimmingd990ced2007-11-07 18:42:55 +010010529 mkfontdisp mainfont $top [mc "Main font"]
10530 mkfontdisp textfont $top [mc "Diff display font"]
10531 mkfontdisp uifont $top [mc "User interface font"]
Paul Mackerras9a7558f2007-10-06 20:16:06 +100010532
Paul Mackerras712fcc02005-11-30 09:28:16 +110010533 frame $top.buts
Christian Stimmingd990ced2007-11-07 18:42:55 +010010534 button $top.buts.ok -text [mc "OK"] -command prefsok -default active
Christian Stimmingd990ced2007-11-07 18:42:55 +010010535 button $top.buts.can -text [mc "Cancel"] -command prefscan -default normal
Alexander Gavrilov76f15942008-11-02 21:59:44 +030010536 bind $top <Key-Return> prefsok
10537 bind $top <Key-Escape> prefscan
Paul Mackerras712fcc02005-11-30 09:28:16 +110010538 grid $top.buts.ok $top.buts.can
10539 grid columnconfigure $top.buts 0 -weight 1 -uniform a
10540 grid columnconfigure $top.buts 1 -weight 1 -uniform a
10541 grid $top.buts - - -pady 10 -sticky ew
Eygene Ryabinkin3a950e92007-03-27 14:36:59 +040010542 bind $top <Visibility> "focus $top.buts.ok"
Paul Mackerras712fcc02005-11-30 09:28:16 +110010543}
10544
Thomas Arcila314f5de2008-03-24 12:55:36 +010010545proc choose_extdiff {} {
10546 global extdifftool
10547
Michele Ballabiob56e0a92009-03-30 21:17:25 +020010548 set prog [tk_getOpenFile -title [mc "External diff tool"] -multiple false]
Thomas Arcila314f5de2008-03-24 12:55:36 +010010549 if {$prog ne {}} {
10550 set extdifftool $prog
10551 }
10552}
10553
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +100010554proc choosecolor {v vi w x cmd} {
10555 global $v
10556
10557 set c [tk_chooseColor -initialcolor [lindex [set $v] $vi] \
Christian Stimmingd990ced2007-11-07 18:42:55 +010010558 -title [mc "Gitk: choose color for %s" $x]]
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +100010559 if {$c eq {}} return
10560 $w conf -background $c
10561 lset $v $vi $c
10562 eval $cmd $c
10563}
10564
Mark Levedahl60378c02007-05-20 12:12:48 -040010565proc setselbg {c} {
10566 global bglist cflist
10567 foreach w $bglist {
10568 $w configure -selectbackground $c
10569 }
10570 $cflist tag configure highlight \
10571 -background [$cflist cget -selectbackground]
10572 allcanvs itemconf secsel -fill $c
10573}
10574
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +100010575proc setbg {c} {
10576 global bglist
10577
10578 foreach w $bglist {
10579 $w conf -background $c
10580 }
10581}
10582
10583proc setfg {c} {
10584 global fglist canv
10585
10586 foreach w $fglist {
10587 $w conf -foreground $c
10588 }
10589 allcanvs itemconf text -fill $c
10590 $canv itemconf circle -outline $c
Paul Mackerrasb9fdba72009-04-09 09:34:46 +100010591 $canv itemconf markid -outline $c
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +100010592}
10593
Paul Mackerras712fcc02005-11-30 09:28:16 +110010594proc prefscan {} {
Paul Mackerras94503912007-10-23 10:33:38 +100010595 global oldprefs prefstop
Paul Mackerras712fcc02005-11-30 09:28:16 +110010596
Paul Mackerras3de07112007-10-23 22:40:50 +100010597 foreach v {maxwidth maxgraphpct showneartags showlocalchanges \
Thomas Rastffe15292009-08-03 23:53:36 +020010598 limitdiffs tabstop perfile_attrs hideremotes} {
Paul Mackerras94503912007-10-23 10:33:38 +100010599 global $v
Paul Mackerras712fcc02005-11-30 09:28:16 +110010600 set $v $oldprefs($v)
10601 }
10602 catch {destroy $prefstop}
10603 unset prefstop
Paul Mackerras9a7558f2007-10-06 20:16:06 +100010604 fontcan
Paul Mackerras712fcc02005-11-30 09:28:16 +110010605}
10606
10607proc prefsok {} {
10608 global maxwidth maxgraphpct
Paul Mackerras219ea3a2006-09-07 10:21:39 +100010609 global oldprefs prefstop showneartags showlocalchanges
Paul Mackerras9a7558f2007-10-06 20:16:06 +100010610 global fontpref mainfont textfont uifont
Paul Mackerras39ee47e2008-10-15 22:23:03 +110010611 global limitdiffs treediffs perfile_attrs
Thomas Rastffe15292009-08-03 23:53:36 +020010612 global hideremotes
Paul Mackerras712fcc02005-11-30 09:28:16 +110010613
10614 catch {destroy $prefstop}
10615 unset prefstop
Paul Mackerras9a7558f2007-10-06 20:16:06 +100010616 fontcan
10617 set fontchanged 0
10618 if {$mainfont ne $fontpref(mainfont)} {
10619 set mainfont $fontpref(mainfont)
10620 parsefont mainfont $mainfont
10621 eval font configure mainfont [fontflags mainfont]
10622 eval font configure mainfontbold [fontflags mainfont 1]
10623 setcoords
10624 set fontchanged 1
10625 }
10626 if {$textfont ne $fontpref(textfont)} {
10627 set textfont $fontpref(textfont)
10628 parsefont textfont $textfont
10629 eval font configure textfont [fontflags textfont]
10630 eval font configure textfontbold [fontflags textfont 1]
10631 }
10632 if {$uifont ne $fontpref(uifont)} {
10633 set uifont $fontpref(uifont)
10634 parsefont uifont $uifont
10635 eval font configure uifont [fontflags uifont]
10636 }
Paul Mackerras32f1b3e2007-09-28 21:27:39 +100010637 settabs
Paul Mackerras219ea3a2006-09-07 10:21:39 +100010638 if {$showlocalchanges != $oldprefs(showlocalchanges)} {
10639 if {$showlocalchanges} {
10640 doshowlocalchanges
10641 } else {
10642 dohidelocalchanges
10643 }
10644 }
Paul Mackerras39ee47e2008-10-15 22:23:03 +110010645 if {$limitdiffs != $oldprefs(limitdiffs) ||
10646 ($perfile_attrs && !$oldprefs(perfile_attrs))} {
10647 # treediffs elements are limited by path;
10648 # won't have encodings cached if perfile_attrs was just turned on
Paul Mackerras74a40c72007-10-24 10:16:56 +100010649 catch {unset treediffs}
10650 }
Paul Mackerras9a7558f2007-10-06 20:16:06 +100010651 if {$fontchanged || $maxwidth != $oldprefs(maxwidth)
Paul Mackerras712fcc02005-11-30 09:28:16 +110010652 || $maxgraphpct != $oldprefs(maxgraphpct)} {
10653 redisplay
Paul Mackerras7a39a172007-10-23 10:15:11 +100010654 } elseif {$showneartags != $oldprefs(showneartags) ||
10655 $limitdiffs != $oldprefs(limitdiffs)} {
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +100010656 reselectline
Paul Mackerras712fcc02005-11-30 09:28:16 +110010657 }
Thomas Rastffe15292009-08-03 23:53:36 +020010658 if {$hideremotes != $oldprefs(hideremotes)} {
10659 rereadrefs
10660 }
Paul Mackerras712fcc02005-11-30 09:28:16 +110010661}
10662
10663proc formatdate {d} {
Arjen Laarhovene8b5f4b2007-08-14 22:02:04 +020010664 global datetimeformat
Paul Mackerras219ea3a2006-09-07 10:21:39 +100010665 if {$d ne {}} {
Arjen Laarhovene8b5f4b2007-08-14 22:02:04 +020010666 set d [clock format $d -format $datetimeformat]
Paul Mackerras219ea3a2006-09-07 10:21:39 +100010667 }
10668 return $d
Paul Mackerras232475d2005-11-15 10:34:03 +110010669}
10670
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +110010671# This list of encoding names and aliases is distilled from
10672# http://www.iana.org/assignments/character-sets.
10673# Not all of them are supported by Tcl.
10674set encoding_aliases {
10675 { ANSI_X3.4-1968 iso-ir-6 ANSI_X3.4-1986 ISO_646.irv:1991 ASCII
10676 ISO646-US US-ASCII us IBM367 cp367 csASCII }
10677 { ISO-10646-UTF-1 csISO10646UTF1 }
10678 { ISO_646.basic:1983 ref csISO646basic1983 }
10679 { INVARIANT csINVARIANT }
10680 { ISO_646.irv:1983 iso-ir-2 irv csISO2IntlRefVersion }
10681 { BS_4730 iso-ir-4 ISO646-GB gb uk csISO4UnitedKingdom }
10682 { NATS-SEFI iso-ir-8-1 csNATSSEFI }
10683 { NATS-SEFI-ADD iso-ir-8-2 csNATSSEFIADD }
10684 { NATS-DANO iso-ir-9-1 csNATSDANO }
10685 { NATS-DANO-ADD iso-ir-9-2 csNATSDANOADD }
10686 { SEN_850200_B iso-ir-10 FI ISO646-FI ISO646-SE se csISO10Swedish }
10687 { SEN_850200_C iso-ir-11 ISO646-SE2 se2 csISO11SwedishForNames }
10688 { KS_C_5601-1987 iso-ir-149 KS_C_5601-1989 KSC_5601 korean csKSC56011987 }
10689 { ISO-2022-KR csISO2022KR }
10690 { EUC-KR csEUCKR }
10691 { ISO-2022-JP csISO2022JP }
10692 { ISO-2022-JP-2 csISO2022JP2 }
10693 { JIS_C6220-1969-jp JIS_C6220-1969 iso-ir-13 katakana x0201-7
10694 csISO13JISC6220jp }
10695 { JIS_C6220-1969-ro iso-ir-14 jp ISO646-JP csISO14JISC6220ro }
10696 { IT iso-ir-15 ISO646-IT csISO15Italian }
10697 { PT iso-ir-16 ISO646-PT csISO16Portuguese }
10698 { ES iso-ir-17 ISO646-ES csISO17Spanish }
10699 { greek7-old iso-ir-18 csISO18Greek7Old }
10700 { latin-greek iso-ir-19 csISO19LatinGreek }
10701 { DIN_66003 iso-ir-21 de ISO646-DE csISO21German }
10702 { NF_Z_62-010_(1973) iso-ir-25 ISO646-FR1 csISO25French }
10703 { Latin-greek-1 iso-ir-27 csISO27LatinGreek1 }
10704 { ISO_5427 iso-ir-37 csISO5427Cyrillic }
10705 { JIS_C6226-1978 iso-ir-42 csISO42JISC62261978 }
10706 { BS_viewdata iso-ir-47 csISO47BSViewdata }
10707 { INIS iso-ir-49 csISO49INIS }
10708 { INIS-8 iso-ir-50 csISO50INIS8 }
10709 { INIS-cyrillic iso-ir-51 csISO51INISCyrillic }
10710 { ISO_5427:1981 iso-ir-54 ISO5427Cyrillic1981 }
10711 { ISO_5428:1980 iso-ir-55 csISO5428Greek }
10712 { GB_1988-80 iso-ir-57 cn ISO646-CN csISO57GB1988 }
10713 { GB_2312-80 iso-ir-58 chinese csISO58GB231280 }
10714 { NS_4551-1 iso-ir-60 ISO646-NO no csISO60DanishNorwegian
10715 csISO60Norwegian1 }
10716 { NS_4551-2 ISO646-NO2 iso-ir-61 no2 csISO61Norwegian2 }
10717 { NF_Z_62-010 iso-ir-69 ISO646-FR fr csISO69French }
10718 { videotex-suppl iso-ir-70 csISO70VideotexSupp1 }
10719 { PT2 iso-ir-84 ISO646-PT2 csISO84Portuguese2 }
10720 { ES2 iso-ir-85 ISO646-ES2 csISO85Spanish2 }
10721 { MSZ_7795.3 iso-ir-86 ISO646-HU hu csISO86Hungarian }
10722 { JIS_C6226-1983 iso-ir-87 x0208 JIS_X0208-1983 csISO87JISX0208 }
10723 { greek7 iso-ir-88 csISO88Greek7 }
10724 { ASMO_449 ISO_9036 arabic7 iso-ir-89 csISO89ASMO449 }
10725 { iso-ir-90 csISO90 }
10726 { JIS_C6229-1984-a iso-ir-91 jp-ocr-a csISO91JISC62291984a }
10727 { JIS_C6229-1984-b iso-ir-92 ISO646-JP-OCR-B jp-ocr-b
10728 csISO92JISC62991984b }
10729 { JIS_C6229-1984-b-add iso-ir-93 jp-ocr-b-add csISO93JIS62291984badd }
10730 { JIS_C6229-1984-hand iso-ir-94 jp-ocr-hand csISO94JIS62291984hand }
10731 { JIS_C6229-1984-hand-add iso-ir-95 jp-ocr-hand-add
10732 csISO95JIS62291984handadd }
10733 { JIS_C6229-1984-kana iso-ir-96 csISO96JISC62291984kana }
10734 { ISO_2033-1983 iso-ir-98 e13b csISO2033 }
10735 { ANSI_X3.110-1983 iso-ir-99 CSA_T500-1983 NAPLPS csISO99NAPLPS }
10736 { ISO_8859-1:1987 iso-ir-100 ISO_8859-1 ISO-8859-1 latin1 l1 IBM819
10737 CP819 csISOLatin1 }
10738 { ISO_8859-2:1987 iso-ir-101 ISO_8859-2 ISO-8859-2 latin2 l2 csISOLatin2 }
10739 { T.61-7bit iso-ir-102 csISO102T617bit }
10740 { T.61-8bit T.61 iso-ir-103 csISO103T618bit }
10741 { ISO_8859-3:1988 iso-ir-109 ISO_8859-3 ISO-8859-3 latin3 l3 csISOLatin3 }
10742 { ISO_8859-4:1988 iso-ir-110 ISO_8859-4 ISO-8859-4 latin4 l4 csISOLatin4 }
10743 { ECMA-cyrillic iso-ir-111 KOI8-E csISO111ECMACyrillic }
10744 { CSA_Z243.4-1985-1 iso-ir-121 ISO646-CA csa7-1 ca csISO121Canadian1 }
10745 { CSA_Z243.4-1985-2 iso-ir-122 ISO646-CA2 csa7-2 csISO122Canadian2 }
10746 { CSA_Z243.4-1985-gr iso-ir-123 csISO123CSAZ24341985gr }
10747 { ISO_8859-6:1987 iso-ir-127 ISO_8859-6 ISO-8859-6 ECMA-114 ASMO-708
10748 arabic csISOLatinArabic }
10749 { ISO_8859-6-E csISO88596E ISO-8859-6-E }
10750 { ISO_8859-6-I csISO88596I ISO-8859-6-I }
10751 { ISO_8859-7:1987 iso-ir-126 ISO_8859-7 ISO-8859-7 ELOT_928 ECMA-118
10752 greek greek8 csISOLatinGreek }
10753 { T.101-G2 iso-ir-128 csISO128T101G2 }
10754 { ISO_8859-8:1988 iso-ir-138 ISO_8859-8 ISO-8859-8 hebrew
10755 csISOLatinHebrew }
10756 { ISO_8859-8-E csISO88598E ISO-8859-8-E }
10757 { ISO_8859-8-I csISO88598I ISO-8859-8-I }
10758 { CSN_369103 iso-ir-139 csISO139CSN369103 }
10759 { JUS_I.B1.002 iso-ir-141 ISO646-YU js yu csISO141JUSIB1002 }
10760 { ISO_6937-2-add iso-ir-142 csISOTextComm }
10761 { IEC_P27-1 iso-ir-143 csISO143IECP271 }
10762 { ISO_8859-5:1988 iso-ir-144 ISO_8859-5 ISO-8859-5 cyrillic
10763 csISOLatinCyrillic }
10764 { JUS_I.B1.003-serb iso-ir-146 serbian csISO146Serbian }
10765 { JUS_I.B1.003-mac macedonian iso-ir-147 csISO147Macedonian }
10766 { ISO_8859-9:1989 iso-ir-148 ISO_8859-9 ISO-8859-9 latin5 l5 csISOLatin5 }
10767 { greek-ccitt iso-ir-150 csISO150 csISO150GreekCCITT }
10768 { NC_NC00-10:81 cuba iso-ir-151 ISO646-CU csISO151Cuba }
10769 { ISO_6937-2-25 iso-ir-152 csISO6937Add }
10770 { GOST_19768-74 ST_SEV_358-88 iso-ir-153 csISO153GOST1976874 }
10771 { ISO_8859-supp iso-ir-154 latin1-2-5 csISO8859Supp }
10772 { ISO_10367-box iso-ir-155 csISO10367Box }
10773 { ISO-8859-10 iso-ir-157 l6 ISO_8859-10:1992 csISOLatin6 latin6 }
10774 { latin-lap lap iso-ir-158 csISO158Lap }
10775 { JIS_X0212-1990 x0212 iso-ir-159 csISO159JISX02121990 }
10776 { DS_2089 DS2089 ISO646-DK dk csISO646Danish }
10777 { us-dk csUSDK }
10778 { dk-us csDKUS }
10779 { JIS_X0201 X0201 csHalfWidthKatakana }
10780 { KSC5636 ISO646-KR csKSC5636 }
10781 { ISO-10646-UCS-2 csUnicode }
10782 { ISO-10646-UCS-4 csUCS4 }
10783 { DEC-MCS dec csDECMCS }
10784 { hp-roman8 roman8 r8 csHPRoman8 }
10785 { macintosh mac csMacintosh }
10786 { IBM037 cp037 ebcdic-cp-us ebcdic-cp-ca ebcdic-cp-wt ebcdic-cp-nl
10787 csIBM037 }
10788 { IBM038 EBCDIC-INT cp038 csIBM038 }
10789 { IBM273 CP273 csIBM273 }
10790 { IBM274 EBCDIC-BE CP274 csIBM274 }
10791 { IBM275 EBCDIC-BR cp275 csIBM275 }
10792 { IBM277 EBCDIC-CP-DK EBCDIC-CP-NO csIBM277 }
10793 { IBM278 CP278 ebcdic-cp-fi ebcdic-cp-se csIBM278 }
10794 { IBM280 CP280 ebcdic-cp-it csIBM280 }
10795 { IBM281 EBCDIC-JP-E cp281 csIBM281 }
10796 { IBM284 CP284 ebcdic-cp-es csIBM284 }
10797 { IBM285 CP285 ebcdic-cp-gb csIBM285 }
10798 { IBM290 cp290 EBCDIC-JP-kana csIBM290 }
10799 { IBM297 cp297 ebcdic-cp-fr csIBM297 }
10800 { IBM420 cp420 ebcdic-cp-ar1 csIBM420 }
10801 { IBM423 cp423 ebcdic-cp-gr csIBM423 }
10802 { IBM424 cp424 ebcdic-cp-he csIBM424 }
10803 { IBM437 cp437 437 csPC8CodePage437 }
10804 { IBM500 CP500 ebcdic-cp-be ebcdic-cp-ch csIBM500 }
10805 { IBM775 cp775 csPC775Baltic }
10806 { IBM850 cp850 850 csPC850Multilingual }
10807 { IBM851 cp851 851 csIBM851 }
10808 { IBM852 cp852 852 csPCp852 }
10809 { IBM855 cp855 855 csIBM855 }
10810 { IBM857 cp857 857 csIBM857 }
10811 { IBM860 cp860 860 csIBM860 }
10812 { IBM861 cp861 861 cp-is csIBM861 }
10813 { IBM862 cp862 862 csPC862LatinHebrew }
10814 { IBM863 cp863 863 csIBM863 }
10815 { IBM864 cp864 csIBM864 }
10816 { IBM865 cp865 865 csIBM865 }
10817 { IBM866 cp866 866 csIBM866 }
10818 { IBM868 CP868 cp-ar csIBM868 }
10819 { IBM869 cp869 869 cp-gr csIBM869 }
10820 { IBM870 CP870 ebcdic-cp-roece ebcdic-cp-yu csIBM870 }
10821 { IBM871 CP871 ebcdic-cp-is csIBM871 }
10822 { IBM880 cp880 EBCDIC-Cyrillic csIBM880 }
10823 { IBM891 cp891 csIBM891 }
10824 { IBM903 cp903 csIBM903 }
10825 { IBM904 cp904 904 csIBBM904 }
10826 { IBM905 CP905 ebcdic-cp-tr csIBM905 }
10827 { IBM918 CP918 ebcdic-cp-ar2 csIBM918 }
10828 { IBM1026 CP1026 csIBM1026 }
10829 { EBCDIC-AT-DE csIBMEBCDICATDE }
10830 { EBCDIC-AT-DE-A csEBCDICATDEA }
10831 { EBCDIC-CA-FR csEBCDICCAFR }
10832 { EBCDIC-DK-NO csEBCDICDKNO }
10833 { EBCDIC-DK-NO-A csEBCDICDKNOA }
10834 { EBCDIC-FI-SE csEBCDICFISE }
10835 { EBCDIC-FI-SE-A csEBCDICFISEA }
10836 { EBCDIC-FR csEBCDICFR }
10837 { EBCDIC-IT csEBCDICIT }
10838 { EBCDIC-PT csEBCDICPT }
10839 { EBCDIC-ES csEBCDICES }
10840 { EBCDIC-ES-A csEBCDICESA }
10841 { EBCDIC-ES-S csEBCDICESS }
10842 { EBCDIC-UK csEBCDICUK }
10843 { EBCDIC-US csEBCDICUS }
10844 { UNKNOWN-8BIT csUnknown8BiT }
10845 { MNEMONIC csMnemonic }
10846 { MNEM csMnem }
10847 { VISCII csVISCII }
10848 { VIQR csVIQR }
10849 { KOI8-R csKOI8R }
10850 { IBM00858 CCSID00858 CP00858 PC-Multilingual-850+euro }
10851 { IBM00924 CCSID00924 CP00924 ebcdic-Latin9--euro }
10852 { IBM01140 CCSID01140 CP01140 ebcdic-us-37+euro }
10853 { IBM01141 CCSID01141 CP01141 ebcdic-de-273+euro }
10854 { IBM01142 CCSID01142 CP01142 ebcdic-dk-277+euro ebcdic-no-277+euro }
10855 { IBM01143 CCSID01143 CP01143 ebcdic-fi-278+euro ebcdic-se-278+euro }
10856 { IBM01144 CCSID01144 CP01144 ebcdic-it-280+euro }
10857 { IBM01145 CCSID01145 CP01145 ebcdic-es-284+euro }
10858 { IBM01146 CCSID01146 CP01146 ebcdic-gb-285+euro }
10859 { IBM01147 CCSID01147 CP01147 ebcdic-fr-297+euro }
10860 { IBM01148 CCSID01148 CP01148 ebcdic-international-500+euro }
10861 { IBM01149 CCSID01149 CP01149 ebcdic-is-871+euro }
10862 { IBM1047 IBM-1047 }
10863 { PTCP154 csPTCP154 PT154 CP154 Cyrillic-Asian }
10864 { Amiga-1251 Ami1251 Amiga1251 Ami-1251 }
10865 { UNICODE-1-1 csUnicode11 }
10866 { CESU-8 csCESU-8 }
10867 { BOCU-1 csBOCU-1 }
10868 { UNICODE-1-1-UTF-7 csUnicode11UTF7 }
10869 { ISO-8859-14 iso-ir-199 ISO_8859-14:1998 ISO_8859-14 latin8 iso-celtic
10870 l8 }
10871 { ISO-8859-15 ISO_8859-15 Latin-9 }
10872 { ISO-8859-16 iso-ir-226 ISO_8859-16:2001 ISO_8859-16 latin10 l10 }
10873 { GBK CP936 MS936 windows-936 }
10874 { JIS_Encoding csJISEncoding }
Alexander Gavrilov09c70292008-10-13 12:12:31 +040010875 { Shift_JIS MS_Kanji csShiftJIS ShiftJIS Shift-JIS }
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +110010876 { Extended_UNIX_Code_Packed_Format_for_Japanese csEUCPkdFmtJapanese
10877 EUC-JP }
10878 { Extended_UNIX_Code_Fixed_Width_for_Japanese csEUCFixWidJapanese }
10879 { ISO-10646-UCS-Basic csUnicodeASCII }
10880 { ISO-10646-Unicode-Latin1 csUnicodeLatin1 ISO-10646 }
10881 { ISO-Unicode-IBM-1261 csUnicodeIBM1261 }
10882 { ISO-Unicode-IBM-1268 csUnicodeIBM1268 }
10883 { ISO-Unicode-IBM-1276 csUnicodeIBM1276 }
10884 { ISO-Unicode-IBM-1264 csUnicodeIBM1264 }
10885 { ISO-Unicode-IBM-1265 csUnicodeIBM1265 }
10886 { ISO-8859-1-Windows-3.0-Latin-1 csWindows30Latin1 }
10887 { ISO-8859-1-Windows-3.1-Latin-1 csWindows31Latin1 }
10888 { ISO-8859-2-Windows-Latin-2 csWindows31Latin2 }
10889 { ISO-8859-9-Windows-Latin-5 csWindows31Latin5 }
10890 { Adobe-Standard-Encoding csAdobeStandardEncoding }
10891 { Ventura-US csVenturaUS }
10892 { Ventura-International csVenturaInternational }
10893 { PC8-Danish-Norwegian csPC8DanishNorwegian }
10894 { PC8-Turkish csPC8Turkish }
10895 { IBM-Symbols csIBMSymbols }
10896 { IBM-Thai csIBMThai }
10897 { HP-Legal csHPLegal }
10898 { HP-Pi-font csHPPiFont }
10899 { HP-Math8 csHPMath8 }
10900 { Adobe-Symbol-Encoding csHPPSMath }
10901 { HP-DeskTop csHPDesktop }
10902 { Ventura-Math csVenturaMath }
10903 { Microsoft-Publishing csMicrosoftPublishing }
10904 { Windows-31J csWindows31J }
10905 { GB2312 csGB2312 }
10906 { Big5 csBig5 }
10907}
10908
10909proc tcl_encoding {enc} {
Paul Mackerras39ee47e2008-10-15 22:23:03 +110010910 global encoding_aliases tcl_encoding_cache
10911 if {[info exists tcl_encoding_cache($enc)]} {
10912 return $tcl_encoding_cache($enc)
10913 }
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +110010914 set names [encoding names]
10915 set lcnames [string tolower $names]
10916 set enc [string tolower $enc]
10917 set i [lsearch -exact $lcnames $enc]
10918 if {$i < 0} {
10919 # look for "isonnn" instead of "iso-nnn" or "iso_nnn"
Alexander Gavrilov09c70292008-10-13 12:12:31 +040010920 if {[regsub {^(iso|cp|ibm|jis)[-_]} $enc {\1} encx]} {
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +110010921 set i [lsearch -exact $lcnames $encx]
10922 }
10923 }
10924 if {$i < 0} {
10925 foreach l $encoding_aliases {
10926 set ll [string tolower $l]
10927 if {[lsearch -exact $ll $enc] < 0} continue
10928 # look through the aliases for one that tcl knows about
10929 foreach e $ll {
10930 set i [lsearch -exact $lcnames $e]
10931 if {$i < 0} {
Alexander Gavrilov09c70292008-10-13 12:12:31 +040010932 if {[regsub {^(iso|cp|ibm|jis)[-_]} $e {\1} ex]} {
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +110010933 set i [lsearch -exact $lcnames $ex]
10934 }
10935 }
10936 if {$i >= 0} break
10937 }
10938 break
10939 }
10940 }
Paul Mackerras39ee47e2008-10-15 22:23:03 +110010941 set tclenc {}
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +110010942 if {$i >= 0} {
Paul Mackerras39ee47e2008-10-15 22:23:03 +110010943 set tclenc [lindex $names $i]
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +110010944 }
Paul Mackerras39ee47e2008-10-15 22:23:03 +110010945 set tcl_encoding_cache($enc) $tclenc
10946 return $tclenc
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +110010947}
10948
Alexander Gavrilov09c70292008-10-13 12:12:31 +040010949proc gitattr {path attr default} {
Paul Mackerras39ee47e2008-10-15 22:23:03 +110010950 global path_attr_cache
10951 if {[info exists path_attr_cache($attr,$path)]} {
10952 set r $path_attr_cache($attr,$path)
10953 } else {
10954 set r "unspecified"
10955 if {![catch {set line [exec git check-attr $attr -- $path]}]} {
Johannes Sixt097e1112009-07-21 10:09:48 +020010956 regexp "(.*): $attr: (.*)" $line m f r
Alexander Gavrilov09c70292008-10-13 12:12:31 +040010957 }
Alexander Gavrilov4db09302008-10-13 12:12:33 +040010958 set path_attr_cache($attr,$path) $r
Paul Mackerras39ee47e2008-10-15 22:23:03 +110010959 }
10960 if {$r eq "unspecified"} {
10961 return $default
10962 }
10963 return $r
Alexander Gavrilov09c70292008-10-13 12:12:31 +040010964}
10965
Alexander Gavrilov4db09302008-10-13 12:12:33 +040010966proc cache_gitattr {attr pathlist} {
Paul Mackerras39ee47e2008-10-15 22:23:03 +110010967 global path_attr_cache
10968 set newlist {}
10969 foreach path $pathlist {
10970 if {![info exists path_attr_cache($attr,$path)]} {
10971 lappend newlist $path
Alexander Gavrilov4db09302008-10-13 12:12:33 +040010972 }
Paul Mackerras39ee47e2008-10-15 22:23:03 +110010973 }
10974 set lim 1000
10975 if {[tk windowingsystem] == "win32"} {
10976 # windows has a 32k limit on the arguments to a command...
10977 set lim 30
10978 }
10979 while {$newlist ne {}} {
10980 set head [lrange $newlist 0 [expr {$lim - 1}]]
10981 set newlist [lrange $newlist $lim end]
10982 if {![catch {set rlist [eval exec git check-attr $attr -- $head]}]} {
10983 foreach row [split $rlist "\n"] {
Johannes Sixt097e1112009-07-21 10:09:48 +020010984 if {[regexp "(.*): $attr: (.*)" $row m path value]} {
Paul Mackerras39ee47e2008-10-15 22:23:03 +110010985 if {[string index $path 0] eq "\""} {
10986 set path [encoding convertfrom [lindex $path 0]]
10987 }
10988 set path_attr_cache($attr,$path) $value
Alexander Gavrilov4db09302008-10-13 12:12:33 +040010989 }
Paul Mackerras39ee47e2008-10-15 22:23:03 +110010990 }
Alexander Gavrilov4db09302008-10-13 12:12:33 +040010991 }
Paul Mackerras39ee47e2008-10-15 22:23:03 +110010992 }
Alexander Gavrilov4db09302008-10-13 12:12:33 +040010993}
10994
Alexander Gavrilov09c70292008-10-13 12:12:31 +040010995proc get_path_encoding {path} {
Paul Mackerras39ee47e2008-10-15 22:23:03 +110010996 global gui_encoding perfile_attrs
10997 set tcl_enc $gui_encoding
10998 if {$path ne {} && $perfile_attrs} {
10999 set enc2 [tcl_encoding [gitattr $path encoding $tcl_enc]]
11000 if {$enc2 ne {}} {
11001 set tcl_enc $enc2
Alexander Gavrilov09c70292008-10-13 12:12:31 +040011002 }
Paul Mackerras39ee47e2008-10-15 22:23:03 +110011003 }
11004 return $tcl_enc
Alexander Gavrilov09c70292008-10-13 12:12:31 +040011005}
11006
Paul Mackerras5d7589d2007-10-20 21:21:03 +100011007# First check that Tcl/Tk is recent enough
11008if {[catch {package require Tk 8.4} err]} {
Christian Stimmingd990ced2007-11-07 18:42:55 +010011009 show_error {} . [mc "Sorry, gitk cannot run with this version of Tcl/Tk.\n\
11010 Gitk requires at least Tcl/Tk 8.4."]
Paul Mackerras5d7589d2007-10-20 21:21:03 +100011011 exit 1
11012}
11013
Paul Mackerras1d10f362005-05-15 12:55:47 +000011014# defaults...
Timo Hirvonen8974c6f2006-05-24 10:57:40 +030011015set wrcomcmd "git diff-tree --stdin -p --pretty"
Junio C Hamano671bc152005-11-27 16:12:51 -080011016
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +110011017set gitencoding {}
Junio C Hamano671bc152005-11-27 16:12:51 -080011018catch {
Paul Mackerras27cb61c2007-02-15 08:54:34 +110011019 set gitencoding [exec git config --get i18n.commitencoding]
Junio C Hamano671bc152005-11-27 16:12:51 -080011020}
Alexander Gavrilov590915d2008-11-09 18:06:07 +030011021catch {
11022 set gitencoding [exec git config --get i18n.logoutputencoding]
11023}
Junio C Hamano671bc152005-11-27 16:12:51 -080011024if {$gitencoding == ""} {
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +110011025 set gitencoding "utf-8"
11026}
11027set tclencoding [tcl_encoding $gitencoding]
11028if {$tclencoding == {}} {
11029 puts stderr "Warning: encoding $gitencoding is not supported by Tcl/Tk"
Junio C Hamano671bc152005-11-27 16:12:51 -080011030}
Paul Mackerras1d10f362005-05-15 12:55:47 +000011031
Alexander Gavrilov09c70292008-10-13 12:12:31 +040011032set gui_encoding [encoding system]
11033catch {
Paul Mackerras39ee47e2008-10-15 22:23:03 +110011034 set enc [exec git config --get gui.encoding]
11035 if {$enc ne {}} {
11036 set tclenc [tcl_encoding $enc]
11037 if {$tclenc ne {}} {
11038 set gui_encoding $tclenc
11039 } else {
11040 puts stderr "Warning: encoding $enc is not supported by Tcl/Tk"
11041 }
11042 }
Alexander Gavrilov09c70292008-10-13 12:12:31 +040011043}
11044
Daniel A. Steffen5fdcbb12009-03-23 12:17:38 +010011045if {[tk windowingsystem] eq "aqua"} {
11046 set mainfont {{Lucida Grande} 9}
11047 set textfont {Monaco 9}
11048 set uifont {{Lucida Grande} 9 bold}
11049} else {
11050 set mainfont {Helvetica 9}
11051 set textfont {Courier 9}
11052 set uifont {Helvetica 9 bold}
11053}
Mark Levedahl7e12f1a2007-05-20 11:45:50 -040011054set tabstop 8
Paul Mackerrasb74fd572005-07-16 07:46:13 -040011055set findmergefiles 0
Paul Mackerras8d858d12005-08-05 09:52:16 +100011056set maxgraphpct 50
Paul Mackerrasf6075eb2005-08-18 09:30:10 +100011057set maxwidth 16
Paul Mackerras232475d2005-11-15 10:34:03 +110011058set revlistorder 0
Paul Mackerras757f17b2005-11-21 09:56:07 +110011059set fastdate 0
Paul Mackerras6e8c8702007-07-31 21:03:06 +100011060set uparrowlen 5
11061set downarrowlen 5
11062set mingaplen 100
Paul Mackerrasf8b28a42006-05-01 09:50:57 +100011063set cmitmode "patch"
Sergey Vlasovf1b86292006-05-15 19:13:14 +040011064set wrapcomment "none"
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +100011065set showneartags 1
Thomas Rastffe15292009-08-03 23:53:36 +020011066set hideremotes 0
Paul Mackerras0a4dd8b2007-06-16 21:21:57 +100011067set maxrefs 20
Paul Mackerras322a8cc2006-10-15 18:03:46 +100011068set maxlinelen 200
Paul Mackerras219ea3a2006-09-07 10:21:39 +100011069set showlocalchanges 1
Paul Mackerras7a39a172007-10-23 10:15:11 +100011070set limitdiffs 1
Arjen Laarhovene8b5f4b2007-08-14 22:02:04 +020011071set datetimeformat "%Y-%m-%d %H:%M:%S"
Jeff King95293b52008-03-06 06:49:25 -050011072set autoselect 1
Paul Mackerras39ee47e2008-10-15 22:23:03 +110011073set perfile_attrs 0
Paul Mackerras1d10f362005-05-15 12:55:47 +000011074
Daniel A. Steffen5fdcbb12009-03-23 12:17:38 +010011075if {[tk windowingsystem] eq "aqua"} {
11076 set extdifftool "opendiff"
11077} else {
11078 set extdifftool "meld"
11079}
Thomas Arcila314f5de2008-03-24 12:55:36 +010011080
Paul Mackerras1d10f362005-05-15 12:55:47 +000011081set colors {green red blue magenta darkgrey brown orange}
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +100011082set bgcolor white
11083set fgcolor black
11084set diffcolors {red "#00a000" blue}
Steffen Prohaska890fae72007-08-12 12:05:46 +020011085set diffcontext 3
Steffen Prohaskab9b86002008-01-17 23:42:55 +010011086set ignorespace 0
Mark Levedahl60378c02007-05-20 12:12:48 -040011087set selectbgcolor gray85
Paul Mackerrase3e901b2008-10-27 22:37:21 +110011088set markbgcolor "#e0e0ff"
Paul Mackerras1d10f362005-05-15 12:55:47 +000011089
Paul Mackerrasc11ff122008-05-26 10:11:33 +100011090set circlecolors {white blue gray blue blue}
11091
Paul Mackerrasd277e892008-09-21 18:11:37 -050011092# button for popping up context menus
11093if {[tk windowingsystem] eq "aqua"} {
11094 set ctxbut <Button-2>
11095} else {
11096 set ctxbut <Button-3>
11097}
11098
Christian Stimming663c3aa2007-11-07 18:40:59 +010011099## For msgcat loading, first locate the installation location.
11100if { [info exists ::env(GITK_MSGSDIR)] } {
11101 ## Msgsdir was manually set in the environment.
11102 set gitk_msgsdir $::env(GITK_MSGSDIR)
11103} else {
11104 ## Let's guess the prefix from argv0.
11105 set gitk_prefix [file dirname [file dirname [file normalize $argv0]]]
11106 set gitk_libdir [file join $gitk_prefix share gitk lib]
11107 set gitk_msgsdir [file join $gitk_libdir msgs]
11108 unset gitk_prefix
11109}
11110
11111## Internationalization (i18n) through msgcat and gettext. See
11112## http://www.gnu.org/software/gettext/manual/html_node/Tcl.html
11113package require msgcat
11114namespace import ::msgcat::mc
11115## And eventually load the actual message catalog
11116::msgcat::mcload $gitk_msgsdir
11117
Paul Mackerras1d10f362005-05-15 12:55:47 +000011118catch {source ~/.gitk}
11119
Paul Mackerras712fcc02005-11-30 09:28:16 +110011120font create optionfont -family sans-serif -size -12
Paul Mackerras17386062005-05-18 22:51:00 +000011121
Paul Mackerras0ed1dd32007-10-06 18:27:37 +100011122parsefont mainfont $mainfont
11123eval font create mainfont [fontflags mainfont]
11124eval font create mainfontbold [fontflags mainfont 1]
11125
11126parsefont textfont $textfont
11127eval font create textfont [fontflags textfont]
11128eval font create textfontbold [fontflags textfont 1]
11129
11130parsefont uifont $uifont
11131eval font create uifont [fontflags uifont]
Paul Mackerras1db95b02005-05-09 04:08:39 +000011132
Paul Mackerrasb039f0a2008-01-06 15:54:46 +110011133setoptions
11134
Paul Mackerrasaa81d972006-02-28 11:27:12 +110011135# check that we can find a .git directory somewhere...
Alex Riesen6c87d602007-07-29 22:29:45 +020011136if {[catch {set gitdir [gitdir]}]} {
Christian Stimmingd990ced2007-11-07 18:42:55 +010011137 show_error {} . [mc "Cannot find a git repository here."]
Alex Riesen6c87d602007-07-29 22:29:45 +020011138 exit 1
11139}
Paul Mackerrasaa81d972006-02-28 11:27:12 +110011140if {![file isdirectory $gitdir]} {
Christian Stimmingd990ced2007-11-07 18:42:55 +010011141 show_error {} . [mc "Cannot find the git directory \"%s\"." $gitdir]
Paul Mackerrasaa81d972006-02-28 11:27:12 +110011142 exit 1
11143}
11144
Alexander Gavrilov39816d62008-08-23 12:27:44 +040011145set selecthead {}
11146set selectheadid {}
11147
Paul Mackerrascdaee5d2007-07-12 22:29:49 +100011148set revtreeargs {}
Paul Mackerras098dd8a2006-05-03 09:32:53 +100011149set cmdline_files {}
Paul Mackerrascdaee5d2007-07-12 22:29:49 +100011150set i 0
Yann Dirson2d480852008-02-21 21:23:31 +010011151set revtreeargscmd {}
Paul Mackerrascdaee5d2007-07-12 22:29:49 +100011152foreach arg $argv {
Yann Dirson2d480852008-02-21 21:23:31 +010011153 switch -glob -- $arg {
Paul Mackerras6ebedab2007-07-13 13:45:55 +100011154 "" { }
Paul Mackerrascdaee5d2007-07-12 22:29:49 +100011155 "--" {
11156 set cmdline_files [lrange $argv [expr {$i + 1}] end]
11157 break
11158 }
Alexander Gavrilov39816d62008-08-23 12:27:44 +040011159 "--select-commit=*" {
11160 set selecthead [string range $arg 16 end]
11161 }
Yann Dirson2d480852008-02-21 21:23:31 +010011162 "--argscmd=*" {
11163 set revtreeargscmd [string range $arg 10 end]
11164 }
Paul Mackerrascdaee5d2007-07-12 22:29:49 +100011165 default {
11166 lappend revtreeargs $arg
11167 }
11168 }
11169 incr i
11170}
11171
Alexander Gavrilov39816d62008-08-23 12:27:44 +040011172if {$selecthead eq "HEAD"} {
11173 set selecthead {}
11174}
11175
Paul Mackerrascdaee5d2007-07-12 22:29:49 +100011176if {$i >= [llength $argv] && $revtreeargs ne {}} {
Paul Mackerras3ed31a82008-04-26 16:00:00 +100011177 # no -- on command line, but some arguments (other than --argscmd)
Paul Mackerras098dd8a2006-05-03 09:32:53 +100011178 if {[catch {
Timo Hirvonen8974c6f2006-05-24 10:57:40 +030011179 set f [eval exec git rev-parse --no-revs --no-flags $revtreeargs]
Paul Mackerras098dd8a2006-05-03 09:32:53 +100011180 set cmdline_files [split $f "\n"]
11181 set n [llength $cmdline_files]
11182 set revtreeargs [lrange $revtreeargs 0 end-$n]
Paul Mackerrascdaee5d2007-07-12 22:29:49 +100011183 # Unfortunately git rev-parse doesn't produce an error when
11184 # something is both a revision and a filename. To be consistent
11185 # with git log and git rev-list, check revtreeargs for filenames.
11186 foreach arg $revtreeargs {
11187 if {[file exists $arg]} {
Christian Stimmingd990ced2007-11-07 18:42:55 +010011188 show_error {} . [mc "Ambiguous argument '%s': both revision\
11189 and filename" $arg]
Paul Mackerrascdaee5d2007-07-12 22:29:49 +100011190 exit 1
11191 }
11192 }
Paul Mackerras098dd8a2006-05-03 09:32:53 +100011193 } err]} {
11194 # unfortunately we get both stdout and stderr in $err,
11195 # so look for "fatal:".
11196 set i [string first "fatal:" $err]
11197 if {$i > 0} {
Junio C Hamanob5e09632006-05-26 00:07:15 -070011198 set err [string range $err [expr {$i + 6}] end]
Paul Mackerras098dd8a2006-05-03 09:32:53 +100011199 }
Christian Stimmingd990ced2007-11-07 18:42:55 +010011200 show_error {} . "[mc "Bad arguments to gitk:"]\n$err"
Paul Mackerras098dd8a2006-05-03 09:32:53 +100011201 exit 1
11202 }
11203}
11204
Paul Mackerras219ea3a2006-09-07 10:21:39 +100011205set nullid "0000000000000000000000000000000000000000"
Paul Mackerras8f489362007-07-13 19:49:37 +100011206set nullid2 "0000000000000000000000000000000000000001"
Thomas Arcila314f5de2008-03-24 12:55:36 +010011207set nullfile "/dev/null"
Paul Mackerras8f489362007-07-13 19:49:37 +100011208
Paul Mackerras32f1b3e2007-09-28 21:27:39 +100011209set have_tk85 [expr {[package vcompare $tk_version "8.5"] >= 0}]
Pat Thoyts194bbf62009-05-18 22:46:01 +010011210set git_version [join [lrange [split [lindex [exec git version] end] .] 0 2] .]
Paul Mackerras219ea3a2006-09-07 10:21:39 +100011211
Paul Mackerras7eb3cb92007-06-17 14:45:00 +100011212set runq {}
Paul Mackerrasd6982062005-08-06 22:06:06 +100011213set history {}
11214set historyindex 0
Paul Mackerras908c3582006-05-20 09:38:11 +100011215set fh_serial 0
Paul Mackerras908c3582006-05-20 09:38:11 +100011216set nhl_names {}
Paul Mackerras63b79192006-05-20 21:31:52 +100011217set highlight_paths {}
Paul Mackerras687c8762007-09-22 12:49:33 +100011218set findpattern {}
Paul Mackerras1902c272006-05-25 21:25:13 +100011219set searchdirn -forwards
Paul Mackerras28593d32008-11-13 23:01:46 +110011220set boldids {}
11221set boldnameids {}
Paul Mackerrasa8d610a2007-04-19 11:39:12 +100011222set diffelide {0 0}
Paul Mackerras4fb0fa12007-07-04 19:43:51 +100011223set markingmatches 0
Paul Mackerras97645682007-08-23 22:24:38 +100011224set linkentercount 0
Paul Mackerras03800812007-08-29 21:45:21 +100011225set need_redisplay 0
11226set nrows_drawn 0
Paul Mackerras32f1b3e2007-09-28 21:27:39 +100011227set firsttabstop 0
Paul Mackerras9f1afe02006-02-19 22:44:47 +110011228
Paul Mackerras50b44ec2006-04-04 10:16:22 +100011229set nextviewnum 1
11230set curview 0
Paul Mackerrasa90a6d22006-04-25 17:12:46 +100011231set selectedview 0
Christian Stimmingb007ee22007-11-07 18:44:35 +010011232set selectedhlview [mc "None"]
11233set highlight_related [mc "None"]
Paul Mackerras687c8762007-09-22 12:49:33 +100011234set highlight_files {}
Paul Mackerras50b44ec2006-04-04 10:16:22 +100011235set viewfiles(0) {}
Paul Mackerrasa90a6d22006-04-25 17:12:46 +100011236set viewperm(0) 0
Paul Mackerras098dd8a2006-05-03 09:32:53 +100011237set viewargs(0) {}
Yann Dirson2d480852008-02-21 21:23:31 +010011238set viewargscmd(0) {}
Paul Mackerras50b44ec2006-04-04 10:16:22 +100011239
Paul Mackerras94b4a692008-05-20 20:51:06 +100011240set selectedline {}
Paul Mackerras6df74032008-05-11 22:13:02 +100011241set numcommits 0
Paul Mackerras7fcc92b2007-12-03 10:33:01 +110011242set loginstance 0
Paul Mackerras098dd8a2006-05-03 09:32:53 +100011243set cmdlineok 0
Paul Mackerras1db95b02005-05-09 04:08:39 +000011244set stopped 0
Paul Mackerras1db95b02005-05-09 04:08:39 +000011245set stuffsaved 0
Paul Mackerras74daedb2005-06-27 19:27:32 +100011246set patchnum 0
Paul Mackerras219ea3a2006-09-07 10:21:39 +100011247set lserial 0
David Aguilarcb8329a2008-03-10 03:54:56 -070011248set isworktree [expr {[exec git rev-parse --is-inside-work-tree] == "true"}]
Paul Mackerras1db95b02005-05-09 04:08:39 +000011249setcoords
Paul Mackerrasd94f8cd2006-04-06 10:18:23 +100011250makewindow
Giuseppe Bilotta37871b72009-03-19 01:54:17 -070011251catch {
11252 image create photo gitlogo -width 16 -height 16
11253
11254 image create photo gitlogominus -width 4 -height 2
11255 gitlogominus put #C00000 -to 0 0 4 2
11256 gitlogo copy gitlogominus -to 1 5
11257 gitlogo copy gitlogominus -to 6 5
11258 gitlogo copy gitlogominus -to 11 5
11259 image delete gitlogominus
11260
11261 image create photo gitlogoplus -width 4 -height 4
11262 gitlogoplus put #008000 -to 1 0 3 4
11263 gitlogoplus put #008000 -to 0 1 4 3
11264 gitlogo copy gitlogoplus -to 1 9
11265 gitlogo copy gitlogoplus -to 6 9
11266 gitlogo copy gitlogoplus -to 11 9
11267 image delete gitlogoplus
11268
Stephen Boydd38d7d42009-03-19 01:54:18 -070011269 image create photo gitlogo32 -width 32 -height 32
11270 gitlogo32 copy gitlogo -zoom 2 2
11271
11272 wm iconphoto . -default gitlogo gitlogo32
Giuseppe Bilotta37871b72009-03-19 01:54:17 -070011273}
Paul Mackerras0eafba12007-07-23 21:35:03 +100011274# wait for the window to become visible
11275tkwait visibility .
Doug Maxey6c283322006-12-10 14:31:46 -060011276wm title . "[file tail $argv0]: [file tail [pwd]]"
Pat Thoyts478afad2009-04-15 17:14:03 +010011277update
Paul Mackerras887fe3c2005-05-21 07:35:37 +000011278readrefs
Paul Mackerrasa8aaf192006-04-23 22:45:55 +100011279
Yann Dirson2d480852008-02-21 21:23:31 +010011280if {$cmdline_files ne {} || $revtreeargs ne {} || $revtreeargscmd ne {}} {
Paul Mackerras50b44ec2006-04-04 10:16:22 +100011281 # create a view for the files/dirs specified on the command line
11282 set curview 1
Paul Mackerrasa90a6d22006-04-25 17:12:46 +100011283 set selectedview 1
Paul Mackerras50b44ec2006-04-04 10:16:22 +100011284 set nextviewnum 2
Christian Stimmingd990ced2007-11-07 18:42:55 +010011285 set viewname(1) [mc "Command line"]
Paul Mackerras50b44ec2006-04-04 10:16:22 +100011286 set viewfiles(1) $cmdline_files
Paul Mackerras098dd8a2006-05-03 09:32:53 +100011287 set viewargs(1) $revtreeargs
Yann Dirson2d480852008-02-21 21:23:31 +010011288 set viewargscmd(1) $revtreeargscmd
Paul Mackerrasa90a6d22006-04-25 17:12:46 +100011289 set viewperm(1) 0
Paul Mackerras3ed31a82008-04-26 16:00:00 +100011290 set vdatemode(1) 0
Paul Mackerrasda7c24d2006-05-02 11:15:29 +100011291 addviewmenu 1
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +110011292 .bar.view entryconf [mca "Edit view..."] -state normal
11293 .bar.view entryconf [mca "Delete view"] -state normal
Paul Mackerras50b44ec2006-04-04 10:16:22 +100011294}
Paul Mackerrasa90a6d22006-04-25 17:12:46 +100011295
11296if {[info exists permviews]} {
11297 foreach v $permviews {
11298 set n $nextviewnum
11299 incr nextviewnum
11300 set viewname($n) [lindex $v 0]
11301 set viewfiles($n) [lindex $v 1]
Paul Mackerras098dd8a2006-05-03 09:32:53 +100011302 set viewargs($n) [lindex $v 2]
Yann Dirson2d480852008-02-21 21:23:31 +010011303 set viewargscmd($n) [lindex $v 3]
Paul Mackerrasa90a6d22006-04-25 17:12:46 +100011304 set viewperm($n) 1
Paul Mackerrasda7c24d2006-05-02 11:15:29 +100011305 addviewmenu $n
Paul Mackerrasa90a6d22006-04-25 17:12:46 +100011306 }
11307}
Johannes Sixte4df5192008-12-18 08:30:49 +010011308
11309if {[tk windowingsystem] eq "win32"} {
11310 focus -force .
11311}
11312
Alexander Gavrilov567c34e2008-07-26 20:13:45 +040011313getcommits {}