blob: 785afd2235273af930f44c08d7b528f5ff3655f1 [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
Guillermo S. Romero5497f7a2009-10-15 18:51:49 +02002522 global colors uicolor 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]
Guillermo S. Romero5497f7a2009-10-15 18:51:49 +02002549 puts $f [list set uicolor $uicolor]
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10002550 puts $f [list set bgcolor $bgcolor]
2551 puts $f [list set fgcolor $fgcolor]
2552 puts $f [list set colors $colors]
2553 puts $f [list set diffcolors $diffcolors]
Paul Mackerrase3e901b2008-10-27 22:37:21 +11002554 puts $f [list set markbgcolor $markbgcolor]
Steffen Prohaska890fae72007-08-12 12:05:46 +02002555 puts $f [list set diffcontext $diffcontext]
Mark Levedahl60378c02007-05-20 12:12:48 -04002556 puts $f [list set selectbgcolor $selectbgcolor]
Thomas Arcila314f5de2008-03-24 12:55:36 +01002557 puts $f [list set extdifftool $extdifftool]
Paul Mackerras39ee47e2008-10-15 22:23:03 +11002558 puts $f [list set perfile_attrs $perfile_attrs]
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002559
Mark Levedahlb6047c52007-02-08 22:22:24 -05002560 puts $f "set geometry(main) [wm geometry .]"
Pat Thoytsc876dba2009-04-14 22:09:53 +01002561 puts $f "set geometry(state) [wm state .]"
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002562 puts $f "set geometry(topwidth) [winfo width .tf]"
2563 puts $f "set geometry(topheight) [winfo height .tf]"
Mark Levedahl9ca72f42007-02-12 19:19:34 -05002564 puts $f "set geometry(pwsash0) \"[.tf.histframe.pwclist sash coord 0]\""
2565 puts $f "set geometry(pwsash1) \"[.tf.histframe.pwclist sash coord 1]\""
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002566 puts $f "set geometry(botwidth) [winfo width .bleft]"
2567 puts $f "set geometry(botheight) [winfo height .bleft]"
2568
Paul Mackerrasa90a6d22006-04-25 17:12:46 +10002569 puts -nonewline $f "set permviews {"
2570 for {set v 0} {$v < $nextviewnum} {incr v} {
2571 if {$viewperm($v)} {
Yann Dirson2d480852008-02-21 21:23:31 +01002572 puts $f "{[list $viewname($v) $viewfiles($v) $viewargs($v) $viewargscmd($v)]}"
Paul Mackerrasa90a6d22006-04-25 17:12:46 +10002573 }
2574 }
2575 puts $f "}"
Paul Mackerras0fba86b2005-05-16 23:54:58 +00002576 close $f
2577 file rename -force "~/.gitk-new" "~/.gitk"
2578 }
2579 set stuffsaved 1
Paul Mackerras1db95b02005-05-09 04:08:39 +00002580}
2581
Paul Mackerras43bddeb2005-05-15 23:19:18 +00002582proc resizeclistpanes {win w} {
2583 global oldwidth
Paul Mackerras418c4c72006-02-07 09:10:18 +11002584 if {[info exists oldwidth($win)]} {
Paul Mackerras43bddeb2005-05-15 23:19:18 +00002585 set s0 [$win sash coord 0]
2586 set s1 [$win sash coord 1]
2587 if {$w < 60} {
2588 set sash0 [expr {int($w/2 - 2)}]
2589 set sash1 [expr {int($w*5/6 - 2)}]
2590 } else {
2591 set factor [expr {1.0 * $w / $oldwidth($win)}]
2592 set sash0 [expr {int($factor * [lindex $s0 0])}]
2593 set sash1 [expr {int($factor * [lindex $s1 0])}]
2594 if {$sash0 < 30} {
2595 set sash0 30
2596 }
2597 if {$sash1 < $sash0 + 20} {
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08002598 set sash1 [expr {$sash0 + 20}]
Paul Mackerras43bddeb2005-05-15 23:19:18 +00002599 }
2600 if {$sash1 > $w - 10} {
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08002601 set sash1 [expr {$w - 10}]
Paul Mackerras43bddeb2005-05-15 23:19:18 +00002602 if {$sash0 > $sash1 - 20} {
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08002603 set sash0 [expr {$sash1 - 20}]
Paul Mackerras43bddeb2005-05-15 23:19:18 +00002604 }
2605 }
2606 }
2607 $win sash place 0 $sash0 [lindex $s0 1]
2608 $win sash place 1 $sash1 [lindex $s1 1]
2609 }
2610 set oldwidth($win) $w
2611}
2612
2613proc resizecdetpanes {win w} {
2614 global oldwidth
Paul Mackerras418c4c72006-02-07 09:10:18 +11002615 if {[info exists oldwidth($win)]} {
Paul Mackerras43bddeb2005-05-15 23:19:18 +00002616 set s0 [$win sash coord 0]
2617 if {$w < 60} {
2618 set sash0 [expr {int($w*3/4 - 2)}]
2619 } else {
2620 set factor [expr {1.0 * $w / $oldwidth($win)}]
2621 set sash0 [expr {int($factor * [lindex $s0 0])}]
2622 if {$sash0 < 45} {
2623 set sash0 45
2624 }
2625 if {$sash0 > $w - 15} {
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08002626 set sash0 [expr {$w - 15}]
Paul Mackerras43bddeb2005-05-15 23:19:18 +00002627 }
2628 }
2629 $win sash place 0 $sash0 [lindex $s0 1]
2630 }
2631 set oldwidth($win) $w
2632}
2633
Paul Mackerrasb5721c72005-05-10 12:08:22 +00002634proc allcanvs args {
2635 global canv canv2 canv3
2636 eval $canv $args
2637 eval $canv2 $args
2638 eval $canv3 $args
2639}
2640
2641proc bindall {event action} {
2642 global canv canv2 canv3
2643 bind $canv $event $action
2644 bind $canv2 $event $action
2645 bind $canv3 $event $action
2646}
2647
Paul Mackerras9a40c502005-05-12 23:46:16 +00002648proc about {} {
Eygene Ryabinkind59c4b62007-03-27 14:36:12 +04002649 global uifont
Paul Mackerras9a40c502005-05-12 23:46:16 +00002650 set w .about
2651 if {[winfo exists $w]} {
2652 raise $w
2653 return
2654 }
2655 toplevel $w
Christian Stimmingd990ced2007-11-07 18:42:55 +01002656 wm title $w [mc "About gitk"]
Alexander Gavrilove7d64002008-11-11 23:55:42 +03002657 make_transient $w .
Christian Stimmingd990ced2007-11-07 18:42:55 +01002658 message $w.m -text [mc "
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002659Gitk - a commit viewer for git
Paul Mackerras9a40c502005-05-12 23:46:16 +00002660
Paul Mackerrasee66e082008-05-09 10:14:07 +10002661Copyright © 2005-2008 Paul Mackerras
Paul Mackerras9a40c502005-05-12 23:46:16 +00002662
Christian Stimmingd990ced2007-11-07 18:42:55 +01002663Use and redistribute under the terms of the GNU General Public License"] \
Eygene Ryabinkin3a950e92007-03-27 14:36:59 +04002664 -justify center -aspect 400 -border 2 -bg white -relief groove
2665 pack $w.m -side top -fill x -padx 2 -pady 2
Christian Stimmingd990ced2007-11-07 18:42:55 +01002666 button $w.ok -text [mc "Close"] -command "destroy $w" -default active
Paul Mackerras9a40c502005-05-12 23:46:16 +00002667 pack $w.ok -side bottom
Eygene Ryabinkin3a950e92007-03-27 14:36:59 +04002668 bind $w <Visibility> "focus $w.ok"
2669 bind $w <Key-Escape> "destroy $w"
2670 bind $w <Key-Return> "destroy $w"
Paul Mackerras9a40c502005-05-12 23:46:16 +00002671}
2672
Paul Mackerras4e95e1f2006-04-05 09:39:51 +10002673proc keys {} {
2674 set w .keys
2675 if {[winfo exists $w]} {
2676 raise $w
2677 return
2678 }
Shawn O. Pearced23d98d2007-07-19 00:37:58 -04002679 if {[tk windowingsystem] eq {aqua}} {
2680 set M1T Cmd
2681 } else {
2682 set M1T Ctrl
2683 }
Paul Mackerras4e95e1f2006-04-05 09:39:51 +10002684 toplevel $w
Christian Stimmingd990ced2007-11-07 18:42:55 +01002685 wm title $w [mc "Gitk key bindings"]
Alexander Gavrilove7d64002008-11-11 23:55:42 +03002686 make_transient $w .
Michele Ballabio3d2c9982008-01-15 23:31:49 +01002687 message $w.m -text "
2688[mc "Gitk key bindings:"]
Paul Mackerras4e95e1f2006-04-05 09:39:51 +10002689
Michele Ballabio3d2c9982008-01-15 23:31:49 +01002690[mc "<%s-Q> Quit" $M1T]
2691[mc "<Home> Move to first commit"]
2692[mc "<End> Move to last commit"]
2693[mc "<Up>, p, i Move up one commit"]
2694[mc "<Down>, n, k Move down one commit"]
2695[mc "<Left>, z, j Go back in history list"]
2696[mc "<Right>, x, l Go forward in history list"]
2697[mc "<PageUp> Move up one page in commit list"]
2698[mc "<PageDown> Move down one page in commit list"]
2699[mc "<%s-Home> Scroll to top of commit list" $M1T]
2700[mc "<%s-End> Scroll to bottom of commit list" $M1T]
2701[mc "<%s-Up> Scroll commit list up one line" $M1T]
2702[mc "<%s-Down> Scroll commit list down one line" $M1T]
2703[mc "<%s-PageUp> Scroll commit list up one page" $M1T]
2704[mc "<%s-PageDown> Scroll commit list down one page" $M1T]
2705[mc "<Shift-Up> Find backwards (upwards, later commits)"]
2706[mc "<Shift-Down> Find forwards (downwards, earlier commits)"]
2707[mc "<Delete>, b Scroll diff view up one page"]
2708[mc "<Backspace> Scroll diff view up one page"]
2709[mc "<Space> Scroll diff view down one page"]
2710[mc "u Scroll diff view up 18 lines"]
2711[mc "d Scroll diff view down 18 lines"]
2712[mc "<%s-F> Find" $M1T]
2713[mc "<%s-G> Move to next find hit" $M1T]
2714[mc "<Return> Move to next find hit"]
Giuseppe Bilotta97bed032008-12-02 02:19:22 +01002715[mc "/ Focus the search box"]
Michele Ballabio3d2c9982008-01-15 23:31:49 +01002716[mc "? Move to previous find hit"]
2717[mc "f Scroll diff view to next file"]
2718[mc "<%s-S> Search for next hit in diff view" $M1T]
2719[mc "<%s-R> Search for previous hit in diff view" $M1T]
2720[mc "<%s-KP+> Increase font size" $M1T]
2721[mc "<%s-plus> Increase font size" $M1T]
2722[mc "<%s-KP-> Decrease font size" $M1T]
2723[mc "<%s-minus> Decrease font size" $M1T]
2724[mc "<F5> Update"]
2725" \
Eygene Ryabinkin3a950e92007-03-27 14:36:59 +04002726 -justify left -bg white -border 2 -relief groove
2727 pack $w.m -side top -fill both -padx 2 -pady 2
Christian Stimmingd990ced2007-11-07 18:42:55 +01002728 button $w.ok -text [mc "Close"] -command "destroy $w" -default active
Alexander Gavrilov76f15942008-11-02 21:59:44 +03002729 bind $w <Key-Escape> [list destroy $w]
Paul Mackerras4e95e1f2006-04-05 09:39:51 +10002730 pack $w.ok -side bottom
Eygene Ryabinkin3a950e92007-03-27 14:36:59 +04002731 bind $w <Visibility> "focus $w.ok"
2732 bind $w <Key-Escape> "destroy $w"
2733 bind $w <Key-Return> "destroy $w"
Paul Mackerras4e95e1f2006-04-05 09:39:51 +10002734}
2735
Paul Mackerras7fcceed2006-04-27 19:21:49 +10002736# Procedures for manipulating the file list window at the
2737# bottom right of the overall window.
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10002738
2739proc treeview {w l openlevs} {
2740 global treecontents treediropen treeheight treeparent treeindex
2741
2742 set ix 0
2743 set treeindex() 0
2744 set lev 0
2745 set prefix {}
2746 set prefixend -1
2747 set prefendstack {}
2748 set htstack {}
2749 set ht 0
2750 set treecontents() {}
2751 $w conf -state normal
2752 foreach f $l {
2753 while {[string range $f 0 $prefixend] ne $prefix} {
2754 if {$lev <= $openlevs} {
2755 $w mark set e:$treeindex($prefix) "end -1c"
2756 $w mark gravity e:$treeindex($prefix) left
2757 }
2758 set treeheight($prefix) $ht
2759 incr ht [lindex $htstack end]
2760 set htstack [lreplace $htstack end end]
2761 set prefixend [lindex $prefendstack end]
2762 set prefendstack [lreplace $prefendstack end end]
2763 set prefix [string range $prefix 0 $prefixend]
2764 incr lev -1
2765 }
2766 set tail [string range $f [expr {$prefixend+1}] end]
2767 while {[set slash [string first "/" $tail]] >= 0} {
2768 lappend htstack $ht
2769 set ht 0
2770 lappend prefendstack $prefixend
2771 incr prefixend [expr {$slash + 1}]
2772 set d [string range $tail 0 $slash]
2773 lappend treecontents($prefix) $d
2774 set oldprefix $prefix
2775 append prefix $d
2776 set treecontents($prefix) {}
2777 set treeindex($prefix) [incr ix]
2778 set treeparent($prefix) $oldprefix
2779 set tail [string range $tail [expr {$slash+1}] end]
2780 if {$lev <= $openlevs} {
2781 set ht 1
2782 set treediropen($prefix) [expr {$lev < $openlevs}]
2783 set bm [expr {$lev == $openlevs? "tri-rt": "tri-dn"}]
2784 $w mark set d:$ix "end -1c"
2785 $w mark gravity d:$ix left
2786 set str "\n"
2787 for {set i 0} {$i < $lev} {incr i} {append str "\t"}
2788 $w insert end $str
2789 $w image create end -align center -image $bm -padx 1 \
2790 -name a:$ix
Paul Mackerras45a9d502006-05-20 22:56:27 +10002791 $w insert end $d [highlight_tag $prefix]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10002792 $w mark set s:$ix "end -1c"
2793 $w mark gravity s:$ix left
2794 }
2795 incr lev
2796 }
2797 if {$tail ne {}} {
2798 if {$lev <= $openlevs} {
2799 incr ht
2800 set str "\n"
2801 for {set i 0} {$i < $lev} {incr i} {append str "\t"}
2802 $w insert end $str
Paul Mackerras45a9d502006-05-20 22:56:27 +10002803 $w insert end $tail [highlight_tag $f]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10002804 }
2805 lappend treecontents($prefix) $tail
2806 }
2807 }
2808 while {$htstack ne {}} {
2809 set treeheight($prefix) $ht
2810 incr ht [lindex $htstack end]
2811 set htstack [lreplace $htstack end end]
Brian Downing096e96b2007-07-05 06:33:02 -05002812 set prefixend [lindex $prefendstack end]
2813 set prefendstack [lreplace $prefendstack end end]
2814 set prefix [string range $prefix 0 $prefixend]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10002815 }
2816 $w conf -state disabled
2817}
2818
2819proc linetoelt {l} {
2820 global treeheight treecontents
2821
2822 set y 2
2823 set prefix {}
2824 while {1} {
2825 foreach e $treecontents($prefix) {
2826 if {$y == $l} {
2827 return "$prefix$e"
2828 }
2829 set n 1
2830 if {[string index $e end] eq "/"} {
2831 set n $treeheight($prefix$e)
2832 if {$y + $n > $l} {
2833 append prefix $e
2834 incr y
2835 break
2836 }
2837 }
2838 incr y $n
2839 }
2840 }
2841}
2842
Paul Mackerras45a9d502006-05-20 22:56:27 +10002843proc highlight_tree {y prefix} {
2844 global treeheight treecontents cflist
2845
2846 foreach e $treecontents($prefix) {
2847 set path $prefix$e
2848 if {[highlight_tag $path] ne {}} {
2849 $cflist tag add bold $y.0 "$y.0 lineend"
2850 }
2851 incr y
2852 if {[string index $e end] eq "/" && $treeheight($path) > 1} {
2853 set y [highlight_tree $y $path]
2854 }
2855 }
2856 return $y
2857}
2858
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10002859proc treeclosedir {w dir} {
2860 global treediropen treeheight treeparent treeindex
2861
2862 set ix $treeindex($dir)
2863 $w conf -state normal
2864 $w delete s:$ix e:$ix
2865 set treediropen($dir) 0
2866 $w image configure a:$ix -image tri-rt
2867 $w conf -state disabled
2868 set n [expr {1 - $treeheight($dir)}]
2869 while {$dir ne {}} {
2870 incr treeheight($dir) $n
2871 set dir $treeparent($dir)
2872 }
2873}
2874
2875proc treeopendir {w dir} {
2876 global treediropen treeheight treeparent treecontents treeindex
2877
2878 set ix $treeindex($dir)
2879 $w conf -state normal
2880 $w image configure a:$ix -image tri-dn
2881 $w mark set e:$ix s:$ix
2882 $w mark gravity e:$ix right
2883 set lev 0
2884 set str "\n"
2885 set n [llength $treecontents($dir)]
2886 for {set x $dir} {$x ne {}} {set x $treeparent($x)} {
2887 incr lev
2888 append str "\t"
2889 incr treeheight($x) $n
2890 }
2891 foreach e $treecontents($dir) {
Paul Mackerras45a9d502006-05-20 22:56:27 +10002892 set de $dir$e
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10002893 if {[string index $e end] eq "/"} {
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10002894 set iy $treeindex($de)
2895 $w mark set d:$iy e:$ix
2896 $w mark gravity d:$iy left
2897 $w insert e:$ix $str
2898 set treediropen($de) 0
2899 $w image create e:$ix -align center -image tri-rt -padx 1 \
2900 -name a:$iy
Paul Mackerras45a9d502006-05-20 22:56:27 +10002901 $w insert e:$ix $e [highlight_tag $de]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10002902 $w mark set s:$iy e:$ix
2903 $w mark gravity s:$iy left
2904 set treeheight($de) 1
2905 } else {
2906 $w insert e:$ix $str
Paul Mackerras45a9d502006-05-20 22:56:27 +10002907 $w insert e:$ix $e [highlight_tag $de]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10002908 }
2909 }
Alexander Gavrilovb8a640e2008-09-08 11:28:16 +04002910 $w mark gravity e:$ix right
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10002911 $w conf -state disabled
2912 set treediropen($dir) 1
2913 set top [lindex [split [$w index @0,0] .] 0]
2914 set ht [$w cget -height]
2915 set l [lindex [split [$w index s:$ix] .] 0]
2916 if {$l < $top} {
2917 $w yview $l.0
2918 } elseif {$l + $n + 1 > $top + $ht} {
2919 set top [expr {$l + $n + 2 - $ht}]
2920 if {$l < $top} {
2921 set top $l
2922 }
2923 $w yview $top.0
2924 }
2925}
2926
2927proc treeclick {w x y} {
2928 global treediropen cmitmode ctext cflist cflist_top
2929
2930 if {$cmitmode ne "tree"} return
2931 if {![info exists cflist_top]} return
2932 set l [lindex [split [$w index "@$x,$y"] "."] 0]
2933 $cflist tag remove highlight $cflist_top.0 "$cflist_top.0 lineend"
2934 $cflist tag add highlight $l.0 "$l.0 lineend"
2935 set cflist_top $l
2936 if {$l == 1} {
2937 $ctext yview 1.0
2938 return
2939 }
2940 set e [linetoelt $l]
2941 if {[string index $e end] ne "/"} {
2942 showfile $e
2943 } elseif {$treediropen($e)} {
2944 treeclosedir $w $e
2945 } else {
2946 treeopendir $w $e
2947 }
2948}
2949
2950proc setfilelist {id} {
Paul Mackerras8a897742008-10-27 21:36:25 +11002951 global treefilelist cflist jump_to_here
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10002952
2953 treeview $cflist $treefilelist($id) 0
Paul Mackerras8a897742008-10-27 21:36:25 +11002954 if {$jump_to_here ne {}} {
2955 set f [lindex $jump_to_here 0]
2956 if {[lsearch -exact $treefilelist($id) $f] >= 0} {
2957 showfile $f
2958 }
2959 }
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10002960}
2961
2962image create bitmap tri-rt -background black -foreground blue -data {
2963 #define tri-rt_width 13
2964 #define tri-rt_height 13
2965 static unsigned char tri-rt_bits[] = {
2966 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x30, 0x00, 0x70, 0x00, 0xf0, 0x00,
2967 0xf0, 0x01, 0xf0, 0x00, 0x70, 0x00, 0x30, 0x00, 0x10, 0x00, 0x00, 0x00,
2968 0x00, 0x00};
2969} -maskdata {
2970 #define tri-rt-mask_width 13
2971 #define tri-rt-mask_height 13
2972 static unsigned char tri-rt-mask_bits[] = {
2973 0x08, 0x00, 0x18, 0x00, 0x38, 0x00, 0x78, 0x00, 0xf8, 0x00, 0xf8, 0x01,
2974 0xf8, 0x03, 0xf8, 0x01, 0xf8, 0x00, 0x78, 0x00, 0x38, 0x00, 0x18, 0x00,
2975 0x08, 0x00};
2976}
2977image create bitmap tri-dn -background black -foreground blue -data {
2978 #define tri-dn_width 13
2979 #define tri-dn_height 13
2980 static unsigned char tri-dn_bits[] = {
2981 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x07, 0xf8, 0x03,
2982 0xf0, 0x01, 0xe0, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2983 0x00, 0x00};
2984} -maskdata {
2985 #define tri-dn-mask_width 13
2986 #define tri-dn-mask_height 13
2987 static unsigned char tri-dn-mask_bits[] = {
2988 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x1f, 0xfe, 0x0f, 0xfc, 0x07,
2989 0xf8, 0x03, 0xf0, 0x01, 0xe0, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00,
2990 0x00, 0x00};
2991}
2992
Paul Mackerras887c9962007-08-20 19:36:20 +10002993image create bitmap reficon-T -background black -foreground yellow -data {
2994 #define tagicon_width 13
2995 #define tagicon_height 9
2996 static unsigned char tagicon_bits[] = {
2997 0x00, 0x00, 0x00, 0x00, 0xf0, 0x07, 0xf8, 0x07,
2998 0xfc, 0x07, 0xf8, 0x07, 0xf0, 0x07, 0x00, 0x00, 0x00, 0x00};
2999} -maskdata {
3000 #define tagicon-mask_width 13
3001 #define tagicon-mask_height 9
3002 static unsigned char tagicon-mask_bits[] = {
3003 0x00, 0x00, 0xf0, 0x0f, 0xf8, 0x0f, 0xfc, 0x0f,
3004 0xfe, 0x0f, 0xfc, 0x0f, 0xf8, 0x0f, 0xf0, 0x0f, 0x00, 0x00};
3005}
3006set rectdata {
3007 #define headicon_width 13
3008 #define headicon_height 9
3009 static unsigned char headicon_bits[] = {
3010 0x00, 0x00, 0x00, 0x00, 0xf8, 0x07, 0xf8, 0x07,
3011 0xf8, 0x07, 0xf8, 0x07, 0xf8, 0x07, 0x00, 0x00, 0x00, 0x00};
3012}
3013set rectmask {
3014 #define headicon-mask_width 13
3015 #define headicon-mask_height 9
3016 static unsigned char headicon-mask_bits[] = {
3017 0x00, 0x00, 0xfc, 0x0f, 0xfc, 0x0f, 0xfc, 0x0f,
3018 0xfc, 0x0f, 0xfc, 0x0f, 0xfc, 0x0f, 0xfc, 0x0f, 0x00, 0x00};
3019}
3020image create bitmap reficon-H -background black -foreground green \
3021 -data $rectdata -maskdata $rectmask
3022image create bitmap reficon-o -background black -foreground "#ddddff" \
3023 -data $rectdata -maskdata $rectmask
3024
Paul Mackerras7fcceed2006-04-27 19:21:49 +10003025proc init_flist {first} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11003026 global cflist cflist_top difffilestart
Paul Mackerras7fcceed2006-04-27 19:21:49 +10003027
3028 $cflist conf -state normal
3029 $cflist delete 0.0 end
3030 if {$first ne {}} {
3031 $cflist insert end $first
3032 set cflist_top 1
Paul Mackerras7fcceed2006-04-27 19:21:49 +10003033 $cflist tag add highlight 1.0 "1.0 lineend"
3034 } else {
3035 catch {unset cflist_top}
3036 }
3037 $cflist conf -state disabled
3038 set difffilestart {}
3039}
3040
Paul Mackerras63b79192006-05-20 21:31:52 +10003041proc highlight_tag {f} {
3042 global highlight_paths
3043
3044 foreach p $highlight_paths {
3045 if {[string match $p $f]} {
3046 return "bold"
3047 }
3048 }
3049 return {}
3050}
3051
3052proc highlight_filelist {} {
Paul Mackerras45a9d502006-05-20 22:56:27 +10003053 global cmitmode cflist
Paul Mackerras63b79192006-05-20 21:31:52 +10003054
Paul Mackerras45a9d502006-05-20 22:56:27 +10003055 $cflist conf -state normal
3056 if {$cmitmode ne "tree"} {
Paul Mackerras63b79192006-05-20 21:31:52 +10003057 set end [lindex [split [$cflist index end] .] 0]
3058 for {set l 2} {$l < $end} {incr l} {
3059 set line [$cflist get $l.0 "$l.0 lineend"]
3060 if {[highlight_tag $line] ne {}} {
3061 $cflist tag add bold $l.0 "$l.0 lineend"
3062 }
3063 }
Paul Mackerras45a9d502006-05-20 22:56:27 +10003064 } else {
3065 highlight_tree 2 {}
Paul Mackerras63b79192006-05-20 21:31:52 +10003066 }
Paul Mackerras45a9d502006-05-20 22:56:27 +10003067 $cflist conf -state disabled
Paul Mackerras63b79192006-05-20 21:31:52 +10003068}
3069
3070proc unhighlight_filelist {} {
Paul Mackerras45a9d502006-05-20 22:56:27 +10003071 global cflist
Paul Mackerras63b79192006-05-20 21:31:52 +10003072
Paul Mackerras45a9d502006-05-20 22:56:27 +10003073 $cflist conf -state normal
3074 $cflist tag remove bold 1.0 end
3075 $cflist conf -state disabled
Paul Mackerras63b79192006-05-20 21:31:52 +10003076}
3077
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10003078proc add_flist {fl} {
Paul Mackerras45a9d502006-05-20 22:56:27 +10003079 global cflist
Paul Mackerras7fcceed2006-04-27 19:21:49 +10003080
Paul Mackerras45a9d502006-05-20 22:56:27 +10003081 $cflist conf -state normal
3082 foreach f $fl {
3083 $cflist insert end "\n"
3084 $cflist insert end $f [highlight_tag $f]
Paul Mackerras7fcceed2006-04-27 19:21:49 +10003085 }
Paul Mackerras45a9d502006-05-20 22:56:27 +10003086 $cflist conf -state disabled
Paul Mackerras7fcceed2006-04-27 19:21:49 +10003087}
3088
3089proc sel_flist {w x y} {
Paul Mackerras45a9d502006-05-20 22:56:27 +10003090 global ctext difffilestart cflist cflist_top cmitmode
Paul Mackerras7fcceed2006-04-27 19:21:49 +10003091
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10003092 if {$cmitmode eq "tree"} return
Paul Mackerras7fcceed2006-04-27 19:21:49 +10003093 if {![info exists cflist_top]} return
3094 set l [lindex [split [$w index "@$x,$y"] "."] 0]
Paul Mackerras89b11d32006-05-02 19:55:31 +10003095 $cflist tag remove highlight $cflist_top.0 "$cflist_top.0 lineend"
3096 $cflist tag add highlight $l.0 "$l.0 lineend"
3097 set cflist_top $l
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10003098 if {$l == 1} {
3099 $ctext yview 1.0
3100 } else {
3101 catch {$ctext yview [lindex $difffilestart [expr {$l - 2}]]}
Paul Mackerras7fcceed2006-04-27 19:21:49 +10003102 }
Paul Mackerras7fcceed2006-04-27 19:21:49 +10003103}
3104
Paul Mackerras32447292007-07-27 22:30:15 +10003105proc pop_flist_menu {w X Y x y} {
3106 global ctext cflist cmitmode flist_menu flist_menu_file
3107 global treediffs diffids
3108
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10003109 stopfinding
Paul Mackerras32447292007-07-27 22:30:15 +10003110 set l [lindex [split [$w index "@$x,$y"] "."] 0]
3111 if {$l <= 1} return
3112 if {$cmitmode eq "tree"} {
3113 set e [linetoelt $l]
3114 if {[string index $e end] eq "/"} return
3115 } else {
3116 set e [lindex $treediffs($diffids) [expr {$l-2}]]
3117 }
3118 set flist_menu_file $e
Thomas Arcila314f5de2008-03-24 12:55:36 +01003119 set xdiffstate "normal"
3120 if {$cmitmode eq "tree"} {
3121 set xdiffstate "disabled"
3122 }
3123 # Disable "External diff" item in tree mode
3124 $flist_menu entryconf 2 -state $xdiffstate
Paul Mackerras32447292007-07-27 22:30:15 +10003125 tk_popup $flist_menu $X $Y
3126}
3127
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003128proc find_ctext_fileinfo {line} {
3129 global ctext_file_names ctext_file_lines
3130
3131 set ok [bsearch $ctext_file_lines $line]
3132 set tline [lindex $ctext_file_lines $ok]
3133
3134 if {$ok >= [llength $ctext_file_lines] || $line < $tline} {
3135 return {}
3136 } else {
3137 return [list [lindex $ctext_file_names $ok] $tline]
3138 }
3139}
3140
3141proc pop_diff_menu {w X Y x y} {
3142 global ctext diff_menu flist_menu_file
3143 global diff_menu_txtpos diff_menu_line
3144 global diff_menu_filebase
3145
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003146 set diff_menu_txtpos [split [$w index "@$x,$y"] "."]
3147 set diff_menu_line [lindex $diff_menu_txtpos 0]
Paul Mackerras190ec522008-10-27 21:13:37 +11003148 # don't pop up the menu on hunk-separator or file-separator lines
3149 if {[lsearch -glob [$ctext tag names $diff_menu_line.0] "*sep"] >= 0} {
3150 return
3151 }
3152 stopfinding
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003153 set f [find_ctext_fileinfo $diff_menu_line]
3154 if {$f eq {}} return
3155 set flist_menu_file [lindex $f 0]
3156 set diff_menu_filebase [lindex $f 1]
3157 tk_popup $diff_menu $X $Y
3158}
3159
Paul Mackerras32447292007-07-27 22:30:15 +10003160proc flist_hl {only} {
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10003161 global flist_menu_file findstring gdttype
Paul Mackerras32447292007-07-27 22:30:15 +10003162
3163 set x [shellquote $flist_menu_file]
Christian Stimmingb007ee22007-11-07 18:44:35 +01003164 if {$only || $findstring eq {} || $gdttype ne [mc "touching paths:"]} {
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10003165 set findstring $x
Paul Mackerras32447292007-07-27 22:30:15 +10003166 } else {
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10003167 append findstring " " $x
Paul Mackerras32447292007-07-27 22:30:15 +10003168 }
Christian Stimmingb007ee22007-11-07 18:44:35 +01003169 set gdttype [mc "touching paths:"]
Paul Mackerras32447292007-07-27 22:30:15 +10003170}
3171
Paul Mackerrasc21398b2009-09-07 10:08:21 +10003172proc gitknewtmpdir {} {
3173 global diffnum gitktmpdir gitdir
3174
3175 if {![info exists gitktmpdir]} {
3176 set gitktmpdir [file join [file dirname $gitdir] \
3177 [format ".gitk-tmp.%s" [pid]]]
3178 if {[catch {file mkdir $gitktmpdir} err]} {
3179 error_popup "[mc "Error creating temporary directory %s:" $gitktmpdir] $err"
3180 unset gitktmpdir
3181 return {}
3182 }
3183 set diffnum 0
3184 }
3185 incr diffnum
3186 set diffdir [file join $gitktmpdir $diffnum]
3187 if {[catch {file mkdir $diffdir} err]} {
3188 error_popup "[mc "Error creating temporary directory %s:" $diffdir] $err"
3189 return {}
3190 }
3191 return $diffdir
3192}
3193
Thomas Arcila314f5de2008-03-24 12:55:36 +01003194proc save_file_from_commit {filename output what} {
3195 global nullfile
3196
3197 if {[catch {exec git show $filename -- > $output} err]} {
3198 if {[string match "fatal: bad revision *" $err]} {
3199 return $nullfile
3200 }
Christian Stimming3945d2c2008-09-12 11:39:43 +02003201 error_popup "[mc "Error getting \"%s\" from %s:" $filename $what] $err"
Thomas Arcila314f5de2008-03-24 12:55:36 +01003202 return {}
3203 }
3204 return $output
3205}
3206
3207proc external_diff_get_one_file {diffid filename diffdir} {
3208 global nullid nullid2 nullfile
3209 global gitdir
3210
3211 if {$diffid == $nullid} {
3212 set difffile [file join [file dirname $gitdir] $filename]
3213 if {[file exists $difffile]} {
3214 return $difffile
3215 }
3216 return $nullfile
3217 }
3218 if {$diffid == $nullid2} {
3219 set difffile [file join $diffdir "\[index\] [file tail $filename]"]
3220 return [save_file_from_commit :$filename $difffile index]
3221 }
3222 set difffile [file join $diffdir "\[$diffid\] [file tail $filename]"]
3223 return [save_file_from_commit $diffid:$filename $difffile \
3224 "revision $diffid"]
3225}
3226
3227proc external_diff {} {
Paul Mackerrasc21398b2009-09-07 10:08:21 +10003228 global nullid nullid2
Thomas Arcila314f5de2008-03-24 12:55:36 +01003229 global flist_menu_file
3230 global diffids
Paul Mackerrasc21398b2009-09-07 10:08:21 +10003231 global extdifftool
Thomas Arcila314f5de2008-03-24 12:55:36 +01003232
3233 if {[llength $diffids] == 1} {
3234 # no reference commit given
3235 set diffidto [lindex $diffids 0]
3236 if {$diffidto eq $nullid} {
3237 # diffing working copy with index
3238 set diffidfrom $nullid2
3239 } elseif {$diffidto eq $nullid2} {
3240 # diffing index with HEAD
3241 set diffidfrom "HEAD"
3242 } else {
3243 # use first parent commit
3244 global parentlist selectedline
3245 set diffidfrom [lindex $parentlist $selectedline 0]
3246 }
3247 } else {
3248 set diffidfrom [lindex $diffids 0]
3249 set diffidto [lindex $diffids 1]
3250 }
3251
3252 # make sure that several diffs wont collide
Paul Mackerrasc21398b2009-09-07 10:08:21 +10003253 set diffdir [gitknewtmpdir]
3254 if {$diffdir eq {}} return
Thomas Arcila314f5de2008-03-24 12:55:36 +01003255
3256 # gather files to diff
3257 set difffromfile [external_diff_get_one_file $diffidfrom $flist_menu_file $diffdir]
3258 set difftofile [external_diff_get_one_file $diffidto $flist_menu_file $diffdir]
3259
3260 if {$difffromfile ne {} && $difftofile ne {}} {
Pat Thoytsb575b2f2009-04-15 16:54:19 +01003261 set cmd [list [shellsplit $extdifftool] $difffromfile $difftofile]
3262 if {[catch {set fl [open |$cmd r]} err]} {
Thomas Arcila314f5de2008-03-24 12:55:36 +01003263 file delete -force $diffdir
Christian Stimming3945d2c2008-09-12 11:39:43 +02003264 error_popup "$extdifftool: [mc "command failed:"] $err"
Thomas Arcila314f5de2008-03-24 12:55:36 +01003265 } else {
3266 fconfigure $fl -blocking 0
3267 filerun $fl [list delete_at_eof $fl $diffdir]
3268 }
3269 }
3270}
3271
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003272proc find_hunk_blamespec {base line} {
3273 global ctext
3274
3275 # Find and parse the hunk header
3276 set s_lix [$ctext search -backwards -regexp ^@@ "$line.0 lineend" $base.0]
3277 if {$s_lix eq {}} return
3278
3279 set s_line [$ctext get $s_lix "$s_lix + 1 lines"]
3280 if {![regexp {^@@@*(( -\d+(,\d+)?)+) \+(\d+)(,\d+)? @@} $s_line \
3281 s_line old_specs osz osz1 new_line nsz]} {
3282 return
3283 }
3284
3285 # base lines for the parents
3286 set base_lines [list $new_line]
3287 foreach old_spec [lrange [split $old_specs " "] 1 end] {
3288 if {![regexp -- {-(\d+)(,\d+)?} $old_spec \
3289 old_spec old_line osz]} {
3290 return
3291 }
3292 lappend base_lines $old_line
3293 }
3294
3295 # Now scan the lines to determine offset within the hunk
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003296 set max_parent [expr {[llength $base_lines]-2}]
3297 set dline 0
3298 set s_lno [lindex [split $s_lix "."] 0]
3299
Paul Mackerras190ec522008-10-27 21:13:37 +11003300 # Determine if the line is removed
3301 set chunk [$ctext get $line.0 "$line.1 + $max_parent chars"]
3302 if {[string match {[-+ ]*} $chunk]} {
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003303 set removed_idx [string first "-" $chunk]
3304 # Choose a parent index
Paul Mackerras190ec522008-10-27 21:13:37 +11003305 if {$removed_idx >= 0} {
3306 set parent $removed_idx
3307 } else {
3308 set unchanged_idx [string first " " $chunk]
3309 if {$unchanged_idx >= 0} {
3310 set parent $unchanged_idx
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003311 } else {
Paul Mackerras190ec522008-10-27 21:13:37 +11003312 # blame the current commit
3313 set parent -1
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003314 }
3315 }
3316 # then count other lines that belong to it
Paul Mackerras190ec522008-10-27 21:13:37 +11003317 for {set i $line} {[incr i -1] > $s_lno} {} {
3318 set chunk [$ctext get $i.0 "$i.1 + $max_parent chars"]
3319 # Determine if the line is removed
3320 set removed_idx [string first "-" $chunk]
3321 if {$parent >= 0} {
3322 set code [string index $chunk $parent]
3323 if {$code eq "-" || ($removed_idx < 0 && $code ne "+")} {
3324 incr dline
3325 }
3326 } else {
3327 if {$removed_idx < 0} {
3328 incr dline
3329 }
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003330 }
3331 }
Paul Mackerras190ec522008-10-27 21:13:37 +11003332 incr parent
3333 } else {
3334 set parent 0
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003335 }
3336
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003337 incr dline [lindex $base_lines $parent]
3338 return [list $parent $dline]
3339}
3340
3341proc external_blame_diff {} {
Paul Mackerras8b07dca2008-11-02 22:34:47 +11003342 global currentid cmitmode
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003343 global diff_menu_txtpos diff_menu_line
3344 global diff_menu_filebase flist_menu_file
3345
3346 if {$cmitmode eq "tree"} {
3347 set parent_idx 0
Paul Mackerras190ec522008-10-27 21:13:37 +11003348 set line [expr {$diff_menu_line - $diff_menu_filebase}]
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003349 } else {
3350 set hinfo [find_hunk_blamespec $diff_menu_filebase $diff_menu_line]
3351 if {$hinfo ne {}} {
3352 set parent_idx [lindex $hinfo 0]
3353 set line [lindex $hinfo 1]
3354 } else {
3355 set parent_idx 0
3356 set line 0
3357 }
3358 }
3359
3360 external_blame $parent_idx $line
3361}
3362
Paul Mackerrasfc4977e2008-11-04 12:57:44 +11003363# Find the SHA1 ID of the blob for file $fname in the index
3364# at stage 0 or 2
3365proc index_sha1 {fname} {
3366 set f [open [list | git ls-files -s $fname] r]
3367 while {[gets $f line] >= 0} {
3368 set info [lindex [split $line "\t"] 0]
3369 set stage [lindex $info 2]
3370 if {$stage eq "0" || $stage eq "2"} {
3371 close $f
3372 return [lindex $info 1]
3373 }
3374 }
3375 close $f
3376 return {}
3377}
3378
Paul Mackerras9712b812008-12-06 21:44:05 +11003379# Turn an absolute path into one relative to the current directory
3380proc make_relative {f} {
3381 set elts [file split $f]
3382 set here [file split [pwd]]
3383 set ei 0
3384 set hi 0
3385 set res {}
3386 foreach d $here {
3387 if {$ei < $hi || $ei >= [llength $elts] || [lindex $elts $ei] ne $d} {
3388 lappend res ".."
3389 } else {
3390 incr ei
3391 }
3392 incr hi
3393 }
3394 set elts [concat $res [lrange $elts $ei end]]
3395 return [eval file join $elts]
3396}
3397
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003398proc external_blame {parent_idx {line {}}} {
Paul Mackerras9712b812008-12-06 21:44:05 +11003399 global flist_menu_file gitdir
Alexander Gavrilov77aa0ae2008-08-23 12:29:08 +04003400 global nullid nullid2
3401 global parentlist selectedline currentid
3402
3403 if {$parent_idx > 0} {
3404 set base_commit [lindex $parentlist $selectedline [expr {$parent_idx-1}]]
3405 } else {
3406 set base_commit $currentid
3407 }
3408
3409 if {$base_commit eq {} || $base_commit eq $nullid || $base_commit eq $nullid2} {
3410 error_popup [mc "No such commit"]
3411 return
3412 }
3413
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003414 set cmdline [list git gui blame]
3415 if {$line ne {} && $line > 1} {
3416 lappend cmdline "--line=$line"
3417 }
Paul Mackerras9712b812008-12-06 21:44:05 +11003418 set f [file join [file dirname $gitdir] $flist_menu_file]
3419 # Unfortunately it seems git gui blame doesn't like
3420 # being given an absolute path...
3421 set f [make_relative $f]
3422 lappend cmdline $base_commit $f
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003423 if {[catch {eval exec $cmdline &} err]} {
Christian Stimming3945d2c2008-09-12 11:39:43 +02003424 error_popup "[mc "git gui blame: command failed:"] $err"
Alexander Gavrilov77aa0ae2008-08-23 12:29:08 +04003425 }
3426}
3427
Paul Mackerras8a897742008-10-27 21:36:25 +11003428proc show_line_source {} {
3429 global cmitmode currentid parents curview blamestuff blameinst
3430 global diff_menu_line diff_menu_filebase flist_menu_file
Paul Mackerrasfc4977e2008-11-04 12:57:44 +11003431 global nullid nullid2 gitdir
Paul Mackerras8a897742008-10-27 21:36:25 +11003432
Paul Mackerrasfc4977e2008-11-04 12:57:44 +11003433 set from_index {}
Paul Mackerras8a897742008-10-27 21:36:25 +11003434 if {$cmitmode eq "tree"} {
3435 set id $currentid
3436 set line [expr {$diff_menu_line - $diff_menu_filebase}]
3437 } else {
3438 set h [find_hunk_blamespec $diff_menu_filebase $diff_menu_line]
3439 if {$h eq {}} return
3440 set pi [lindex $h 0]
3441 if {$pi == 0} {
3442 mark_ctext_line $diff_menu_line
3443 return
3444 }
Paul Mackerrasfc4977e2008-11-04 12:57:44 +11003445 incr pi -1
3446 if {$currentid eq $nullid} {
3447 if {$pi > 0} {
3448 # must be a merge in progress...
3449 if {[catch {
3450 # get the last line from .git/MERGE_HEAD
3451 set f [open [file join $gitdir MERGE_HEAD] r]
3452 set id [lindex [split [read $f] "\n"] end-1]
3453 close $f
3454 } err]} {
3455 error_popup [mc "Couldn't read merge head: %s" $err]
3456 return
3457 }
3458 } elseif {$parents($curview,$currentid) eq $nullid2} {
3459 # need to do the blame from the index
3460 if {[catch {
3461 set from_index [index_sha1 $flist_menu_file]
3462 } err]} {
3463 error_popup [mc "Error reading index: %s" $err]
3464 return
3465 }
Paul Mackerras9712b812008-12-06 21:44:05 +11003466 } else {
3467 set id $parents($curview,$currentid)
Paul Mackerrasfc4977e2008-11-04 12:57:44 +11003468 }
3469 } else {
3470 set id [lindex $parents($curview,$currentid) $pi]
3471 }
Paul Mackerras8a897742008-10-27 21:36:25 +11003472 set line [lindex $h 1]
3473 }
Paul Mackerrasfc4977e2008-11-04 12:57:44 +11003474 set blameargs {}
3475 if {$from_index ne {}} {
3476 lappend blameargs | git cat-file blob $from_index
3477 }
3478 lappend blameargs | git blame -p -L$line,+1
3479 if {$from_index ne {}} {
3480 lappend blameargs --contents -
3481 } else {
3482 lappend blameargs $id
3483 }
Paul Mackerras9712b812008-12-06 21:44:05 +11003484 lappend blameargs -- [file join [file dirname $gitdir] $flist_menu_file]
Paul Mackerras8a897742008-10-27 21:36:25 +11003485 if {[catch {
Paul Mackerrasfc4977e2008-11-04 12:57:44 +11003486 set f [open $blameargs r]
Paul Mackerras8a897742008-10-27 21:36:25 +11003487 } err]} {
3488 error_popup [mc "Couldn't start git blame: %s" $err]
3489 return
3490 }
Alexander Gavrilovf3413072008-12-01 20:30:09 +03003491 nowbusy blaming [mc "Searching"]
Paul Mackerras8a897742008-10-27 21:36:25 +11003492 fconfigure $f -blocking 0
3493 set i [reg_instance $f]
3494 set blamestuff($i) {}
3495 set blameinst $i
3496 filerun $f [list read_line_source $f $i]
3497}
3498
3499proc stopblaming {} {
3500 global blameinst
3501
3502 if {[info exists blameinst]} {
3503 stop_instance $blameinst
3504 unset blameinst
Alexander Gavrilovf3413072008-12-01 20:30:09 +03003505 notbusy blaming
Paul Mackerras8a897742008-10-27 21:36:25 +11003506 }
3507}
3508
3509proc read_line_source {fd inst} {
Paul Mackerrasfc4977e2008-11-04 12:57:44 +11003510 global blamestuff curview commfd blameinst nullid nullid2
Paul Mackerras8a897742008-10-27 21:36:25 +11003511
3512 while {[gets $fd line] >= 0} {
3513 lappend blamestuff($inst) $line
3514 }
3515 if {![eof $fd]} {
3516 return 1
3517 }
3518 unset commfd($inst)
3519 unset blameinst
Alexander Gavrilovf3413072008-12-01 20:30:09 +03003520 notbusy blaming
Paul Mackerras8a897742008-10-27 21:36:25 +11003521 fconfigure $fd -blocking 1
3522 if {[catch {close $fd} err]} {
3523 error_popup [mc "Error running git blame: %s" $err]
3524 return 0
3525 }
3526
3527 set fname {}
3528 set line [split [lindex $blamestuff($inst) 0] " "]
3529 set id [lindex $line 0]
3530 set lnum [lindex $line 1]
3531 if {[string length $id] == 40 && [string is xdigit $id] &&
3532 [string is digit -strict $lnum]} {
3533 # look for "filename" line
3534 foreach l $blamestuff($inst) {
3535 if {[string match "filename *" $l]} {
3536 set fname [string range $l 9 end]
3537 break
3538 }
3539 }
3540 }
3541 if {$fname ne {}} {
3542 # all looks good, select it
Paul Mackerrasfc4977e2008-11-04 12:57:44 +11003543 if {$id eq $nullid} {
3544 # blame uses all-zeroes to mean not committed,
3545 # which would mean a change in the index
3546 set id $nullid2
3547 }
Paul Mackerras8a897742008-10-27 21:36:25 +11003548 if {[commitinview $id $curview]} {
3549 selectline [rowofcommit $id] 1 [list $fname $lnum]
3550 } else {
3551 error_popup [mc "That line comes from commit %s, \
3552 which is not in this view" [shortids $id]]
3553 }
3554 } else {
3555 puts "oops couldn't parse git blame output"
3556 }
3557 return 0
3558}
3559
Thomas Arcila314f5de2008-03-24 12:55:36 +01003560# delete $dir when we see eof on $f (presumably because the child has exited)
3561proc delete_at_eof {f dir} {
3562 while {[gets $f line] >= 0} {}
3563 if {[eof $f]} {
3564 if {[catch {close $f} err]} {
Christian Stimming3945d2c2008-09-12 11:39:43 +02003565 error_popup "[mc "External diff viewer failed:"] $err"
Thomas Arcila314f5de2008-03-24 12:55:36 +01003566 }
3567 file delete -force $dir
3568 return 0
3569 }
3570 return 1
3571}
3572
Paul Mackerras098dd8a2006-05-03 09:32:53 +10003573# Functions for adding and removing shell-type quoting
3574
3575proc shellquote {str} {
3576 if {![string match "*\['\"\\ \t]*" $str]} {
3577 return $str
3578 }
3579 if {![string match "*\['\"\\]*" $str]} {
3580 return "\"$str\""
3581 }
3582 if {![string match "*'*" $str]} {
3583 return "'$str'"
3584 }
3585 return "\"[string map {\" \\\" \\ \\\\} $str]\""
3586}
3587
3588proc shellarglist {l} {
3589 set str {}
3590 foreach a $l {
3591 if {$str ne {}} {
3592 append str " "
3593 }
3594 append str [shellquote $a]
3595 }
3596 return $str
3597}
3598
3599proc shelldequote {str} {
3600 set ret {}
3601 set used -1
3602 while {1} {
3603 incr used
3604 if {![regexp -start $used -indices "\['\"\\\\ \t]" $str first]} {
3605 append ret [string range $str $used end]
3606 set used [string length $str]
3607 break
3608 }
3609 set first [lindex $first 0]
3610 set ch [string index $str $first]
3611 if {$first > $used} {
3612 append ret [string range $str $used [expr {$first - 1}]]
3613 set used $first
3614 }
3615 if {$ch eq " " || $ch eq "\t"} break
3616 incr used
3617 if {$ch eq "'"} {
3618 set first [string first "'" $str $used]
3619 if {$first < 0} {
3620 error "unmatched single-quote"
3621 }
3622 append ret [string range $str $used [expr {$first - 1}]]
3623 set used $first
3624 continue
3625 }
3626 if {$ch eq "\\"} {
3627 if {$used >= [string length $str]} {
3628 error "trailing backslash"
3629 }
3630 append ret [string index $str $used]
3631 continue
3632 }
3633 # here ch == "\""
3634 while {1} {
3635 if {![regexp -start $used -indices "\[\"\\\\]" $str first]} {
3636 error "unmatched double-quote"
3637 }
3638 set first [lindex $first 0]
3639 set ch [string index $str $first]
3640 if {$first > $used} {
3641 append ret [string range $str $used [expr {$first - 1}]]
3642 set used $first
3643 }
3644 if {$ch eq "\""} break
3645 incr used
3646 append ret [string index $str $used]
3647 incr used
3648 }
3649 }
3650 return [list $used $ret]
3651}
3652
3653proc shellsplit {str} {
3654 set l {}
3655 while {1} {
3656 set str [string trimleft $str]
3657 if {$str eq {}} break
3658 set dq [shelldequote $str]
3659 set n [lindex $dq 0]
3660 set word [lindex $dq 1]
3661 set str [string range $str $n end]
3662 lappend l $word
3663 }
3664 return $l
3665}
3666
Paul Mackerras7fcceed2006-04-27 19:21:49 +10003667# Code to implement multiple views
3668
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10003669proc newview {ishighlight} {
Alexander Gavrilov218a9002008-11-02 21:59:48 +03003670 global nextviewnum newviewname newishighlight
3671 global revtreeargs viewargscmd newviewopts curview
Paul Mackerras50b44ec2006-04-04 10:16:22 +10003672
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10003673 set newishighlight $ishighlight
Paul Mackerras50b44ec2006-04-04 10:16:22 +10003674 set top .gitkview
3675 if {[winfo exists $top]} {
3676 raise $top
3677 return
3678 }
Michele Ballabioa3a1f572008-03-03 21:12:47 +01003679 set newviewname($nextviewnum) "[mc "View"] $nextviewnum"
Alexander Gavrilov218a9002008-11-02 21:59:48 +03003680 set newviewopts($nextviewnum,perm) 0
3681 set newviewopts($nextviewnum,cmd) $viewargscmd($curview)
3682 decode_view_opts $nextviewnum $revtreeargs
Christian Stimmingd990ced2007-11-07 18:42:55 +01003683 vieweditor $top $nextviewnum [mc "Gitk view definition"]
Paul Mackerrasd16c0812006-04-25 21:21:10 +10003684}
3685
Alexander Gavrilov218a9002008-11-02 21:59:48 +03003686set known_view_options {
Elijah Newren13d40b62009-03-23 11:57:46 -06003687 {perm b . {} {mc "Remember this view"}}
3688 {reflabel l + {} {mc "References (space separated list):"}}
3689 {refs t15 .. {} {mc "Branches & tags:"}}
3690 {allrefs b *. "--all" {mc "All refs"}}
3691 {branches b . "--branches" {mc "All (local) branches"}}
3692 {tags b . "--tags" {mc "All tags"}}
3693 {remotes b . "--remotes" {mc "All remote-tracking branches"}}
3694 {commitlbl l + {} {mc "Commit Info (regular expressions):"}}
3695 {author t15 .. "--author=*" {mc "Author:"}}
3696 {committer t15 . "--committer=*" {mc "Committer:"}}
3697 {loginfo t15 .. "--grep=*" {mc "Commit Message:"}}
3698 {allmatch b .. "--all-match" {mc "Matches all Commit Info criteria"}}
3699 {changes_l l + {} {mc "Changes to Files:"}}
3700 {pickaxe_s r0 . {} {mc "Fixed String"}}
3701 {pickaxe_t r1 . "--pickaxe-regex" {mc "Regular Expression"}}
3702 {pickaxe t15 .. "-S*" {mc "Search string:"}}
3703 {datelabel l + {} {mc "Commit Dates (\"2 weeks ago\", \"2009-03-17 15:27:38\", \"March 17, 2009 15:27:38\"):"}}
3704 {since t15 .. {"--since=*" "--after=*"} {mc "Since:"}}
3705 {until t15 . {"--until=*" "--before=*"} {mc "Until:"}}
3706 {limit_lbl l + {} {mc "Limit and/or skip a number of revisions (positive integer):"}}
3707 {limit t10 *. "--max-count=*" {mc "Number to show:"}}
3708 {skip t10 . "--skip=*" {mc "Number to skip:"}}
3709 {misc_lbl l + {} {mc "Miscellaneous options:"}}
3710 {dorder b *. {"--date-order" "-d"} {mc "Strictly sort by date"}}
3711 {lright b . "--left-right" {mc "Mark branch sides"}}
3712 {first b . "--first-parent" {mc "Limit to first parent"}}
Dirk Suesserottf687aaa2009-05-21 15:35:40 +02003713 {smplhst b . "--simplify-by-decoration" {mc "Simple history"}}
Elijah Newren13d40b62009-03-23 11:57:46 -06003714 {args t50 *. {} {mc "Additional arguments to git log:"}}
3715 {allpaths path + {} {mc "Enter files and directories to include, one per line:"}}
3716 {cmd t50= + {} {mc "Command to generate more commits to include:"}}
Alexander Gavrilov218a9002008-11-02 21:59:48 +03003717 }
3718
3719proc encode_view_opts {n} {
3720 global known_view_options newviewopts
3721
3722 set rargs [list]
3723 foreach opt $known_view_options {
3724 set patterns [lindex $opt 3]
3725 if {$patterns eq {}} continue
3726 set pattern [lindex $patterns 0]
3727
Alexander Gavrilov218a9002008-11-02 21:59:48 +03003728 if {[lindex $opt 1] eq "b"} {
Elijah Newren13d40b62009-03-23 11:57:46 -06003729 set val $newviewopts($n,[lindex $opt 0])
Alexander Gavrilov218a9002008-11-02 21:59:48 +03003730 if {$val} {
3731 lappend rargs $pattern
3732 }
Elijah Newren13d40b62009-03-23 11:57:46 -06003733 } elseif {[regexp {^r(\d+)$} [lindex $opt 1] type value]} {
3734 regexp {^(.*_)} [lindex $opt 0] uselessvar button_id
3735 set val $newviewopts($n,$button_id)
3736 if {$val eq $value} {
3737 lappend rargs $pattern
3738 }
Alexander Gavrilov218a9002008-11-02 21:59:48 +03003739 } else {
Elijah Newren13d40b62009-03-23 11:57:46 -06003740 set val $newviewopts($n,[lindex $opt 0])
Alexander Gavrilov218a9002008-11-02 21:59:48 +03003741 set val [string trim $val]
3742 if {$val ne {}} {
3743 set pfix [string range $pattern 0 end-1]
3744 lappend rargs $pfix$val
3745 }
3746 }
3747 }
Elijah Newren13d40b62009-03-23 11:57:46 -06003748 set rargs [concat $rargs [shellsplit $newviewopts($n,refs)]]
Alexander Gavrilov218a9002008-11-02 21:59:48 +03003749 return [concat $rargs [shellsplit $newviewopts($n,args)]]
3750}
3751
3752proc decode_view_opts {n view_args} {
3753 global known_view_options newviewopts
3754
3755 foreach opt $known_view_options {
Elijah Newren13d40b62009-03-23 11:57:46 -06003756 set id [lindex $opt 0]
Alexander Gavrilov218a9002008-11-02 21:59:48 +03003757 if {[lindex $opt 1] eq "b"} {
Elijah Newren13d40b62009-03-23 11:57:46 -06003758 # Checkboxes
3759 set val 0
3760 } elseif {[regexp {^r(\d+)$} [lindex $opt 1]]} {
3761 # Radiobuttons
3762 regexp {^(.*_)} $id uselessvar id
Alexander Gavrilov218a9002008-11-02 21:59:48 +03003763 set val 0
3764 } else {
Elijah Newren13d40b62009-03-23 11:57:46 -06003765 # Text fields
Alexander Gavrilov218a9002008-11-02 21:59:48 +03003766 set val {}
3767 }
Elijah Newren13d40b62009-03-23 11:57:46 -06003768 set newviewopts($n,$id) $val
Alexander Gavrilov218a9002008-11-02 21:59:48 +03003769 }
3770 set oargs [list]
Elijah Newren13d40b62009-03-23 11:57:46 -06003771 set refargs [list]
Alexander Gavrilov218a9002008-11-02 21:59:48 +03003772 foreach arg $view_args {
3773 if {[regexp -- {^-([0-9]+)$} $arg arg cnt]
3774 && ![info exists found(limit)]} {
3775 set newviewopts($n,limit) $cnt
3776 set found(limit) 1
3777 continue
3778 }
3779 catch { unset val }
3780 foreach opt $known_view_options {
3781 set id [lindex $opt 0]
3782 if {[info exists found($id)]} continue
3783 foreach pattern [lindex $opt 3] {
3784 if {![string match $pattern $arg]} continue
Elijah Newren13d40b62009-03-23 11:57:46 -06003785 if {[lindex $opt 1] eq "b"} {
3786 # Check buttons
3787 set val 1
3788 } elseif {[regexp {^r(\d+)$} [lindex $opt 1] match num]} {
3789 # Radio buttons
3790 regexp {^(.*_)} $id uselessvar id
3791 set val $num
3792 } else {
3793 # Text input fields
Alexander Gavrilov218a9002008-11-02 21:59:48 +03003794 set size [string length $pattern]
3795 set val [string range $arg [expr {$size-1}] end]
Alexander Gavrilov218a9002008-11-02 21:59:48 +03003796 }
3797 set newviewopts($n,$id) $val
3798 set found($id) 1
3799 break
3800 }
3801 if {[info exists val]} break
3802 }
3803 if {[info exists val]} continue
Elijah Newren13d40b62009-03-23 11:57:46 -06003804 if {[regexp {^-} $arg]} {
3805 lappend oargs $arg
3806 } else {
3807 lappend refargs $arg
3808 }
Alexander Gavrilov218a9002008-11-02 21:59:48 +03003809 }
Elijah Newren13d40b62009-03-23 11:57:46 -06003810 set newviewopts($n,refs) [shellarglist $refargs]
Alexander Gavrilov218a9002008-11-02 21:59:48 +03003811 set newviewopts($n,args) [shellarglist $oargs]
3812}
3813
Alexander Gavrilovcea07cf2008-11-09 13:00:45 +03003814proc edit_or_newview {} {
3815 global curview
3816
3817 if {$curview > 0} {
3818 editview
3819 } else {
3820 newview 0
3821 }
3822}
3823
Paul Mackerrasd16c0812006-04-25 21:21:10 +10003824proc editview {} {
3825 global curview
Alexander Gavrilov218a9002008-11-02 21:59:48 +03003826 global viewname viewperm newviewname newviewopts
3827 global viewargs viewargscmd
Paul Mackerrasd16c0812006-04-25 21:21:10 +10003828
3829 set top .gitkvedit-$curview
3830 if {[winfo exists $top]} {
3831 raise $top
3832 return
3833 }
Alexander Gavrilov218a9002008-11-02 21:59:48 +03003834 set newviewname($curview) $viewname($curview)
3835 set newviewopts($curview,perm) $viewperm($curview)
3836 set newviewopts($curview,cmd) $viewargscmd($curview)
3837 decode_view_opts $curview $viewargs($curview)
Michele Ballabiob56e0a92009-03-30 21:17:25 +02003838 vieweditor $top $curview "[mc "Gitk: edit view"] $viewname($curview)"
Paul Mackerrasd16c0812006-04-25 21:21:10 +10003839}
3840
3841proc vieweditor {top n title} {
Alexander Gavrilov218a9002008-11-02 21:59:48 +03003842 global newviewname newviewopts viewfiles bgcolor
3843 global known_view_options
Paul Mackerrasd16c0812006-04-25 21:21:10 +10003844
Paul Mackerras50b44ec2006-04-04 10:16:22 +10003845 toplevel $top
Michele Ballabioe0a01992009-05-23 11:48:25 +02003846 wm title $top [concat $title [mc "-- criteria for selecting revisions"]]
Alexander Gavrilove7d64002008-11-11 23:55:42 +03003847 make_transient $top .
Alexander Gavrilov218a9002008-11-02 21:59:48 +03003848
3849 # View name
3850 frame $top.nfr
Elijah Newren13d40b62009-03-23 11:57:46 -06003851 label $top.nl -text [mc "View Name:"]
Paul Mackerrasb039f0a2008-01-06 15:54:46 +11003852 entry $top.name -width 20 -textvariable newviewname($n)
Alexander Gavrilov218a9002008-11-02 21:59:48 +03003853 pack $top.nfr -in $top -fill x -pady 5 -padx 3
Elijah Newren13d40b62009-03-23 11:57:46 -06003854 pack $top.nl -in $top.nfr -side left -padx {0 5}
3855 pack $top.name -in $top.nfr -side left -padx {0 25}
Yann Dirson2d480852008-02-21 21:23:31 +01003856
Alexander Gavrilov218a9002008-11-02 21:59:48 +03003857 # View options
3858 set cframe $top.nfr
3859 set cexpand 0
3860 set cnt 0
3861 foreach opt $known_view_options {
3862 set id [lindex $opt 0]
3863 set type [lindex $opt 1]
3864 set flags [lindex $opt 2]
3865 set title [eval [lindex $opt 4]]
3866 set lxpad 0
Yann Dirson2d480852008-02-21 21:23:31 +01003867
Alexander Gavrilov218a9002008-11-02 21:59:48 +03003868 if {$flags eq "+" || $flags eq "*"} {
3869 set cframe $top.fr$cnt
3870 incr cnt
3871 frame $cframe
3872 pack $cframe -in $top -fill x -pady 3 -padx 3
3873 set cexpand [expr {$flags eq "*"}]
Elijah Newren13d40b62009-03-23 11:57:46 -06003874 } elseif {$flags eq ".." || $flags eq "*."} {
3875 set cframe $top.fr$cnt
3876 incr cnt
3877 frame $cframe
3878 pack $cframe -in $top -fill x -pady 3 -padx [list 15 3]
3879 set cexpand [expr {$flags eq "*."}]
Alexander Gavrilov218a9002008-11-02 21:59:48 +03003880 } else {
3881 set lxpad 5
3882 }
3883
Elijah Newren13d40b62009-03-23 11:57:46 -06003884 if {$type eq "l"} {
3885 label $cframe.l_$id -text $title
3886 pack $cframe.l_$id -in $cframe -side left -pady [list 3 0] -anchor w
3887 } elseif {$type eq "b"} {
Alexander Gavrilov218a9002008-11-02 21:59:48 +03003888 checkbutton $cframe.c_$id -text $title -variable newviewopts($n,$id)
3889 pack $cframe.c_$id -in $cframe -side left \
3890 -padx [list $lxpad 0] -expand $cexpand -anchor w
Elijah Newren13d40b62009-03-23 11:57:46 -06003891 } elseif {[regexp {^r(\d+)$} $type type sz]} {
3892 regexp {^(.*_)} $id uselessvar button_id
3893 radiobutton $cframe.c_$id -text $title -variable newviewopts($n,$button_id) -value $sz
3894 pack $cframe.c_$id -in $cframe -side left \
3895 -padx [list $lxpad 0] -expand $cexpand -anchor w
Alexander Gavrilov218a9002008-11-02 21:59:48 +03003896 } elseif {[regexp {^t(\d+)$} $type type sz]} {
3897 message $cframe.l_$id -aspect 1500 -text $title
3898 entry $cframe.e_$id -width $sz -background $bgcolor \
3899 -textvariable newviewopts($n,$id)
3900 pack $cframe.l_$id -in $cframe -side left -padx [list $lxpad 0]
3901 pack $cframe.e_$id -in $cframe -side left -expand 1 -fill x
3902 } elseif {[regexp {^t(\d+)=$} $type type sz]} {
3903 message $cframe.l_$id -aspect 1500 -text $title
3904 entry $cframe.e_$id -width $sz -background $bgcolor \
3905 -textvariable newviewopts($n,$id)
3906 pack $cframe.l_$id -in $cframe -side top -pady [list 3 0] -anchor w
3907 pack $cframe.e_$id -in $cframe -side top -fill x
Elijah Newren13d40b62009-03-23 11:57:46 -06003908 } elseif {$type eq "path"} {
3909 message $top.l -aspect 1500 -text $title
3910 pack $top.l -in $top -side top -pady [list 3 0] -anchor w -padx 3
3911 text $top.t -width 40 -height 5 -background $bgcolor -font uifont
3912 if {[info exists viewfiles($n)]} {
3913 foreach f $viewfiles($n) {
3914 $top.t insert end $f
3915 $top.t insert end "\n"
3916 }
3917 $top.t delete {end - 1c} end
3918 $top.t mark set insert 0.0
3919 }
3920 pack $top.t -in $top -side top -pady [list 0 5] -fill both -expand 1 -padx 3
Alexander Gavrilov218a9002008-11-02 21:59:48 +03003921 }
3922 }
3923
Paul Mackerras50b44ec2006-04-04 10:16:22 +10003924 frame $top.buts
Paul Mackerrasb039f0a2008-01-06 15:54:46 +11003925 button $top.buts.ok -text [mc "OK"] -command [list newviewok $top $n]
Alexander Gavrilov218a9002008-11-02 21:59:48 +03003926 button $top.buts.apply -text [mc "Apply (F5)"] -command [list newviewok $top $n 1]
Paul Mackerrasb039f0a2008-01-06 15:54:46 +11003927 button $top.buts.can -text [mc "Cancel"] -command [list destroy $top]
Alexander Gavrilov218a9002008-11-02 21:59:48 +03003928 bind $top <Control-Return> [list newviewok $top $n]
3929 bind $top <F5> [list newviewok $top $n 1]
Alexander Gavrilov76f15942008-11-02 21:59:44 +03003930 bind $top <Escape> [list destroy $top]
Alexander Gavrilov218a9002008-11-02 21:59:48 +03003931 grid $top.buts.ok $top.buts.apply $top.buts.can
Paul Mackerras50b44ec2006-04-04 10:16:22 +10003932 grid columnconfigure $top.buts 0 -weight 1 -uniform a
3933 grid columnconfigure $top.buts 1 -weight 1 -uniform a
Alexander Gavrilov218a9002008-11-02 21:59:48 +03003934 grid columnconfigure $top.buts 2 -weight 1 -uniform a
3935 pack $top.buts -in $top -side top -fill x
Paul Mackerras50b44ec2006-04-04 10:16:22 +10003936 focus $top.t
3937}
3938
Paul Mackerras908c3582006-05-20 09:38:11 +10003939proc doviewmenu {m first cmd op argv} {
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10003940 set nmenu [$m index end]
3941 for {set i $first} {$i <= $nmenu} {incr i} {
3942 if {[$m entrycget $i -command] eq $cmd} {
Paul Mackerras908c3582006-05-20 09:38:11 +10003943 eval $m $op $i $argv
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10003944 break
Paul Mackerrasd16c0812006-04-25 21:21:10 +10003945 }
3946 }
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10003947}
3948
3949proc allviewmenus {n op args} {
Paul Mackerras687c8762007-09-22 12:49:33 +10003950 # global viewhlmenu
Paul Mackerras908c3582006-05-20 09:38:11 +10003951
Paul Mackerras3cd204e2006-11-23 21:06:16 +11003952 doviewmenu .bar.view 5 [list showview $n] $op $args
Paul Mackerras687c8762007-09-22 12:49:33 +10003953 # doviewmenu $viewhlmenu 1 [list addvhighlight $n] $op $args
Paul Mackerrasd16c0812006-04-25 21:21:10 +10003954}
Paul Mackerras50b44ec2006-04-04 10:16:22 +10003955
Alexander Gavrilov218a9002008-11-02 21:59:48 +03003956proc newviewok {top n {apply 0}} {
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10003957 global nextviewnum newviewperm newviewname newishighlight
Paul Mackerrasd16c0812006-04-25 21:21:10 +10003958 global viewname viewfiles viewperm selectedview curview
Alexander Gavrilov218a9002008-11-02 21:59:48 +03003959 global viewargs viewargscmd newviewopts viewhlmenu
Paul Mackerrasd16c0812006-04-25 21:21:10 +10003960
Paul Mackerras098dd8a2006-05-03 09:32:53 +10003961 if {[catch {
Alexander Gavrilov218a9002008-11-02 21:59:48 +03003962 set newargs [encode_view_opts $n]
Paul Mackerras098dd8a2006-05-03 09:32:53 +10003963 } err]} {
Alexander Gavrilov84a76f12008-11-02 21:59:45 +03003964 error_popup "[mc "Error in commit selection arguments:"] $err" $top
Paul Mackerras098dd8a2006-05-03 09:32:53 +10003965 return
3966 }
Paul Mackerras50b44ec2006-04-04 10:16:22 +10003967 set files {}
Paul Mackerrasd16c0812006-04-25 21:21:10 +10003968 foreach f [split [$top.t get 0.0 end] "\n"] {
Paul Mackerras50b44ec2006-04-04 10:16:22 +10003969 set ft [string trim $f]
3970 if {$ft ne {}} {
3971 lappend files $ft
3972 }
3973 }
Paul Mackerrasd16c0812006-04-25 21:21:10 +10003974 if {![info exists viewfiles($n)]} {
3975 # creating a new view
3976 incr nextviewnum
3977 set viewname($n) $newviewname($n)
Alexander Gavrilov218a9002008-11-02 21:59:48 +03003978 set viewperm($n) $newviewopts($n,perm)
Paul Mackerrasd16c0812006-04-25 21:21:10 +10003979 set viewfiles($n) $files
Paul Mackerras098dd8a2006-05-03 09:32:53 +10003980 set viewargs($n) $newargs
Alexander Gavrilov218a9002008-11-02 21:59:48 +03003981 set viewargscmd($n) $newviewopts($n,cmd)
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10003982 addviewmenu $n
3983 if {!$newishighlight} {
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10003984 run showview $n
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10003985 } else {
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10003986 run addvhighlight $n
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10003987 }
Paul Mackerrasd16c0812006-04-25 21:21:10 +10003988 } else {
3989 # editing an existing view
Alexander Gavrilov218a9002008-11-02 21:59:48 +03003990 set viewperm($n) $newviewopts($n,perm)
Paul Mackerrasd16c0812006-04-25 21:21:10 +10003991 if {$newviewname($n) ne $viewname($n)} {
3992 set viewname($n) $newviewname($n)
Paul Mackerras3cd204e2006-11-23 21:06:16 +11003993 doviewmenu .bar.view 5 [list showview $n] \
Paul Mackerras908c3582006-05-20 09:38:11 +10003994 entryconf [list -label $viewname($n)]
Paul Mackerras687c8762007-09-22 12:49:33 +10003995 # doviewmenu $viewhlmenu 1 [list addvhighlight $n] \
3996 # entryconf [list -label $viewname($n) -value $viewname($n)]
Paul Mackerrasd16c0812006-04-25 21:21:10 +10003997 }
Yann Dirson2d480852008-02-21 21:23:31 +01003998 if {$files ne $viewfiles($n) || $newargs ne $viewargs($n) || \
Alexander Gavrilov218a9002008-11-02 21:59:48 +03003999 $newviewopts($n,cmd) ne $viewargscmd($n)} {
Paul Mackerrasd16c0812006-04-25 21:21:10 +10004000 set viewfiles($n) $files
Paul Mackerras098dd8a2006-05-03 09:32:53 +10004001 set viewargs($n) $newargs
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004002 set viewargscmd($n) $newviewopts($n,cmd)
Paul Mackerrasd16c0812006-04-25 21:21:10 +10004003 if {$curview == $n} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004004 run reloadcommits
Paul Mackerrasd16c0812006-04-25 21:21:10 +10004005 }
4006 }
4007 }
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004008 if {$apply} return
Paul Mackerrasd16c0812006-04-25 21:21:10 +10004009 catch {destroy $top}
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004010}
4011
4012proc delview {} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004013 global curview viewperm hlview selectedhlview
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004014
4015 if {$curview == 0} return
Paul Mackerras908c3582006-05-20 09:38:11 +10004016 if {[info exists hlview] && $hlview == $curview} {
Christian Stimmingb007ee22007-11-07 18:44:35 +01004017 set selectedhlview [mc "None"]
Paul Mackerras908c3582006-05-20 09:38:11 +10004018 unset hlview
4019 }
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004020 allviewmenus $curview delete
Paul Mackerrasa90a6d22006-04-25 17:12:46 +10004021 set viewperm($curview) 0
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004022 showview 0
4023}
4024
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004025proc addviewmenu {n} {
Paul Mackerras908c3582006-05-20 09:38:11 +10004026 global viewname viewhlmenu
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004027
4028 .bar.view add radiobutton -label $viewname($n) \
4029 -command [list showview $n] -variable selectedview -value $n
Paul Mackerras687c8762007-09-22 12:49:33 +10004030 #$viewhlmenu add radiobutton -label $viewname($n) \
4031 # -command [list addvhighlight $n] -variable selectedhlview
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004032}
4033
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004034proc showview {n} {
Paul Mackerras3ed31a82008-04-26 16:00:00 +10004035 global curview cached_commitrow ordertok
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10004036 global displayorder parentlist rowidlist rowisopt rowfinal
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004037 global colormap rowtextx nextcolor canvxmax
4038 global numcommits viewcomplete
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004039 global selectedline currentid canv canvy0
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004040 global treediffs
Paul Mackerras3e766082008-01-13 17:26:30 +11004041 global pending_select mainheadid
Paul Mackerras03800812007-08-29 21:45:21 +10004042 global commitidx
Paul Mackerras3e766082008-01-13 17:26:30 +11004043 global selectedview
Paul Mackerras97645682007-08-23 22:24:38 +10004044 global hlview selectedhlview commitinterest
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004045
4046 if {$n == $curview} return
4047 set selid {}
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004048 set ymax [lindex [$canv cget -scrollregion] 3]
4049 set span [$canv yview]
4050 set ytop [expr {[lindex $span 0] * $ymax}]
4051 set ybot [expr {[lindex $span 1] * $ymax}]
4052 set yscreen [expr {($ybot - $ytop) / 2}]
Paul Mackerras94b4a692008-05-20 20:51:06 +10004053 if {$selectedline ne {}} {
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004054 set selid $currentid
4055 set y [yc $selectedline]
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004056 if {$ytop < $y && $y < $ybot} {
4057 set yscreen [expr {$y - $ytop}]
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004058 }
Paul Mackerrase507fd42007-06-16 21:51:08 +10004059 } elseif {[info exists pending_select]} {
4060 set selid $pending_select
4061 unset pending_select
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004062 }
4063 unselectline
Paul Mackerrasfdedbcf2006-04-06 21:22:52 +10004064 normalline
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004065 catch {unset treediffs}
4066 clear_display
Paul Mackerras908c3582006-05-20 09:38:11 +10004067 if {[info exists hlview] && $hlview == $n} {
4068 unset hlview
Christian Stimmingb007ee22007-11-07 18:44:35 +01004069 set selectedhlview [mc "None"]
Paul Mackerras908c3582006-05-20 09:38:11 +10004070 }
Paul Mackerras97645682007-08-23 22:24:38 +10004071 catch {unset commitinterest}
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004072 catch {unset cached_commitrow}
Paul Mackerras9257d8f2007-12-11 10:45:38 +11004073 catch {unset ordertok}
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004074
4075 set curview $n
Paul Mackerrasa90a6d22006-04-25 17:12:46 +10004076 set selectedview $n
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11004077 .bar.view entryconf [mca "Edit view..."] -state [expr {$n == 0? "disabled": "normal"}]
4078 .bar.view entryconf [mca "Delete view"] -state [expr {$n == 0? "disabled": "normal"}]
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004079
Paul Mackerrasdf904492007-08-29 22:03:07 +10004080 run refill_reflist
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004081 if {![info exists viewcomplete($n)]} {
Alexander Gavrilov567c34e2008-07-26 20:13:45 +04004082 getcommits $selid
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004083 return
4084 }
4085
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004086 set displayorder {}
4087 set parentlist {}
4088 set rowidlist {}
4089 set rowisopt {}
4090 set rowfinal {}
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10004091 set numcommits $commitidx($n)
Paul Mackerras22626ef2006-04-17 09:56:02 +10004092
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004093 catch {unset colormap}
4094 catch {unset rowtextx}
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004095 set nextcolor 0
4096 set canvxmax [$canv cget -width]
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004097 set curview $n
4098 set row 0
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004099 setcanvscroll
4100 set yf 0
Paul Mackerrase507fd42007-06-16 21:51:08 +10004101 set row {}
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004102 if {$selid ne {} && [commitinview $selid $n]} {
4103 set row [rowofcommit $selid]
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004104 # try to get the selected row in the same position on the screen
4105 set ymax [lindex [$canv cget -scrollregion] 3]
4106 set ytop [expr {[yc $row] - $yscreen}]
4107 if {$ytop < 0} {
4108 set ytop 0
4109 }
4110 set yf [expr {$ytop * 1.0 / $ymax}]
4111 }
4112 allcanvs yview moveto $yf
4113 drawvisible
Paul Mackerrase507fd42007-06-16 21:51:08 +10004114 if {$row ne {}} {
4115 selectline $row 0
Paul Mackerras3e766082008-01-13 17:26:30 +11004116 } elseif {!$viewcomplete($n)} {
Alexander Gavrilov567c34e2008-07-26 20:13:45 +04004117 reset_pending_select $selid
Paul Mackerrase507fd42007-06-16 21:51:08 +10004118 } else {
Alexander Gavrilov835e62a2008-07-26 20:15:54 +04004119 reset_pending_select {}
4120
4121 if {[commitinview $pending_select $curview]} {
4122 selectline [rowofcommit $pending_select] 1
4123 } else {
4124 set row [first_real_row]
4125 if {$row < $numcommits} {
4126 selectline $row 0
4127 }
Paul Mackerrase507fd42007-06-16 21:51:08 +10004128 }
4129 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004130 if {!$viewcomplete($n)} {
4131 if {$numcommits == 0} {
Christian Stimmingd990ced2007-11-07 18:42:55 +01004132 show_status [mc "Reading commits..."]
Paul Mackerrasd16c0812006-04-25 21:21:10 +10004133 }
Paul Mackerras098dd8a2006-05-03 09:32:53 +10004134 } elseif {$numcommits == 0} {
Christian Stimmingd990ced2007-11-07 18:42:55 +01004135 show_status [mc "No commits selected"]
Paul Mackerras2516dae2006-04-21 10:35:31 +10004136 }
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004137}
4138
Paul Mackerras908c3582006-05-20 09:38:11 +10004139# Stuff relating to the highlighting facility
4140
Paul Mackerras476ca632008-01-07 22:16:31 +11004141proc ishighlighted {id} {
Paul Mackerras164ff272006-05-29 19:50:02 +10004142 global vhighlights fhighlights nhighlights rhighlights
Paul Mackerras908c3582006-05-20 09:38:11 +10004143
Paul Mackerras476ca632008-01-07 22:16:31 +11004144 if {[info exists nhighlights($id)] && $nhighlights($id) > 0} {
4145 return $nhighlights($id)
Paul Mackerras908c3582006-05-20 09:38:11 +10004146 }
Paul Mackerras476ca632008-01-07 22:16:31 +11004147 if {[info exists vhighlights($id)] && $vhighlights($id) > 0} {
4148 return $vhighlights($id)
Paul Mackerras908c3582006-05-20 09:38:11 +10004149 }
Paul Mackerras476ca632008-01-07 22:16:31 +11004150 if {[info exists fhighlights($id)] && $fhighlights($id) > 0} {
4151 return $fhighlights($id)
Paul Mackerras908c3582006-05-20 09:38:11 +10004152 }
Paul Mackerras476ca632008-01-07 22:16:31 +11004153 if {[info exists rhighlights($id)] && $rhighlights($id) > 0} {
4154 return $rhighlights($id)
Paul Mackerras164ff272006-05-29 19:50:02 +10004155 }
Paul Mackerras908c3582006-05-20 09:38:11 +10004156 return 0
4157}
4158
Paul Mackerras28593d32008-11-13 23:01:46 +11004159proc bolden {id font} {
Paul Mackerrasb9fdba72009-04-09 09:34:46 +10004160 global canv linehtag currentid boldids need_redisplay markedid
Paul Mackerras908c3582006-05-20 09:38:11 +10004161
Paul Mackerrasd98d50e2008-11-13 22:39:00 +11004162 # need_redisplay = 1 means the display is stale and about to be redrawn
4163 if {$need_redisplay} return
Paul Mackerras28593d32008-11-13 23:01:46 +11004164 lappend boldids $id
4165 $canv itemconf $linehtag($id) -font $font
4166 if {[info exists currentid] && $id eq $currentid} {
Paul Mackerras908c3582006-05-20 09:38:11 +10004167 $canv delete secsel
Paul Mackerras28593d32008-11-13 23:01:46 +11004168 set t [eval $canv create rect [$canv bbox $linehtag($id)] \
Paul Mackerras908c3582006-05-20 09:38:11 +10004169 -outline {{}} -tags secsel \
4170 -fill [$canv cget -selectbackground]]
4171 $canv lower $t
4172 }
Paul Mackerrasb9fdba72009-04-09 09:34:46 +10004173 if {[info exists markedid] && $id eq $markedid} {
4174 make_idmark $id
4175 }
Paul Mackerras908c3582006-05-20 09:38:11 +10004176}
4177
Paul Mackerras28593d32008-11-13 23:01:46 +11004178proc bolden_name {id font} {
4179 global canv2 linentag currentid boldnameids need_redisplay
Paul Mackerras908c3582006-05-20 09:38:11 +10004180
Paul Mackerrasd98d50e2008-11-13 22:39:00 +11004181 if {$need_redisplay} return
Paul Mackerras28593d32008-11-13 23:01:46 +11004182 lappend boldnameids $id
4183 $canv2 itemconf $linentag($id) -font $font
4184 if {[info exists currentid] && $id eq $currentid} {
Paul Mackerras908c3582006-05-20 09:38:11 +10004185 $canv2 delete secsel
Paul Mackerras28593d32008-11-13 23:01:46 +11004186 set t [eval $canv2 create rect [$canv2 bbox $linentag($id)] \
Paul Mackerras908c3582006-05-20 09:38:11 +10004187 -outline {{}} -tags secsel \
4188 -fill [$canv2 cget -selectbackground]]
4189 $canv2 lower $t
4190 }
4191}
4192
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004193proc unbolden {} {
Paul Mackerras28593d32008-11-13 23:01:46 +11004194 global boldids
Paul Mackerras908c3582006-05-20 09:38:11 +10004195
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004196 set stillbold {}
Paul Mackerras28593d32008-11-13 23:01:46 +11004197 foreach id $boldids {
4198 if {![ishighlighted $id]} {
4199 bolden $id mainfont
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004200 } else {
Paul Mackerras28593d32008-11-13 23:01:46 +11004201 lappend stillbold $id
Paul Mackerras908c3582006-05-20 09:38:11 +10004202 }
4203 }
Paul Mackerras28593d32008-11-13 23:01:46 +11004204 set boldids $stillbold
Paul Mackerras908c3582006-05-20 09:38:11 +10004205}
4206
4207proc addvhighlight {n} {
Paul Mackerras476ca632008-01-07 22:16:31 +11004208 global hlview viewcomplete curview vhl_done commitidx
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004209
4210 if {[info exists hlview]} {
Paul Mackerras908c3582006-05-20 09:38:11 +10004211 delvhighlight
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004212 }
4213 set hlview $n
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004214 if {$n != $curview && ![info exists viewcomplete($n)]} {
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004215 start_rev_list $n
Paul Mackerras908c3582006-05-20 09:38:11 +10004216 }
4217 set vhl_done $commitidx($hlview)
4218 if {$vhl_done > 0} {
4219 drawvisible
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004220 }
4221}
4222
Paul Mackerras908c3582006-05-20 09:38:11 +10004223proc delvhighlight {} {
4224 global hlview vhighlights
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004225
4226 if {![info exists hlview]} return
4227 unset hlview
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004228 catch {unset vhighlights}
4229 unbolden
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004230}
4231
Paul Mackerras908c3582006-05-20 09:38:11 +10004232proc vhighlightmore {} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004233 global hlview vhl_done commitidx vhighlights curview
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004234
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004235 set max $commitidx($hlview)
Paul Mackerras908c3582006-05-20 09:38:11 +10004236 set vr [visiblerows]
4237 set r0 [lindex $vr 0]
4238 set r1 [lindex $vr 1]
4239 for {set i $vhl_done} {$i < $max} {incr i} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004240 set id [commitonrow $i $hlview]
4241 if {[commitinview $id $curview]} {
4242 set row [rowofcommit $id]
Paul Mackerras908c3582006-05-20 09:38:11 +10004243 if {$r0 <= $row && $row <= $r1} {
4244 if {![highlighted $row]} {
Paul Mackerras28593d32008-11-13 23:01:46 +11004245 bolden $id mainfontbold
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004246 }
Paul Mackerras476ca632008-01-07 22:16:31 +11004247 set vhighlights($id) 1
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004248 }
4249 }
4250 }
Paul Mackerras908c3582006-05-20 09:38:11 +10004251 set vhl_done $max
Paul Mackerrasac1276a2008-03-03 10:11:08 +11004252 return 0
Paul Mackerras908c3582006-05-20 09:38:11 +10004253}
4254
4255proc askvhighlight {row id} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004256 global hlview vhighlights iddrawn
Paul Mackerras908c3582006-05-20 09:38:11 +10004257
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004258 if {[commitinview $id $hlview]} {
Paul Mackerras476ca632008-01-07 22:16:31 +11004259 if {[info exists iddrawn($id)] && ![ishighlighted $id]} {
Paul Mackerras28593d32008-11-13 23:01:46 +11004260 bolden $id mainfontbold
Paul Mackerras908c3582006-05-20 09:38:11 +10004261 }
Paul Mackerras476ca632008-01-07 22:16:31 +11004262 set vhighlights($id) 1
Paul Mackerras908c3582006-05-20 09:38:11 +10004263 } else {
Paul Mackerras476ca632008-01-07 22:16:31 +11004264 set vhighlights($id) 0
Paul Mackerras908c3582006-05-20 09:38:11 +10004265 }
4266}
4267
Paul Mackerras687c8762007-09-22 12:49:33 +10004268proc hfiles_change {} {
Paul Mackerras908c3582006-05-20 09:38:11 +10004269 global highlight_files filehighlight fhighlights fh_serial
Paul Mackerras8b39e042008-12-02 09:02:46 +11004270 global highlight_paths
Paul Mackerras908c3582006-05-20 09:38:11 +10004271
4272 if {[info exists filehighlight]} {
4273 # delete previous highlights
4274 catch {close $filehighlight}
4275 unset filehighlight
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004276 catch {unset fhighlights}
4277 unbolden
Paul Mackerras63b79192006-05-20 21:31:52 +10004278 unhighlight_filelist
Paul Mackerras908c3582006-05-20 09:38:11 +10004279 }
Paul Mackerras63b79192006-05-20 21:31:52 +10004280 set highlight_paths {}
Paul Mackerras908c3582006-05-20 09:38:11 +10004281 after cancel do_file_hl $fh_serial
4282 incr fh_serial
4283 if {$highlight_files ne {}} {
4284 after 300 do_file_hl $fh_serial
4285 }
4286}
4287
Paul Mackerras687c8762007-09-22 12:49:33 +10004288proc gdttype_change {name ix op} {
4289 global gdttype highlight_files findstring findpattern
4290
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10004291 stopfinding
Paul Mackerras687c8762007-09-22 12:49:33 +10004292 if {$findstring ne {}} {
Christian Stimmingb007ee22007-11-07 18:44:35 +01004293 if {$gdttype eq [mc "containing:"]} {
Paul Mackerras687c8762007-09-22 12:49:33 +10004294 if {$highlight_files ne {}} {
4295 set highlight_files {}
4296 hfiles_change
4297 }
4298 findcom_change
4299 } else {
4300 if {$findpattern ne {}} {
4301 set findpattern {}
4302 findcom_change
4303 }
4304 set highlight_files $findstring
4305 hfiles_change
4306 }
4307 drawvisible
4308 }
4309 # enable/disable findtype/findloc menus too
4310}
4311
4312proc find_change {name ix op} {
4313 global gdttype findstring highlight_files
4314
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10004315 stopfinding
Christian Stimmingb007ee22007-11-07 18:44:35 +01004316 if {$gdttype eq [mc "containing:"]} {
Paul Mackerras687c8762007-09-22 12:49:33 +10004317 findcom_change
4318 } else {
4319 if {$highlight_files ne $findstring} {
4320 set highlight_files $findstring
4321 hfiles_change
4322 }
4323 }
4324 drawvisible
4325}
4326
Paul Mackerras64b5f142007-10-04 22:19:24 +10004327proc findcom_change args {
Paul Mackerras28593d32008-11-13 23:01:46 +11004328 global nhighlights boldnameids
Paul Mackerras687c8762007-09-22 12:49:33 +10004329 global findpattern findtype findstring gdttype
4330
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10004331 stopfinding
Paul Mackerras687c8762007-09-22 12:49:33 +10004332 # delete previous highlights, if any
Paul Mackerras28593d32008-11-13 23:01:46 +11004333 foreach id $boldnameids {
4334 bolden_name $id mainfont
Paul Mackerras687c8762007-09-22 12:49:33 +10004335 }
Paul Mackerras28593d32008-11-13 23:01:46 +11004336 set boldnameids {}
Paul Mackerras687c8762007-09-22 12:49:33 +10004337 catch {unset nhighlights}
4338 unbolden
4339 unmarkmatches
Christian Stimmingb007ee22007-11-07 18:44:35 +01004340 if {$gdttype ne [mc "containing:"] || $findstring eq {}} {
Paul Mackerras687c8762007-09-22 12:49:33 +10004341 set findpattern {}
Christian Stimmingb007ee22007-11-07 18:44:35 +01004342 } elseif {$findtype eq [mc "Regexp"]} {
Paul Mackerras687c8762007-09-22 12:49:33 +10004343 set findpattern $findstring
4344 } else {
4345 set e [string map {"*" "\\*" "?" "\\?" "\[" "\\\[" "\\" "\\\\"} \
4346 $findstring]
4347 set findpattern "*$e*"
4348 }
4349}
4350
Paul Mackerras63b79192006-05-20 21:31:52 +10004351proc makepatterns {l} {
4352 set ret {}
4353 foreach e $l {
4354 set ee [string map {"*" "\\*" "?" "\\?" "\[" "\\\[" "\\" "\\\\"} $e]
4355 if {[string index $ee end] eq "/"} {
4356 lappend ret "$ee*"
4357 } else {
4358 lappend ret $ee
4359 lappend ret "$ee/*"
4360 }
4361 }
4362 return $ret
4363}
4364
Paul Mackerras908c3582006-05-20 09:38:11 +10004365proc do_file_hl {serial} {
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004366 global highlight_files filehighlight highlight_paths gdttype fhl_list
Paul Mackerras908c3582006-05-20 09:38:11 +10004367
Christian Stimmingb007ee22007-11-07 18:44:35 +01004368 if {$gdttype eq [mc "touching paths:"]} {
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10004369 if {[catch {set paths [shellsplit $highlight_files]}]} return
4370 set highlight_paths [makepatterns $paths]
4371 highlight_filelist
4372 set gdtargs [concat -- $paths]
Christian Stimmingb007ee22007-11-07 18:44:35 +01004373 } elseif {$gdttype eq [mc "adding/removing string:"]} {
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10004374 set gdtargs [list "-S$highlight_files"]
Paul Mackerras687c8762007-09-22 12:49:33 +10004375 } else {
4376 # must be "containing:", i.e. we're searching commit info
4377 return
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10004378 }
Brandon Casey1ce09dd2007-03-19 18:00:37 -05004379 set cmd [concat | git diff-tree -r -s --stdin $gdtargs]
Paul Mackerras908c3582006-05-20 09:38:11 +10004380 set filehighlight [open $cmd r+]
4381 fconfigure $filehighlight -blocking 0
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004382 filerun $filehighlight readfhighlight
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004383 set fhl_list {}
Paul Mackerras908c3582006-05-20 09:38:11 +10004384 drawvisible
4385 flushhighlights
4386}
4387
4388proc flushhighlights {} {
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004389 global filehighlight fhl_list
Paul Mackerras908c3582006-05-20 09:38:11 +10004390
4391 if {[info exists filehighlight]} {
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004392 lappend fhl_list {}
Paul Mackerras908c3582006-05-20 09:38:11 +10004393 puts $filehighlight ""
4394 flush $filehighlight
4395 }
4396}
4397
4398proc askfilehighlight {row id} {
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004399 global filehighlight fhighlights fhl_list
Paul Mackerras908c3582006-05-20 09:38:11 +10004400
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004401 lappend fhl_list $id
Paul Mackerras476ca632008-01-07 22:16:31 +11004402 set fhighlights($id) -1
Paul Mackerras908c3582006-05-20 09:38:11 +10004403 puts $filehighlight $id
4404}
4405
4406proc readfhighlight {} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004407 global filehighlight fhighlights curview iddrawn
Paul Mackerras687c8762007-09-22 12:49:33 +10004408 global fhl_list find_dirn
Paul Mackerras908c3582006-05-20 09:38:11 +10004409
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004410 if {![info exists filehighlight]} {
4411 return 0
4412 }
4413 set nr 0
4414 while {[incr nr] <= 100 && [gets $filehighlight line] >= 0} {
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004415 set line [string trim $line]
4416 set i [lsearch -exact $fhl_list $line]
4417 if {$i < 0} continue
4418 for {set j 0} {$j < $i} {incr j} {
4419 set id [lindex $fhl_list $j]
Paul Mackerras476ca632008-01-07 22:16:31 +11004420 set fhighlights($id) 0
Paul Mackerras908c3582006-05-20 09:38:11 +10004421 }
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004422 set fhl_list [lrange $fhl_list [expr {$i+1}] end]
4423 if {$line eq {}} continue
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004424 if {![commitinview $line $curview]} continue
Paul Mackerras476ca632008-01-07 22:16:31 +11004425 if {[info exists iddrawn($line)] && ![ishighlighted $line]} {
Paul Mackerras28593d32008-11-13 23:01:46 +11004426 bolden $line mainfontbold
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004427 }
Paul Mackerras476ca632008-01-07 22:16:31 +11004428 set fhighlights($line) 1
Paul Mackerras908c3582006-05-20 09:38:11 +10004429 }
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004430 if {[eof $filehighlight]} {
4431 # strange...
Brandon Casey1ce09dd2007-03-19 18:00:37 -05004432 puts "oops, git diff-tree died"
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004433 catch {close $filehighlight}
4434 unset filehighlight
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004435 return 0
Paul Mackerras908c3582006-05-20 09:38:11 +10004436 }
Paul Mackerras687c8762007-09-22 12:49:33 +10004437 if {[info exists find_dirn]} {
Paul Mackerrascca5d942007-10-27 21:16:56 +10004438 run findmore
Paul Mackerras687c8762007-09-22 12:49:33 +10004439 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004440 return 1
Paul Mackerras908c3582006-05-20 09:38:11 +10004441}
4442
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004443proc doesmatch {f} {
Paul Mackerras687c8762007-09-22 12:49:33 +10004444 global findtype findpattern
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004445
Christian Stimmingb007ee22007-11-07 18:44:35 +01004446 if {$findtype eq [mc "Regexp"]} {
Paul Mackerras687c8762007-09-22 12:49:33 +10004447 return [regexp $findpattern $f]
Christian Stimmingb007ee22007-11-07 18:44:35 +01004448 } elseif {$findtype eq [mc "IgnCase"]} {
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004449 return [string match -nocase $findpattern $f]
4450 } else {
4451 return [string match $findpattern $f]
4452 }
4453}
4454
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10004455proc askfindhighlight {row id} {
Paul Mackerras9c311b32007-10-04 22:27:13 +10004456 global nhighlights commitinfo iddrawn
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004457 global findloc
4458 global markingmatches
Paul Mackerras908c3582006-05-20 09:38:11 +10004459
4460 if {![info exists commitinfo($id)]} {
4461 getcommit $id
4462 }
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10004463 set info $commitinfo($id)
Paul Mackerras908c3582006-05-20 09:38:11 +10004464 set isbold 0
Christian Stimmingb007ee22007-11-07 18:44:35 +01004465 set fldtypes [list [mc Headline] [mc Author] [mc Date] [mc Committer] [mc CDate] [mc Comments]]
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10004466 foreach f $info ty $fldtypes {
Christian Stimmingb007ee22007-11-07 18:44:35 +01004467 if {($findloc eq [mc "All fields"] || $findloc eq $ty) &&
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004468 [doesmatch $f]} {
Christian Stimmingb007ee22007-11-07 18:44:35 +01004469 if {$ty eq [mc "Author"]} {
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10004470 set isbold 2
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004471 break
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10004472 }
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004473 set isbold 1
Paul Mackerras908c3582006-05-20 09:38:11 +10004474 }
4475 }
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004476 if {$isbold && [info exists iddrawn($id)]} {
Paul Mackerras476ca632008-01-07 22:16:31 +11004477 if {![ishighlighted $id]} {
Paul Mackerras28593d32008-11-13 23:01:46 +11004478 bolden $id mainfontbold
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004479 if {$isbold > 1} {
Paul Mackerras28593d32008-11-13 23:01:46 +11004480 bolden_name $id mainfontbold
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004481 }
Paul Mackerras908c3582006-05-20 09:38:11 +10004482 }
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004483 if {$markingmatches} {
Paul Mackerras005a2f42007-07-26 22:36:39 +10004484 markrowmatches $row $id
Paul Mackerras908c3582006-05-20 09:38:11 +10004485 }
4486 }
Paul Mackerras476ca632008-01-07 22:16:31 +11004487 set nhighlights($id) $isbold
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004488}
4489
Paul Mackerras005a2f42007-07-26 22:36:39 +10004490proc markrowmatches {row id} {
4491 global canv canv2 linehtag linentag commitinfo findloc
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004492
Paul Mackerras005a2f42007-07-26 22:36:39 +10004493 set headline [lindex $commitinfo($id) 0]
4494 set author [lindex $commitinfo($id) 1]
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004495 $canv delete match$row
4496 $canv2 delete match$row
Christian Stimmingb007ee22007-11-07 18:44:35 +01004497 if {$findloc eq [mc "All fields"] || $findloc eq [mc "Headline"]} {
Paul Mackerras005a2f42007-07-26 22:36:39 +10004498 set m [findmatches $headline]
4499 if {$m ne {}} {
Paul Mackerras28593d32008-11-13 23:01:46 +11004500 markmatches $canv $row $headline $linehtag($id) $m \
4501 [$canv itemcget $linehtag($id) -font] $row
Paul Mackerras005a2f42007-07-26 22:36:39 +10004502 }
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004503 }
Christian Stimmingb007ee22007-11-07 18:44:35 +01004504 if {$findloc eq [mc "All fields"] || $findloc eq [mc "Author"]} {
Paul Mackerras005a2f42007-07-26 22:36:39 +10004505 set m [findmatches $author]
4506 if {$m ne {}} {
Paul Mackerras28593d32008-11-13 23:01:46 +11004507 markmatches $canv2 $row $author $linentag($id) $m \
4508 [$canv2 itemcget $linentag($id) -font] $row
Paul Mackerras005a2f42007-07-26 22:36:39 +10004509 }
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004510 }
4511}
4512
Paul Mackerras164ff272006-05-29 19:50:02 +10004513proc vrel_change {name ix op} {
4514 global highlight_related
4515
4516 rhighlight_none
Christian Stimmingb007ee22007-11-07 18:44:35 +01004517 if {$highlight_related ne [mc "None"]} {
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004518 run drawvisible
Paul Mackerras164ff272006-05-29 19:50:02 +10004519 }
4520}
4521
4522# prepare for testing whether commits are descendents or ancestors of a
4523proc rhighlight_sel {a} {
4524 global descendent desc_todo ancestor anc_todo
Paul Mackerras476ca632008-01-07 22:16:31 +11004525 global highlight_related
Paul Mackerras164ff272006-05-29 19:50:02 +10004526
4527 catch {unset descendent}
4528 set desc_todo [list $a]
4529 catch {unset ancestor}
4530 set anc_todo [list $a]
Christian Stimmingb007ee22007-11-07 18:44:35 +01004531 if {$highlight_related ne [mc "None"]} {
Paul Mackerras164ff272006-05-29 19:50:02 +10004532 rhighlight_none
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004533 run drawvisible
Paul Mackerras164ff272006-05-29 19:50:02 +10004534 }
4535}
4536
4537proc rhighlight_none {} {
4538 global rhighlights
4539
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004540 catch {unset rhighlights}
4541 unbolden
Paul Mackerras164ff272006-05-29 19:50:02 +10004542}
4543
4544proc is_descendent {a} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004545 global curview children descendent desc_todo
Paul Mackerras164ff272006-05-29 19:50:02 +10004546
4547 set v $curview
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004548 set la [rowofcommit $a]
Paul Mackerras164ff272006-05-29 19:50:02 +10004549 set todo $desc_todo
4550 set leftover {}
4551 set done 0
4552 for {set i 0} {$i < [llength $todo]} {incr i} {
4553 set do [lindex $todo $i]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004554 if {[rowofcommit $do] < $la} {
Paul Mackerras164ff272006-05-29 19:50:02 +10004555 lappend leftover $do
4556 continue
4557 }
4558 foreach nk $children($v,$do) {
4559 if {![info exists descendent($nk)]} {
4560 set descendent($nk) 1
4561 lappend todo $nk
4562 if {$nk eq $a} {
4563 set done 1
4564 }
4565 }
4566 }
4567 if {$done} {
4568 set desc_todo [concat $leftover [lrange $todo [expr {$i+1}] end]]
4569 return
4570 }
4571 }
4572 set descendent($a) 0
4573 set desc_todo $leftover
4574}
4575
4576proc is_ancestor {a} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004577 global curview parents ancestor anc_todo
Paul Mackerras164ff272006-05-29 19:50:02 +10004578
4579 set v $curview
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004580 set la [rowofcommit $a]
Paul Mackerras164ff272006-05-29 19:50:02 +10004581 set todo $anc_todo
4582 set leftover {}
4583 set done 0
4584 for {set i 0} {$i < [llength $todo]} {incr i} {
4585 set do [lindex $todo $i]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004586 if {![commitinview $do $v] || [rowofcommit $do] > $la} {
Paul Mackerras164ff272006-05-29 19:50:02 +10004587 lappend leftover $do
4588 continue
4589 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004590 foreach np $parents($v,$do) {
Paul Mackerras164ff272006-05-29 19:50:02 +10004591 if {![info exists ancestor($np)]} {
4592 set ancestor($np) 1
4593 lappend todo $np
4594 if {$np eq $a} {
4595 set done 1
4596 }
4597 }
4598 }
4599 if {$done} {
4600 set anc_todo [concat $leftover [lrange $todo [expr {$i+1}] end]]
4601 return
4602 }
4603 }
4604 set ancestor($a) 0
4605 set anc_todo $leftover
4606}
4607
4608proc askrelhighlight {row id} {
Paul Mackerras9c311b32007-10-04 22:27:13 +10004609 global descendent highlight_related iddrawn rhighlights
Paul Mackerras164ff272006-05-29 19:50:02 +10004610 global selectedline ancestor
4611
Paul Mackerras94b4a692008-05-20 20:51:06 +10004612 if {$selectedline eq {}} return
Paul Mackerras164ff272006-05-29 19:50:02 +10004613 set isbold 0
Christian Stimming55e34432008-01-09 22:23:18 +01004614 if {$highlight_related eq [mc "Descendant"] ||
4615 $highlight_related eq [mc "Not descendant"]} {
Paul Mackerras164ff272006-05-29 19:50:02 +10004616 if {![info exists descendent($id)]} {
4617 is_descendent $id
4618 }
Christian Stimming55e34432008-01-09 22:23:18 +01004619 if {$descendent($id) == ($highlight_related eq [mc "Descendant"])} {
Paul Mackerras164ff272006-05-29 19:50:02 +10004620 set isbold 1
4621 }
Christian Stimmingb007ee22007-11-07 18:44:35 +01004622 } elseif {$highlight_related eq [mc "Ancestor"] ||
4623 $highlight_related eq [mc "Not ancestor"]} {
Paul Mackerras164ff272006-05-29 19:50:02 +10004624 if {![info exists ancestor($id)]} {
4625 is_ancestor $id
4626 }
Christian Stimmingb007ee22007-11-07 18:44:35 +01004627 if {$ancestor($id) == ($highlight_related eq [mc "Ancestor"])} {
Paul Mackerras164ff272006-05-29 19:50:02 +10004628 set isbold 1
4629 }
4630 }
4631 if {[info exists iddrawn($id)]} {
Paul Mackerras476ca632008-01-07 22:16:31 +11004632 if {$isbold && ![ishighlighted $id]} {
Paul Mackerras28593d32008-11-13 23:01:46 +11004633 bolden $id mainfontbold
Paul Mackerras164ff272006-05-29 19:50:02 +10004634 }
4635 }
Paul Mackerras476ca632008-01-07 22:16:31 +11004636 set rhighlights($id) $isbold
Paul Mackerras164ff272006-05-29 19:50:02 +10004637}
4638
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004639# Graph layout functions
4640
Paul Mackerras9f1afe02006-02-19 22:44:47 +11004641proc shortids {ids} {
4642 set res {}
4643 foreach id $ids {
4644 if {[llength $id] > 1} {
4645 lappend res [shortids $id]
4646 } elseif {[regexp {^[0-9a-f]{40}$} $id]} {
4647 lappend res [string range $id 0 7]
4648 } else {
4649 lappend res $id
4650 }
4651 }
4652 return $res
4653}
4654
Paul Mackerras9f1afe02006-02-19 22:44:47 +11004655proc ntimes {n o} {
4656 set ret {}
Paul Mackerras03800812007-08-29 21:45:21 +10004657 set o [list $o]
4658 for {set mask 1} {$mask <= $n} {incr mask $mask} {
4659 if {($n & $mask) != 0} {
4660 set ret [concat $ret $o]
4661 }
4662 set o [concat $o $o]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11004663 }
4664 return $ret
4665}
4666
Paul Mackerras9257d8f2007-12-11 10:45:38 +11004667proc ordertoken {id} {
4668 global ordertok curview varcid varcstart varctok curview parents children
4669 global nullid nullid2
4670
4671 if {[info exists ordertok($id)]} {
4672 return $ordertok($id)
4673 }
4674 set origid $id
4675 set todo {}
4676 while {1} {
4677 if {[info exists varcid($curview,$id)]} {
4678 set a $varcid($curview,$id)
4679 set p [lindex $varcstart($curview) $a]
4680 } else {
4681 set p [lindex $children($curview,$id) 0]
4682 }
4683 if {[info exists ordertok($p)]} {
4684 set tok $ordertok($p)
4685 break
4686 }
Paul Mackerrasc8c9f3d2008-01-06 13:54:58 +11004687 set id [first_real_child $curview,$p]
4688 if {$id eq {}} {
Paul Mackerras9257d8f2007-12-11 10:45:38 +11004689 # it's a root
Paul Mackerras46308ea2008-01-15 22:16:32 +11004690 set tok [lindex $varctok($curview) $varcid($curview,$p)]
Paul Mackerras9257d8f2007-12-11 10:45:38 +11004691 break
4692 }
Paul Mackerras9257d8f2007-12-11 10:45:38 +11004693 if {[llength $parents($curview,$id)] == 1} {
4694 lappend todo [list $p {}]
4695 } else {
4696 set j [lsearch -exact $parents($curview,$id) $p]
4697 if {$j < 0} {
4698 puts "oops didn't find [shortids $p] in parents of [shortids $id]"
4699 }
4700 lappend todo [list $p [strrep $j]]
4701 }
4702 }
4703 for {set i [llength $todo]} {[incr i -1] >= 0} {} {
4704 set p [lindex $todo $i 0]
4705 append tok [lindex $todo $i 1]
4706 set ordertok($p) $tok
4707 }
4708 set ordertok($origid) $tok
4709 return $tok
4710}
4711
Paul Mackerras6e8c8702007-07-31 21:03:06 +10004712# Work out where id should go in idlist so that order-token
4713# values increase from left to right
4714proc idcol {idlist id {i 0}} {
Paul Mackerras9257d8f2007-12-11 10:45:38 +11004715 set t [ordertoken $id]
Paul Mackerrase5b37ac2007-12-12 18:13:51 +11004716 if {$i < 0} {
4717 set i 0
4718 }
Paul Mackerras9257d8f2007-12-11 10:45:38 +11004719 if {$i >= [llength $idlist] || $t < [ordertoken [lindex $idlist $i]]} {
Paul Mackerras6e8c8702007-07-31 21:03:06 +10004720 if {$i > [llength $idlist]} {
4721 set i [llength $idlist]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11004722 }
Paul Mackerras9257d8f2007-12-11 10:45:38 +11004723 while {[incr i -1] >= 0 && $t < [ordertoken [lindex $idlist $i]]} {}
Paul Mackerras6e8c8702007-07-31 21:03:06 +10004724 incr i
4725 } else {
Paul Mackerras9257d8f2007-12-11 10:45:38 +11004726 if {$t > [ordertoken [lindex $idlist $i]]} {
Paul Mackerras6e8c8702007-07-31 21:03:06 +10004727 while {[incr i] < [llength $idlist] &&
Paul Mackerras9257d8f2007-12-11 10:45:38 +11004728 $t >= [ordertoken [lindex $idlist $i]]} {}
Paul Mackerras9f1afe02006-02-19 22:44:47 +11004729 }
4730 }
Paul Mackerras6e8c8702007-07-31 21:03:06 +10004731 return $i
Paul Mackerras9f1afe02006-02-19 22:44:47 +11004732}
4733
4734proc initlayout {} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004735 global rowidlist rowisopt rowfinal displayorder parentlist
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004736 global numcommits canvxmax canv
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11004737 global nextcolor
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004738 global colormap rowtextx
Paul Mackerras9f1afe02006-02-19 22:44:47 +11004739
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11004740 set numcommits 0
4741 set displayorder {}
Paul Mackerras79b2c752006-04-02 20:47:40 +10004742 set parentlist {}
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11004743 set nextcolor 0
Paul Mackerras03800812007-08-29 21:45:21 +10004744 set rowidlist {}
4745 set rowisopt {}
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10004746 set rowfinal {}
Paul Mackerrasbe0cd092006-03-31 09:55:11 +11004747 set canvxmax [$canv cget -width]
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004748 catch {unset colormap}
4749 catch {unset rowtextx}
Paul Mackerrasac1276a2008-03-03 10:11:08 +11004750 setcanvscroll
Paul Mackerrasbe0cd092006-03-31 09:55:11 +11004751}
4752
4753proc setcanvscroll {} {
4754 global canv canv2 canv3 numcommits linespc canvxmax canvy0
Paul Mackerrasac1276a2008-03-03 10:11:08 +11004755 global lastscrollset lastscrollrows
Paul Mackerrasbe0cd092006-03-31 09:55:11 +11004756
4757 set ymax [expr {$canvy0 + ($numcommits - 0.5) * $linespc + 2}]
4758 $canv conf -scrollregion [list 0 0 $canvxmax $ymax]
4759 $canv2 conf -scrollregion [list 0 0 0 $ymax]
4760 $canv3 conf -scrollregion [list 0 0 0 $ymax]
Paul Mackerrasac1276a2008-03-03 10:11:08 +11004761 set lastscrollset [clock clicks -milliseconds]
4762 set lastscrollrows $numcommits
Paul Mackerras9f1afe02006-02-19 22:44:47 +11004763}
4764
4765proc visiblerows {} {
4766 global canv numcommits linespc
4767
4768 set ymax [lindex [$canv cget -scrollregion] 3]
4769 if {$ymax eq {} || $ymax == 0} return
4770 set f [$canv yview]
4771 set y0 [expr {int([lindex $f 0] * $ymax)}]
4772 set r0 [expr {int(($y0 - 3) / $linespc) - 1}]
4773 if {$r0 < 0} {
4774 set r0 0
4775 }
4776 set y1 [expr {int([lindex $f 1] * $ymax)}]
4777 set r1 [expr {int(($y1 - 3) / $linespc) + 1}]
4778 if {$r1 >= $numcommits} {
4779 set r1 [expr {$numcommits - 1}]
4780 }
4781 return [list $r0 $r1]
4782}
4783
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10004784proc layoutmore {} {
Paul Mackerras38dfe932007-12-06 20:50:31 +11004785 global commitidx viewcomplete curview
Paul Mackerras94b4a692008-05-20 20:51:06 +10004786 global numcommits pending_select curview
Paul Mackerrasd375ef92008-10-21 10:18:12 +11004787 global lastscrollset lastscrollrows
Paul Mackerras9f1afe02006-02-19 22:44:47 +11004788
Paul Mackerrasac1276a2008-03-03 10:11:08 +11004789 if {$lastscrollrows < 100 || $viewcomplete($curview) ||
4790 [clock clicks -milliseconds] - $lastscrollset > 500} {
Paul Mackerrasa2c22362006-10-31 15:00:53 +11004791 setcanvscroll
4792 }
Paul Mackerrasd94f8cd2006-04-06 10:18:23 +10004793 if {[info exists pending_select] &&
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004794 [commitinview $pending_select $curview]} {
Alexander Gavrilov567c34e2008-07-26 20:13:45 +04004795 update
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004796 selectline [rowofcommit $pending_select] 1
Paul Mackerrasd94f8cd2006-04-06 10:18:23 +10004797 }
Paul Mackerrasac1276a2008-03-03 10:11:08 +11004798 drawvisible
Paul Mackerras219ea3a2006-09-07 10:21:39 +10004799}
4800
Paul Mackerrascdc84292008-11-18 19:54:14 +11004801# With path limiting, we mightn't get the actual HEAD commit,
4802# so ask git rev-list what is the first ancestor of HEAD that
4803# touches a file in the path limit.
4804proc get_viewmainhead {view} {
4805 global viewmainheadid vfilelimit viewinstances mainheadid
Paul Mackerras219ea3a2006-09-07 10:21:39 +10004806
Paul Mackerrascdc84292008-11-18 19:54:14 +11004807 catch {
4808 set rfd [open [concat | git rev-list -1 $mainheadid \
4809 -- $vfilelimit($view)] r]
4810 set j [reg_instance $rfd]
4811 lappend viewinstances($view) $j
4812 fconfigure $rfd -blocking 0
4813 filerun $rfd [list getviewhead $rfd $j $view]
4814 set viewmainheadid($curview) {}
4815 }
4816}
4817
4818# git rev-list should give us just 1 line to use as viewmainheadid($view)
4819proc getviewhead {fd inst view} {
4820 global viewmainheadid commfd curview viewinstances showlocalchanges
4821
4822 set id {}
4823 if {[gets $fd line] < 0} {
4824 if {![eof $fd]} {
4825 return 1
4826 }
4827 } elseif {[string length $line] == 40 && [string is xdigit $line]} {
4828 set id $line
4829 }
4830 set viewmainheadid($view) $id
4831 close $fd
4832 unset commfd($inst)
4833 set i [lsearch -exact $viewinstances($view) $inst]
4834 if {$i >= 0} {
4835 set viewinstances($view) [lreplace $viewinstances($view) $i $i]
4836 }
4837 if {$showlocalchanges && $id ne {} && $view == $curview} {
4838 doshowlocalchanges
4839 }
4840 return 0
4841}
4842
4843proc doshowlocalchanges {} {
4844 global curview viewmainheadid
4845
4846 if {$viewmainheadid($curview) eq {}} return
4847 if {[commitinview $viewmainheadid($curview) $curview]} {
Paul Mackerras219ea3a2006-09-07 10:21:39 +10004848 dodiffindex
Paul Mackerras38dfe932007-12-06 20:50:31 +11004849 } else {
Paul Mackerrascdc84292008-11-18 19:54:14 +11004850 interestedin $viewmainheadid($curview) dodiffindex
Paul Mackerras219ea3a2006-09-07 10:21:39 +10004851 }
4852}
4853
4854proc dohidelocalchanges {} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004855 global nullid nullid2 lserial curview
Paul Mackerras219ea3a2006-09-07 10:21:39 +10004856
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004857 if {[commitinview $nullid $curview]} {
Paul Mackerrasb8a938c2008-02-13 22:12:31 +11004858 removefakerow $nullid
Paul Mackerras8f489362007-07-13 19:49:37 +10004859 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004860 if {[commitinview $nullid2 $curview]} {
Paul Mackerrasb8a938c2008-02-13 22:12:31 +11004861 removefakerow $nullid2
Paul Mackerras219ea3a2006-09-07 10:21:39 +10004862 }
4863 incr lserial
4864}
4865
Paul Mackerras8f489362007-07-13 19:49:37 +10004866# spawn off a process to do git diff-index --cached HEAD
Paul Mackerras219ea3a2006-09-07 10:21:39 +10004867proc dodiffindex {} {
Paul Mackerrascdc84292008-11-18 19:54:14 +11004868 global lserial showlocalchanges vfilelimit curview
David Aguilarcb8329a2008-03-10 03:54:56 -07004869 global isworktree
Paul Mackerras219ea3a2006-09-07 10:21:39 +10004870
David Aguilarcb8329a2008-03-10 03:54:56 -07004871 if {!$showlocalchanges || !$isworktree} return
Paul Mackerras219ea3a2006-09-07 10:21:39 +10004872 incr lserial
Paul Mackerrascdc84292008-11-18 19:54:14 +11004873 set cmd "|git diff-index --cached HEAD"
4874 if {$vfilelimit($curview) ne {}} {
4875 set cmd [concat $cmd -- $vfilelimit($curview)]
4876 }
4877 set fd [open $cmd r]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10004878 fconfigure $fd -blocking 0
Alexander Gavrilove439e092008-07-13 16:40:47 +04004879 set i [reg_instance $fd]
4880 filerun $fd [list readdiffindex $fd $lserial $i]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10004881}
4882
Alexander Gavrilove439e092008-07-13 16:40:47 +04004883proc readdiffindex {fd serial inst} {
Paul Mackerrascdc84292008-11-18 19:54:14 +11004884 global viewmainheadid nullid nullid2 curview commitinfo commitdata lserial
4885 global vfilelimit
Paul Mackerras219ea3a2006-09-07 10:21:39 +10004886
Paul Mackerras8f489362007-07-13 19:49:37 +10004887 set isdiff 1
Paul Mackerras219ea3a2006-09-07 10:21:39 +10004888 if {[gets $fd line] < 0} {
Paul Mackerras8f489362007-07-13 19:49:37 +10004889 if {![eof $fd]} {
4890 return 1
Paul Mackerras219ea3a2006-09-07 10:21:39 +10004891 }
Paul Mackerras8f489362007-07-13 19:49:37 +10004892 set isdiff 0
Paul Mackerras219ea3a2006-09-07 10:21:39 +10004893 }
4894 # we only need to see one line and we don't really care what it says...
Alexander Gavrilove439e092008-07-13 16:40:47 +04004895 stop_instance $inst
Paul Mackerras219ea3a2006-09-07 10:21:39 +10004896
Paul Mackerras24f7a662007-12-19 09:35:33 +11004897 if {$serial != $lserial} {
4898 return 0
Paul Mackerras8f489362007-07-13 19:49:37 +10004899 }
4900
Paul Mackerras24f7a662007-12-19 09:35:33 +11004901 # now see if there are any local changes not checked in to the index
Paul Mackerrascdc84292008-11-18 19:54:14 +11004902 set cmd "|git diff-files"
4903 if {$vfilelimit($curview) ne {}} {
4904 set cmd [concat $cmd -- $vfilelimit($curview)]
4905 }
4906 set fd [open $cmd r]
Paul Mackerras24f7a662007-12-19 09:35:33 +11004907 fconfigure $fd -blocking 0
Alexander Gavrilove439e092008-07-13 16:40:47 +04004908 set i [reg_instance $fd]
4909 filerun $fd [list readdifffiles $fd $serial $i]
Paul Mackerras24f7a662007-12-19 09:35:33 +11004910
4911 if {$isdiff && ![commitinview $nullid2 $curview]} {
Paul Mackerras8f489362007-07-13 19:49:37 +10004912 # add the line for the changes in the index to the graph
Christian Stimmingd990ced2007-11-07 18:42:55 +01004913 set hl [mc "Local changes checked in to index but not committed"]
Paul Mackerras8f489362007-07-13 19:49:37 +10004914 set commitinfo($nullid2) [list $hl {} {} {} {} " $hl\n"]
4915 set commitdata($nullid2) "\n $hl\n"
Paul Mackerrasfc2a2562007-12-26 23:03:43 +11004916 if {[commitinview $nullid $curview]} {
Paul Mackerrasb8a938c2008-02-13 22:12:31 +11004917 removefakerow $nullid
Paul Mackerrasfc2a2562007-12-26 23:03:43 +11004918 }
Paul Mackerrascdc84292008-11-18 19:54:14 +11004919 insertfakerow $nullid2 $viewmainheadid($curview)
Paul Mackerras24f7a662007-12-19 09:35:33 +11004920 } elseif {!$isdiff && [commitinview $nullid2 $curview]} {
Paul Mackerrascdc84292008-11-18 19:54:14 +11004921 if {[commitinview $nullid $curview]} {
4922 removefakerow $nullid
4923 }
Paul Mackerrasb8a938c2008-02-13 22:12:31 +11004924 removefakerow $nullid2
Paul Mackerras8f489362007-07-13 19:49:37 +10004925 }
4926 return 0
4927}
4928
Alexander Gavrilove439e092008-07-13 16:40:47 +04004929proc readdifffiles {fd serial inst} {
Paul Mackerrascdc84292008-11-18 19:54:14 +11004930 global viewmainheadid nullid nullid2 curview
Paul Mackerras8f489362007-07-13 19:49:37 +10004931 global commitinfo commitdata lserial
4932
4933 set isdiff 1
4934 if {[gets $fd line] < 0} {
4935 if {![eof $fd]} {
4936 return 1
4937 }
4938 set isdiff 0
4939 }
4940 # we only need to see one line and we don't really care what it says...
Alexander Gavrilove439e092008-07-13 16:40:47 +04004941 stop_instance $inst
Paul Mackerras8f489362007-07-13 19:49:37 +10004942
Paul Mackerras24f7a662007-12-19 09:35:33 +11004943 if {$serial != $lserial} {
4944 return 0
4945 }
4946
4947 if {$isdiff && ![commitinview $nullid $curview]} {
Paul Mackerras219ea3a2006-09-07 10:21:39 +10004948 # add the line for the local diff to the graph
Christian Stimmingd990ced2007-11-07 18:42:55 +01004949 set hl [mc "Local uncommitted changes, not checked in to index"]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10004950 set commitinfo($nullid) [list $hl {} {} {} {} " $hl\n"]
4951 set commitdata($nullid) "\n $hl\n"
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004952 if {[commitinview $nullid2 $curview]} {
4953 set p $nullid2
4954 } else {
Paul Mackerrascdc84292008-11-18 19:54:14 +11004955 set p $viewmainheadid($curview)
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004956 }
Paul Mackerrasb8a938c2008-02-13 22:12:31 +11004957 insertfakerow $nullid $p
Paul Mackerras24f7a662007-12-19 09:35:33 +11004958 } elseif {!$isdiff && [commitinview $nullid $curview]} {
Paul Mackerrasb8a938c2008-02-13 22:12:31 +11004959 removefakerow $nullid
Paul Mackerras219ea3a2006-09-07 10:21:39 +10004960 }
4961 return 0
Paul Mackerras9f1afe02006-02-19 22:44:47 +11004962}
4963
Paul Mackerras8f0bc7e2007-08-24 22:16:42 +10004964proc nextuse {id row} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004965 global curview children
Paul Mackerras8f0bc7e2007-08-24 22:16:42 +10004966
4967 if {[info exists children($curview,$id)]} {
4968 foreach kid $children($curview,$id) {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004969 if {![commitinview $kid $curview]} {
Paul Mackerras03800812007-08-29 21:45:21 +10004970 return -1
4971 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004972 if {[rowofcommit $kid] > $row} {
4973 return [rowofcommit $kid]
Paul Mackerras8f0bc7e2007-08-24 22:16:42 +10004974 }
4975 }
4976 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004977 if {[commitinview $id $curview]} {
4978 return [rowofcommit $id]
Paul Mackerras8f0bc7e2007-08-24 22:16:42 +10004979 }
4980 return -1
4981}
4982
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10004983proc prevuse {id row} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004984 global curview children
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10004985
4986 set ret -1
4987 if {[info exists children($curview,$id)]} {
4988 foreach kid $children($curview,$id) {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004989 if {![commitinview $kid $curview]} break
4990 if {[rowofcommit $kid] < $row} {
4991 set ret [rowofcommit $kid]
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10004992 }
4993 }
4994 }
4995 return $ret
4996}
4997
Paul Mackerras03800812007-08-29 21:45:21 +10004998proc make_idlist {row} {
4999 global displayorder parentlist uparrowlen downarrowlen mingaplen
Paul Mackerras9257d8f2007-12-11 10:45:38 +11005000 global commitidx curview children
Paul Mackerras03800812007-08-29 21:45:21 +10005001
5002 set r [expr {$row - $mingaplen - $downarrowlen - 1}]
5003 if {$r < 0} {
5004 set r 0
5005 }
5006 set ra [expr {$row - $downarrowlen}]
5007 if {$ra < 0} {
5008 set ra 0
5009 }
5010 set rb [expr {$row + $uparrowlen}]
5011 if {$rb > $commitidx($curview)} {
5012 set rb $commitidx($curview)
5013 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005014 make_disporder $r [expr {$rb + 1}]
Paul Mackerras03800812007-08-29 21:45:21 +10005015 set ids {}
5016 for {} {$r < $ra} {incr r} {
5017 set nextid [lindex $displayorder [expr {$r + 1}]]
5018 foreach p [lindex $parentlist $r] {
5019 if {$p eq $nextid} continue
5020 set rn [nextuse $p $r]
5021 if {$rn >= $row &&
5022 $rn <= $r + $downarrowlen + $mingaplen + $uparrowlen} {
Paul Mackerras9257d8f2007-12-11 10:45:38 +11005023 lappend ids [list [ordertoken $p] $p]
Paul Mackerras03800812007-08-29 21:45:21 +10005024 }
5025 }
5026 }
5027 for {} {$r < $row} {incr r} {
5028 set nextid [lindex $displayorder [expr {$r + 1}]]
5029 foreach p [lindex $parentlist $r] {
5030 if {$p eq $nextid} continue
5031 set rn [nextuse $p $r]
5032 if {$rn < 0 || $rn >= $row} {
Paul Mackerras9257d8f2007-12-11 10:45:38 +11005033 lappend ids [list [ordertoken $p] $p]
Paul Mackerras03800812007-08-29 21:45:21 +10005034 }
5035 }
5036 }
5037 set id [lindex $displayorder $row]
Paul Mackerras9257d8f2007-12-11 10:45:38 +11005038 lappend ids [list [ordertoken $id] $id]
Paul Mackerras03800812007-08-29 21:45:21 +10005039 while {$r < $rb} {
5040 foreach p [lindex $parentlist $r] {
5041 set firstkid [lindex $children($curview,$p) 0]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005042 if {[rowofcommit $firstkid] < $row} {
Paul Mackerras9257d8f2007-12-11 10:45:38 +11005043 lappend ids [list [ordertoken $p] $p]
Paul Mackerras03800812007-08-29 21:45:21 +10005044 }
5045 }
5046 incr r
5047 set id [lindex $displayorder $r]
5048 if {$id ne {}} {
5049 set firstkid [lindex $children($curview,$id) 0]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005050 if {$firstkid ne {} && [rowofcommit $firstkid] < $row} {
Paul Mackerras9257d8f2007-12-11 10:45:38 +11005051 lappend ids [list [ordertoken $id] $id]
Paul Mackerras03800812007-08-29 21:45:21 +10005052 }
5053 }
5054 }
5055 set idlist {}
5056 foreach idx [lsort -unique $ids] {
5057 lappend idlist [lindex $idx 1]
5058 }
5059 return $idlist
5060}
5061
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10005062proc rowsequal {a b} {
5063 while {[set i [lsearch -exact $a {}]] >= 0} {
5064 set a [lreplace $a $i $i]
5065 }
5066 while {[set i [lsearch -exact $b {}]] >= 0} {
5067 set b [lreplace $b $i $i]
5068 }
5069 return [expr {$a eq $b}]
5070}
5071
5072proc makeupline {id row rend col} {
5073 global rowidlist uparrowlen downarrowlen mingaplen
5074
5075 for {set r $rend} {1} {set r $rstart} {
5076 set rstart [prevuse $id $r]
5077 if {$rstart < 0} return
5078 if {$rstart < $row} break
5079 }
5080 if {$rstart + $uparrowlen + $mingaplen + $downarrowlen < $rend} {
5081 set rstart [expr {$rend - $uparrowlen - 1}]
5082 }
5083 for {set r $rstart} {[incr r] <= $row} {} {
5084 set idlist [lindex $rowidlist $r]
5085 if {$idlist ne {} && [lsearch -exact $idlist $id] < 0} {
5086 set col [idcol $idlist $id $col]
5087 lset rowidlist $r [linsert $idlist $col $id]
5088 changedrow $r
5089 }
5090 }
5091}
5092
Paul Mackerras03800812007-08-29 21:45:21 +10005093proc layoutrows {row endrow} {
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10005094 global rowidlist rowisopt rowfinal displayorder
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005095 global uparrowlen downarrowlen maxwidth mingaplen
Paul Mackerras6a90bff2007-06-18 09:48:23 +10005096 global children parentlist
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005097 global commitidx viewcomplete curview
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005098
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005099 make_disporder [expr {$row - 1}] [expr {$endrow + $uparrowlen}]
Paul Mackerras03800812007-08-29 21:45:21 +10005100 set idlist {}
5101 if {$row > 0} {
Paul Mackerrasf56782a2007-09-15 09:04:11 +10005102 set rm1 [expr {$row - 1}]
5103 foreach id [lindex $rowidlist $rm1] {
Paul Mackerras03800812007-08-29 21:45:21 +10005104 if {$id ne {}} {
5105 lappend idlist $id
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005106 }
5107 }
Paul Mackerrasf56782a2007-09-15 09:04:11 +10005108 set final [lindex $rowfinal $rm1]
Paul Mackerras8f0bc7e2007-08-24 22:16:42 +10005109 }
Paul Mackerras03800812007-08-29 21:45:21 +10005110 for {} {$row < $endrow} {incr row} {
5111 set rm1 [expr {$row - 1}]
Paul Mackerrasf56782a2007-09-15 09:04:11 +10005112 if {$rm1 < 0 || $idlist eq {}} {
Paul Mackerras03800812007-08-29 21:45:21 +10005113 set idlist [make_idlist $row]
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10005114 set final 1
Paul Mackerras03800812007-08-29 21:45:21 +10005115 } else {
5116 set id [lindex $displayorder $rm1]
5117 set col [lsearch -exact $idlist $id]
5118 set idlist [lreplace $idlist $col $col]
5119 foreach p [lindex $parentlist $rm1] {
5120 if {[lsearch -exact $idlist $p] < 0} {
5121 set col [idcol $idlist $p $col]
5122 set idlist [linsert $idlist $col $p]
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10005123 # if not the first child, we have to insert a line going up
5124 if {$id ne [lindex $children($curview,$p) 0]} {
5125 makeupline $p $rm1 $row $col
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005126 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005127 }
5128 }
Paul Mackerras03800812007-08-29 21:45:21 +10005129 set id [lindex $displayorder $row]
5130 if {$row > $downarrowlen} {
5131 set termrow [expr {$row - $downarrowlen - 1}]
5132 foreach p [lindex $parentlist $termrow] {
5133 set i [lsearch -exact $idlist $p]
5134 if {$i < 0} continue
5135 set nr [nextuse $p $termrow]
5136 if {$nr < 0 || $nr >= $row + $mingaplen + $uparrowlen} {
5137 set idlist [lreplace $idlist $i $i]
5138 }
5139 }
5140 }
5141 set col [lsearch -exact $idlist $id]
5142 if {$col < 0} {
5143 set col [idcol $idlist $id]
5144 set idlist [linsert $idlist $col $id]
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10005145 if {$children($curview,$id) ne {}} {
5146 makeupline $id $rm1 $row $col
5147 }
Paul Mackerras03800812007-08-29 21:45:21 +10005148 }
5149 set r [expr {$row + $uparrowlen - 1}]
5150 if {$r < $commitidx($curview)} {
5151 set x $col
5152 foreach p [lindex $parentlist $r] {
5153 if {[lsearch -exact $idlist $p] >= 0} continue
5154 set fk [lindex $children($curview,$p) 0]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005155 if {[rowofcommit $fk] < $row} {
Paul Mackerras03800812007-08-29 21:45:21 +10005156 set x [idcol $idlist $p $x]
5157 set idlist [linsert $idlist $x $p]
5158 }
5159 }
5160 if {[incr r] < $commitidx($curview)} {
5161 set p [lindex $displayorder $r]
5162 if {[lsearch -exact $idlist $p] < 0} {
5163 set fk [lindex $children($curview,$p) 0]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005164 if {$fk ne {} && [rowofcommit $fk] < $row} {
Paul Mackerras03800812007-08-29 21:45:21 +10005165 set x [idcol $idlist $p $x]
5166 set idlist [linsert $idlist $x $p]
5167 }
5168 }
5169 }
Paul Mackerras7b459a12007-08-13 14:52:00 +10005170 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005171 }
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10005172 if {$final && !$viewcomplete($curview) &&
5173 $row + $uparrowlen + $mingaplen + $downarrowlen
5174 >= $commitidx($curview)} {
5175 set final 0
Paul Mackerras7b459a12007-08-13 14:52:00 +10005176 }
Paul Mackerras03800812007-08-29 21:45:21 +10005177 set l [llength $rowidlist]
5178 if {$row == $l} {
5179 lappend rowidlist $idlist
5180 lappend rowisopt 0
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10005181 lappend rowfinal $final
Paul Mackerras03800812007-08-29 21:45:21 +10005182 } elseif {$row < $l} {
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10005183 if {![rowsequal $idlist [lindex $rowidlist $row]]} {
Paul Mackerras03800812007-08-29 21:45:21 +10005184 lset rowidlist $row $idlist
5185 changedrow $row
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005186 }
Paul Mackerrasf56782a2007-09-15 09:04:11 +10005187 lset rowfinal $row $final
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005188 } else {
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10005189 set pad [ntimes [expr {$row - $l}] {}]
5190 set rowidlist [concat $rowidlist $pad]
Paul Mackerras03800812007-08-29 21:45:21 +10005191 lappend rowidlist $idlist
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10005192 set rowfinal [concat $rowfinal $pad]
5193 lappend rowfinal $final
Paul Mackerras03800812007-08-29 21:45:21 +10005194 set rowisopt [concat $rowisopt [ntimes [expr {$row - $l + 1}] 0]]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005195 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005196 }
5197 return $row
5198}
5199
Paul Mackerras03800812007-08-29 21:45:21 +10005200proc changedrow {row} {
5201 global displayorder iddrawn rowisopt need_redisplay
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005202
Paul Mackerras03800812007-08-29 21:45:21 +10005203 set l [llength $rowisopt]
5204 if {$row < $l} {
5205 lset rowisopt $row 0
5206 if {$row + 1 < $l} {
5207 lset rowisopt [expr {$row + 1}] 0
5208 if {$row + 2 < $l} {
5209 lset rowisopt [expr {$row + 2}] 0
5210 }
5211 }
Paul Mackerras79b2c752006-04-02 20:47:40 +10005212 }
Paul Mackerras03800812007-08-29 21:45:21 +10005213 set id [lindex $displayorder $row]
5214 if {[info exists iddrawn($id)]} {
5215 set need_redisplay 1
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005216 }
5217}
5218
5219proc insert_pad {row col npad} {
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005220 global rowidlist
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005221
5222 set pad [ntimes $npad {}]
Paul Mackerrase341c062007-08-12 12:42:57 +10005223 set idlist [lindex $rowidlist $row]
5224 set bef [lrange $idlist 0 [expr {$col - 1}]]
5225 set aft [lrange $idlist $col end]
5226 set i [lsearch -exact $aft {}]
5227 if {$i > 0} {
5228 set aft [lreplace $aft $i $i]
5229 }
5230 lset rowidlist $row [concat $bef $pad $aft]
Paul Mackerras03800812007-08-29 21:45:21 +10005231 changedrow $row
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005232}
5233
5234proc optimize_rows {row col endrow} {
Paul Mackerras03800812007-08-29 21:45:21 +10005235 global rowidlist rowisopt displayorder curview children
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005236
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005237 if {$row < 1} {
5238 set row 1
5239 }
Paul Mackerras03800812007-08-29 21:45:21 +10005240 for {} {$row < $endrow} {incr row; set col 0} {
5241 if {[lindex $rowisopt $row]} continue
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005242 set haspad 0
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005243 set y0 [expr {$row - 1}]
5244 set ym [expr {$row - 2}]
Paul Mackerras03800812007-08-29 21:45:21 +10005245 set idlist [lindex $rowidlist $row]
5246 set previdlist [lindex $rowidlist $y0]
5247 if {$idlist eq {} || $previdlist eq {}} continue
5248 if {$ym >= 0} {
5249 set pprevidlist [lindex $rowidlist $ym]
5250 if {$pprevidlist eq {}} continue
5251 } else {
5252 set pprevidlist {}
5253 }
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005254 set x0 -1
5255 set xm -1
5256 for {} {$col < [llength $idlist]} {incr col} {
5257 set id [lindex $idlist $col]
5258 if {[lindex $previdlist $col] eq $id} continue
5259 if {$id eq {}} {
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005260 set haspad 1
5261 continue
5262 }
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005263 set x0 [lsearch -exact $previdlist $id]
5264 if {$x0 < 0} continue
5265 set z [expr {$x0 - $col}]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005266 set isarrow 0
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005267 set z0 {}
5268 if {$ym >= 0} {
5269 set xm [lsearch -exact $pprevidlist $id]
5270 if {$xm >= 0} {
5271 set z0 [expr {$xm - $x0}]
5272 }
5273 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005274 if {$z0 eq {}} {
Paul Mackerras92ed6662007-08-22 22:35:28 +10005275 # if row y0 is the first child of $id then it's not an arrow
5276 if {[lindex $children($curview,$id) 0] ne
5277 [lindex $displayorder $y0]} {
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005278 set isarrow 1
5279 }
5280 }
Paul Mackerrase341c062007-08-12 12:42:57 +10005281 if {!$isarrow && $id ne [lindex $displayorder $row] &&
5282 [lsearch -exact [lindex $rowidlist [expr {$row+1}]] $id] < 0} {
5283 set isarrow 1
5284 }
Paul Mackerras3fc42792006-09-15 09:45:23 +10005285 # Looking at lines from this row to the previous row,
5286 # make them go straight up if they end in an arrow on
5287 # the previous row; otherwise make them go straight up
5288 # or at 45 degrees.
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005289 if {$z < -1 || ($z < 0 && $isarrow)} {
Paul Mackerras3fc42792006-09-15 09:45:23 +10005290 # Line currently goes left too much;
5291 # insert pads in the previous row, then optimize it
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005292 set npad [expr {-1 - $z + $isarrow}]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005293 insert_pad $y0 $x0 $npad
5294 if {$y0 > 0} {
5295 optimize_rows $y0 $x0 $row
5296 }
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005297 set previdlist [lindex $rowidlist $y0]
5298 set x0 [lsearch -exact $previdlist $id]
5299 set z [expr {$x0 - $col}]
5300 if {$z0 ne {}} {
5301 set pprevidlist [lindex $rowidlist $ym]
5302 set xm [lsearch -exact $pprevidlist $id]
5303 set z0 [expr {$xm - $x0}]
5304 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005305 } elseif {$z > 1 || ($z > 0 && $isarrow)} {
Paul Mackerras3fc42792006-09-15 09:45:23 +10005306 # Line currently goes right too much;
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005307 # insert pads in this line
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005308 set npad [expr {$z - 1 + $isarrow}]
Paul Mackerrase341c062007-08-12 12:42:57 +10005309 insert_pad $row $col $npad
5310 set idlist [lindex $rowidlist $row]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005311 incr col $npad
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005312 set z [expr {$x0 - $col}]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005313 set haspad 1
5314 }
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005315 if {$z0 eq {} && !$isarrow && $ym >= 0} {
Paul Mackerraseb447a12006-03-18 23:11:37 +11005316 # this line links to its first child on row $row-2
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005317 set id [lindex $displayorder $ym]
5318 set xc [lsearch -exact $pprevidlist $id]
Paul Mackerraseb447a12006-03-18 23:11:37 +11005319 if {$xc >= 0} {
5320 set z0 [expr {$xc - $x0}]
5321 }
5322 }
Paul Mackerras3fc42792006-09-15 09:45:23 +10005323 # avoid lines jigging left then immediately right
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005324 if {$z0 ne {} && $z < 0 && $z0 > 0} {
5325 insert_pad $y0 $x0 1
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005326 incr x0
5327 optimize_rows $y0 $x0 $row
5328 set previdlist [lindex $rowidlist $y0]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005329 }
5330 }
5331 if {!$haspad} {
Paul Mackerras3fc42792006-09-15 09:45:23 +10005332 # Find the first column that doesn't have a line going right
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005333 for {set col [llength $idlist]} {[incr col -1] >= 0} {} {
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005334 set id [lindex $idlist $col]
5335 if {$id eq {}} break
5336 set x0 [lsearch -exact $previdlist $id]
5337 if {$x0 < 0} {
Paul Mackerraseb447a12006-03-18 23:11:37 +11005338 # check if this is the link to the first child
Paul Mackerras92ed6662007-08-22 22:35:28 +10005339 set kid [lindex $displayorder $y0]
5340 if {[lindex $children($curview,$id) 0] eq $kid} {
Paul Mackerraseb447a12006-03-18 23:11:37 +11005341 # it is, work out offset to child
Paul Mackerras92ed6662007-08-22 22:35:28 +10005342 set x0 [lsearch -exact $previdlist $kid]
Paul Mackerraseb447a12006-03-18 23:11:37 +11005343 }
5344 }
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005345 if {$x0 <= $col} break
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005346 }
Paul Mackerras3fc42792006-09-15 09:45:23 +10005347 # Insert a pad at that column as long as it has a line and
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005348 # isn't the last column
5349 if {$x0 >= 0 && [incr col] < [llength $idlist]} {
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005350 set idlist [linsert $idlist $col {}]
Paul Mackerras03800812007-08-29 21:45:21 +10005351 lset rowidlist $row $idlist
5352 changedrow $row
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005353 }
5354 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005355 }
5356}
5357
5358proc xc {row col} {
5359 global canvx0 linespc
5360 return [expr {$canvx0 + $col * $linespc}]
5361}
5362
5363proc yc {row} {
5364 global canvy0 linespc
5365 return [expr {$canvy0 + $row * $linespc}]
5366}
5367
Paul Mackerrasc934a8a2006-03-02 23:00:44 +11005368proc linewidth {id} {
5369 global thickerline lthickness
5370
5371 set wid $lthickness
5372 if {[info exists thickerline] && $id eq $thickerline} {
5373 set wid [expr {2 * $lthickness}]
5374 }
5375 return $wid
5376}
5377
Paul Mackerras50b44ec2006-04-04 10:16:22 +10005378proc rowranges {id} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005379 global curview children uparrowlen downarrowlen
Paul Mackerras92ed6662007-08-22 22:35:28 +10005380 global rowidlist
Paul Mackerras50b44ec2006-04-04 10:16:22 +10005381
Paul Mackerras92ed6662007-08-22 22:35:28 +10005382 set kids $children($curview,$id)
5383 if {$kids eq {}} {
5384 return {}
Paul Mackerras50b44ec2006-04-04 10:16:22 +10005385 }
Paul Mackerras92ed6662007-08-22 22:35:28 +10005386 set ret {}
5387 lappend kids $id
5388 foreach child $kids {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005389 if {![commitinview $child $curview]} break
5390 set row [rowofcommit $child]
Paul Mackerras92ed6662007-08-22 22:35:28 +10005391 if {![info exists prev]} {
5392 lappend ret [expr {$row + 1}]
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005393 } else {
Paul Mackerras92ed6662007-08-22 22:35:28 +10005394 if {$row <= $prevrow} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005395 puts "oops children of [shortids $id] out of order [shortids $child] $row <= [shortids $prev] $prevrow"
Paul Mackerras92ed6662007-08-22 22:35:28 +10005396 }
5397 # see if the line extends the whole way from prevrow to row
5398 if {$row > $prevrow + $uparrowlen + $downarrowlen &&
5399 [lsearch -exact [lindex $rowidlist \
5400 [expr {int(($row + $prevrow) / 2)}]] $id] < 0} {
5401 # it doesn't, see where it ends
5402 set r [expr {$prevrow + $downarrowlen}]
5403 if {[lsearch -exact [lindex $rowidlist $r] $id] < 0} {
5404 while {[incr r -1] > $prevrow &&
5405 [lsearch -exact [lindex $rowidlist $r] $id] < 0} {}
5406 } else {
5407 while {[incr r] <= $row &&
5408 [lsearch -exact [lindex $rowidlist $r] $id] >= 0} {}
5409 incr r -1
5410 }
5411 lappend ret $r
5412 # see where it starts up again
5413 set r [expr {$row - $uparrowlen}]
5414 if {[lsearch -exact [lindex $rowidlist $r] $id] < 0} {
5415 while {[incr r] < $row &&
5416 [lsearch -exact [lindex $rowidlist $r] $id] < 0} {}
5417 } else {
5418 while {[incr r -1] >= $prevrow &&
5419 [lsearch -exact [lindex $rowidlist $r] $id] >= 0} {}
5420 incr r
5421 }
5422 lappend ret $r
5423 }
Paul Mackerraseb447a12006-03-18 23:11:37 +11005424 }
Paul Mackerras92ed6662007-08-22 22:35:28 +10005425 if {$child eq $id} {
5426 lappend ret $row
5427 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005428 set prev $child
Paul Mackerras92ed6662007-08-22 22:35:28 +10005429 set prevrow $row
Paul Mackerraseb447a12006-03-18 23:11:37 +11005430 }
Paul Mackerras92ed6662007-08-22 22:35:28 +10005431 return $ret
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005432}
5433
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005434proc drawlineseg {id row endrow arrowlow} {
5435 global rowidlist displayorder iddrawn linesegs
Paul Mackerrase341c062007-08-12 12:42:57 +10005436 global canv colormap linespc curview maxlinelen parentlist
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005437
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005438 set cols [list [lsearch -exact [lindex $rowidlist $row] $id]]
5439 set le [expr {$row + 1}]
5440 set arrowhigh 1
5441 while {1} {
5442 set c [lsearch -exact [lindex $rowidlist $le] $id]
5443 if {$c < 0} {
5444 incr le -1
5445 break
5446 }
5447 lappend cols $c
5448 set x [lindex $displayorder $le]
5449 if {$x eq $id} {
5450 set arrowhigh 0
5451 break
5452 }
5453 if {[info exists iddrawn($x)] || $le == $endrow} {
5454 set c [lsearch -exact [lindex $rowidlist [expr {$le+1}]] $id]
5455 if {$c >= 0} {
5456 lappend cols $c
5457 set arrowhigh 0
5458 }
5459 break
5460 }
5461 incr le
5462 }
5463 if {$le <= $row} {
5464 return $row
5465 }
5466
5467 set lines {}
5468 set i 0
5469 set joinhigh 0
5470 if {[info exists linesegs($id)]} {
5471 set lines $linesegs($id)
5472 foreach li $lines {
5473 set r0 [lindex $li 0]
5474 if {$r0 > $row} {
5475 if {$r0 == $le && [lindex $li 1] - $row <= $maxlinelen} {
5476 set joinhigh 1
5477 }
5478 break
5479 }
5480 incr i
5481 }
5482 }
5483 set joinlow 0
5484 if {$i > 0} {
5485 set li [lindex $lines [expr {$i-1}]]
5486 set r1 [lindex $li 1]
5487 if {$r1 == $row && $le - [lindex $li 0] <= $maxlinelen} {
5488 set joinlow 1
5489 }
5490 }
5491
5492 set x [lindex $cols [expr {$le - $row}]]
5493 set xp [lindex $cols [expr {$le - 1 - $row}]]
5494 set dir [expr {$xp - $x}]
5495 if {$joinhigh} {
5496 set ith [lindex $lines $i 2]
5497 set coords [$canv coords $ith]
5498 set ah [$canv itemcget $ith -arrow]
5499 set arrowhigh [expr {$ah eq "first" || $ah eq "both"}]
5500 set x2 [lindex $cols [expr {$le + 1 - $row}]]
5501 if {$x2 ne {} && $x - $x2 == $dir} {
5502 set coords [lrange $coords 0 end-2]
5503 }
5504 } else {
5505 set coords [list [xc $le $x] [yc $le]]
5506 }
5507 if {$joinlow} {
5508 set itl [lindex $lines [expr {$i-1}] 2]
5509 set al [$canv itemcget $itl -arrow]
5510 set arrowlow [expr {$al eq "last" || $al eq "both"}]
Paul Mackerrase341c062007-08-12 12:42:57 +10005511 } elseif {$arrowlow} {
5512 if {[lsearch -exact [lindex $rowidlist [expr {$row-1}]] $id] >= 0 ||
5513 [lsearch -exact [lindex $parentlist [expr {$row-1}]] $id] >= 0} {
5514 set arrowlow 0
5515 }
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005516 }
5517 set arrow [lindex {none first last both} [expr {$arrowhigh + 2*$arrowlow}]]
5518 for {set y $le} {[incr y -1] > $row} {} {
5519 set x $xp
5520 set xp [lindex $cols [expr {$y - 1 - $row}]]
5521 set ndir [expr {$xp - $x}]
5522 if {$dir != $ndir || $xp < 0} {
5523 lappend coords [xc $y $x] [yc $y]
5524 }
5525 set dir $ndir
5526 }
5527 if {!$joinlow} {
5528 if {$xp < 0} {
5529 # join parent line to first child
5530 set ch [lindex $displayorder $row]
5531 set xc [lsearch -exact [lindex $rowidlist $row] $ch]
5532 if {$xc < 0} {
5533 puts "oops: drawlineseg: child $ch not on row $row"
Paul Mackerrase341c062007-08-12 12:42:57 +10005534 } elseif {$xc != $x} {
5535 if {($arrowhigh && $le == $row + 1) || $dir == 0} {
5536 set d [expr {int(0.5 * $linespc)}]
5537 set x1 [xc $row $x]
5538 if {$xc < $x} {
5539 set x2 [expr {$x1 - $d}]
5540 } else {
5541 set x2 [expr {$x1 + $d}]
5542 }
5543 set y2 [yc $row]
5544 set y1 [expr {$y2 + $d}]
5545 lappend coords $x1 $y1 $x2 $y2
5546 } elseif {$xc < $x - 1} {
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005547 lappend coords [xc $row [expr {$x-1}]] [yc $row]
5548 } elseif {$xc > $x + 1} {
5549 lappend coords [xc $row [expr {$x+1}]] [yc $row]
5550 }
5551 set x $xc
5552 }
5553 lappend coords [xc $row $x] [yc $row]
5554 } else {
5555 set xn [xc $row $xp]
5556 set yn [yc $row]
Paul Mackerrase341c062007-08-12 12:42:57 +10005557 lappend coords $xn $yn
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005558 }
5559 if {!$joinhigh} {
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005560 assigncolor $id
5561 set t [$canv create line $coords -width [linewidth $id] \
5562 -fill $colormap($id) -tags lines.$id -arrow $arrow]
5563 $canv lower $t
5564 bindline $t $id
5565 set lines [linsert $lines $i [list $row $le $t]]
5566 } else {
5567 $canv coords $ith $coords
5568 if {$arrow ne $ah} {
5569 $canv itemconf $ith -arrow $arrow
5570 }
5571 lset lines $i 0 $row
5572 }
5573 } else {
5574 set xo [lsearch -exact [lindex $rowidlist [expr {$row - 1}]] $id]
5575 set ndir [expr {$xo - $xp}]
5576 set clow [$canv coords $itl]
5577 if {$dir == $ndir} {
5578 set clow [lrange $clow 2 end]
5579 }
5580 set coords [concat $coords $clow]
5581 if {!$joinhigh} {
5582 lset lines [expr {$i-1}] 1 $le
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005583 } else {
5584 # coalesce two pieces
5585 $canv delete $ith
5586 set b [lindex $lines [expr {$i-1}] 0]
5587 set e [lindex $lines $i 1]
5588 set lines [lreplace $lines [expr {$i-1}] $i [list $b $e $itl]]
5589 }
5590 $canv coords $itl $coords
5591 if {$arrow ne $al} {
5592 $canv itemconf $itl -arrow $arrow
5593 }
5594 }
5595
5596 set linesegs($id) $lines
5597 return $le
5598}
5599
5600proc drawparentlinks {id row} {
5601 global rowidlist canv colormap curview parentlist
Paul Mackerras513a54d2007-08-01 22:27:57 +10005602 global idpos linespc
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005603
5604 set rowids [lindex $rowidlist $row]
5605 set col [lsearch -exact $rowids $id]
5606 if {$col < 0} return
5607 set olds [lindex $parentlist $row]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005608 set row2 [expr {$row + 1}]
5609 set x [xc $row $col]
5610 set y [yc $row]
5611 set y2 [yc $row2]
Paul Mackerrase341c062007-08-12 12:42:57 +10005612 set d [expr {int(0.5 * $linespc)}]
Paul Mackerras513a54d2007-08-01 22:27:57 +10005613 set ymid [expr {$y + $d}]
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11005614 set ids [lindex $rowidlist $row2]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005615 # rmx = right-most X coord used
5616 set rmx 0
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005617 foreach p $olds {
Paul Mackerrasf3408442006-03-31 09:54:24 +11005618 set i [lsearch -exact $ids $p]
5619 if {$i < 0} {
5620 puts "oops, parent $p of $id not in list"
5621 continue
5622 }
5623 set x2 [xc $row2 $i]
5624 if {$x2 > $rmx} {
5625 set rmx $x2
5626 }
Paul Mackerras513a54d2007-08-01 22:27:57 +10005627 set j [lsearch -exact $rowids $p]
5628 if {$j < 0} {
Paul Mackerraseb447a12006-03-18 23:11:37 +11005629 # drawlineseg will do this one for us
5630 continue
5631 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005632 assigncolor $p
5633 # should handle duplicated parents here...
5634 set coords [list $x $y]
Paul Mackerras513a54d2007-08-01 22:27:57 +10005635 if {$i != $col} {
5636 # if attaching to a vertical segment, draw a smaller
5637 # slant for visual distinctness
5638 if {$i == $j} {
5639 if {$i < $col} {
5640 lappend coords [expr {$x2 + $d}] $y $x2 $ymid
5641 } else {
5642 lappend coords [expr {$x2 - $d}] $y $x2 $ymid
5643 }
5644 } elseif {$i < $col && $i < $j} {
5645 # segment slants towards us already
5646 lappend coords [xc $row $j] $y
5647 } else {
5648 if {$i < $col - 1} {
5649 lappend coords [expr {$x2 + $linespc}] $y
5650 } elseif {$i > $col + 1} {
5651 lappend coords [expr {$x2 - $linespc}] $y
5652 }
5653 lappend coords $x2 $y2
5654 }
5655 } else {
5656 lappend coords $x2 $y2
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005657 }
Paul Mackerrasc934a8a2006-03-02 23:00:44 +11005658 set t [$canv create line $coords -width [linewidth $p] \
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005659 -fill $colormap($p) -tags lines.$p]
5660 $canv lower $t
5661 bindline $t $p
5662 }
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005663 if {$rmx > [lindex $idpos($id) 1]} {
5664 lset idpos($id) 1 $rmx
5665 redrawtags $id
5666 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005667}
5668
Paul Mackerrasc934a8a2006-03-02 23:00:44 +11005669proc drawlines {id} {
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005670 global canv
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005671
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005672 $canv itemconf lines.$id -width [linewidth $id]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005673}
5674
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005675proc drawcmittext {id row col} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005676 global linespc canv canv2 canv3 fgcolor curview
5677 global cmitlisted commitinfo rowidlist parentlist
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005678 global rowtextx idpos idtags idheads idotherrefs
Paul Mackerras03800812007-08-29 21:45:21 +10005679 global linehtag linentag linedtag selectedline
Paul Mackerrasb9fdba72009-04-09 09:34:46 +10005680 global canvxmax boldids boldnameids fgcolor markedid
Paul Mackerrasd277e892008-09-21 18:11:37 -05005681 global mainheadid nullid nullid2 circleitem circlecolors ctxbut
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005682
Linus Torvalds1407ade2008-02-09 14:02:07 -08005683 # listed is 0 for boundary, 1 for normal, 2 for negative, 3 for left, 4 for right
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005684 set listed $cmitlisted($curview,$id)
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005685 if {$id eq $nullid} {
5686 set ofill red
Paul Mackerras8f489362007-07-13 19:49:37 +10005687 } elseif {$id eq $nullid2} {
Paul Mackerrasef3192b2007-07-22 22:05:30 +10005688 set ofill green
Paul Mackerrasc11ff122008-05-26 10:11:33 +10005689 } elseif {$id eq $mainheadid} {
5690 set ofill yellow
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005691 } else {
Paul Mackerrasc11ff122008-05-26 10:11:33 +10005692 set ofill [lindex $circlecolors $listed]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005693 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005694 set x [xc $row $col]
5695 set y [yc $row]
5696 set orad [expr {$linespc / 3}]
Linus Torvalds1407ade2008-02-09 14:02:07 -08005697 if {$listed <= 2} {
Paul Mackerrasc961b222007-07-09 22:45:47 +10005698 set t [$canv create oval [expr {$x - $orad}] [expr {$y - $orad}] \
5699 [expr {$x + $orad - 1}] [expr {$y + $orad - 1}] \
5700 -fill $ofill -outline $fgcolor -width 1 -tags circle]
Linus Torvalds1407ade2008-02-09 14:02:07 -08005701 } elseif {$listed == 3} {
Paul Mackerrasc961b222007-07-09 22:45:47 +10005702 # triangle pointing left for left-side commits
5703 set t [$canv create polygon \
5704 [expr {$x - $orad}] $y \
5705 [expr {$x + $orad - 1}] [expr {$y - $orad}] \
5706 [expr {$x + $orad - 1}] [expr {$y + $orad - 1}] \
5707 -fill $ofill -outline $fgcolor -width 1 -tags circle]
5708 } else {
5709 # triangle pointing right for right-side commits
5710 set t [$canv create polygon \
5711 [expr {$x + $orad - 1}] $y \
5712 [expr {$x - $orad}] [expr {$y - $orad}] \
5713 [expr {$x - $orad}] [expr {$y + $orad - 1}] \
5714 -fill $ofill -outline $fgcolor -width 1 -tags circle]
5715 }
Paul Mackerrasc11ff122008-05-26 10:11:33 +10005716 set circleitem($row) $t
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005717 $canv raise $t
5718 $canv bind $t <1> {selcanvline {} %x %y}
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005719 set rmx [llength [lindex $rowidlist $row]]
5720 set olds [lindex $parentlist $row]
5721 if {$olds ne {}} {
5722 set nextids [lindex $rowidlist [expr {$row + 1}]]
5723 foreach p $olds {
5724 set i [lsearch -exact $nextids $p]
5725 if {$i > $rmx} {
5726 set rmx $i
5727 }
5728 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005729 }
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005730 set xt [xc $row $rmx]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005731 set rowtextx($row) $xt
5732 set idpos($id) [list $x $xt $y]
5733 if {[info exists idtags($id)] || [info exists idheads($id)]
5734 || [info exists idotherrefs($id)]} {
5735 set xt [drawtags $id $x $xt $y]
5736 }
5737 set headline [lindex $commitinfo($id) 0]
5738 set name [lindex $commitinfo($id) 1]
5739 set date [lindex $commitinfo($id) 2]
5740 set date [formatdate $date]
Paul Mackerras9c311b32007-10-04 22:27:13 +10005741 set font mainfont
5742 set nfont mainfont
Paul Mackerras476ca632008-01-07 22:16:31 +11005743 set isbold [ishighlighted $id]
Paul Mackerras908c3582006-05-20 09:38:11 +10005744 if {$isbold > 0} {
Paul Mackerras28593d32008-11-13 23:01:46 +11005745 lappend boldids $id
Paul Mackerras9c311b32007-10-04 22:27:13 +10005746 set font mainfontbold
Paul Mackerras908c3582006-05-20 09:38:11 +10005747 if {$isbold > 1} {
Paul Mackerras28593d32008-11-13 23:01:46 +11005748 lappend boldnameids $id
Paul Mackerras9c311b32007-10-04 22:27:13 +10005749 set nfont mainfontbold
Paul Mackerras908c3582006-05-20 09:38:11 +10005750 }
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10005751 }
Paul Mackerras28593d32008-11-13 23:01:46 +11005752 set linehtag($id) [$canv create text $xt $y -anchor w -fill $fgcolor \
5753 -text $headline -font $font -tags text]
5754 $canv bind $linehtag($id) $ctxbut "rowmenu %X %Y $id"
5755 set linentag($id) [$canv2 create text 3 $y -anchor w -fill $fgcolor \
5756 -text $name -font $nfont -tags text]
5757 set linedtag($id) [$canv3 create text 3 $y -anchor w -fill $fgcolor \
5758 -text $date -font mainfont -tags text]
Paul Mackerras94b4a692008-05-20 20:51:06 +10005759 if {$selectedline == $row} {
Paul Mackerras28593d32008-11-13 23:01:46 +11005760 make_secsel $id
Paul Mackerras03800812007-08-29 21:45:21 +10005761 }
Paul Mackerrasb9fdba72009-04-09 09:34:46 +10005762 if {[info exists markedid] && $markedid eq $id} {
5763 make_idmark $id
5764 }
Paul Mackerras9c311b32007-10-04 22:27:13 +10005765 set xr [expr {$xt + [font measure $font $headline]}]
Paul Mackerrasbe0cd092006-03-31 09:55:11 +11005766 if {$xr > $canvxmax} {
5767 set canvxmax $xr
5768 setcanvscroll
5769 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005770}
5771
5772proc drawcmitrow {row} {
Paul Mackerras03800812007-08-29 21:45:21 +10005773 global displayorder rowidlist nrows_drawn
Paul Mackerras005a2f42007-07-26 22:36:39 +10005774 global iddrawn markingmatches
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005775 global commitinfo numcommits
Paul Mackerras687c8762007-09-22 12:49:33 +10005776 global filehighlight fhighlights findpattern nhighlights
Paul Mackerras908c3582006-05-20 09:38:11 +10005777 global hlview vhighlights
Paul Mackerras164ff272006-05-29 19:50:02 +10005778 global highlight_related rhighlights
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005779
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11005780 if {$row >= $numcommits} return
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005781
5782 set id [lindex $displayorder $row]
Paul Mackerras476ca632008-01-07 22:16:31 +11005783 if {[info exists hlview] && ![info exists vhighlights($id)]} {
Paul Mackerras908c3582006-05-20 09:38:11 +10005784 askvhighlight $row $id
5785 }
Paul Mackerras476ca632008-01-07 22:16:31 +11005786 if {[info exists filehighlight] && ![info exists fhighlights($id)]} {
Paul Mackerras908c3582006-05-20 09:38:11 +10005787 askfilehighlight $row $id
5788 }
Paul Mackerras476ca632008-01-07 22:16:31 +11005789 if {$findpattern ne {} && ![info exists nhighlights($id)]} {
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10005790 askfindhighlight $row $id
Paul Mackerras908c3582006-05-20 09:38:11 +10005791 }
Paul Mackerras476ca632008-01-07 22:16:31 +11005792 if {$highlight_related ne [mc "None"] && ![info exists rhighlights($id)]} {
Paul Mackerras164ff272006-05-29 19:50:02 +10005793 askrelhighlight $row $id
5794 }
Paul Mackerras005a2f42007-07-26 22:36:39 +10005795 if {![info exists iddrawn($id)]} {
5796 set col [lsearch -exact [lindex $rowidlist $row] $id]
5797 if {$col < 0} {
5798 puts "oops, row $row id $id not in list"
5799 return
5800 }
5801 if {![info exists commitinfo($id)]} {
5802 getcommit $id
5803 }
5804 assigncolor $id
5805 drawcmittext $id $row $col
5806 set iddrawn($id) 1
Paul Mackerras03800812007-08-29 21:45:21 +10005807 incr nrows_drawn
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005808 }
Paul Mackerras005a2f42007-07-26 22:36:39 +10005809 if {$markingmatches} {
5810 markrowmatches $row $id
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005811 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005812}
5813
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005814proc drawcommits {row {endrow {}}} {
Paul Mackerras03800812007-08-29 21:45:21 +10005815 global numcommits iddrawn displayorder curview need_redisplay
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10005816 global parentlist rowidlist rowfinal uparrowlen downarrowlen nrows_drawn
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005817
5818 if {$row < 0} {
5819 set row 0
5820 }
5821 if {$endrow eq {}} {
5822 set endrow $row
5823 }
5824 if {$endrow >= $numcommits} {
5825 set endrow [expr {$numcommits - 1}]
5826 }
5827
Paul Mackerras03800812007-08-29 21:45:21 +10005828 set rl1 [expr {$row - $downarrowlen - 3}]
5829 if {$rl1 < 0} {
5830 set rl1 0
5831 }
5832 set ro1 [expr {$row - 3}]
5833 if {$ro1 < 0} {
5834 set ro1 0
5835 }
5836 set r2 [expr {$endrow + $uparrowlen + 3}]
5837 if {$r2 > $numcommits} {
5838 set r2 $numcommits
5839 }
5840 for {set r $rl1} {$r < $r2} {incr r} {
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10005841 if {[lindex $rowidlist $r] ne {} && [lindex $rowfinal $r]} {
Paul Mackerras03800812007-08-29 21:45:21 +10005842 if {$rl1 < $r} {
5843 layoutrows $rl1 $r
5844 }
5845 set rl1 [expr {$r + 1}]
5846 }
5847 }
5848 if {$rl1 < $r} {
5849 layoutrows $rl1 $r
5850 }
5851 optimize_rows $ro1 0 $r2
5852 if {$need_redisplay || $nrows_drawn > 2000} {
5853 clear_display
Paul Mackerras03800812007-08-29 21:45:21 +10005854 }
5855
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005856 # make the lines join to already-drawn rows either side
5857 set r [expr {$row - 1}]
5858 if {$r < 0 || ![info exists iddrawn([lindex $displayorder $r])]} {
5859 set r $row
5860 }
5861 set er [expr {$endrow + 1}]
5862 if {$er >= $numcommits ||
5863 ![info exists iddrawn([lindex $displayorder $er])]} {
5864 set er $endrow
5865 }
5866 for {} {$r <= $er} {incr r} {
5867 set id [lindex $displayorder $r]
5868 set wasdrawn [info exists iddrawn($id)]
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10005869 drawcmitrow $r
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005870 if {$r == $er} break
5871 set nextid [lindex $displayorder [expr {$r + 1}]]
Paul Mackerrase5ef6f92007-10-21 12:58:42 +10005872 if {$wasdrawn && [info exists iddrawn($nextid)]} continue
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005873 drawparentlinks $id $r
5874
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005875 set rowids [lindex $rowidlist $r]
5876 foreach lid $rowids {
5877 if {$lid eq {}} continue
Paul Mackerrase5ef6f92007-10-21 12:58:42 +10005878 if {[info exists lineend($lid)] && $lineend($lid) > $r} continue
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005879 if {$lid eq $id} {
5880 # see if this is the first child of any of its parents
5881 foreach p [lindex $parentlist $r] {
5882 if {[lsearch -exact $rowids $p] < 0} {
5883 # make this line extend up to the child
Paul Mackerrase5ef6f92007-10-21 12:58:42 +10005884 set lineend($p) [drawlineseg $p $r $er 0]
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005885 }
5886 }
Paul Mackerrase5ef6f92007-10-21 12:58:42 +10005887 } else {
5888 set lineend($lid) [drawlineseg $lid $r $er 1]
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005889 }
5890 }
5891 }
5892}
5893
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005894proc undolayout {row} {
5895 global uparrowlen mingaplen downarrowlen
5896 global rowidlist rowisopt rowfinal need_redisplay
5897
5898 set r [expr {$row - ($uparrowlen + $mingaplen + $downarrowlen)}]
5899 if {$r < 0} {
5900 set r 0
5901 }
5902 if {[llength $rowidlist] > $r} {
5903 incr r -1
5904 set rowidlist [lrange $rowidlist 0 $r]
5905 set rowfinal [lrange $rowfinal 0 $r]
5906 set rowisopt [lrange $rowisopt 0 $r]
5907 set need_redisplay 1
5908 run drawvisible
5909 }
5910}
5911
Paul Mackerras31c0eaa2007-12-30 22:41:14 +11005912proc drawvisible {} {
5913 global canv linespc curview vrowmod selectedline targetrow targetid
Paul Mackerras42a671f2008-01-02 09:59:39 +11005914 global need_redisplay cscroll numcommits
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005915
Paul Mackerras31c0eaa2007-12-30 22:41:14 +11005916 set fs [$canv yview]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005917 set ymax [lindex [$canv cget -scrollregion] 3]
Paul Mackerras5a7f5772008-01-15 22:45:36 +11005918 if {$ymax eq {} || $ymax == 0 || $numcommits == 0} return
Paul Mackerras31c0eaa2007-12-30 22:41:14 +11005919 set f0 [lindex $fs 0]
5920 set f1 [lindex $fs 1]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005921 set y0 [expr {int($f0 * $ymax)}]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005922 set y1 [expr {int($f1 * $ymax)}]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005923
Paul Mackerras31c0eaa2007-12-30 22:41:14 +11005924 if {[info exists targetid]} {
Paul Mackerras42a671f2008-01-02 09:59:39 +11005925 if {[commitinview $targetid $curview]} {
5926 set r [rowofcommit $targetid]
5927 if {$r != $targetrow} {
5928 # Fix up the scrollregion and change the scrolling position
5929 # now that our target row has moved.
5930 set diff [expr {($r - $targetrow) * $linespc}]
5931 set targetrow $r
5932 setcanvscroll
5933 set ymax [lindex [$canv cget -scrollregion] 3]
5934 incr y0 $diff
5935 incr y1 $diff
5936 set f0 [expr {$y0 / $ymax}]
5937 set f1 [expr {$y1 / $ymax}]
5938 allcanvs yview moveto $f0
5939 $cscroll set $f0 $f1
5940 set need_redisplay 1
5941 }
5942 } else {
5943 unset targetid
Paul Mackerras31c0eaa2007-12-30 22:41:14 +11005944 }
5945 }
5946
5947 set row [expr {int(($y0 - 3) / $linespc) - 1}]
5948 set endrow [expr {int(($y1 - 3) / $linespc) + 1}]
5949 if {$endrow >= $vrowmod($curview)} {
5950 update_arcrows $curview
5951 }
Paul Mackerras94b4a692008-05-20 20:51:06 +10005952 if {$selectedline ne {} &&
Paul Mackerras31c0eaa2007-12-30 22:41:14 +11005953 $row <= $selectedline && $selectedline <= $endrow} {
5954 set targetrow $selectedline
Paul Mackerrasac1276a2008-03-03 10:11:08 +11005955 } elseif {[info exists targetid]} {
Paul Mackerras31c0eaa2007-12-30 22:41:14 +11005956 set targetrow [expr {int(($row + $endrow) / 2)}]
5957 }
Paul Mackerrasac1276a2008-03-03 10:11:08 +11005958 if {[info exists targetrow]} {
5959 if {$targetrow >= $numcommits} {
5960 set targetrow [expr {$numcommits - 1}]
5961 }
5962 set targetid [commitonrow $targetrow]
Paul Mackerras42a671f2008-01-02 09:59:39 +11005963 }
Paul Mackerras31c0eaa2007-12-30 22:41:14 +11005964 drawcommits $row $endrow
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005965}
5966
5967proc clear_display {} {
Paul Mackerras03800812007-08-29 21:45:21 +10005968 global iddrawn linesegs need_redisplay nrows_drawn
Paul Mackerras164ff272006-05-29 19:50:02 +10005969 global vhighlights fhighlights nhighlights rhighlights
Paul Mackerras28593d32008-11-13 23:01:46 +11005970 global linehtag linentag linedtag boldids boldnameids
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005971
5972 allcanvs delete all
5973 catch {unset iddrawn}
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005974 catch {unset linesegs}
Paul Mackerras94503a62008-05-19 09:48:45 +10005975 catch {unset linehtag}
5976 catch {unset linentag}
5977 catch {unset linedtag}
Paul Mackerras28593d32008-11-13 23:01:46 +11005978 set boldids {}
5979 set boldnameids {}
Paul Mackerras908c3582006-05-20 09:38:11 +10005980 catch {unset vhighlights}
5981 catch {unset fhighlights}
5982 catch {unset nhighlights}
Paul Mackerras164ff272006-05-29 19:50:02 +10005983 catch {unset rhighlights}
Paul Mackerras03800812007-08-29 21:45:21 +10005984 set need_redisplay 0
5985 set nrows_drawn 0
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005986}
5987
Paul Mackerras50b44ec2006-04-04 10:16:22 +10005988proc findcrossings {id} {
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005989 global rowidlist parentlist numcommits displayorder
Paul Mackerras50b44ec2006-04-04 10:16:22 +10005990
5991 set cross {}
5992 set ccross {}
5993 foreach {s e} [rowranges $id] {
5994 if {$e >= $numcommits} {
5995 set e [expr {$numcommits - 1}]
Paul Mackerras50b44ec2006-04-04 10:16:22 +10005996 }
Paul Mackerrasd94f8cd2006-04-06 10:18:23 +10005997 if {$e <= $s} continue
Paul Mackerras50b44ec2006-04-04 10:16:22 +10005998 for {set row $e} {[incr row -1] >= $s} {} {
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005999 set x [lsearch -exact [lindex $rowidlist $row] $id]
6000 if {$x < 0} break
Paul Mackerras50b44ec2006-04-04 10:16:22 +10006001 set olds [lindex $parentlist $row]
6002 set kid [lindex $displayorder $row]
6003 set kidx [lsearch -exact [lindex $rowidlist $row] $kid]
6004 if {$kidx < 0} continue
6005 set nextrow [lindex $rowidlist [expr {$row + 1}]]
6006 foreach p $olds {
6007 set px [lsearch -exact $nextrow $p]
6008 if {$px < 0} continue
6009 if {($kidx < $x && $x < $px) || ($px < $x && $x < $kidx)} {
6010 if {[lsearch -exact $ccross $p] >= 0} continue
6011 if {$x == $px + ($kidx < $px? -1: 1)} {
6012 lappend ccross $p
6013 } elseif {[lsearch -exact $cross $p] < 0} {
6014 lappend cross $p
6015 }
6016 }
6017 }
Paul Mackerras50b44ec2006-04-04 10:16:22 +10006018 }
6019 }
6020 return [concat $ccross {{}} $cross]
6021}
6022
Paul Mackerrase5c2d852005-05-11 23:44:54 +00006023proc assigncolor {id} {
Paul Mackerrasaa81d972006-02-28 11:27:12 +11006024 global colormap colors nextcolor
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11006025 global parents children children curview
Paul Mackerras6c20ff32005-06-22 19:53:32 +10006026
Paul Mackerras418c4c72006-02-07 09:10:18 +11006027 if {[info exists colormap($id)]} return
Paul Mackerrase5c2d852005-05-11 23:44:54 +00006028 set ncolors [llength $colors]
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10006029 if {[info exists children($curview,$id)]} {
6030 set kids $children($curview,$id)
Paul Mackerras79b2c752006-04-02 20:47:40 +10006031 } else {
6032 set kids {}
6033 }
6034 if {[llength $kids] == 1} {
6035 set child [lindex $kids 0]
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +00006036 if {[info exists colormap($child)]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11006037 && [llength $parents($curview,$child)] == 1} {
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +00006038 set colormap($id) $colormap($child)
6039 return
Paul Mackerrase5c2d852005-05-11 23:44:54 +00006040 }
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +00006041 }
6042 set badcolors {}
Paul Mackerras50b44ec2006-04-04 10:16:22 +10006043 set origbad {}
6044 foreach x [findcrossings $id] {
6045 if {$x eq {}} {
6046 # delimiter between corner crossings and other crossings
6047 if {[llength $badcolors] >= $ncolors - 1} break
6048 set origbad $badcolors
Paul Mackerrase5c2d852005-05-11 23:44:54 +00006049 }
Paul Mackerras50b44ec2006-04-04 10:16:22 +10006050 if {[info exists colormap($x)]
6051 && [lsearch -exact $badcolors $colormap($x)] < 0} {
6052 lappend badcolors $colormap($x)
Paul Mackerras6c20ff32005-06-22 19:53:32 +10006053 }
6054 }
Paul Mackerras50b44ec2006-04-04 10:16:22 +10006055 if {[llength $badcolors] >= $ncolors} {
6056 set badcolors $origbad
6057 }
Paul Mackerras6c20ff32005-06-22 19:53:32 +10006058 set origbad $badcolors
6059 if {[llength $badcolors] < $ncolors - 1} {
Paul Mackerras79b2c752006-04-02 20:47:40 +10006060 foreach child $kids {
Paul Mackerras6c20ff32005-06-22 19:53:32 +10006061 if {[info exists colormap($child)]
6062 && [lsearch -exact $badcolors $colormap($child)] < 0} {
6063 lappend badcolors $colormap($child)
6064 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11006065 foreach p $parents($curview,$child) {
Paul Mackerras79b2c752006-04-02 20:47:40 +10006066 if {[info exists colormap($p)]
6067 && [lsearch -exact $badcolors $colormap($p)] < 0} {
6068 lappend badcolors $colormap($p)
Paul Mackerrase5c2d852005-05-11 23:44:54 +00006069 }
6070 }
6071 }
Paul Mackerras6c20ff32005-06-22 19:53:32 +10006072 if {[llength $badcolors] >= $ncolors} {
6073 set badcolors $origbad
6074 }
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +00006075 }
6076 for {set i 0} {$i <= $ncolors} {incr i} {
6077 set c [lindex $colors $nextcolor]
6078 if {[incr nextcolor] >= $ncolors} {
6079 set nextcolor 0
Paul Mackerrase5c2d852005-05-11 23:44:54 +00006080 }
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +00006081 if {[lsearch -exact $badcolors $c]} break
6082 }
6083 set colormap($id) $c
6084}
6085
Paul Mackerrasa823a912005-06-21 10:01:38 +10006086proc bindline {t id} {
6087 global canv
6088
Paul Mackerrasa823a912005-06-21 10:01:38 +10006089 $canv bind $t <Enter> "lineenter %x %y $id"
6090 $canv bind $t <Motion> "linemotion %x %y $id"
6091 $canv bind $t <Leave> "lineleave $id"
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10006092 $canv bind $t <Button-1> "lineclick %x %y $id 1"
Paul Mackerrasa823a912005-06-21 10:01:38 +10006093}
6094
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006095proc drawtags {id x xt y1} {
Paul Mackerras8a485712006-07-06 10:21:23 +10006096 global idtags idheads idotherrefs mainhead
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006097 global linespc lthickness
Paul Mackerrasd277e892008-09-21 18:11:37 -05006098 global canv rowtextx curview fgcolor bgcolor ctxbut
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006099
6100 set marks {}
6101 set ntags 0
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10006102 set nheads 0
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006103 if {[info exists idtags($id)]} {
6104 set marks $idtags($id)
6105 set ntags [llength $marks]
6106 }
6107 if {[info exists idheads($id)]} {
6108 set marks [concat $marks $idheads($id)]
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10006109 set nheads [llength $idheads($id)]
6110 }
6111 if {[info exists idotherrefs($id)]} {
6112 set marks [concat $marks $idotherrefs($id)]
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006113 }
6114 if {$marks eq {}} {
6115 return $xt
6116 }
6117
6118 set delta [expr {int(0.5 * ($linespc - $lthickness))}]
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08006119 set yt [expr {$y1 - 0.5 * $linespc}]
6120 set yb [expr {$yt + $linespc - 1}]
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006121 set xvals {}
6122 set wvals {}
Paul Mackerras8a485712006-07-06 10:21:23 +10006123 set i -1
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006124 foreach tag $marks {
Paul Mackerras8a485712006-07-06 10:21:23 +10006125 incr i
6126 if {$i >= $ntags && $i < $ntags + $nheads && $tag eq $mainhead} {
Paul Mackerras9c311b32007-10-04 22:27:13 +10006127 set wid [font measure mainfontbold $tag]
Paul Mackerras8a485712006-07-06 10:21:23 +10006128 } else {
Paul Mackerras9c311b32007-10-04 22:27:13 +10006129 set wid [font measure mainfont $tag]
Paul Mackerras8a485712006-07-06 10:21:23 +10006130 }
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006131 lappend xvals $xt
6132 lappend wvals $wid
6133 set xt [expr {$xt + $delta + $wid + $lthickness + $linespc}]
6134 }
6135 set t [$canv create line $x $y1 [lindex $xvals end] $y1 \
6136 -width $lthickness -fill black -tags tag.$id]
6137 $canv lower $t
6138 foreach tag $marks x $xvals wid $wvals {
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08006139 set xl [expr {$x + $delta}]
6140 set xr [expr {$x + $delta + $wid + $lthickness}]
Paul Mackerras9c311b32007-10-04 22:27:13 +10006141 set font mainfont
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006142 if {[incr ntags -1] >= 0} {
6143 # draw a tag
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08006144 set t [$canv create polygon $x [expr {$yt + $delta}] $xl $yt \
6145 $xr $yt $xr $yb $xl $yb $x [expr {$yb - $delta}] \
Paul Mackerras106288c2005-08-19 23:11:39 +10006146 -width 1 -outline black -fill yellow -tags tag.$id]
6147 $canv bind $t <1> [list showtag $tag 1]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11006148 set rowtextx([rowofcommit $id]) [expr {$xr + $linespc}]
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006149 } else {
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10006150 # draw a head or other ref
6151 if {[incr nheads -1] >= 0} {
6152 set col green
Paul Mackerras8a485712006-07-06 10:21:23 +10006153 if {$tag eq $mainhead} {
Paul Mackerras9c311b32007-10-04 22:27:13 +10006154 set font mainfontbold
Paul Mackerras8a485712006-07-06 10:21:23 +10006155 }
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10006156 } else {
6157 set col "#ddddff"
6158 }
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08006159 set xl [expr {$xl - $delta/2}]
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006160 $canv create polygon $x $yt $xr $yt $xr $yb $x $yb \
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10006161 -width 1 -outline black -fill $col -tags tag.$id
Josef Weidendorfera970fcf2006-04-18 23:53:07 +02006162 if {[regexp {^(remotes/.*/|remotes/)} $tag match remoteprefix]} {
Paul Mackerras9c311b32007-10-04 22:27:13 +10006163 set rwid [font measure mainfont $remoteprefix]
Josef Weidendorfera970fcf2006-04-18 23:53:07 +02006164 set xi [expr {$x + 1}]
6165 set yti [expr {$yt + 1}]
6166 set xri [expr {$x + $rwid}]
6167 $canv create polygon $xi $yti $xri $yti $xri $yb $xi $yb \
6168 -width 0 -fill "#ffddaa" -tags tag.$id
6169 }
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006170 }
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10006171 set t [$canv create text $xl $y1 -anchor w -text $tag -fill $fgcolor \
Paul Mackerras8a485712006-07-06 10:21:23 +10006172 -font $font -tags [list tag.$id text]]
Paul Mackerras106288c2005-08-19 23:11:39 +10006173 if {$ntags >= 0} {
6174 $canv bind $t <1> [list showtag $tag 1]
Paul Mackerras10299152006-08-02 09:52:01 +10006175 } elseif {$nheads >= 0} {
Paul Mackerrasd277e892008-09-21 18:11:37 -05006176 $canv bind $t $ctxbut [list headmenu %X %Y $id $tag]
Paul Mackerras106288c2005-08-19 23:11:39 +10006177 }
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006178 }
6179 return $xt
6180}
6181
Paul Mackerras8d858d12005-08-05 09:52:16 +10006182proc xcoord {i level ln} {
6183 global canvx0 xspc1 xspc2
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +00006184
Paul Mackerras8d858d12005-08-05 09:52:16 +10006185 set x [expr {$canvx0 + $i * $xspc1($ln)}]
6186 if {$i > 0 && $i == $level} {
6187 set x [expr {$x + 0.5 * ($xspc2 - $xspc1($ln))}]
6188 } elseif {$i > $level} {
6189 set x [expr {$x + $xspc2 - $xspc1($ln)}]
6190 }
6191 return $x
6192}
6193
Paul Mackerras098dd8a2006-05-03 09:32:53 +10006194proc show_status {msg} {
Paul Mackerras9c311b32007-10-04 22:27:13 +10006195 global canv fgcolor
Paul Mackerras098dd8a2006-05-03 09:32:53 +10006196
6197 clear_display
Paul Mackerras9c311b32007-10-04 22:27:13 +10006198 $canv create text 3 3 -anchor nw -text $msg -font mainfont \
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10006199 -tags text -fill $fgcolor
Paul Mackerras098dd8a2006-05-03 09:32:53 +10006200}
6201
Paul Mackerras94a2eed2005-08-07 15:27:57 +10006202# Don't change the text pane cursor if it is currently the hand cursor,
6203# showing that we are over a sha1 ID link.
6204proc settextcursor {c} {
6205 global ctext curtextcursor
6206
6207 if {[$ctext cget -cursor] == $curtextcursor} {
6208 $ctext config -cursor $c
6209 }
6210 set curtextcursor $c
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +00006211}
6212
Paul Mackerrasa137a902007-10-23 21:12:49 +10006213proc nowbusy {what {name {}}} {
6214 global isbusy busyname statusw
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10006215
6216 if {[array names isbusy] eq {}} {
6217 . config -cursor watch
6218 settextcursor watch
6219 }
6220 set isbusy($what) 1
Paul Mackerrasa137a902007-10-23 21:12:49 +10006221 set busyname($what) $name
6222 if {$name ne {}} {
6223 $statusw conf -text $name
6224 }
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10006225}
6226
6227proc notbusy {what} {
Paul Mackerrasa137a902007-10-23 21:12:49 +10006228 global isbusy maincursor textcursor busyname statusw
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10006229
Paul Mackerrasa137a902007-10-23 21:12:49 +10006230 catch {
6231 unset isbusy($what)
6232 if {$busyname($what) ne {} &&
6233 [$statusw cget -text] eq $busyname($what)} {
6234 $statusw conf -text {}
6235 }
6236 }
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10006237 if {[array names isbusy] eq {}} {
6238 . config -cursor $maincursor
6239 settextcursor $textcursor
6240 }
6241}
6242
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00006243proc findmatches {f} {
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006244 global findtype findstring
Christian Stimmingb007ee22007-11-07 18:44:35 +01006245 if {$findtype == [mc "Regexp"]} {
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006246 set matches [regexp -indices -all -inline $findstring $f]
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00006247 } else {
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006248 set fs $findstring
Christian Stimmingb007ee22007-11-07 18:44:35 +01006249 if {$findtype == [mc "IgnCase"]} {
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006250 set f [string tolower $f]
6251 set fs [string tolower $fs]
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00006252 }
6253 set matches {}
6254 set i 0
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006255 set l [string length $fs]
6256 while {[set j [string first $fs $f $i]] >= 0} {
6257 lappend matches [list $j [expr {$j+$l-1}]]
6258 set i [expr {$j + $l}]
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00006259 }
6260 }
6261 return $matches
6262}
6263
Paul Mackerrascca5d942007-10-27 21:16:56 +10006264proc dofind {{dirn 1} {wrap 1}} {
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006265 global findstring findstartline findcurline selectedline numcommits
Paul Mackerrascca5d942007-10-27 21:16:56 +10006266 global gdttype filehighlight fh_serial find_dirn findallowwrap
Paul Mackerrasb74fd572005-07-16 07:46:13 -04006267
Paul Mackerrascca5d942007-10-27 21:16:56 +10006268 if {[info exists find_dirn]} {
6269 if {$find_dirn == $dirn} return
6270 stopfinding
6271 }
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00006272 focus .
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006273 if {$findstring eq {} || $numcommits == 0} return
Paul Mackerras94b4a692008-05-20 20:51:06 +10006274 if {$selectedline eq {}} {
Paul Mackerrascca5d942007-10-27 21:16:56 +10006275 set findstartline [lindex [visiblerows] [expr {$dirn < 0}]]
Paul Mackerras98f350e2005-05-15 05:56:51 +00006276 } else {
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006277 set findstartline $selectedline
Paul Mackerras98f350e2005-05-15 05:56:51 +00006278 }
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006279 set findcurline $findstartline
Christian Stimmingb007ee22007-11-07 18:44:35 +01006280 nowbusy finding [mc "Searching"]
6281 if {$gdttype ne [mc "containing:"] && ![info exists filehighlight]} {
Paul Mackerras687c8762007-09-22 12:49:33 +10006282 after cancel do_file_hl $fh_serial
6283 do_file_hl $fh_serial
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006284 }
Paul Mackerrascca5d942007-10-27 21:16:56 +10006285 set find_dirn $dirn
6286 set findallowwrap $wrap
6287 run findmore
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006288}
6289
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10006290proc stopfinding {} {
6291 global find_dirn findcurline fprogcoord
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006292
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10006293 if {[info exists find_dirn]} {
6294 unset find_dirn
6295 unset findcurline
6296 notbusy finding
6297 set fprogcoord 0
6298 adjustprogress
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006299 }
Paul Mackerras8a897742008-10-27 21:36:25 +11006300 stopblaming
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006301}
6302
6303proc findmore {} {
Paul Mackerras687c8762007-09-22 12:49:33 +10006304 global commitdata commitinfo numcommits findpattern findloc
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11006305 global findstartline findcurline findallowwrap
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10006306 global find_dirn gdttype fhighlights fprogcoord
Paul Mackerrascd2bcae2008-01-02 21:44:06 +11006307 global curview varcorder vrownum varccommits vrowmod
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006308
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10006309 if {![info exists find_dirn]} {
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006310 return 0
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00006311 }
Christian Stimmingb007ee22007-11-07 18:44:35 +01006312 set fldtypes [list [mc "Headline"] [mc "Author"] [mc "Date"] [mc "Committer"] [mc "CDate"] [mc "Comments"]]
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006313 set l $findcurline
Paul Mackerrascca5d942007-10-27 21:16:56 +10006314 set moretodo 0
6315 if {$find_dirn > 0} {
6316 incr l
6317 if {$l >= $numcommits} {
6318 set l 0
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006319 }
Paul Mackerrascca5d942007-10-27 21:16:56 +10006320 if {$l <= $findstartline} {
6321 set lim [expr {$findstartline + 1}]
6322 } else {
6323 set lim $numcommits
6324 set moretodo $findallowwrap
6325 }
Paul Mackerras98f350e2005-05-15 05:56:51 +00006326 } else {
Paul Mackerrascca5d942007-10-27 21:16:56 +10006327 if {$l == 0} {
6328 set l $numcommits
6329 }
6330 incr l -1
6331 if {$l >= $findstartline} {
6332 set lim [expr {$findstartline - 1}]
6333 } else {
6334 set lim -1
6335 set moretodo $findallowwrap
6336 }
Paul Mackerras98f350e2005-05-15 05:56:51 +00006337 }
Paul Mackerrascca5d942007-10-27 21:16:56 +10006338 set n [expr {($lim - $l) * $find_dirn}]
6339 if {$n > 500} {
6340 set n 500
6341 set moretodo 1
Paul Mackerras98f350e2005-05-15 05:56:51 +00006342 }
Paul Mackerrascd2bcae2008-01-02 21:44:06 +11006343 if {$l + ($find_dirn > 0? $n: 1) > $vrowmod($curview)} {
6344 update_arcrows $curview
6345 }
Paul Mackerras687c8762007-09-22 12:49:33 +10006346 set found 0
6347 set domore 1
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11006348 set ai [bsearch $vrownum($curview) $l]
6349 set a [lindex $varcorder($curview) $ai]
6350 set arow [lindex $vrownum($curview) $ai]
6351 set ids [lindex $varccommits($curview,$a)]
6352 set arowend [expr {$arow + [llength $ids]}]
Christian Stimmingb007ee22007-11-07 18:44:35 +01006353 if {$gdttype eq [mc "containing:"]} {
Paul Mackerrascca5d942007-10-27 21:16:56 +10006354 for {} {$n > 0} {incr n -1; incr l $find_dirn} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11006355 if {$l < $arow || $l >= $arowend} {
6356 incr ai $find_dirn
6357 set a [lindex $varcorder($curview) $ai]
6358 set arow [lindex $vrownum($curview) $ai]
6359 set ids [lindex $varccommits($curview,$a)]
6360 set arowend [expr {$arow + [llength $ids]}]
6361 }
6362 set id [lindex $ids [expr {$l - $arow}]]
Paul Mackerras687c8762007-09-22 12:49:33 +10006363 # shouldn't happen unless git log doesn't give all the commits...
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11006364 if {![info exists commitdata($id)] ||
6365 ![doesmatch $commitdata($id)]} {
6366 continue
6367 }
Paul Mackerras687c8762007-09-22 12:49:33 +10006368 if {![info exists commitinfo($id)]} {
6369 getcommit $id
6370 }
6371 set info $commitinfo($id)
6372 foreach f $info ty $fldtypes {
Christian Stimmingb007ee22007-11-07 18:44:35 +01006373 if {($findloc eq [mc "All fields"] || $findloc eq $ty) &&
Paul Mackerras687c8762007-09-22 12:49:33 +10006374 [doesmatch $f]} {
6375 set found 1
6376 break
6377 }
6378 }
6379 if {$found} break
Paul Mackerras98f350e2005-05-15 05:56:51 +00006380 }
Paul Mackerras687c8762007-09-22 12:49:33 +10006381 } else {
Paul Mackerrascca5d942007-10-27 21:16:56 +10006382 for {} {$n > 0} {incr n -1; incr l $find_dirn} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11006383 if {$l < $arow || $l >= $arowend} {
6384 incr ai $find_dirn
6385 set a [lindex $varcorder($curview) $ai]
6386 set arow [lindex $vrownum($curview) $ai]
6387 set ids [lindex $varccommits($curview,$a)]
6388 set arowend [expr {$arow + [llength $ids]}]
6389 }
6390 set id [lindex $ids [expr {$l - $arow}]]
Paul Mackerras476ca632008-01-07 22:16:31 +11006391 if {![info exists fhighlights($id)]} {
6392 # this sets fhighlights($id) to -1
Paul Mackerras687c8762007-09-22 12:49:33 +10006393 askfilehighlight $l $id
Paul Mackerrascd2bcae2008-01-02 21:44:06 +11006394 }
Paul Mackerras476ca632008-01-07 22:16:31 +11006395 if {$fhighlights($id) > 0} {
Paul Mackerrascd2bcae2008-01-02 21:44:06 +11006396 set found $domore
6397 break
6398 }
Paul Mackerras476ca632008-01-07 22:16:31 +11006399 if {$fhighlights($id) < 0} {
Paul Mackerras687c8762007-09-22 12:49:33 +10006400 if {$domore} {
6401 set domore 0
Paul Mackerrascca5d942007-10-27 21:16:56 +10006402 set findcurline [expr {$l - $find_dirn}]
Paul Mackerras687c8762007-09-22 12:49:33 +10006403 }
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006404 }
6405 }
6406 }
Paul Mackerrascca5d942007-10-27 21:16:56 +10006407 if {$found || ($domore && !$moretodo)} {
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006408 unset findcurline
Paul Mackerras687c8762007-09-22 12:49:33 +10006409 unset find_dirn
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006410 notbusy finding
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10006411 set fprogcoord 0
6412 adjustprogress
6413 if {$found} {
6414 findselectline $l
6415 } else {
6416 bell
6417 }
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006418 return 0
6419 }
Paul Mackerras687c8762007-09-22 12:49:33 +10006420 if {!$domore} {
6421 flushhighlights
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10006422 } else {
Paul Mackerrascca5d942007-10-27 21:16:56 +10006423 set findcurline [expr {$l - $find_dirn}]
Paul Mackerras687c8762007-09-22 12:49:33 +10006424 }
Paul Mackerrascca5d942007-10-27 21:16:56 +10006425 set n [expr {($findcurline - $findstartline) * $find_dirn - 1}]
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10006426 if {$n < 0} {
6427 incr n $numcommits
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006428 }
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10006429 set fprogcoord [expr {$n * 1.0 / $numcommits}]
6430 adjustprogress
6431 return $domore
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00006432}
6433
6434proc findselectline {l} {
Paul Mackerras687c8762007-09-22 12:49:33 +10006435 global findloc commentend ctext findcurline markingmatches gdttype
Paul Mackerras005a2f42007-07-26 22:36:39 +10006436
Paul Mackerras8b39e042008-12-02 09:02:46 +11006437 set markingmatches [expr {$gdttype eq [mc "containing:"]}]
Paul Mackerras005a2f42007-07-26 22:36:39 +10006438 set findcurline $l
Paul Mackerrasd6982062005-08-06 22:06:06 +10006439 selectline $l 1
Paul Mackerras8b39e042008-12-02 09:02:46 +11006440 if {$markingmatches &&
6441 ($findloc eq [mc "All fields"] || $findloc eq [mc "Comments"])} {
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00006442 # highlight the matches in the comments
6443 set f [$ctext get 1.0 $commentend]
6444 set matches [findmatches $f]
6445 foreach match $matches {
6446 set start [lindex $match 0]
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08006447 set end [expr {[lindex $match 1] + 1}]
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00006448 $ctext tag add found "1.0 + $start c" "1.0 + $end c"
6449 }
Paul Mackerras98f350e2005-05-15 05:56:51 +00006450 }
Paul Mackerras005a2f42007-07-26 22:36:39 +10006451 drawvisible
Paul Mackerras98f350e2005-05-15 05:56:51 +00006452}
6453
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006454# mark the bits of a headline or author that match a find string
Paul Mackerras005a2f42007-07-26 22:36:39 +10006455proc markmatches {canv l str tag matches font row} {
6456 global selectedline
6457
Paul Mackerras98f350e2005-05-15 05:56:51 +00006458 set bbox [$canv bbox $tag]
6459 set x0 [lindex $bbox 0]
6460 set y0 [lindex $bbox 1]
6461 set y1 [lindex $bbox 3]
6462 foreach match $matches {
6463 set start [lindex $match 0]
6464 set end [lindex $match 1]
6465 if {$start > $end} continue
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08006466 set xoff [font measure $font [string range $str 0 [expr {$start-1}]]]
6467 set xlen [font measure $font [string range $str 0 [expr {$end}]]]
6468 set t [$canv create rect [expr {$x0+$xoff}] $y0 \
6469 [expr {$x0+$xlen+2}] $y1 \
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006470 -outline {} -tags [list match$l matches] -fill yellow]
Paul Mackerras98f350e2005-05-15 05:56:51 +00006471 $canv lower $t
Paul Mackerras94b4a692008-05-20 20:51:06 +10006472 if {$row == $selectedline} {
Paul Mackerras005a2f42007-07-26 22:36:39 +10006473 $canv raise $t secsel
6474 }
Paul Mackerras98f350e2005-05-15 05:56:51 +00006475 }
6476}
6477
6478proc unmarkmatches {} {
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10006479 global markingmatches
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006480
Paul Mackerras98f350e2005-05-15 05:56:51 +00006481 allcanvs delete matches
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006482 set markingmatches 0
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10006483 stopfinding
Paul Mackerras98f350e2005-05-15 05:56:51 +00006484}
6485
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10006486proc selcanvline {w x y} {
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10006487 global canv canvy0 ctext linespc
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006488 global rowtextx
Paul Mackerras1db95b02005-05-09 04:08:39 +00006489 set ymax [lindex [$canv cget -scrollregion] 3]
Paul Mackerrascfb45632005-05-31 12:14:42 +00006490 if {$ymax == {}} return
Paul Mackerras1db95b02005-05-09 04:08:39 +00006491 set yfrac [lindex [$canv yview] 0]
6492 set y [expr {$y + $yfrac * $ymax}]
6493 set l [expr {int(($y - $canvy0) / $linespc + 0.5)}]
6494 if {$l < 0} {
6495 set l 0
6496 }
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10006497 if {$w eq $canv} {
Paul Mackerrasfc2a2562007-12-26 23:03:43 +11006498 set xmax [lindex [$canv cget -scrollregion] 2]
6499 set xleft [expr {[lindex [$canv xview] 0] * $xmax}]
6500 if {![info exists rowtextx($l)] || $xleft + $x < $rowtextx($l)} return
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10006501 }
Paul Mackerras98f350e2005-05-15 05:56:51 +00006502 unmarkmatches
Paul Mackerrasd6982062005-08-06 22:06:06 +10006503 selectline $l 1
Paul Mackerras5ad588d2005-05-10 01:02:55 +00006504}
6505
Linus Torvaldsb1ba39e2005-08-08 20:04:20 -07006506proc commit_descriptor {p} {
6507 global commitinfo
Paul Mackerrasb0934482006-05-15 09:56:08 +10006508 if {![info exists commitinfo($p)]} {
6509 getcommit $p
6510 }
Linus Torvaldsb1ba39e2005-08-08 20:04:20 -07006511 set l "..."
Paul Mackerrasb0934482006-05-15 09:56:08 +10006512 if {[llength $commitinfo($p)] > 1} {
Linus Torvaldsb1ba39e2005-08-08 20:04:20 -07006513 set l [lindex $commitinfo($p) 0]
6514 }
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10006515 return "$p ($l)\n"
Linus Torvaldsb1ba39e2005-08-08 20:04:20 -07006516}
6517
Paul Mackerras106288c2005-08-19 23:11:39 +10006518# append some text to the ctext widget, and make any SHA1 ID
6519# that we know about be a clickable link.
Sergey Vlasovf1b86292006-05-15 19:13:14 +04006520proc appendwithlinks {text tags} {
Paul Mackerrasd375ef92008-10-21 10:18:12 +11006521 global ctext linknum curview
Paul Mackerras106288c2005-08-19 23:11:39 +10006522
6523 set start [$ctext index "end - 1c"]
Sergey Vlasovf1b86292006-05-15 19:13:14 +04006524 $ctext insert end $text $tags
Paul Mackerrasd375ef92008-10-21 10:18:12 +11006525 set links [regexp -indices -all -inline {\m[0-9a-f]{6,40}\M} $text]
Paul Mackerras106288c2005-08-19 23:11:39 +10006526 foreach l $links {
6527 set s [lindex $l 0]
6528 set e [lindex $l 1]
6529 set linkid [string range $text $s $e]
Paul Mackerras106288c2005-08-19 23:11:39 +10006530 incr e
Paul Mackerrasc73adce2007-09-27 10:35:05 +10006531 $ctext tag delete link$linknum
Paul Mackerras106288c2005-08-19 23:11:39 +10006532 $ctext tag add link$linknum "$start + $s c" "$start + $e c"
Paul Mackerras97645682007-08-23 22:24:38 +10006533 setlink $linkid link$linknum
Paul Mackerras106288c2005-08-19 23:11:39 +10006534 incr linknum
6535 }
Paul Mackerras97645682007-08-23 22:24:38 +10006536}
6537
6538proc setlink {id lk} {
Paul Mackerrasd375ef92008-10-21 10:18:12 +11006539 global curview ctext pendinglinks
Paul Mackerras97645682007-08-23 22:24:38 +10006540
Paul Mackerrasd375ef92008-10-21 10:18:12 +11006541 set known 0
6542 if {[string length $id] < 40} {
6543 set matches [longid $id]
6544 if {[llength $matches] > 0} {
6545 if {[llength $matches] > 1} return
6546 set known 1
6547 set id [lindex $matches 0]
6548 }
6549 } else {
6550 set known [commitinview $id $curview]
6551 }
6552 if {$known} {
Paul Mackerras97645682007-08-23 22:24:38 +10006553 $ctext tag conf $lk -foreground blue -underline 1
Paul Mackerrasd375ef92008-10-21 10:18:12 +11006554 $ctext tag bind $lk <1> [list selbyid $id]
Paul Mackerras97645682007-08-23 22:24:38 +10006555 $ctext tag bind $lk <Enter> {linkcursor %W 1}
6556 $ctext tag bind $lk <Leave> {linkcursor %W -1}
6557 } else {
6558 lappend pendinglinks($id) $lk
Paul Mackerrasd375ef92008-10-21 10:18:12 +11006559 interestedin $id {makelink %P}
Paul Mackerras97645682007-08-23 22:24:38 +10006560 }
6561}
6562
Paul Mackerras6f63fc12009-04-21 22:22:31 +10006563proc appendshortlink {id {pre {}} {post {}}} {
6564 global ctext linknum
6565
6566 $ctext insert end $pre
6567 $ctext tag delete link$linknum
6568 $ctext insert end [string range $id 0 7] link$linknum
6569 $ctext insert end $post
6570 setlink $id link$linknum
6571 incr linknum
6572}
6573
Paul Mackerras97645682007-08-23 22:24:38 +10006574proc makelink {id} {
6575 global pendinglinks
6576
6577 if {![info exists pendinglinks($id)]} return
6578 foreach lk $pendinglinks($id) {
6579 setlink $id $lk
6580 }
6581 unset pendinglinks($id)
6582}
6583
6584proc linkcursor {w inc} {
6585 global linkentercount curtextcursor
6586
6587 if {[incr linkentercount $inc] > 0} {
6588 $w configure -cursor hand2
6589 } else {
6590 $w configure -cursor $curtextcursor
6591 if {$linkentercount < 0} {
6592 set linkentercount 0
6593 }
6594 }
Paul Mackerras106288c2005-08-19 23:11:39 +10006595}
6596
Rutger Nijlunsing6e5f7202006-04-05 10:24:03 +10006597proc viewnextline {dir} {
6598 global canv linespc
6599
6600 $canv delete hover
6601 set ymax [lindex [$canv cget -scrollregion] 3]
6602 set wnow [$canv yview]
6603 set wtop [expr {[lindex $wnow 0] * $ymax}]
6604 set newtop [expr {$wtop + $dir * $linespc}]
6605 if {$newtop < 0} {
6606 set newtop 0
6607 } elseif {$newtop > $ymax} {
6608 set newtop $ymax
6609 }
6610 allcanvs yview moveto [expr {$newtop * 1.0 / $ymax}]
6611}
6612
Paul Mackerrasef030b82006-06-04 11:50:38 +10006613# add a list of tag or branch names at position pos
6614# returns the number of names inserted
Paul Mackerrase11f1232007-06-16 20:29:25 +10006615proc appendrefs {pos ids var} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11006616 global ctext linknum curview $var maxrefs
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10006617
Paul Mackerrasef030b82006-06-04 11:50:38 +10006618 if {[catch {$ctext index $pos}]} {
6619 return 0
6620 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10006621 $ctext conf -state normal
6622 $ctext delete $pos "$pos lineend"
6623 set tags {}
6624 foreach id $ids {
6625 foreach tag [set $var\($id\)] {
6626 lappend tags [list $tag $id]
6627 }
6628 }
Paul Mackerras0a4dd8b2007-06-16 21:21:57 +10006629 if {[llength $tags] > $maxrefs} {
Christian Stimming84b4b832009-03-26 21:13:45 +01006630 $ctext insert $pos "[mc "many"] ([llength $tags])"
Paul Mackerras0a4dd8b2007-06-16 21:21:57 +10006631 } else {
6632 set tags [lsort -index 0 -decreasing $tags]
6633 set sep {}
6634 foreach ti $tags {
6635 set id [lindex $ti 1]
6636 set lk link$linknum
6637 incr linknum
6638 $ctext tag delete $lk
6639 $ctext insert $pos $sep
6640 $ctext insert $pos [lindex $ti 0] $lk
Paul Mackerras97645682007-08-23 22:24:38 +10006641 setlink $id $lk
Paul Mackerras0a4dd8b2007-06-16 21:21:57 +10006642 set sep ", "
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10006643 }
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10006644 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10006645 $ctext conf -state disabled
Paul Mackerrasef030b82006-06-04 11:50:38 +10006646 return [llength $tags]
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10006647}
6648
6649# called when we have finished computing the nearby tags
Paul Mackerrase11f1232007-06-16 20:29:25 +10006650proc dispneartags {delay} {
6651 global selectedline currentid showneartags tagphase
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10006652
Paul Mackerras94b4a692008-05-20 20:51:06 +10006653 if {$selectedline eq {} || !$showneartags} return
Paul Mackerrase11f1232007-06-16 20:29:25 +10006654 after cancel dispnexttag
6655 if {$delay} {
6656 after 200 dispnexttag
6657 set tagphase -1
6658 } else {
6659 after idle dispnexttag
6660 set tagphase 0
6661 }
6662}
6663
6664proc dispnexttag {} {
6665 global selectedline currentid showneartags tagphase ctext
6666
Paul Mackerras94b4a692008-05-20 20:51:06 +10006667 if {$selectedline eq {} || !$showneartags} return
Paul Mackerrase11f1232007-06-16 20:29:25 +10006668 switch -- $tagphase {
6669 0 {
6670 set dtags [desctags $currentid]
6671 if {$dtags ne {}} {
6672 appendrefs precedes $dtags idtags
6673 }
6674 }
6675 1 {
6676 set atags [anctags $currentid]
6677 if {$atags ne {}} {
6678 appendrefs follows $atags idtags
6679 }
6680 }
6681 2 {
6682 set dheads [descheads $currentid]
6683 if {$dheads ne {}} {
6684 if {[appendrefs branch $dheads idheads] > 1
6685 && [$ctext get "branch -3c"] eq "h"} {
6686 # turn "Branch" into "Branches"
6687 $ctext conf -state normal
6688 $ctext insert "branch -2c" "es"
6689 $ctext conf -state disabled
6690 }
6691 }
Paul Mackerrasef030b82006-06-04 11:50:38 +10006692 }
6693 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10006694 if {[incr tagphase] <= 2} {
6695 after idle dispnexttag
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10006696 }
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10006697}
6698
Paul Mackerras28593d32008-11-13 23:01:46 +11006699proc make_secsel {id} {
Paul Mackerras03800812007-08-29 21:45:21 +10006700 global linehtag linentag linedtag canv canv2 canv3
6701
Paul Mackerras28593d32008-11-13 23:01:46 +11006702 if {![info exists linehtag($id)]} return
Paul Mackerras03800812007-08-29 21:45:21 +10006703 $canv delete secsel
Paul Mackerras28593d32008-11-13 23:01:46 +11006704 set t [eval $canv create rect [$canv bbox $linehtag($id)] -outline {{}} \
Paul Mackerras03800812007-08-29 21:45:21 +10006705 -tags secsel -fill [$canv cget -selectbackground]]
6706 $canv lower $t
6707 $canv2 delete secsel
Paul Mackerras28593d32008-11-13 23:01:46 +11006708 set t [eval $canv2 create rect [$canv2 bbox $linentag($id)] -outline {{}} \
Paul Mackerras03800812007-08-29 21:45:21 +10006709 -tags secsel -fill [$canv2 cget -selectbackground]]
6710 $canv2 lower $t
6711 $canv3 delete secsel
Paul Mackerras28593d32008-11-13 23:01:46 +11006712 set t [eval $canv3 create rect [$canv3 bbox $linedtag($id)] -outline {{}} \
Paul Mackerras03800812007-08-29 21:45:21 +10006713 -tags secsel -fill [$canv3 cget -selectbackground]]
6714 $canv3 lower $t
6715}
6716
Paul Mackerrasb9fdba72009-04-09 09:34:46 +10006717proc make_idmark {id} {
6718 global linehtag canv fgcolor
6719
6720 if {![info exists linehtag($id)]} return
6721 $canv delete markid
6722 set t [eval $canv create rect [$canv bbox $linehtag($id)] \
6723 -tags markid -outline $fgcolor]
6724 $canv raise $t
6725}
6726
Paul Mackerras8a897742008-10-27 21:36:25 +11006727proc selectline {l isnew {desired_loc {}}} {
Paul Mackerras03800812007-08-29 21:45:21 +10006728 global canv ctext commitinfo selectedline
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11006729 global canvy0 linespc parents children curview
Paul Mackerras7fcceed2006-04-27 19:21:49 +10006730 global currentid sha1entry
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006731 global commentend idtags linknum
Paul Mackerrasd94f8cd2006-04-06 10:18:23 +10006732 global mergemax numcommits pending_select
Paul Mackerrase11f1232007-06-16 20:29:25 +10006733 global cmitmode showneartags allcommits
Paul Mackerrasc30acc72008-03-07 22:51:55 +11006734 global targetrow targetid lastscrollrows
Paul Mackerras8a897742008-10-27 21:36:25 +11006735 global autoselect jump_to_here
Paul Mackerrasd6982062005-08-06 22:06:06 +10006736
Paul Mackerrasd94f8cd2006-04-06 10:18:23 +10006737 catch {unset pending_select}
Paul Mackerras84ba7342005-06-17 00:12:26 +00006738 $canv delete hover
Paul Mackerras9843c302005-08-30 10:57:11 +10006739 normalline
Paul Mackerras887c9962007-08-20 19:36:20 +10006740 unsel_reflist
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10006741 stopfinding
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11006742 if {$l < 0 || $l >= $numcommits} return
Paul Mackerrasac1276a2008-03-03 10:11:08 +11006743 set id [commitonrow $l]
6744 set targetid $id
6745 set targetrow $l
Paul Mackerrasc30acc72008-03-07 22:51:55 +11006746 set selectedline $l
6747 set currentid $id
6748 if {$lastscrollrows < $numcommits} {
6749 setcanvscroll
6750 }
Paul Mackerrasac1276a2008-03-03 10:11:08 +11006751
Paul Mackerras5ad588d2005-05-10 01:02:55 +00006752 set y [expr {$canvy0 + $l * $linespc}]
Paul Mackerras17386062005-05-18 22:51:00 +00006753 set ymax [lindex [$canv cget -scrollregion] 3]
Paul Mackerras58422152005-05-19 10:56:42 +00006754 set ytop [expr {$y - $linespc - 1}]
6755 set ybot [expr {$y + $linespc + 1}]
Paul Mackerras5ad588d2005-05-10 01:02:55 +00006756 set wnow [$canv yview]
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08006757 set wtop [expr {[lindex $wnow 0] * $ymax}]
6758 set wbot [expr {[lindex $wnow 1] * $ymax}]
Paul Mackerras58422152005-05-19 10:56:42 +00006759 set wh [expr {$wbot - $wtop}]
6760 set newtop $wtop
Paul Mackerras17386062005-05-18 22:51:00 +00006761 if {$ytop < $wtop} {
Paul Mackerras58422152005-05-19 10:56:42 +00006762 if {$ybot < $wtop} {
6763 set newtop [expr {$y - $wh / 2.0}]
6764 } else {
6765 set newtop $ytop
6766 if {$newtop > $wtop - $linespc} {
6767 set newtop [expr {$wtop - $linespc}]
6768 }
Paul Mackerras17386062005-05-18 22:51:00 +00006769 }
Paul Mackerras58422152005-05-19 10:56:42 +00006770 } elseif {$ybot > $wbot} {
6771 if {$ytop > $wbot} {
6772 set newtop [expr {$y - $wh / 2.0}]
6773 } else {
6774 set newtop [expr {$ybot - $wh}]
6775 if {$newtop < $wtop + $linespc} {
6776 set newtop [expr {$wtop + $linespc}]
6777 }
Paul Mackerras17386062005-05-18 22:51:00 +00006778 }
Paul Mackerras58422152005-05-19 10:56:42 +00006779 }
6780 if {$newtop != $wtop} {
6781 if {$newtop < 0} {
6782 set newtop 0
6783 }
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08006784 allcanvs yview moveto [expr {$newtop * 1.0 / $ymax}]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006785 drawvisible
Paul Mackerras5ad588d2005-05-10 01:02:55 +00006786 }
Paul Mackerrasd6982062005-08-06 22:06:06 +10006787
Paul Mackerras28593d32008-11-13 23:01:46 +11006788 make_secsel $id
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006789
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10006790 if {$isnew} {
Paul Mackerrasfc2a2562007-12-26 23:03:43 +11006791 addtohistory [list selbyid $id]
Paul Mackerrasd6982062005-08-06 22:06:06 +10006792 }
6793
Paul Mackerras98f350e2005-05-15 05:56:51 +00006794 $sha1entry delete 0 end
6795 $sha1entry insert 0 $id
Jeff King95293b52008-03-06 06:49:25 -05006796 if {$autoselect} {
6797 $sha1entry selection from 0
6798 $sha1entry selection to end
6799 }
Paul Mackerras164ff272006-05-29 19:50:02 +10006800 rhighlight_sel $id
Paul Mackerras98f350e2005-05-15 05:56:51 +00006801
Paul Mackerras5ad588d2005-05-10 01:02:55 +00006802 $ctext conf -state normal
Paul Mackerras3ea06f92006-05-24 10:16:03 +10006803 clear_ctext
Paul Mackerras106288c2005-08-19 23:11:39 +10006804 set linknum 0
Paul Mackerrasd76afb12008-03-07 21:19:18 +11006805 if {![info exists commitinfo($id)]} {
6806 getcommit $id
6807 }
Paul Mackerras1db95b02005-05-09 04:08:39 +00006808 set info $commitinfo($id)
Paul Mackerras232475d2005-11-15 10:34:03 +11006809 set date [formatdate [lindex $info 2]]
Christian Stimmingd990ced2007-11-07 18:42:55 +01006810 $ctext insert end "[mc "Author"]: [lindex $info 1] $date\n"
Paul Mackerras232475d2005-11-15 10:34:03 +11006811 set date [formatdate [lindex $info 4]]
Christian Stimmingd990ced2007-11-07 18:42:55 +01006812 $ctext insert end "[mc "Committer"]: [lindex $info 3] $date\n"
Paul Mackerras887fe3c2005-05-21 07:35:37 +00006813 if {[info exists idtags($id)]} {
Christian Stimmingd990ced2007-11-07 18:42:55 +01006814 $ctext insert end [mc "Tags:"]
Paul Mackerras887fe3c2005-05-21 07:35:37 +00006815 foreach tag $idtags($id) {
6816 $ctext insert end " $tag"
6817 }
6818 $ctext insert end "\n"
6819 }
Mark Levedahl40b87ff2007-02-01 08:44:46 -05006820
Sergey Vlasovf1b86292006-05-15 19:13:14 +04006821 set headers {}
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11006822 set olds $parents($curview,$id)
Paul Mackerras79b2c752006-04-02 20:47:40 +10006823 if {[llength $olds] > 1} {
Paul Mackerrasb77b0272006-02-07 09:13:52 +11006824 set np 0
Paul Mackerras79b2c752006-04-02 20:47:40 +10006825 foreach p $olds {
Paul Mackerrasb77b0272006-02-07 09:13:52 +11006826 if {$np >= $mergemax} {
6827 set tag mmax
6828 } else {
6829 set tag m$np
6830 }
Christian Stimmingd990ced2007-11-07 18:42:55 +01006831 $ctext insert end "[mc "Parent"]: " $tag
Sergey Vlasovf1b86292006-05-15 19:13:14 +04006832 appendwithlinks [commit_descriptor $p] {}
Paul Mackerrasb77b0272006-02-07 09:13:52 +11006833 incr np
6834 }
6835 } else {
Paul Mackerras79b2c752006-04-02 20:47:40 +10006836 foreach p $olds {
Christian Stimmingd990ced2007-11-07 18:42:55 +01006837 append headers "[mc "Parent"]: [commit_descriptor $p]"
Linus Torvalds8b192802005-08-07 13:58:56 -07006838 }
Linus Torvaldsb1ba39e2005-08-08 20:04:20 -07006839 }
Paul Mackerrasb77b0272006-02-07 09:13:52 +11006840
Paul Mackerras6a90bff2007-06-18 09:48:23 +10006841 foreach c $children($curview,$id) {
Christian Stimmingd990ced2007-11-07 18:42:55 +01006842 append headers "[mc "Child"]: [commit_descriptor $c]"
Linus Torvalds8b192802005-08-07 13:58:56 -07006843 }
Paul Mackerrasd6982062005-08-06 22:06:06 +10006844
6845 # make anything that looks like a SHA1 ID be a clickable link
Sergey Vlasovf1b86292006-05-15 19:13:14 +04006846 appendwithlinks $headers {}
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10006847 if {$showneartags} {
6848 if {![info exists allcommits]} {
6849 getallcommits
6850 }
Christian Stimmingd990ced2007-11-07 18:42:55 +01006851 $ctext insert end "[mc "Branch"]: "
Paul Mackerrasef030b82006-06-04 11:50:38 +10006852 $ctext mark set branch "end -1c"
6853 $ctext mark gravity branch left
Christian Stimmingd990ced2007-11-07 18:42:55 +01006854 $ctext insert end "\n[mc "Follows"]: "
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10006855 $ctext mark set follows "end -1c"
6856 $ctext mark gravity follows left
Christian Stimmingd990ced2007-11-07 18:42:55 +01006857 $ctext insert end "\n[mc "Precedes"]: "
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10006858 $ctext mark set precedes "end -1c"
6859 $ctext mark gravity precedes left
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10006860 $ctext insert end "\n"
Paul Mackerrase11f1232007-06-16 20:29:25 +10006861 dispneartags 1
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10006862 }
6863 $ctext insert end "\n"
Paul Mackerras43c25072006-09-27 10:56:02 +10006864 set comment [lindex $info 5]
6865 if {[string first "\r" $comment] >= 0} {
6866 set comment [string map {"\r" "\n "} $comment]
6867 }
6868 appendwithlinks $comment {comment}
Paul Mackerrasd6982062005-08-06 22:06:06 +10006869
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00006870 $ctext tag remove found 1.0 end
Paul Mackerras5ad588d2005-05-10 01:02:55 +00006871 $ctext conf -state disabled
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00006872 set commentend [$ctext index "end - 1c"]
Paul Mackerras5ad588d2005-05-10 01:02:55 +00006873
Paul Mackerras8a897742008-10-27 21:36:25 +11006874 set jump_to_here $desired_loc
Christian Stimmingb007ee22007-11-07 18:44:35 +01006875 init_flist [mc "Comments"]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10006876 if {$cmitmode eq "tree"} {
6877 gettree $id
6878 } elseif {[llength $olds] <= 1} {
Paul Mackerrasd3272442005-11-28 20:41:56 +11006879 startdiff $id
Paul Mackerras7b5ff7e2006-03-30 20:50:40 +11006880 } else {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11006881 mergediff $id
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10006882 }
6883}
6884
Rutger Nijlunsing6e5f7202006-04-05 10:24:03 +10006885proc selfirstline {} {
6886 unmarkmatches
6887 selectline 0 1
6888}
6889
6890proc sellastline {} {
6891 global numcommits
6892 unmarkmatches
6893 set l [expr {$numcommits - 1}]
6894 selectline $l 1
6895}
6896
Paul Mackerrase5c2d852005-05-11 23:44:54 +00006897proc selnextline {dir} {
6898 global selectedline
Mark Levedahlbd441de2007-08-07 21:40:34 -04006899 focus .
Paul Mackerras94b4a692008-05-20 20:51:06 +10006900 if {$selectedline eq {}} return
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08006901 set l [expr {$selectedline + $dir}]
Paul Mackerras98f350e2005-05-15 05:56:51 +00006902 unmarkmatches
Paul Mackerrasd6982062005-08-06 22:06:06 +10006903 selectline $l 1
6904}
6905
Rutger Nijlunsing6e5f7202006-04-05 10:24:03 +10006906proc selnextpage {dir} {
6907 global canv linespc selectedline numcommits
6908
6909 set lpp [expr {([winfo height $canv] - 2) / $linespc}]
6910 if {$lpp < 1} {
6911 set lpp 1
6912 }
6913 allcanvs yview scroll [expr {$dir * $lpp}] units
Paul Mackerrase72ee5e2006-05-20 09:58:49 +10006914 drawvisible
Paul Mackerras94b4a692008-05-20 20:51:06 +10006915 if {$selectedline eq {}} return
Rutger Nijlunsing6e5f7202006-04-05 10:24:03 +10006916 set l [expr {$selectedline + $dir * $lpp}]
6917 if {$l < 0} {
6918 set l 0
6919 } elseif {$l >= $numcommits} {
6920 set l [expr $numcommits - 1]
6921 }
6922 unmarkmatches
Mark Levedahl40b87ff2007-02-01 08:44:46 -05006923 selectline $l 1
Rutger Nijlunsing6e5f7202006-04-05 10:24:03 +10006924}
6925
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10006926proc unselectline {} {
Paul Mackerras50b44ec2006-04-04 10:16:22 +10006927 global selectedline currentid
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10006928
Paul Mackerras94b4a692008-05-20 20:51:06 +10006929 set selectedline {}
Paul Mackerras50b44ec2006-04-04 10:16:22 +10006930 catch {unset currentid}
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10006931 allcanvs delete secsel
Paul Mackerras164ff272006-05-29 19:50:02 +10006932 rhighlight_none
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10006933}
6934
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10006935proc reselectline {} {
6936 global selectedline
6937
Paul Mackerras94b4a692008-05-20 20:51:06 +10006938 if {$selectedline ne {}} {
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10006939 selectline $selectedline 0
6940 }
6941}
6942
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10006943proc addtohistory {cmd} {
Paul Mackerras2516dae2006-04-21 10:35:31 +10006944 global history historyindex curview
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10006945
Paul Mackerras2516dae2006-04-21 10:35:31 +10006946 set elt [list $curview $cmd]
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10006947 if {$historyindex > 0
Paul Mackerras2516dae2006-04-21 10:35:31 +10006948 && [lindex $history [expr {$historyindex - 1}]] == $elt} {
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10006949 return
6950 }
6951
6952 if {$historyindex < [llength $history]} {
Paul Mackerras2516dae2006-04-21 10:35:31 +10006953 set history [lreplace $history $historyindex end $elt]
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10006954 } else {
Paul Mackerras2516dae2006-04-21 10:35:31 +10006955 lappend history $elt
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10006956 }
6957 incr historyindex
6958 if {$historyindex > 1} {
Junio C Hamanoe9937d22007-02-01 08:46:38 -05006959 .tf.bar.leftbut conf -state normal
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10006960 } else {
Junio C Hamanoe9937d22007-02-01 08:46:38 -05006961 .tf.bar.leftbut conf -state disabled
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10006962 }
Junio C Hamanoe9937d22007-02-01 08:46:38 -05006963 .tf.bar.rightbut conf -state disabled
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10006964}
6965
Paul Mackerras2516dae2006-04-21 10:35:31 +10006966proc godo {elt} {
6967 global curview
6968
6969 set view [lindex $elt 0]
6970 set cmd [lindex $elt 1]
6971 if {$curview != $view} {
6972 showview $view
6973 }
6974 eval $cmd
6975}
6976
Paul Mackerrasd6982062005-08-06 22:06:06 +10006977proc goback {} {
6978 global history historyindex
Mark Levedahlbd441de2007-08-07 21:40:34 -04006979 focus .
Paul Mackerrasd6982062005-08-06 22:06:06 +10006980
6981 if {$historyindex > 1} {
6982 incr historyindex -1
Paul Mackerras2516dae2006-04-21 10:35:31 +10006983 godo [lindex $history [expr {$historyindex - 1}]]
Junio C Hamanoe9937d22007-02-01 08:46:38 -05006984 .tf.bar.rightbut conf -state normal
Paul Mackerrasd6982062005-08-06 22:06:06 +10006985 }
6986 if {$historyindex <= 1} {
Junio C Hamanoe9937d22007-02-01 08:46:38 -05006987 .tf.bar.leftbut conf -state disabled
Paul Mackerrasd6982062005-08-06 22:06:06 +10006988 }
6989}
6990
6991proc goforw {} {
6992 global history historyindex
Mark Levedahlbd441de2007-08-07 21:40:34 -04006993 focus .
Paul Mackerrasd6982062005-08-06 22:06:06 +10006994
6995 if {$historyindex < [llength $history]} {
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10006996 set cmd [lindex $history $historyindex]
Paul Mackerrasd6982062005-08-06 22:06:06 +10006997 incr historyindex
Paul Mackerras2516dae2006-04-21 10:35:31 +10006998 godo $cmd
Junio C Hamanoe9937d22007-02-01 08:46:38 -05006999 .tf.bar.leftbut conf -state normal
Paul Mackerrasd6982062005-08-06 22:06:06 +10007000 }
7001 if {$historyindex >= [llength $history]} {
Junio C Hamanoe9937d22007-02-01 08:46:38 -05007002 .tf.bar.rightbut conf -state disabled
Paul Mackerrasd6982062005-08-06 22:06:06 +10007003 }
Paul Mackerras5ad588d2005-05-10 01:02:55 +00007004}
7005
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007006proc gettree {id} {
Paul Mackerras8f489362007-07-13 19:49:37 +10007007 global treefilelist treeidlist diffids diffmergeid treepending
7008 global nullid nullid2
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007009
7010 set diffids $id
7011 catch {unset diffmergeid}
7012 if {![info exists treefilelist($id)]} {
7013 if {![info exists treepending]} {
Paul Mackerras8f489362007-07-13 19:49:37 +10007014 if {$id eq $nullid} {
7015 set cmd [list | git ls-files]
7016 } elseif {$id eq $nullid2} {
7017 set cmd [list | git ls-files --stage -t]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007018 } else {
Paul Mackerras8f489362007-07-13 19:49:37 +10007019 set cmd [list | git ls-tree -r $id]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007020 }
7021 if {[catch {set gtf [open $cmd r]}]} {
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007022 return
7023 }
7024 set treepending $id
7025 set treefilelist($id) {}
7026 set treeidlist($id) {}
Alexander Gavrilov09c70292008-10-13 12:12:31 +04007027 fconfigure $gtf -blocking 0 -encoding binary
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007028 filerun $gtf [list gettreeline $gtf $id]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007029 }
7030 } else {
7031 setfilelist $id
7032 }
7033}
7034
7035proc gettreeline {gtf id} {
Paul Mackerras8f489362007-07-13 19:49:37 +10007036 global treefilelist treeidlist treepending cmitmode diffids nullid nullid2
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007037
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007038 set nl 0
7039 while {[incr nl] <= 1000 && [gets $gtf line] >= 0} {
Paul Mackerras8f489362007-07-13 19:49:37 +10007040 if {$diffids eq $nullid} {
7041 set fname $line
7042 } else {
Paul Mackerras9396cd32007-06-23 20:28:15 +10007043 set i [string first "\t" $line]
7044 if {$i < 0} continue
Paul Mackerras9396cd32007-06-23 20:28:15 +10007045 set fname [string range $line [expr {$i+1}] end]
Paul Mackerrasf31fa2c2008-04-28 09:40:50 +10007046 set line [string range $line 0 [expr {$i-1}]]
7047 if {$diffids ne $nullid2 && [lindex $line 1] ne "blob"} continue
7048 set sha1 [lindex $line 2]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007049 lappend treeidlist($id) $sha1
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007050 }
Alexander Gavrilov09c70292008-10-13 12:12:31 +04007051 if {[string index $fname 0] eq "\""} {
7052 set fname [lindex $fname 0]
7053 }
7054 set fname [encoding convertfrom $fname]
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007055 lappend treefilelist($id) $fname
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007056 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007057 if {![eof $gtf]} {
7058 return [expr {$nl >= 1000? 2: 1}]
7059 }
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007060 close $gtf
7061 unset treepending
7062 if {$cmitmode ne "tree"} {
7063 if {![info exists diffmergeid]} {
7064 gettreediffs $diffids
7065 }
7066 } elseif {$id ne $diffids} {
7067 gettree $diffids
7068 } else {
7069 setfilelist $id
7070 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007071 return 0
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007072}
7073
7074proc showfile {f} {
Paul Mackerras8f489362007-07-13 19:49:37 +10007075 global treefilelist treeidlist diffids nullid nullid2
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04007076 global ctext_file_names ctext_file_lines
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007077 global ctext commentend
7078
7079 set i [lsearch -exact $treefilelist($diffids) $f]
7080 if {$i < 0} {
7081 puts "oops, $f not in list for id $diffids"
7082 return
7083 }
Paul Mackerras8f489362007-07-13 19:49:37 +10007084 if {$diffids eq $nullid} {
7085 if {[catch {set bf [open $f r]} err]} {
7086 puts "oops, can't read $f: $err"
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007087 return
7088 }
7089 } else {
Paul Mackerras8f489362007-07-13 19:49:37 +10007090 set blob [lindex $treeidlist($diffids) $i]
7091 if {[catch {set bf [open [concat | git cat-file blob $blob] r]} err]} {
7092 puts "oops, error reading blob $blob: $err"
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007093 return
7094 }
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007095 }
Alexander Gavrilov09c70292008-10-13 12:12:31 +04007096 fconfigure $bf -blocking 0 -encoding [get_path_encoding $f]
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007097 filerun $bf [list getblobline $bf $diffids]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007098 $ctext config -state normal
Paul Mackerras3ea06f92006-05-24 10:16:03 +10007099 clear_ctext $commentend
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04007100 lappend ctext_file_names $f
7101 lappend ctext_file_lines [lindex [split $commentend "."] 0]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007102 $ctext insert end "\n"
7103 $ctext insert end "$f\n" filesep
7104 $ctext config -state disabled
7105 $ctext yview $commentend
Paul Mackerras32f1b3e2007-09-28 21:27:39 +10007106 settabs 0
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007107}
7108
7109proc getblobline {bf id} {
7110 global diffids cmitmode ctext
7111
7112 if {$id ne $diffids || $cmitmode ne "tree"} {
7113 catch {close $bf}
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007114 return 0
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007115 }
7116 $ctext config -state normal
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007117 set nl 0
7118 while {[incr nl] <= 1000 && [gets $bf line] >= 0} {
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007119 $ctext insert end "$line\n"
7120 }
7121 if {[eof $bf]} {
Paul Mackerras8a897742008-10-27 21:36:25 +11007122 global jump_to_here ctext_file_names commentend
7123
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007124 # delete last newline
7125 $ctext delete "end - 2c" "end - 1c"
7126 close $bf
Paul Mackerras8a897742008-10-27 21:36:25 +11007127 if {$jump_to_here ne {} &&
7128 [lindex $jump_to_here 0] eq [lindex $ctext_file_names 0]} {
7129 set lnum [expr {[lindex $jump_to_here 1] +
7130 [lindex [split $commentend .] 0]}]
7131 mark_ctext_line $lnum
7132 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007133 return 0
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007134 }
7135 $ctext config -state disabled
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007136 return [expr {$nl >= 1000? 2: 1}]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007137}
7138
Paul Mackerras8a897742008-10-27 21:36:25 +11007139proc mark_ctext_line {lnum} {
Paul Mackerrase3e901b2008-10-27 22:37:21 +11007140 global ctext markbgcolor
Paul Mackerras8a897742008-10-27 21:36:25 +11007141
7142 $ctext tag delete omark
7143 $ctext tag add omark $lnum.0 "$lnum.0 + 1 line"
Paul Mackerrase3e901b2008-10-27 22:37:21 +11007144 $ctext tag conf omark -background $markbgcolor
Paul Mackerras8a897742008-10-27 21:36:25 +11007145 $ctext see $lnum.0
7146}
7147
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11007148proc mergediff {id} {
Paul Mackerras8b07dca2008-11-02 22:34:47 +11007149 global diffmergeid
Alexander Gavrilov2df64422008-10-08 11:05:37 +04007150 global diffids treediffs
Paul Mackerras8b07dca2008-11-02 22:34:47 +11007151 global parents curview
Paul Mackerrase2ed4322005-07-17 03:39:44 -04007152
Paul Mackerras3c461ff2005-07-20 09:13:46 -04007153 set diffmergeid $id
Paul Mackerras7a1d9d12006-03-22 10:21:45 +11007154 set diffids $id
Alexander Gavrilov2df64422008-10-08 11:05:37 +04007155 set treediffs($id) {}
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11007156 set np [llength $parents($curview,$id)]
Paul Mackerras32f1b3e2007-09-28 21:27:39 +10007157 settabs $np
Paul Mackerras8b07dca2008-11-02 22:34:47 +11007158 getblobdiffs $id
Paul Mackerrasc8a4acb2005-07-29 09:23:03 -05007159}
7160
Paul Mackerras3c461ff2005-07-20 09:13:46 -04007161proc startdiff {ids} {
Paul Mackerras8f489362007-07-13 19:49:37 +10007162 global treediffs diffids treepending diffmergeid nullid nullid2
Paul Mackerras3c461ff2005-07-20 09:13:46 -04007163
Paul Mackerras32f1b3e2007-09-28 21:27:39 +10007164 settabs 1
Paul Mackerras3c461ff2005-07-20 09:13:46 -04007165 set diffids $ids
7166 catch {unset diffmergeid}
Paul Mackerras8f489362007-07-13 19:49:37 +10007167 if {![info exists treediffs($ids)] ||
7168 [lsearch -exact $ids $nullid] >= 0 ||
7169 [lsearch -exact $ids $nullid2] >= 0} {
Paul Mackerras3c461ff2005-07-20 09:13:46 -04007170 if {![info exists treepending]} {
7171 gettreediffs $ids
7172 }
7173 } else {
7174 addtocflist $ids
7175 }
7176}
7177
Paul Mackerras7a39a172007-10-23 10:15:11 +10007178proc path_filter {filter name} {
7179 foreach p $filter {
7180 set l [string length $p]
Paul Mackerras74a40c72007-10-24 10:16:56 +10007181 if {[string index $p end] eq "/"} {
7182 if {[string compare -length $l $p $name] == 0} {
7183 return 1
7184 }
7185 } else {
7186 if {[string compare -length $l $p $name] == 0 &&
7187 ([string length $name] == $l ||
7188 [string index $name $l] eq "/")} {
7189 return 1
7190 }
Paul Mackerras7a39a172007-10-23 10:15:11 +10007191 }
7192 }
7193 return 0
7194}
7195
Paul Mackerras3c461ff2005-07-20 09:13:46 -04007196proc addtocflist {ids} {
Paul Mackerras74a40c72007-10-24 10:16:56 +10007197 global treediffs
Paul Mackerras7a39a172007-10-23 10:15:11 +10007198
Paul Mackerras74a40c72007-10-24 10:16:56 +10007199 add_flist $treediffs($ids)
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10007200 getblobdiffs $ids
Paul Mackerrasd2610d12005-05-11 00:45:38 +00007201}
7202
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007203proc diffcmd {ids flags} {
Paul Mackerras8f489362007-07-13 19:49:37 +10007204 global nullid nullid2
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007205
7206 set i [lsearch -exact $ids $nullid]
Paul Mackerras8f489362007-07-13 19:49:37 +10007207 set j [lsearch -exact $ids $nullid2]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007208 if {$i >= 0} {
Paul Mackerras8f489362007-07-13 19:49:37 +10007209 if {[llength $ids] > 1 && $j < 0} {
7210 # comparing working directory with some specific revision
7211 set cmd [concat | git diff-index $flags]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007212 if {$i == 0} {
7213 lappend cmd -R [lindex $ids 1]
7214 } else {
7215 lappend cmd [lindex $ids 0]
7216 }
7217 } else {
Paul Mackerras8f489362007-07-13 19:49:37 +10007218 # comparing working directory with index
7219 set cmd [concat | git diff-files $flags]
7220 if {$j == 1} {
7221 lappend cmd -R
7222 }
7223 }
7224 } elseif {$j >= 0} {
7225 set cmd [concat | git diff-index --cached $flags]
7226 if {[llength $ids] > 1} {
7227 # comparing index with specific revision
Jens Lehmann90a77922009-10-27 18:13:42 +01007228 if {$j == 0} {
Paul Mackerras8f489362007-07-13 19:49:37 +10007229 lappend cmd -R [lindex $ids 1]
7230 } else {
7231 lappend cmd [lindex $ids 0]
7232 }
7233 } else {
7234 # comparing index with HEAD
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007235 lappend cmd HEAD
7236 }
7237 } else {
Paul Mackerras8f489362007-07-13 19:49:37 +10007238 set cmd [concat | git diff-tree -r $flags $ids]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007239 }
7240 return $cmd
7241}
7242
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10007243proc gettreediffs {ids} {
Paul Mackerras79b2c752006-04-02 20:47:40 +10007244 global treediff treepending
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007245
Alexander Gavrilov72721312008-07-26 18:48:41 +04007246 if {[catch {set gdtf [open [diffcmd $ids {--no-commit-id}] r]}]} return
7247
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10007248 set treepending $ids
Paul Mackerras3c461ff2005-07-20 09:13:46 -04007249 set treediff {}
Alexander Gavrilov09c70292008-10-13 12:12:31 +04007250 fconfigure $gdtf -blocking 0 -encoding binary
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007251 filerun $gdtf [list gettreediffline $gdtf $ids]
Paul Mackerrasd2610d12005-05-11 00:45:38 +00007252}
7253
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10007254proc gettreediffline {gdtf ids} {
Paul Mackerras3c461ff2005-07-20 09:13:46 -04007255 global treediff treediffs treepending diffids diffmergeid
Paul Mackerras39ee47e2008-10-15 22:23:03 +11007256 global cmitmode vfilelimit curview limitdiffs perfile_attrs
Paul Mackerras3c461ff2005-07-20 09:13:46 -04007257
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007258 set nr 0
Alexander Gavrilov4db09302008-10-13 12:12:33 +04007259 set sublist {}
Paul Mackerras39ee47e2008-10-15 22:23:03 +11007260 set max 1000
7261 if {$perfile_attrs} {
7262 # cache_gitattr is slow, and even slower on win32 where we
7263 # have to invoke it for only about 30 paths at a time
7264 set max 500
7265 if {[tk windowingsystem] == "win32"} {
7266 set max 120
7267 }
7268 }
7269 while {[incr nr] <= $max && [gets $gdtf line] >= 0} {
Paul Mackerras9396cd32007-06-23 20:28:15 +10007270 set i [string first "\t" $line]
7271 if {$i >= 0} {
7272 set file [string range $line [expr {$i+1}] end]
7273 if {[string index $file 0] eq "\""} {
7274 set file [lindex $file 0]
7275 }
Alexander Gavrilov09c70292008-10-13 12:12:31 +04007276 set file [encoding convertfrom $file]
Paul Mackerras48a81b72008-11-04 21:09:00 +11007277 if {$file ne [lindex $treediff end]} {
7278 lappend treediff $file
7279 lappend sublist $file
7280 }
Paul Mackerras9396cd32007-06-23 20:28:15 +10007281 }
Paul Mackerrasd2610d12005-05-11 00:45:38 +00007282 }
Paul Mackerras39ee47e2008-10-15 22:23:03 +11007283 if {$perfile_attrs} {
7284 cache_gitattr encoding $sublist
7285 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007286 if {![eof $gdtf]} {
Paul Mackerras39ee47e2008-10-15 22:23:03 +11007287 return [expr {$nr >= $max? 2: 1}]
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007288 }
7289 close $gdtf
Paul Mackerras3ed31a82008-04-26 16:00:00 +10007290 if {$limitdiffs && $vfilelimit($curview) ne {}} {
Paul Mackerras74a40c72007-10-24 10:16:56 +10007291 set flist {}
7292 foreach f $treediff {
Paul Mackerras3ed31a82008-04-26 16:00:00 +10007293 if {[path_filter $vfilelimit($curview) $f]} {
Paul Mackerras74a40c72007-10-24 10:16:56 +10007294 lappend flist $f
7295 }
7296 }
7297 set treediffs($ids) $flist
7298 } else {
7299 set treediffs($ids) $treediff
7300 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007301 unset treepending
Paul Mackerrase1160132008-11-18 21:40:32 +11007302 if {$cmitmode eq "tree" && [llength $diffids] == 1} {
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007303 gettree $diffids
7304 } elseif {$ids != $diffids} {
7305 if {![info exists diffmergeid]} {
7306 gettreediffs $diffids
7307 }
7308 } else {
7309 addtocflist $ids
7310 }
7311 return 0
Paul Mackerrasd2610d12005-05-11 00:45:38 +00007312}
7313
Steffen Prohaska890fae72007-08-12 12:05:46 +02007314# empty string or positive integer
7315proc diffcontextvalidate {v} {
7316 return [regexp {^(|[1-9][0-9]*)$} $v]
7317}
7318
7319proc diffcontextchange {n1 n2 op} {
7320 global diffcontextstring diffcontext
7321
7322 if {[string is integer -strict $diffcontextstring]} {
Markus Heidelberga41ddbb2009-05-23 19:31:37 +02007323 if {$diffcontextstring >= 0} {
Steffen Prohaska890fae72007-08-12 12:05:46 +02007324 set diffcontext $diffcontextstring
7325 reselectline
7326 }
7327 }
7328}
7329
Steffen Prohaskab9b86002008-01-17 23:42:55 +01007330proc changeignorespace {} {
7331 reselectline
7332}
7333
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10007334proc getblobdiffs {ids} {
Paul Mackerras8d73b242007-10-06 20:22:00 +10007335 global blobdifffd diffids env
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007336 global diffinhdr treediffs
Steffen Prohaska890fae72007-08-12 12:05:46 +02007337 global diffcontext
Steffen Prohaskab9b86002008-01-17 23:42:55 +01007338 global ignorespace
Paul Mackerras3ed31a82008-04-26 16:00:00 +10007339 global limitdiffs vfilelimit curview
Paul Mackerras8b07dca2008-11-02 22:34:47 +11007340 global diffencoding targetline diffnparents
Paul Mackerrasa8138732009-05-16 21:06:01 +10007341 global git_version
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10007342
Paul Mackerrasa8138732009-05-16 21:06:01 +10007343 set textconv {}
7344 if {[package vcompare $git_version "1.6.1"] >= 0} {
7345 set textconv "--textconv"
7346 }
7347 set cmd [diffcmd $ids "-p $textconv -C --cc --no-commit-id -U$diffcontext"]
Steffen Prohaskab9b86002008-01-17 23:42:55 +01007348 if {$ignorespace} {
7349 append cmd " -w"
7350 }
Paul Mackerras3ed31a82008-04-26 16:00:00 +10007351 if {$limitdiffs && $vfilelimit($curview) ne {}} {
7352 set cmd [concat $cmd -- $vfilelimit($curview)]
Paul Mackerras7a39a172007-10-23 10:15:11 +10007353 }
7354 if {[catch {set bdf [open $cmd r]} err]} {
Paul Mackerras8b07dca2008-11-02 22:34:47 +11007355 error_popup [mc "Error getting diffs: %s" $err]
Paul Mackerrase5c2d852005-05-11 23:44:54 +00007356 return
7357 }
Paul Mackerras8a897742008-10-27 21:36:25 +11007358 set targetline {}
Paul Mackerras8b07dca2008-11-02 22:34:47 +11007359 set diffnparents 0
Paul Mackerras4f2c2642005-07-17 11:11:44 -04007360 set diffinhdr 0
Alexander Gavrilov09c70292008-10-13 12:12:31 +04007361 set diffencoding [get_path_encoding {}]
Pat Thoyts681c3292009-03-16 10:24:40 +00007362 fconfigure $bdf -blocking 0 -encoding binary -eofchar {}
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10007363 set blobdifffd($ids) $bdf
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007364 filerun $bdf [list getblobdiffline $bdf $diffids]
Paul Mackerrase5c2d852005-05-11 23:44:54 +00007365}
7366
Paul Mackerras89b11d32006-05-02 19:55:31 +10007367proc setinlist {var i val} {
7368 global $var
7369
7370 while {[llength [set $var]] < $i} {
7371 lappend $var {}
7372 }
7373 if {[llength [set $var]] == $i} {
7374 lappend $var $val
7375 } else {
7376 lset $var $i $val
7377 }
7378}
7379
Paul Mackerras9396cd32007-06-23 20:28:15 +10007380proc makediffhdr {fname ids} {
Paul Mackerras8b07dca2008-11-02 22:34:47 +11007381 global ctext curdiffstart treediffs diffencoding
Paul Mackerras8a897742008-10-27 21:36:25 +11007382 global ctext_file_names jump_to_here targetline diffline
Paul Mackerras9396cd32007-06-23 20:28:15 +10007383
Paul Mackerras8b07dca2008-11-02 22:34:47 +11007384 set fname [encoding convertfrom $fname]
7385 set diffencoding [get_path_encoding $fname]
Paul Mackerras9396cd32007-06-23 20:28:15 +10007386 set i [lsearch -exact $treediffs($ids) $fname]
7387 if {$i >= 0} {
7388 setinlist difffilestart $i $curdiffstart
7389 }
Paul Mackerras48a81b72008-11-04 21:09:00 +11007390 lset ctext_file_names end $fname
Paul Mackerras9396cd32007-06-23 20:28:15 +10007391 set l [expr {(78 - [string length $fname]) / 2}]
7392 set pad [string range "----------------------------------------" 1 $l]
7393 $ctext insert $curdiffstart "$pad $fname $pad" filesep
Paul Mackerras8a897742008-10-27 21:36:25 +11007394 set targetline {}
7395 if {$jump_to_here ne {} && [lindex $jump_to_here 0] eq $fname} {
7396 set targetline [lindex $jump_to_here 1]
7397 }
7398 set diffline 0
Paul Mackerras9396cd32007-06-23 20:28:15 +10007399}
7400
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10007401proc getblobdiffline {bdf ids} {
Paul Mackerras9396cd32007-06-23 20:28:15 +10007402 global diffids blobdifffd ctext curdiffstart
Paul Mackerras7eab2932005-07-20 12:25:54 -04007403 global diffnexthead diffnextnote difffilestart
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04007404 global ctext_file_names ctext_file_lines
Paul Mackerras8b07dca2008-11-02 22:34:47 +11007405 global diffinhdr treediffs mergemax diffnparents
Paul Mackerras8a897742008-10-27 21:36:25 +11007406 global diffencoding jump_to_here targetline diffline
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10007407
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007408 set nr 0
Paul Mackerrase5c2d852005-05-11 23:44:54 +00007409 $ctext conf -state normal
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007410 while {[incr nr] <= 1000 && [gets $bdf line] >= 0} {
7411 if {$ids != $diffids || $bdf != $blobdifffd($ids)} {
Paul Mackerrasc21398b2009-09-07 10:08:21 +10007412 catch {close $bdf}
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007413 return 0
Paul Mackerras89b11d32006-05-02 19:55:31 +10007414 }
Paul Mackerras8b07dca2008-11-02 22:34:47 +11007415 if {![string compare -length 5 "diff " $line]} {
7416 if {![regexp {^diff (--cc|--git) } $line m type]} {
7417 set line [encoding convertfrom $line]
7418 $ctext insert end "$line\n" hunksep
7419 continue
7420 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007421 # start of a new file
Paul Mackerras8b07dca2008-11-02 22:34:47 +11007422 set diffinhdr 1
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007423 $ctext insert end "\n"
Paul Mackerras9396cd32007-06-23 20:28:15 +10007424 set curdiffstart [$ctext index "end - 1c"]
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04007425 lappend ctext_file_names ""
7426 lappend ctext_file_lines [lindex [split $curdiffstart "."] 0]
Paul Mackerras9396cd32007-06-23 20:28:15 +10007427 $ctext insert end "\n" filesep
Paul Mackerras8b07dca2008-11-02 22:34:47 +11007428
7429 if {$type eq "--cc"} {
7430 # start of a new file in a merge diff
7431 set fname [string range $line 10 end]
7432 if {[lsearch -exact $treediffs($ids) $fname] < 0} {
7433 lappend treediffs($ids) $fname
7434 add_flist [list $fname]
7435 }
7436
Paul Mackerras9396cd32007-06-23 20:28:15 +10007437 } else {
Paul Mackerras8b07dca2008-11-02 22:34:47 +11007438 set line [string range $line 11 end]
7439 # If the name hasn't changed the length will be odd,
7440 # the middle char will be a space, and the two bits either
7441 # side will be a/name and b/name, or "a/name" and "b/name".
7442 # If the name has changed we'll get "rename from" and
7443 # "rename to" or "copy from" and "copy to" lines following
7444 # this, and we'll use them to get the filenames.
7445 # This complexity is necessary because spaces in the
7446 # filename(s) don't get escaped.
7447 set l [string length $line]
7448 set i [expr {$l / 2}]
7449 if {!(($l & 1) && [string index $line $i] eq " " &&
7450 [string range $line 2 [expr {$i - 1}]] eq \
7451 [string range $line [expr {$i + 3}] end])} {
7452 continue
7453 }
7454 # unescape if quoted and chop off the a/ from the front
7455 if {[string index $line 0] eq "\""} {
7456 set fname [string range [lindex $line 0] 2 end]
7457 } else {
7458 set fname [string range $line 2 [expr {$i - 1}]]
7459 }
Paul Mackerrase5c2d852005-05-11 23:44:54 +00007460 }
Paul Mackerras9396cd32007-06-23 20:28:15 +10007461 makediffhdr $fname $ids
7462
Paul Mackerras48a81b72008-11-04 21:09:00 +11007463 } elseif {![string compare -length 16 "* Unmerged path " $line]} {
7464 set fname [encoding convertfrom [string range $line 16 end]]
7465 $ctext insert end "\n"
7466 set curdiffstart [$ctext index "end - 1c"]
7467 lappend ctext_file_names $fname
7468 lappend ctext_file_lines [lindex [split $curdiffstart "."] 0]
7469 $ctext insert end "$line\n" filesep
7470 set i [lsearch -exact $treediffs($ids) $fname]
7471 if {$i >= 0} {
7472 setinlist difffilestart $i $curdiffstart
7473 }
7474
Paul Mackerras8b07dca2008-11-02 22:34:47 +11007475 } elseif {![string compare -length 2 "@@" $line]} {
7476 regexp {^@@+} $line ats
Alexander Gavrilov09c70292008-10-13 12:12:31 +04007477 set line [encoding convertfrom $diffencoding $line]
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007478 $ctext insert end "$line\n" hunksep
Paul Mackerras8b07dca2008-11-02 22:34:47 +11007479 if {[regexp { \+(\d+),\d+ @@} $line m nl]} {
7480 set diffline $nl
7481 }
7482 set diffnparents [expr {[string length $ats] - 1}]
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007483 set diffinhdr 0
Paul Mackerras9396cd32007-06-23 20:28:15 +10007484
7485 } elseif {$diffinhdr} {
Johannes Sixt5e85ec42007-10-02 16:16:54 +02007486 if {![string compare -length 12 "rename from " $line]} {
Johannes Sixtd1cb2982007-08-16 14:32:29 +02007487 set fname [string range $line [expr 6 + [string first " from " $line] ] end]
Paul Mackerras9396cd32007-06-23 20:28:15 +10007488 if {[string index $fname 0] eq "\""} {
7489 set fname [lindex $fname 0]
7490 }
Alexander Gavrilov09c70292008-10-13 12:12:31 +04007491 set fname [encoding convertfrom $fname]
Paul Mackerras9396cd32007-06-23 20:28:15 +10007492 set i [lsearch -exact $treediffs($ids) $fname]
7493 if {$i >= 0} {
7494 setinlist difffilestart $i $curdiffstart
7495 }
Johannes Sixtd1cb2982007-08-16 14:32:29 +02007496 } elseif {![string compare -length 10 $line "rename to "] ||
7497 ![string compare -length 8 $line "copy to "]} {
7498 set fname [string range $line [expr 4 + [string first " to " $line] ] end]
Paul Mackerras9396cd32007-06-23 20:28:15 +10007499 if {[string index $fname 0] eq "\""} {
7500 set fname [lindex $fname 0]
7501 }
7502 makediffhdr $fname $ids
7503 } elseif {[string compare -length 3 $line "---"] == 0} {
7504 # do nothing
7505 continue
7506 } elseif {[string compare -length 3 $line "+++"] == 0} {
7507 set diffinhdr 0
7508 continue
7509 }
7510 $ctext insert end "$line\n" filesep
7511
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007512 } else {
Pat Thoyts681c3292009-03-16 10:24:40 +00007513 set line [string map {\x1A ^Z} \
7514 [encoding convertfrom $diffencoding $line]]
Paul Mackerras8b07dca2008-11-02 22:34:47 +11007515 # parse the prefix - one ' ', '-' or '+' for each parent
7516 set prefix [string range $line 0 [expr {$diffnparents - 1}]]
7517 set tag [expr {$diffnparents > 1? "m": "d"}]
7518 if {[string trim $prefix " -+"] eq {}} {
7519 # prefix only has " ", "-" and "+" in it: normal diff line
7520 set num [string first "-" $prefix]
7521 if {$num >= 0} {
7522 # removed line, first parent with line is $num
7523 if {$num >= $mergemax} {
7524 set num "max"
7525 }
7526 $ctext insert end "$line\n" $tag$num
7527 } else {
7528 set tags {}
7529 if {[string first "+" $prefix] >= 0} {
7530 # added line
7531 lappend tags ${tag}result
7532 if {$diffnparents > 1} {
7533 set num [string first " " $prefix]
7534 if {$num >= 0} {
7535 if {$num >= $mergemax} {
7536 set num "max"
7537 }
7538 lappend tags m$num
7539 }
7540 }
7541 }
7542 if {$targetline ne {}} {
7543 if {$diffline == $targetline} {
7544 set seehere [$ctext index "end - 1 chars"]
7545 set targetline {}
7546 } else {
7547 incr diffline
7548 }
7549 }
7550 $ctext insert end "$line\n" $tags
7551 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007552 } else {
Paul Mackerras9396cd32007-06-23 20:28:15 +10007553 # "\ No newline at end of file",
7554 # or something else we don't recognize
7555 $ctext insert end "$line\n" hunksep
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007556 }
Paul Mackerrase5c2d852005-05-11 23:44:54 +00007557 }
7558 }
Paul Mackerras8b07dca2008-11-02 22:34:47 +11007559 if {[info exists seehere]} {
7560 mark_ctext_line [lindex [split $seehere .] 0]
7561 }
Paul Mackerrase5c2d852005-05-11 23:44:54 +00007562 $ctext conf -state disabled
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007563 if {[eof $bdf]} {
Paul Mackerrasc21398b2009-09-07 10:08:21 +10007564 catch {close $bdf}
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007565 return 0
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10007566 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007567 return [expr {$nr >= 1000? 2: 1}]
Paul Mackerrase5c2d852005-05-11 23:44:54 +00007568}
7569
Paul Mackerrasa8d610a2007-04-19 11:39:12 +10007570proc changediffdisp {} {
7571 global ctext diffelide
7572
7573 $ctext tag conf d0 -elide [lindex $diffelide 0]
Paul Mackerras8b07dca2008-11-02 22:34:47 +11007574 $ctext tag conf dresult -elide [lindex $diffelide 1]
Paul Mackerrasa8d610a2007-04-19 11:39:12 +10007575}
7576
Paul Mackerrasf4c54b32008-05-10 13:15:36 +10007577proc highlightfile {loc cline} {
7578 global ctext cflist cflist_top
7579
7580 $ctext yview $loc
7581 $cflist tag remove highlight $cflist_top.0 "$cflist_top.0 lineend"
7582 $cflist tag add highlight $cline.0 "$cline.0 lineend"
7583 $cflist see $cline.0
7584 set cflist_top $cline
7585}
7586
OGAWA Hirofumi67c22872006-09-27 12:32:19 +09007587proc prevfile {} {
Paul Mackerrasf4c54b32008-05-10 13:15:36 +10007588 global difffilestart ctext cmitmode
7589
7590 if {$cmitmode eq "tree"} return
7591 set prev 0.0
7592 set prevline 1
OGAWA Hirofumi67c22872006-09-27 12:32:19 +09007593 set here [$ctext index @0,0]
7594 foreach loc $difffilestart {
7595 if {[$ctext compare $loc >= $here]} {
Paul Mackerrasf4c54b32008-05-10 13:15:36 +10007596 highlightfile $prev $prevline
OGAWA Hirofumi67c22872006-09-27 12:32:19 +09007597 return
7598 }
7599 set prev $loc
Paul Mackerrasf4c54b32008-05-10 13:15:36 +10007600 incr prevline
OGAWA Hirofumi67c22872006-09-27 12:32:19 +09007601 }
Paul Mackerrasf4c54b32008-05-10 13:15:36 +10007602 highlightfile $prev $prevline
OGAWA Hirofumi67c22872006-09-27 12:32:19 +09007603}
7604
Paul Mackerras39ad8572005-05-19 12:35:53 +00007605proc nextfile {} {
Paul Mackerrasf4c54b32008-05-10 13:15:36 +10007606 global difffilestart ctext cmitmode
7607
7608 if {$cmitmode eq "tree"} return
Paul Mackerras39ad8572005-05-19 12:35:53 +00007609 set here [$ctext index @0,0]
Paul Mackerrasf4c54b32008-05-10 13:15:36 +10007610 set line 1
Paul Mackerras7fcceed2006-04-27 19:21:49 +10007611 foreach loc $difffilestart {
Paul Mackerrasf4c54b32008-05-10 13:15:36 +10007612 incr line
Paul Mackerras7fcceed2006-04-27 19:21:49 +10007613 if {[$ctext compare $loc > $here]} {
Paul Mackerrasf4c54b32008-05-10 13:15:36 +10007614 highlightfile $loc $line
OGAWA Hirofumi67c22872006-09-27 12:32:19 +09007615 return
Paul Mackerras39ad8572005-05-19 12:35:53 +00007616 }
7617 }
Paul Mackerras1db95b02005-05-09 04:08:39 +00007618}
7619
Paul Mackerras3ea06f92006-05-24 10:16:03 +10007620proc clear_ctext {{first 1.0}} {
7621 global ctext smarktop smarkbot
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04007622 global ctext_file_names ctext_file_lines
Paul Mackerras97645682007-08-23 22:24:38 +10007623 global pendinglinks
Paul Mackerras3ea06f92006-05-24 10:16:03 +10007624
Paul Mackerras1902c272006-05-25 21:25:13 +10007625 set l [lindex [split $first .] 0]
7626 if {![info exists smarktop] || [$ctext compare $first < $smarktop.0]} {
7627 set smarktop $l
Paul Mackerras3ea06f92006-05-24 10:16:03 +10007628 }
Paul Mackerras1902c272006-05-25 21:25:13 +10007629 if {![info exists smarkbot] || [$ctext compare $first < $smarkbot.0]} {
7630 set smarkbot $l
Paul Mackerras3ea06f92006-05-24 10:16:03 +10007631 }
7632 $ctext delete $first end
Paul Mackerras97645682007-08-23 22:24:38 +10007633 if {$first eq "1.0"} {
7634 catch {unset pendinglinks}
7635 }
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04007636 set ctext_file_names {}
7637 set ctext_file_lines {}
Paul Mackerras3ea06f92006-05-24 10:16:03 +10007638}
7639
Paul Mackerras32f1b3e2007-09-28 21:27:39 +10007640proc settabs {{firstab {}}} {
Paul Mackerras9c311b32007-10-04 22:27:13 +10007641 global firsttabstop tabstop ctext have_tk85
Paul Mackerras32f1b3e2007-09-28 21:27:39 +10007642
7643 if {$firstab ne {} && $have_tk85} {
7644 set firsttabstop $firstab
7645 }
Paul Mackerras9c311b32007-10-04 22:27:13 +10007646 set w [font measure textfont "0"]
Paul Mackerras32f1b3e2007-09-28 21:27:39 +10007647 if {$firsttabstop != 0} {
Paul Mackerras64b5f142007-10-04 22:19:24 +10007648 $ctext conf -tabs [list [expr {($firsttabstop + $tabstop) * $w}] \
7649 [expr {($firsttabstop + 2 * $tabstop) * $w}]]
Paul Mackerras32f1b3e2007-09-28 21:27:39 +10007650 } elseif {$have_tk85 || $tabstop != 8} {
7651 $ctext conf -tabs [expr {$tabstop * $w}]
7652 } else {
7653 $ctext conf -tabs {}
7654 }
Paul Mackerras3ea06f92006-05-24 10:16:03 +10007655}
7656
7657proc incrsearch {name ix op} {
Paul Mackerras1902c272006-05-25 21:25:13 +10007658 global ctext searchstring searchdirn
Paul Mackerras3ea06f92006-05-24 10:16:03 +10007659
7660 $ctext tag remove found 1.0 end
Paul Mackerras1902c272006-05-25 21:25:13 +10007661 if {[catch {$ctext index anchor}]} {
7662 # no anchor set, use start of selection, or of visible area
7663 set sel [$ctext tag ranges sel]
7664 if {$sel ne {}} {
7665 $ctext mark set anchor [lindex $sel 0]
7666 } elseif {$searchdirn eq "-forwards"} {
7667 $ctext mark set anchor @0,0
7668 } else {
7669 $ctext mark set anchor @0,[winfo height $ctext]
7670 }
7671 }
Paul Mackerras3ea06f92006-05-24 10:16:03 +10007672 if {$searchstring ne {}} {
Paul Mackerras1902c272006-05-25 21:25:13 +10007673 set here [$ctext search $searchdirn -- $searchstring anchor]
7674 if {$here ne {}} {
7675 $ctext see $here
7676 }
Paul Mackerras3ea06f92006-05-24 10:16:03 +10007677 searchmarkvisible 1
7678 }
7679}
7680
7681proc dosearch {} {
Paul Mackerras1902c272006-05-25 21:25:13 +10007682 global sstring ctext searchstring searchdirn
Paul Mackerras3ea06f92006-05-24 10:16:03 +10007683
7684 focus $sstring
7685 $sstring icursor end
Paul Mackerras1902c272006-05-25 21:25:13 +10007686 set searchdirn -forwards
7687 if {$searchstring ne {}} {
7688 set sel [$ctext tag ranges sel]
7689 if {$sel ne {}} {
7690 set start "[lindex $sel 0] + 1c"
7691 } elseif {[catch {set start [$ctext index anchor]}]} {
7692 set start "@0,0"
7693 }
7694 set match [$ctext search -count mlen -- $searchstring $start]
7695 $ctext tag remove sel 1.0 end
7696 if {$match eq {}} {
7697 bell
7698 return
7699 }
7700 $ctext see $match
7701 set mend "$match + $mlen c"
7702 $ctext tag add sel $match $mend
7703 $ctext mark unset anchor
Paul Mackerras3ea06f92006-05-24 10:16:03 +10007704 }
Paul Mackerras1902c272006-05-25 21:25:13 +10007705}
7706
7707proc dosearchback {} {
7708 global sstring ctext searchstring searchdirn
7709
7710 focus $sstring
7711 $sstring icursor end
7712 set searchdirn -backwards
7713 if {$searchstring ne {}} {
7714 set sel [$ctext tag ranges sel]
7715 if {$sel ne {}} {
7716 set start [lindex $sel 0]
7717 } elseif {[catch {set start [$ctext index anchor]}]} {
7718 set start @0,[winfo height $ctext]
7719 }
7720 set match [$ctext search -backwards -count ml -- $searchstring $start]
7721 $ctext tag remove sel 1.0 end
7722 if {$match eq {}} {
7723 bell
7724 return
7725 }
7726 $ctext see $match
7727 set mend "$match + $ml c"
7728 $ctext tag add sel $match $mend
7729 $ctext mark unset anchor
7730 }
Paul Mackerras3ea06f92006-05-24 10:16:03 +10007731}
7732
7733proc searchmark {first last} {
7734 global ctext searchstring
7735
7736 set mend $first.0
7737 while {1} {
7738 set match [$ctext search -count mlen -- $searchstring $mend $last.end]
7739 if {$match eq {}} break
7740 set mend "$match + $mlen c"
7741 $ctext tag add found $match $mend
7742 }
7743}
7744
7745proc searchmarkvisible {doall} {
7746 global ctext smarktop smarkbot
7747
7748 set topline [lindex [split [$ctext index @0,0] .] 0]
7749 set botline [lindex [split [$ctext index @0,[winfo height $ctext]] .] 0]
7750 if {$doall || $botline < $smarktop || $topline > $smarkbot} {
7751 # no overlap with previous
7752 searchmark $topline $botline
7753 set smarktop $topline
7754 set smarkbot $botline
7755 } else {
7756 if {$topline < $smarktop} {
7757 searchmark $topline [expr {$smarktop-1}]
7758 set smarktop $topline
7759 }
7760 if {$botline > $smarkbot} {
7761 searchmark [expr {$smarkbot+1}] $botline
7762 set smarkbot $botline
7763 }
7764 }
7765}
7766
7767proc scrolltext {f0 f1} {
Paul Mackerras1902c272006-05-25 21:25:13 +10007768 global searchstring
Paul Mackerras3ea06f92006-05-24 10:16:03 +10007769
Pekka Kaitaniemi8809d692008-03-08 14:27:23 +02007770 .bleft.bottom.sb set $f0 $f1
Paul Mackerras3ea06f92006-05-24 10:16:03 +10007771 if {$searchstring ne {}} {
7772 searchmarkvisible 0
7773 }
7774}
7775
Paul Mackerras1d10f362005-05-15 12:55:47 +00007776proc setcoords {} {
Paul Mackerras9c311b32007-10-04 22:27:13 +10007777 global linespc charspc canvx0 canvy0
Paul Mackerrasf6075eb2005-08-18 09:30:10 +10007778 global xspc1 xspc2 lthickness
Paul Mackerras8d858d12005-08-05 09:52:16 +10007779
Paul Mackerras9c311b32007-10-04 22:27:13 +10007780 set linespc [font metrics mainfont -linespace]
7781 set charspc [font measure mainfont "m"]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11007782 set canvy0 [expr {int(3 + 0.5 * $linespc)}]
7783 set canvx0 [expr {int(3 + 0.5 * $linespc)}]
Paul Mackerrasf6075eb2005-08-18 09:30:10 +10007784 set lthickness [expr {int($linespc / 9) + 1}]
Paul Mackerras8d858d12005-08-05 09:52:16 +10007785 set xspc1(0) $linespc
7786 set xspc2 $linespc
Paul Mackerras9a40c502005-05-12 23:46:16 +00007787}
Paul Mackerras1db95b02005-05-09 04:08:39 +00007788
Paul Mackerras1d10f362005-05-15 12:55:47 +00007789proc redisplay {} {
Paul Mackerrasbe0cd092006-03-31 09:55:11 +11007790 global canv
Paul Mackerras9f1afe02006-02-19 22:44:47 +11007791 global selectedline
7792
7793 set ymax [lindex [$canv cget -scrollregion] 3]
7794 if {$ymax eq {} || $ymax == 0} return
7795 set span [$canv yview]
7796 clear_display
Paul Mackerrasbe0cd092006-03-31 09:55:11 +11007797 setcanvscroll
Paul Mackerras9f1afe02006-02-19 22:44:47 +11007798 allcanvs yview moveto [lindex $span 0]
7799 drawvisible
Paul Mackerras94b4a692008-05-20 20:51:06 +10007800 if {$selectedline ne {}} {
Paul Mackerras9f1afe02006-02-19 22:44:47 +11007801 selectline $selectedline 0
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10007802 allcanvs yview moveto [lindex $span 0]
Paul Mackerras1db95b02005-05-09 04:08:39 +00007803 }
7804}
Paul Mackerras1d10f362005-05-15 12:55:47 +00007805
Paul Mackerras0ed1dd32007-10-06 18:27:37 +10007806proc parsefont {f n} {
7807 global fontattr
7808
7809 set fontattr($f,family) [lindex $n 0]
7810 set s [lindex $n 1]
7811 if {$s eq {} || $s == 0} {
7812 set s 10
7813 } elseif {$s < 0} {
7814 set s [expr {int(-$s / [winfo fpixels . 1p] + 0.5)}]
Paul Mackerras9c311b32007-10-04 22:27:13 +10007815 }
Paul Mackerras0ed1dd32007-10-06 18:27:37 +10007816 set fontattr($f,size) $s
7817 set fontattr($f,weight) normal
7818 set fontattr($f,slant) roman
7819 foreach style [lrange $n 2 end] {
7820 switch -- $style {
7821 "normal" -
7822 "bold" {set fontattr($f,weight) $style}
7823 "roman" -
7824 "italic" {set fontattr($f,slant) $style}
7825 }
Paul Mackerras9c311b32007-10-04 22:27:13 +10007826 }
Paul Mackerras0ed1dd32007-10-06 18:27:37 +10007827}
7828
7829proc fontflags {f {isbold 0}} {
7830 global fontattr
7831
7832 return [list -family $fontattr($f,family) -size $fontattr($f,size) \
7833 -weight [expr {$isbold? "bold": $fontattr($f,weight)}] \
7834 -slant $fontattr($f,slant)]
7835}
7836
7837proc fontname {f} {
7838 global fontattr
7839
7840 set n [list $fontattr($f,family) $fontattr($f,size)]
7841 if {$fontattr($f,weight) eq "bold"} {
7842 lappend n "bold"
Paul Mackerras9c311b32007-10-04 22:27:13 +10007843 }
Paul Mackerras0ed1dd32007-10-06 18:27:37 +10007844 if {$fontattr($f,slant) eq "italic"} {
7845 lappend n "italic"
Paul Mackerras9c311b32007-10-04 22:27:13 +10007846 }
Paul Mackerras0ed1dd32007-10-06 18:27:37 +10007847 return $n
Paul Mackerras9c311b32007-10-04 22:27:13 +10007848}
7849
Paul Mackerras1d10f362005-05-15 12:55:47 +00007850proc incrfont {inc} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11007851 global mainfont textfont ctext canv cflist showrefstop
Paul Mackerras0ed1dd32007-10-06 18:27:37 +10007852 global stopped entries fontattr
7853
Paul Mackerras1d10f362005-05-15 12:55:47 +00007854 unmarkmatches
Paul Mackerras0ed1dd32007-10-06 18:27:37 +10007855 set s $fontattr(mainfont,size)
Paul Mackerras9c311b32007-10-04 22:27:13 +10007856 incr s $inc
7857 if {$s < 1} {
7858 set s 1
7859 }
Paul Mackerras0ed1dd32007-10-06 18:27:37 +10007860 set fontattr(mainfont,size) $s
Paul Mackerras9c311b32007-10-04 22:27:13 +10007861 font config mainfont -size $s
7862 font config mainfontbold -size $s
Paul Mackerras0ed1dd32007-10-06 18:27:37 +10007863 set mainfont [fontname mainfont]
7864 set s $fontattr(textfont,size)
Paul Mackerras9c311b32007-10-04 22:27:13 +10007865 incr s $inc
7866 if {$s < 1} {
7867 set s 1
7868 }
Paul Mackerras0ed1dd32007-10-06 18:27:37 +10007869 set fontattr(textfont,size) $s
Paul Mackerras9c311b32007-10-04 22:27:13 +10007870 font config textfont -size $s
7871 font config textfontbold -size $s
Paul Mackerras0ed1dd32007-10-06 18:27:37 +10007872 set textfont [fontname textfont]
Paul Mackerras1d10f362005-05-15 12:55:47 +00007873 setcoords
Paul Mackerras32f1b3e2007-09-28 21:27:39 +10007874 settabs
Paul Mackerras1d10f362005-05-15 12:55:47 +00007875 redisplay
Paul Mackerras1db95b02005-05-09 04:08:39 +00007876}
Paul Mackerras1d10f362005-05-15 12:55:47 +00007877
Paul Mackerrasee3dc722005-06-25 16:37:13 +10007878proc clearsha1 {} {
7879 global sha1entry sha1string
7880 if {[string length $sha1string] == 40} {
7881 $sha1entry delete 0 end
7882 }
7883}
7884
Paul Mackerras887fe3c2005-05-21 07:35:37 +00007885proc sha1change {n1 n2 op} {
7886 global sha1string currentid sha1but
7887 if {$sha1string == {}
7888 || ([info exists currentid] && $sha1string == $currentid)} {
7889 set state disabled
7890 } else {
7891 set state normal
7892 }
7893 if {[$sha1but cget -state] == $state} return
7894 if {$state == "normal"} {
Christian Stimmingd990ced2007-11-07 18:42:55 +01007895 $sha1but conf -state normal -relief raised -text "[mc "Goto:"] "
Paul Mackerras887fe3c2005-05-21 07:35:37 +00007896 } else {
Christian Stimmingd990ced2007-11-07 18:42:55 +01007897 $sha1but conf -state disabled -relief flat -text "[mc "SHA1 ID:"] "
Paul Mackerras887fe3c2005-05-21 07:35:37 +00007898 }
7899}
7900
7901proc gotocommit {} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11007902 global sha1string tagids headids curview varcid
Paul Mackerrasf3b8b3c2005-07-18 12:16:35 -04007903
Paul Mackerras887fe3c2005-05-21 07:35:37 +00007904 if {$sha1string == {}
7905 || ([info exists currentid] && $sha1string == $currentid)} return
7906 if {[info exists tagids($sha1string)]} {
7907 set id $tagids($sha1string)
Stephen Rothwelle1007122006-03-30 16:13:12 +11007908 } elseif {[info exists headids($sha1string)]} {
7909 set id $headids($sha1string)
Paul Mackerras887fe3c2005-05-21 07:35:37 +00007910 } else {
7911 set id [string tolower $sha1string]
Paul Mackerrasf3b8b3c2005-07-18 12:16:35 -04007912 if {[regexp {^[0-9a-f]{4,39}$} $id]} {
Paul Mackerrasd375ef92008-10-21 10:18:12 +11007913 set matches [longid $id]
Paul Mackerrasf3b8b3c2005-07-18 12:16:35 -04007914 if {$matches ne {}} {
7915 if {[llength $matches] > 1} {
Christian Stimmingd990ced2007-11-07 18:42:55 +01007916 error_popup [mc "Short SHA1 id %s is ambiguous" $id]
Paul Mackerrasf3b8b3c2005-07-18 12:16:35 -04007917 return
7918 }
Paul Mackerrasd375ef92008-10-21 10:18:12 +11007919 set id [lindex $matches 0]
Paul Mackerrasf3b8b3c2005-07-18 12:16:35 -04007920 }
Thomas Rast9bf3acf2009-08-13 09:25:03 +02007921 } else {
7922 if {[catch {set id [exec git rev-parse --verify $sha1string]}]} {
7923 error_popup [mc "Revision %s is not known" $sha1string]
7924 return
7925 }
Paul Mackerrasf3b8b3c2005-07-18 12:16:35 -04007926 }
Paul Mackerras887fe3c2005-05-21 07:35:37 +00007927 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11007928 if {[commitinview $id $curview]} {
7929 selectline [rowofcommit $id] 1
Paul Mackerras887fe3c2005-05-21 07:35:37 +00007930 return
7931 }
Paul Mackerrasf3b8b3c2005-07-18 12:16:35 -04007932 if {[regexp {^[0-9a-fA-F]{4,}$} $sha1string]} {
Christian Stimmingd990ced2007-11-07 18:42:55 +01007933 set msg [mc "SHA1 id %s is not known" $sha1string]
Paul Mackerras887fe3c2005-05-21 07:35:37 +00007934 } else {
Thomas Rast9bf3acf2009-08-13 09:25:03 +02007935 set msg [mc "Revision %s is not in the current view" $sha1string]
Paul Mackerras887fe3c2005-05-21 07:35:37 +00007936 }
Christian Stimmingd990ced2007-11-07 18:42:55 +01007937 error_popup $msg
Paul Mackerras887fe3c2005-05-21 07:35:37 +00007938}
7939
Paul Mackerras84ba7342005-06-17 00:12:26 +00007940proc lineenter {x y id} {
7941 global hoverx hovery hoverid hovertimer
7942 global commitinfo canv
7943
Paul Mackerras8ed16482006-03-02 22:56:44 +11007944 if {![info exists commitinfo($id)] && ![getcommit $id]} return
Paul Mackerras84ba7342005-06-17 00:12:26 +00007945 set hoverx $x
7946 set hovery $y
7947 set hoverid $id
7948 if {[info exists hovertimer]} {
7949 after cancel $hovertimer
7950 }
7951 set hovertimer [after 500 linehover]
7952 $canv delete hover
7953}
7954
7955proc linemotion {x y id} {
7956 global hoverx hovery hoverid hovertimer
7957
7958 if {[info exists hoverid] && $id == $hoverid} {
7959 set hoverx $x
7960 set hovery $y
7961 if {[info exists hovertimer]} {
7962 after cancel $hovertimer
7963 }
7964 set hovertimer [after 500 linehover]
7965 }
7966}
7967
7968proc lineleave {id} {
7969 global hoverid hovertimer canv
7970
7971 if {[info exists hoverid] && $id == $hoverid} {
7972 $canv delete hover
7973 if {[info exists hovertimer]} {
7974 after cancel $hovertimer
7975 unset hovertimer
7976 }
7977 unset hoverid
7978 }
7979}
7980
7981proc linehover {} {
7982 global hoverx hovery hoverid hovertimer
7983 global canv linespc lthickness
Paul Mackerras9c311b32007-10-04 22:27:13 +10007984 global commitinfo
Paul Mackerras84ba7342005-06-17 00:12:26 +00007985
7986 set text [lindex $commitinfo($hoverid) 0]
7987 set ymax [lindex [$canv cget -scrollregion] 3]
7988 if {$ymax == {}} return
7989 set yfrac [lindex [$canv yview] 0]
7990 set x [expr {$hoverx + 2 * $linespc}]
7991 set y [expr {$hovery + $yfrac * $ymax - $linespc / 2}]
7992 set x0 [expr {$x - 2 * $lthickness}]
7993 set y0 [expr {$y - 2 * $lthickness}]
Paul Mackerras9c311b32007-10-04 22:27:13 +10007994 set x1 [expr {$x + [font measure mainfont $text] + 2 * $lthickness}]
Paul Mackerras84ba7342005-06-17 00:12:26 +00007995 set y1 [expr {$y + $linespc + 2 * $lthickness}]
7996 set t [$canv create rectangle $x0 $y0 $x1 $y1 \
7997 -fill \#ffff80 -outline black -width 1 -tags hover]
7998 $canv raise $t
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10007999 set t [$canv create text $x $y -anchor nw -text $text -tags hover \
Paul Mackerras9c311b32007-10-04 22:27:13 +10008000 -font mainfont]
Paul Mackerras84ba7342005-06-17 00:12:26 +00008001 $canv raise $t
8002}
8003
Paul Mackerras9843c302005-08-30 10:57:11 +10008004proc clickisonarrow {id y} {
Paul Mackerras50b44ec2006-04-04 10:16:22 +10008005 global lthickness
Paul Mackerras9843c302005-08-30 10:57:11 +10008006
Paul Mackerras50b44ec2006-04-04 10:16:22 +10008007 set ranges [rowranges $id]
Paul Mackerras9843c302005-08-30 10:57:11 +10008008 set thresh [expr {2 * $lthickness + 6}]
Paul Mackerras50b44ec2006-04-04 10:16:22 +10008009 set n [expr {[llength $ranges] - 1}]
Paul Mackerrasf6342482006-02-28 10:02:03 +11008010 for {set i 1} {$i < $n} {incr i} {
Paul Mackerras50b44ec2006-04-04 10:16:22 +10008011 set row [lindex $ranges $i]
Paul Mackerrasf6342482006-02-28 10:02:03 +11008012 if {abs([yc $row] - $y) < $thresh} {
8013 return $i
Paul Mackerras9843c302005-08-30 10:57:11 +10008014 }
8015 }
8016 return {}
8017}
8018
Paul Mackerrasf6342482006-02-28 10:02:03 +11008019proc arrowjump {id n y} {
Paul Mackerras50b44ec2006-04-04 10:16:22 +10008020 global canv
Paul Mackerras9843c302005-08-30 10:57:11 +10008021
Paul Mackerrasf6342482006-02-28 10:02:03 +11008022 # 1 <-> 2, 3 <-> 4, etc...
8023 set n [expr {(($n - 1) ^ 1) + 1}]
Paul Mackerras50b44ec2006-04-04 10:16:22 +10008024 set row [lindex [rowranges $id] $n]
Paul Mackerrasf6342482006-02-28 10:02:03 +11008025 set yt [yc $row]
Paul Mackerras9843c302005-08-30 10:57:11 +10008026 set ymax [lindex [$canv cget -scrollregion] 3]
8027 if {$ymax eq {} || $ymax <= 0} return
8028 set view [$canv yview]
8029 set yspan [expr {[lindex $view 1] - [lindex $view 0]}]
8030 set yfrac [expr {$yt / $ymax - $yspan / 2}]
8031 if {$yfrac < 0} {
8032 set yfrac 0
8033 }
Paul Mackerrasf6342482006-02-28 10:02:03 +11008034 allcanvs yview moveto $yfrac
Paul Mackerras9843c302005-08-30 10:57:11 +10008035}
8036
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10008037proc lineclick {x y id isnew} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11008038 global ctext commitinfo children canv thickerline curview
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008039
Paul Mackerras8ed16482006-03-02 22:56:44 +11008040 if {![info exists commitinfo($id)] && ![getcommit $id]} return
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008041 unmarkmatches
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10008042 unselectline
Paul Mackerras9843c302005-08-30 10:57:11 +10008043 normalline
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008044 $canv delete hover
Paul Mackerras9843c302005-08-30 10:57:11 +10008045 # draw this line thicker than normal
Paul Mackerras9843c302005-08-30 10:57:11 +10008046 set thickerline $id
Paul Mackerrasc934a8a2006-03-02 23:00:44 +11008047 drawlines $id
Paul Mackerras9843c302005-08-30 10:57:11 +10008048 if {$isnew} {
8049 set ymax [lindex [$canv cget -scrollregion] 3]
8050 if {$ymax eq {}} return
8051 set yfrac [lindex [$canv yview] 0]
8052 set y [expr {$y + $yfrac * $ymax}]
8053 }
8054 set dirn [clickisonarrow $id $y]
8055 if {$dirn ne {}} {
8056 arrowjump $id $dirn $y
8057 return
8058 }
8059
8060 if {$isnew} {
8061 addtohistory [list lineclick $x $y $id 0]
8062 }
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008063 # fill the details pane with info about this line
8064 $ctext conf -state normal
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008065 clear_ctext
Paul Mackerras32f1b3e2007-09-28 21:27:39 +10008066 settabs 0
Christian Stimmingd990ced2007-11-07 18:42:55 +01008067 $ctext insert end "[mc "Parent"]:\t"
Paul Mackerras97645682007-08-23 22:24:38 +10008068 $ctext insert end $id link0
8069 setlink $id link0
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008070 set info $commitinfo($id)
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10008071 $ctext insert end "\n\t[lindex $info 0]\n"
Christian Stimmingd990ced2007-11-07 18:42:55 +01008072 $ctext insert end "\t[mc "Author"]:\t[lindex $info 1]\n"
Paul Mackerras232475d2005-11-15 10:34:03 +11008073 set date [formatdate [lindex $info 2]]
Christian Stimmingd990ced2007-11-07 18:42:55 +01008074 $ctext insert end "\t[mc "Date"]:\t$date\n"
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10008075 set kids $children($curview,$id)
Paul Mackerras79b2c752006-04-02 20:47:40 +10008076 if {$kids ne {}} {
Christian Stimmingd990ced2007-11-07 18:42:55 +01008077 $ctext insert end "\n[mc "Children"]:"
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10008078 set i 0
Paul Mackerras79b2c752006-04-02 20:47:40 +10008079 foreach child $kids {
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10008080 incr i
Paul Mackerras8ed16482006-03-02 22:56:44 +11008081 if {![info exists commitinfo($child)] && ![getcommit $child]} continue
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008082 set info $commitinfo($child)
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10008083 $ctext insert end "\n\t"
Paul Mackerras97645682007-08-23 22:24:38 +10008084 $ctext insert end $child link$i
8085 setlink $child link$i
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10008086 $ctext insert end "\n\t[lindex $info 0]"
Christian Stimmingd990ced2007-11-07 18:42:55 +01008087 $ctext insert end "\n\t[mc "Author"]:\t[lindex $info 1]"
Paul Mackerras232475d2005-11-15 10:34:03 +11008088 set date [formatdate [lindex $info 2]]
Christian Stimmingd990ced2007-11-07 18:42:55 +01008089 $ctext insert end "\n\t[mc "Date"]:\t$date\n"
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008090 }
8091 }
8092 $ctext conf -state disabled
Paul Mackerras7fcceed2006-04-27 19:21:49 +10008093 init_flist {}
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008094}
8095
Paul Mackerras9843c302005-08-30 10:57:11 +10008096proc normalline {} {
8097 global thickerline
8098 if {[info exists thickerline]} {
Paul Mackerrasc934a8a2006-03-02 23:00:44 +11008099 set id $thickerline
Paul Mackerras9843c302005-08-30 10:57:11 +10008100 unset thickerline
Paul Mackerrasc934a8a2006-03-02 23:00:44 +11008101 drawlines $id
Paul Mackerras9843c302005-08-30 10:57:11 +10008102 }
8103}
8104
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008105proc selbyid {id} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11008106 global curview
8107 if {[commitinview $id $curview]} {
8108 selectline [rowofcommit $id] 1
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008109 }
8110}
8111
8112proc mstime {} {
8113 global startmstime
8114 if {![info exists startmstime]} {
8115 set startmstime [clock clicks -milliseconds]
8116 }
8117 return [format "%.3f" [expr {([clock click -milliseconds] - $startmstime) / 1000.0}]]
8118}
8119
8120proc rowmenu {x y id} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11008121 global rowctxmenu selectedline rowmenuid curview
Paul Mackerrasb9fdba72009-04-09 09:34:46 +10008122 global nullid nullid2 fakerowmenu mainhead markedid
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008123
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10008124 stopfinding
Paul Mackerras219ea3a2006-09-07 10:21:39 +10008125 set rowmenuid $id
Paul Mackerras94b4a692008-05-20 20:51:06 +10008126 if {$selectedline eq {} || [rowofcommit $id] eq $selectedline} {
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008127 set state disabled
8128 } else {
8129 set state normal
8130 }
Paul Mackerras8f489362007-07-13 19:49:37 +10008131 if {$id ne $nullid && $id ne $nullid2} {
Paul Mackerras219ea3a2006-09-07 10:21:39 +10008132 set menu $rowctxmenu
Michele Ballabio5e3502d2008-05-02 17:46:20 +02008133 if {$mainhead ne {}} {
Johannes Sixtda12e592008-12-03 13:43:20 +01008134 $menu entryconfigure 7 -label [mc "Reset %s branch to here" $mainhead] -state normal
Michele Ballabio5e3502d2008-05-02 17:46:20 +02008135 } else {
8136 $menu entryconfigure 7 -label [mc "Detached head: can't reset" $mainhead] -state disabled
8137 }
Paul Mackerrasb9fdba72009-04-09 09:34:46 +10008138 if {[info exists markedid] && $markedid ne $id} {
8139 $menu entryconfigure 9 -state normal
8140 $menu entryconfigure 10 -state normal
Paul Mackerras010509f2009-04-09 22:10:20 +10008141 $menu entryconfigure 11 -state normal
Paul Mackerrasb9fdba72009-04-09 09:34:46 +10008142 } else {
8143 $menu entryconfigure 9 -state disabled
8144 $menu entryconfigure 10 -state disabled
Paul Mackerras010509f2009-04-09 22:10:20 +10008145 $menu entryconfigure 11 -state disabled
Paul Mackerrasb9fdba72009-04-09 09:34:46 +10008146 }
Paul Mackerras219ea3a2006-09-07 10:21:39 +10008147 } else {
8148 set menu $fakerowmenu
8149 }
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11008150 $menu entryconfigure [mca "Diff this -> selected"] -state $state
8151 $menu entryconfigure [mca "Diff selected -> this"] -state $state
8152 $menu entryconfigure [mca "Make patch"] -state $state
Paul Mackerras219ea3a2006-09-07 10:21:39 +10008153 tk_popup $menu $x $y
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008154}
8155
Paul Mackerrasb9fdba72009-04-09 09:34:46 +10008156proc markhere {} {
8157 global rowmenuid markedid canv
8158
8159 set markedid $rowmenuid
8160 make_idmark $markedid
8161}
8162
8163proc gotomark {} {
8164 global markedid
8165
8166 if {[info exists markedid]} {
8167 selbyid $markedid
8168 }
8169}
8170
8171proc replace_by_kids {l r} {
8172 global curview children
8173
8174 set id [commitonrow $r]
8175 set l [lreplace $l 0 0]
8176 foreach kid $children($curview,$id) {
8177 lappend l [rowofcommit $kid]
8178 }
8179 return [lsort -integer -decreasing -unique $l]
8180}
8181
8182proc find_common_desc {} {
8183 global markedid rowmenuid curview children
8184
8185 if {![info exists markedid]} return
8186 if {![commitinview $markedid $curview] ||
8187 ![commitinview $rowmenuid $curview]} return
8188 #set t1 [clock clicks -milliseconds]
8189 set l1 [list [rowofcommit $markedid]]
8190 set l2 [list [rowofcommit $rowmenuid]]
8191 while 1 {
8192 set r1 [lindex $l1 0]
8193 set r2 [lindex $l2 0]
8194 if {$r1 eq {} || $r2 eq {}} break
8195 if {$r1 == $r2} {
8196 selectline $r1 1
8197 break
8198 }
8199 if {$r1 > $r2} {
8200 set l1 [replace_by_kids $l1 $r1]
8201 } else {
8202 set l2 [replace_by_kids $l2 $r2]
8203 }
8204 }
8205 #set t2 [clock clicks -milliseconds]
8206 #puts "took [expr {$t2-$t1}]ms"
8207}
8208
Paul Mackerras010509f2009-04-09 22:10:20 +10008209proc compare_commits {} {
8210 global markedid rowmenuid curview children
8211
8212 if {![info exists markedid]} return
8213 if {![commitinview $markedid $curview]} return
8214 addtohistory [list do_cmp_commits $markedid $rowmenuid]
8215 do_cmp_commits $markedid $rowmenuid
8216}
8217
8218proc getpatchid {id} {
8219 global patchids
8220
8221 if {![info exists patchids($id)]} {
Paul Mackerras6f63fc12009-04-21 22:22:31 +10008222 set cmd [diffcmd [list $id] {-p --root}]
8223 # trim off the initial "|"
8224 set cmd [lrange $cmd 1 end]
8225 if {[catch {
8226 set x [eval exec $cmd | git patch-id]
8227 set patchids($id) [lindex $x 0]
8228 }]} {
8229 set patchids($id) "error"
8230 }
Paul Mackerras010509f2009-04-09 22:10:20 +10008231 }
8232 return $patchids($id)
8233}
8234
8235proc do_cmp_commits {a b} {
8236 global ctext curview parents children patchids commitinfo
8237
8238 $ctext conf -state normal
8239 clear_ctext
8240 init_flist {}
8241 for {set i 0} {$i < 100} {incr i} {
Paul Mackerras010509f2009-04-09 22:10:20 +10008242 set skipa 0
8243 set skipb 0
8244 if {[llength $parents($curview,$a)] > 1} {
Paul Mackerras6f63fc12009-04-21 22:22:31 +10008245 appendshortlink $a [mc "Skipping merge commit "] "\n"
Paul Mackerras010509f2009-04-09 22:10:20 +10008246 set skipa 1
8247 } else {
8248 set patcha [getpatchid $a]
8249 }
8250 if {[llength $parents($curview,$b)] > 1} {
Paul Mackerras6f63fc12009-04-21 22:22:31 +10008251 appendshortlink $b [mc "Skipping merge commit "] "\n"
Paul Mackerras010509f2009-04-09 22:10:20 +10008252 set skipb 1
8253 } else {
8254 set patchb [getpatchid $b]
8255 }
8256 if {!$skipa && !$skipb} {
8257 set heada [lindex $commitinfo($a) 0]
8258 set headb [lindex $commitinfo($b) 0]
Paul Mackerras6f63fc12009-04-21 22:22:31 +10008259 if {$patcha eq "error"} {
8260 appendshortlink $a [mc "Error getting patch ID for "] \
8261 [mc " - stopping\n"]
8262 break
8263 }
8264 if {$patchb eq "error"} {
8265 appendshortlink $b [mc "Error getting patch ID for "] \
8266 [mc " - stopping\n"]
8267 break
8268 }
Paul Mackerras010509f2009-04-09 22:10:20 +10008269 if {$patcha eq $patchb} {
8270 if {$heada eq $headb} {
Paul Mackerras6f63fc12009-04-21 22:22:31 +10008271 appendshortlink $a [mc "Commit "]
8272 appendshortlink $b " == " " $heada\n"
Paul Mackerras010509f2009-04-09 22:10:20 +10008273 } else {
Paul Mackerras6f63fc12009-04-21 22:22:31 +10008274 appendshortlink $a [mc "Commit "] " $heada\n"
8275 appendshortlink $b [mc " is the same patch as\n "] \
8276 " $headb\n"
Paul Mackerras010509f2009-04-09 22:10:20 +10008277 }
8278 set skipa 1
8279 set skipb 1
8280 } else {
8281 $ctext insert end "\n"
Paul Mackerras6f63fc12009-04-21 22:22:31 +10008282 appendshortlink $a [mc "Commit "] " $heada\n"
8283 appendshortlink $b [mc " differs from\n "] \
8284 " $headb\n"
Paul Mackerrasc21398b2009-09-07 10:08:21 +10008285 $ctext insert end [mc "Diff of commits:\n\n"]
8286 $ctext conf -state disabled
8287 update
8288 diffcommits $a $b
8289 return
Paul Mackerras010509f2009-04-09 22:10:20 +10008290 }
8291 }
8292 if {$skipa} {
8293 if {[llength $children($curview,$a)] != 1} {
8294 $ctext insert end "\n"
Paul Mackerras6f63fc12009-04-21 22:22:31 +10008295 appendshortlink $a [mc "Commit "] \
8296 [mc " has %s children - stopping\n" \
8297 [llength $children($curview,$a)]]
Paul Mackerras010509f2009-04-09 22:10:20 +10008298 break
8299 }
8300 set a [lindex $children($curview,$a) 0]
8301 }
8302 if {$skipb} {
8303 if {[llength $children($curview,$b)] != 1} {
Paul Mackerras6f63fc12009-04-21 22:22:31 +10008304 appendshortlink $b [mc "Commit "] \
8305 [mc " has %s children - stopping\n" \
8306 [llength $children($curview,$b)]]
Paul Mackerras010509f2009-04-09 22:10:20 +10008307 break
8308 }
8309 set b [lindex $children($curview,$b) 0]
8310 }
8311 }
8312 $ctext conf -state disabled
8313}
8314
Paul Mackerrasc21398b2009-09-07 10:08:21 +10008315proc diffcommits {a b} {
8316 global diffcontext diffids blobdifffd diffinhdr
8317
8318 set tmpdir [gitknewtmpdir]
8319 set fna [file join $tmpdir "commit-[string range $a 0 7]"]
8320 set fnb [file join $tmpdir "commit-[string range $b 0 7]"]
8321 if {[catch {
8322 exec git diff-tree -p --pretty $a >$fna
8323 exec git diff-tree -p --pretty $b >$fnb
8324 } err]} {
8325 error_popup [mc "Error writing commit to file: %s" $err]
8326 return
8327 }
8328 if {[catch {
8329 set fd [open "| diff -U$diffcontext $fna $fnb" r]
8330 } err]} {
8331 error_popup [mc "Error diffing commits: %s" $err]
8332 return
8333 }
8334 set diffids [list commits $a $b]
8335 set blobdifffd($diffids) $fd
8336 set diffinhdr 0
8337 filerun $fd [list getblobdiffline $fd $diffids]
8338}
8339
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008340proc diffvssel {dirn} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11008341 global rowmenuid selectedline
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008342
Paul Mackerras94b4a692008-05-20 20:51:06 +10008343 if {$selectedline eq {}} return
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008344 if {$dirn} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11008345 set oldid [commitonrow $selectedline]
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008346 set newid $rowmenuid
8347 } else {
8348 set oldid $rowmenuid
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11008349 set newid [commitonrow $selectedline]
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008350 }
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10008351 addtohistory [list doseldiff $oldid $newid]
8352 doseldiff $oldid $newid
8353}
8354
8355proc doseldiff {oldid newid} {
Paul Mackerras7fcceed2006-04-27 19:21:49 +10008356 global ctext
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10008357 global commitinfo
8358
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008359 $ctext conf -state normal
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008360 clear_ctext
Christian Stimmingd990ced2007-11-07 18:42:55 +01008361 init_flist [mc "Top"]
8362 $ctext insert end "[mc "From"] "
Paul Mackerras97645682007-08-23 22:24:38 +10008363 $ctext insert end $oldid link0
8364 setlink $oldid link0
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10008365 $ctext insert end "\n "
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008366 $ctext insert end [lindex $commitinfo($oldid) 0]
Christian Stimmingd990ced2007-11-07 18:42:55 +01008367 $ctext insert end "\n\n[mc "To"] "
Paul Mackerras97645682007-08-23 22:24:38 +10008368 $ctext insert end $newid link1
8369 setlink $newid link1
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10008370 $ctext insert end "\n "
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008371 $ctext insert end [lindex $commitinfo($newid) 0]
8372 $ctext insert end "\n"
8373 $ctext conf -state disabled
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008374 $ctext tag remove found 1.0 end
Paul Mackerrasd3272442005-11-28 20:41:56 +11008375 startdiff [list $oldid $newid]
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008376}
8377
Paul Mackerras74daedb2005-06-27 19:27:32 +10008378proc mkpatch {} {
8379 global rowmenuid currentid commitinfo patchtop patchnum
8380
8381 if {![info exists currentid]} return
8382 set oldid $currentid
8383 set oldhead [lindex $commitinfo($oldid) 0]
8384 set newid $rowmenuid
8385 set newhead [lindex $commitinfo($newid) 0]
8386 set top .patch
8387 set patchtop $top
8388 catch {destroy $top}
8389 toplevel $top
Alexander Gavrilove7d64002008-11-11 23:55:42 +03008390 make_transient $top .
Christian Stimmingd990ced2007-11-07 18:42:55 +01008391 label $top.title -text [mc "Generate patch"]
Paul Mackerras4a2139f2005-06-29 09:47:48 +10008392 grid $top.title - -pady 10
Christian Stimmingd990ced2007-11-07 18:42:55 +01008393 label $top.from -text [mc "From:"]
Paul Mackerras4a2139f2005-06-29 09:47:48 +10008394 entry $top.fromsha1 -width 40 -relief flat
Paul Mackerras74daedb2005-06-27 19:27:32 +10008395 $top.fromsha1 insert 0 $oldid
8396 $top.fromsha1 conf -state readonly
8397 grid $top.from $top.fromsha1 -sticky w
Paul Mackerras4a2139f2005-06-29 09:47:48 +10008398 entry $top.fromhead -width 60 -relief flat
Paul Mackerras74daedb2005-06-27 19:27:32 +10008399 $top.fromhead insert 0 $oldhead
8400 $top.fromhead conf -state readonly
8401 grid x $top.fromhead -sticky w
Christian Stimmingd990ced2007-11-07 18:42:55 +01008402 label $top.to -text [mc "To:"]
Paul Mackerras4a2139f2005-06-29 09:47:48 +10008403 entry $top.tosha1 -width 40 -relief flat
Paul Mackerras74daedb2005-06-27 19:27:32 +10008404 $top.tosha1 insert 0 $newid
8405 $top.tosha1 conf -state readonly
8406 grid $top.to $top.tosha1 -sticky w
Paul Mackerras4a2139f2005-06-29 09:47:48 +10008407 entry $top.tohead -width 60 -relief flat
Paul Mackerras74daedb2005-06-27 19:27:32 +10008408 $top.tohead insert 0 $newhead
8409 $top.tohead conf -state readonly
8410 grid x $top.tohead -sticky w
Christian Stimmingd990ced2007-11-07 18:42:55 +01008411 button $top.rev -text [mc "Reverse"] -command mkpatchrev -padx 5
Paul Mackerras74daedb2005-06-27 19:27:32 +10008412 grid $top.rev x -pady 10
Christian Stimmingd990ced2007-11-07 18:42:55 +01008413 label $top.flab -text [mc "Output file:"]
Paul Mackerras74daedb2005-06-27 19:27:32 +10008414 entry $top.fname -width 60
8415 $top.fname insert 0 [file normalize "patch$patchnum.patch"]
8416 incr patchnum
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10008417 grid $top.flab $top.fname -sticky w
Paul Mackerras74daedb2005-06-27 19:27:32 +10008418 frame $top.buts
Christian Stimmingd990ced2007-11-07 18:42:55 +01008419 button $top.buts.gen -text [mc "Generate"] -command mkpatchgo
8420 button $top.buts.can -text [mc "Cancel"] -command mkpatchcan
Alexander Gavrilov76f15942008-11-02 21:59:44 +03008421 bind $top <Key-Return> mkpatchgo
8422 bind $top <Key-Escape> mkpatchcan
Paul Mackerras74daedb2005-06-27 19:27:32 +10008423 grid $top.buts.gen $top.buts.can
8424 grid columnconfigure $top.buts 0 -weight 1 -uniform a
8425 grid columnconfigure $top.buts 1 -weight 1 -uniform a
8426 grid $top.buts - -pady 10 -sticky ew
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10008427 focus $top.fname
Paul Mackerras74daedb2005-06-27 19:27:32 +10008428}
8429
8430proc mkpatchrev {} {
8431 global patchtop
8432
8433 set oldid [$patchtop.fromsha1 get]
8434 set oldhead [$patchtop.fromhead get]
8435 set newid [$patchtop.tosha1 get]
8436 set newhead [$patchtop.tohead get]
8437 foreach e [list fromsha1 fromhead tosha1 tohead] \
8438 v [list $newid $newhead $oldid $oldhead] {
8439 $patchtop.$e conf -state normal
8440 $patchtop.$e delete 0 end
8441 $patchtop.$e insert 0 $v
8442 $patchtop.$e conf -state readonly
8443 }
8444}
8445
8446proc mkpatchgo {} {
Paul Mackerras8f489362007-07-13 19:49:37 +10008447 global patchtop nullid nullid2
Paul Mackerras74daedb2005-06-27 19:27:32 +10008448
8449 set oldid [$patchtop.fromsha1 get]
8450 set newid [$patchtop.tosha1 get]
8451 set fname [$patchtop.fname get]
Paul Mackerras8f489362007-07-13 19:49:37 +10008452 set cmd [diffcmd [list $oldid $newid] -p]
Paul Mackerrasd372e212007-09-15 12:08:38 +10008453 # trim off the initial "|"
8454 set cmd [lrange $cmd 1 end]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10008455 lappend cmd >$fname &
8456 if {[catch {eval exec $cmd} err]} {
Alexander Gavrilov84a76f12008-11-02 21:59:45 +03008457 error_popup "[mc "Error creating patch:"] $err" $patchtop
Paul Mackerras74daedb2005-06-27 19:27:32 +10008458 }
8459 catch {destroy $patchtop}
8460 unset patchtop
8461}
8462
8463proc mkpatchcan {} {
8464 global patchtop
8465
8466 catch {destroy $patchtop}
8467 unset patchtop
8468}
8469
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10008470proc mktag {} {
8471 global rowmenuid mktagtop commitinfo
8472
8473 set top .maketag
8474 set mktagtop $top
8475 catch {destroy $top}
8476 toplevel $top
Alexander Gavrilove7d64002008-11-11 23:55:42 +03008477 make_transient $top .
Christian Stimmingd990ced2007-11-07 18:42:55 +01008478 label $top.title -text [mc "Create tag"]
Paul Mackerras4a2139f2005-06-29 09:47:48 +10008479 grid $top.title - -pady 10
Christian Stimmingd990ced2007-11-07 18:42:55 +01008480 label $top.id -text [mc "ID:"]
Paul Mackerras4a2139f2005-06-29 09:47:48 +10008481 entry $top.sha1 -width 40 -relief flat
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10008482 $top.sha1 insert 0 $rowmenuid
8483 $top.sha1 conf -state readonly
8484 grid $top.id $top.sha1 -sticky w
Paul Mackerras4a2139f2005-06-29 09:47:48 +10008485 entry $top.head -width 60 -relief flat
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10008486 $top.head insert 0 [lindex $commitinfo($rowmenuid) 0]
8487 $top.head conf -state readonly
8488 grid x $top.head -sticky w
Christian Stimmingd990ced2007-11-07 18:42:55 +01008489 label $top.tlab -text [mc "Tag name:"]
Paul Mackerras4a2139f2005-06-29 09:47:48 +10008490 entry $top.tag -width 60
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10008491 grid $top.tlab $top.tag -sticky w
8492 frame $top.buts
Christian Stimmingd990ced2007-11-07 18:42:55 +01008493 button $top.buts.gen -text [mc "Create"] -command mktaggo
8494 button $top.buts.can -text [mc "Cancel"] -command mktagcan
Alexander Gavrilov76f15942008-11-02 21:59:44 +03008495 bind $top <Key-Return> mktaggo
8496 bind $top <Key-Escape> mktagcan
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10008497 grid $top.buts.gen $top.buts.can
8498 grid columnconfigure $top.buts 0 -weight 1 -uniform a
8499 grid columnconfigure $top.buts 1 -weight 1 -uniform a
8500 grid $top.buts - -pady 10 -sticky ew
8501 focus $top.tag
8502}
8503
8504proc domktag {} {
8505 global mktagtop env tagids idtags
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10008506
8507 set id [$mktagtop.sha1 get]
8508 set tag [$mktagtop.tag get]
8509 if {$tag == {}} {
Alexander Gavrilov84a76f12008-11-02 21:59:45 +03008510 error_popup [mc "No tag name specified"] $mktagtop
8511 return 0
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10008512 }
8513 if {[info exists tagids($tag)]} {
Alexander Gavrilov84a76f12008-11-02 21:59:45 +03008514 error_popup [mc "Tag \"%s\" already exists" $tag] $mktagtop
8515 return 0
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10008516 }
8517 if {[catch {
Gerrit Pape48750d62008-02-11 10:57:40 +00008518 exec git tag $tag $id
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10008519 } err]} {
Alexander Gavrilov84a76f12008-11-02 21:59:45 +03008520 error_popup "[mc "Error creating tag:"] $err" $mktagtop
8521 return 0
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10008522 }
8523
8524 set tagids($tag) $id
8525 lappend idtags($id) $tag
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10008526 redrawtags $id
Paul Mackerrasceadfe92006-08-08 20:55:36 +10008527 addedtag $id
Paul Mackerras887c9962007-08-20 19:36:20 +10008528 dispneartags 0
8529 run refill_reflist
Alexander Gavrilov84a76f12008-11-02 21:59:45 +03008530 return 1
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10008531}
8532
8533proc redrawtags {id} {
Paul Mackerrasb9fdba72009-04-09 09:34:46 +10008534 global canv linehtag idpos currentid curview cmitlisted markedid
Paul Mackerrasc11ff122008-05-26 10:11:33 +10008535 global canvxmax iddrawn circleitem mainheadid circlecolors
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10008536
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11008537 if {![commitinview $id $curview]} return
Paul Mackerras322a8cc2006-10-15 18:03:46 +10008538 if {![info exists iddrawn($id)]} return
Paul Mackerrasfc2a2562007-12-26 23:03:43 +11008539 set row [rowofcommit $id]
Paul Mackerrasc11ff122008-05-26 10:11:33 +10008540 if {$id eq $mainheadid} {
8541 set ofill yellow
8542 } else {
8543 set ofill [lindex $circlecolors $cmitlisted($curview,$id)]
8544 }
8545 $canv itemconf $circleitem($row) -fill $ofill
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10008546 $canv delete tag.$id
8547 set xt [eval drawtags $id $idpos($id)]
Paul Mackerras28593d32008-11-13 23:01:46 +11008548 $canv coords $linehtag($id) $xt [lindex $idpos($id) 2]
8549 set text [$canv itemcget $linehtag($id) -text]
8550 set font [$canv itemcget $linehtag($id) -font]
Paul Mackerrasfc2a2562007-12-26 23:03:43 +11008551 set xr [expr {$xt + [font measure $font $text]}]
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10008552 if {$xr > $canvxmax} {
8553 set canvxmax $xr
8554 setcanvscroll
8555 }
Paul Mackerrasfc2a2562007-12-26 23:03:43 +11008556 if {[info exists currentid] && $currentid == $id} {
Paul Mackerras28593d32008-11-13 23:01:46 +11008557 make_secsel $id
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10008558 }
Paul Mackerrasb9fdba72009-04-09 09:34:46 +10008559 if {[info exists markedid] && $markedid eq $id} {
8560 make_idmark $id
8561 }
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10008562}
8563
8564proc mktagcan {} {
8565 global mktagtop
8566
8567 catch {destroy $mktagtop}
8568 unset mktagtop
8569}
8570
8571proc mktaggo {} {
Alexander Gavrilov84a76f12008-11-02 21:59:45 +03008572 if {![domktag]} return
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10008573 mktagcan
8574}
8575
Paul Mackerras4a2139f2005-06-29 09:47:48 +10008576proc writecommit {} {
8577 global rowmenuid wrcomtop commitinfo wrcomcmd
8578
8579 set top .writecommit
8580 set wrcomtop $top
8581 catch {destroy $top}
8582 toplevel $top
Alexander Gavrilove7d64002008-11-11 23:55:42 +03008583 make_transient $top .
Christian Stimmingd990ced2007-11-07 18:42:55 +01008584 label $top.title -text [mc "Write commit to file"]
Paul Mackerras4a2139f2005-06-29 09:47:48 +10008585 grid $top.title - -pady 10
Christian Stimmingd990ced2007-11-07 18:42:55 +01008586 label $top.id -text [mc "ID:"]
Paul Mackerras4a2139f2005-06-29 09:47:48 +10008587 entry $top.sha1 -width 40 -relief flat
8588 $top.sha1 insert 0 $rowmenuid
8589 $top.sha1 conf -state readonly
8590 grid $top.id $top.sha1 -sticky w
8591 entry $top.head -width 60 -relief flat
8592 $top.head insert 0 [lindex $commitinfo($rowmenuid) 0]
8593 $top.head conf -state readonly
8594 grid x $top.head -sticky w
Christian Stimmingd990ced2007-11-07 18:42:55 +01008595 label $top.clab -text [mc "Command:"]
Paul Mackerras4a2139f2005-06-29 09:47:48 +10008596 entry $top.cmd -width 60 -textvariable wrcomcmd
8597 grid $top.clab $top.cmd -sticky w -pady 10
Christian Stimmingd990ced2007-11-07 18:42:55 +01008598 label $top.flab -text [mc "Output file:"]
Paul Mackerras4a2139f2005-06-29 09:47:48 +10008599 entry $top.fname -width 60
8600 $top.fname insert 0 [file normalize "commit-[string range $rowmenuid 0 6]"]
8601 grid $top.flab $top.fname -sticky w
8602 frame $top.buts
Christian Stimmingd990ced2007-11-07 18:42:55 +01008603 button $top.buts.gen -text [mc "Write"] -command wrcomgo
8604 button $top.buts.can -text [mc "Cancel"] -command wrcomcan
Alexander Gavrilov76f15942008-11-02 21:59:44 +03008605 bind $top <Key-Return> wrcomgo
8606 bind $top <Key-Escape> wrcomcan
Paul Mackerras4a2139f2005-06-29 09:47:48 +10008607 grid $top.buts.gen $top.buts.can
8608 grid columnconfigure $top.buts 0 -weight 1 -uniform a
8609 grid columnconfigure $top.buts 1 -weight 1 -uniform a
8610 grid $top.buts - -pady 10 -sticky ew
8611 focus $top.fname
8612}
8613
8614proc wrcomgo {} {
8615 global wrcomtop
8616
8617 set id [$wrcomtop.sha1 get]
8618 set cmd "echo $id | [$wrcomtop.cmd get]"
8619 set fname [$wrcomtop.fname get]
8620 if {[catch {exec sh -c $cmd >$fname &} err]} {
Alexander Gavrilov84a76f12008-11-02 21:59:45 +03008621 error_popup "[mc "Error writing commit:"] $err" $wrcomtop
Paul Mackerras4a2139f2005-06-29 09:47:48 +10008622 }
8623 catch {destroy $wrcomtop}
8624 unset wrcomtop
8625}
8626
8627proc wrcomcan {} {
8628 global wrcomtop
8629
8630 catch {destroy $wrcomtop}
8631 unset wrcomtop
8632}
8633
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10008634proc mkbranch {} {
8635 global rowmenuid mkbrtop
8636
8637 set top .makebranch
8638 catch {destroy $top}
8639 toplevel $top
Alexander Gavrilove7d64002008-11-11 23:55:42 +03008640 make_transient $top .
Christian Stimmingd990ced2007-11-07 18:42:55 +01008641 label $top.title -text [mc "Create new branch"]
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10008642 grid $top.title - -pady 10
Christian Stimmingd990ced2007-11-07 18:42:55 +01008643 label $top.id -text [mc "ID:"]
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10008644 entry $top.sha1 -width 40 -relief flat
8645 $top.sha1 insert 0 $rowmenuid
8646 $top.sha1 conf -state readonly
8647 grid $top.id $top.sha1 -sticky w
Christian Stimmingd990ced2007-11-07 18:42:55 +01008648 label $top.nlab -text [mc "Name:"]
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10008649 entry $top.name -width 40
8650 grid $top.nlab $top.name -sticky w
8651 frame $top.buts
Christian Stimmingd990ced2007-11-07 18:42:55 +01008652 button $top.buts.go -text [mc "Create"] -command [list mkbrgo $top]
8653 button $top.buts.can -text [mc "Cancel"] -command "catch {destroy $top}"
Alexander Gavrilov76f15942008-11-02 21:59:44 +03008654 bind $top <Key-Return> [list mkbrgo $top]
8655 bind $top <Key-Escape> "catch {destroy $top}"
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10008656 grid $top.buts.go $top.buts.can
8657 grid columnconfigure $top.buts 0 -weight 1 -uniform a
8658 grid columnconfigure $top.buts 1 -weight 1 -uniform a
8659 grid $top.buts - -pady 10 -sticky ew
8660 focus $top.name
8661}
8662
8663proc mkbrgo {top} {
8664 global headids idheads
8665
8666 set name [$top.name get]
8667 set id [$top.sha1 get]
Alexander Gavrilovbee866f2008-10-08 11:05:35 +04008668 set cmdargs {}
8669 set old_id {}
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10008670 if {$name eq {}} {
Alexander Gavrilov84a76f12008-11-02 21:59:45 +03008671 error_popup [mc "Please specify a name for the new branch"] $top
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10008672 return
8673 }
Alexander Gavrilovbee866f2008-10-08 11:05:35 +04008674 if {[info exists headids($name)]} {
8675 if {![confirm_popup [mc \
Alexander Gavrilov84a76f12008-11-02 21:59:45 +03008676 "Branch '%s' already exists. Overwrite?" $name] $top]} {
Alexander Gavrilovbee866f2008-10-08 11:05:35 +04008677 return
8678 }
8679 set old_id $headids($name)
8680 lappend cmdargs -f
8681 }
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10008682 catch {destroy $top}
Alexander Gavrilovbee866f2008-10-08 11:05:35 +04008683 lappend cmdargs $name $id
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10008684 nowbusy newbranch
8685 update
8686 if {[catch {
Alexander Gavrilovbee866f2008-10-08 11:05:35 +04008687 eval exec git branch $cmdargs
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10008688 } err]} {
8689 notbusy newbranch
8690 error_popup $err
8691 } else {
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10008692 notbusy newbranch
Alexander Gavrilovbee866f2008-10-08 11:05:35 +04008693 if {$old_id ne {}} {
8694 movehead $id $name
8695 movedhead $id $name
8696 redrawtags $old_id
8697 redrawtags $id
8698 } else {
8699 set headids($name) $id
8700 lappend idheads($id) $name
8701 addedhead $id $name
8702 redrawtags $id
8703 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10008704 dispneartags 0
Paul Mackerras887c9962007-08-20 19:36:20 +10008705 run refill_reflist
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10008706 }
8707}
8708
Alexander Gavrilov15e35052008-11-02 21:59:47 +03008709proc exec_citool {tool_args {baseid {}}} {
8710 global commitinfo env
8711
8712 set save_env [array get env GIT_AUTHOR_*]
8713
8714 if {$baseid ne {}} {
8715 if {![info exists commitinfo($baseid)]} {
8716 getcommit $baseid
8717 }
8718 set author [lindex $commitinfo($baseid) 1]
8719 set date [lindex $commitinfo($baseid) 2]
8720 if {[regexp {^\s*(\S.*\S|\S)\s*<(.*)>\s*$} \
8721 $author author name email]
8722 && $date ne {}} {
8723 set env(GIT_AUTHOR_NAME) $name
8724 set env(GIT_AUTHOR_EMAIL) $email
8725 set env(GIT_AUTHOR_DATE) $date
8726 }
8727 }
8728
8729 eval exec git citool $tool_args &
8730
8731 array unset env GIT_AUTHOR_*
8732 array set env $save_env
8733}
8734
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10008735proc cherrypick {} {
Paul Mackerras468bcae2008-03-03 10:19:35 +11008736 global rowmenuid curview
Paul Mackerrasb8a938c2008-02-13 22:12:31 +11008737 global mainhead mainheadid
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10008738
Paul Mackerrase11f1232007-06-16 20:29:25 +10008739 set oldhead [exec git rev-parse HEAD]
8740 set dheads [descheads $rowmenuid]
8741 if {$dheads ne {} && [lsearch -exact $dheads $oldhead] >= 0} {
Christian Stimmingd990ced2007-11-07 18:42:55 +01008742 set ok [confirm_popup [mc "Commit %s is already\
8743 included in branch %s -- really re-apply it?" \
8744 [string range $rowmenuid 0 7] $mainhead]]
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10008745 if {!$ok} return
8746 }
Christian Stimmingd990ced2007-11-07 18:42:55 +01008747 nowbusy cherrypick [mc "Cherry-picking"]
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10008748 update
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10008749 # Unfortunately git-cherry-pick writes stuff to stderr even when
8750 # no error occurs, and exec takes that as an indication of error...
8751 if {[catch {exec sh -c "git cherry-pick -r $rowmenuid 2>&1"} err]} {
8752 notbusy cherrypick
Alexander Gavrilov15e35052008-11-02 21:59:47 +03008753 if {[regexp -line \
Paul Mackerras887a7912008-11-08 21:37:09 +11008754 {Entry '(.*)' (would be overwritten by merge|not uptodate)} \
8755 $err msg fname]} {
8756 error_popup [mc "Cherry-pick failed because of local changes\
8757 to file '%s'.\nPlease commit, reset or stash\
8758 your changes and try again." $fname]
8759 } elseif {[regexp -line \
8760 {^(CONFLICT \(.*\):|Automatic cherry-pick failed)} \
8761 $err]} {
8762 if {[confirm_popup [mc "Cherry-pick failed because of merge\
8763 conflict.\nDo you wish to run git citool to\
8764 resolve it?"]]} {
8765 # Force citool to read MERGE_MSG
8766 file delete [file join [gitdir] "GITGUI_MSG"]
8767 exec_citool {} $rowmenuid
8768 }
Alexander Gavrilov15e35052008-11-02 21:59:47 +03008769 } else {
8770 error_popup $err
8771 }
Paul Mackerras887a7912008-11-08 21:37:09 +11008772 run updatecommits
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10008773 return
8774 }
8775 set newhead [exec git rev-parse HEAD]
8776 if {$newhead eq $oldhead} {
8777 notbusy cherrypick
Christian Stimmingd990ced2007-11-07 18:42:55 +01008778 error_popup [mc "No changes committed"]
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10008779 return
8780 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10008781 addnewchild $newhead $oldhead
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11008782 if {[commitinview $oldhead $curview]} {
Paul Mackerrascdc84292008-11-18 19:54:14 +11008783 # XXX this isn't right if we have a path limit...
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11008784 insertrow $newhead $oldhead $curview
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10008785 if {$mainhead ne {}} {
Paul Mackerrase11f1232007-06-16 20:29:25 +10008786 movehead $newhead $mainhead
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10008787 movedhead $newhead $mainhead
8788 }
Paul Mackerrasc11ff122008-05-26 10:11:33 +10008789 set mainheadid $newhead
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10008790 redrawtags $oldhead
8791 redrawtags $newhead
Paul Mackerras46308ea2008-01-15 22:16:32 +11008792 selbyid $newhead
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10008793 }
8794 notbusy cherrypick
8795}
8796
Paul Mackerras6fb735a2006-10-19 10:09:06 +10008797proc resethead {} {
Paul Mackerrasb8a938c2008-02-13 22:12:31 +11008798 global mainhead rowmenuid confirm_ok resettype
Paul Mackerras6fb735a2006-10-19 10:09:06 +10008799
8800 set confirm_ok 0
8801 set w ".confirmreset"
8802 toplevel $w
Alexander Gavrilove7d64002008-11-11 23:55:42 +03008803 make_transient $w .
Christian Stimmingd990ced2007-11-07 18:42:55 +01008804 wm title $w [mc "Confirm reset"]
Paul Mackerras6fb735a2006-10-19 10:09:06 +10008805 message $w.m -text \
Christian Stimmingd990ced2007-11-07 18:42:55 +01008806 [mc "Reset branch %s to %s?" $mainhead [string range $rowmenuid 0 7]] \
Paul Mackerras6fb735a2006-10-19 10:09:06 +10008807 -justify center -aspect 1000
8808 pack $w.m -side top -fill x -padx 20 -pady 20
8809 frame $w.f -relief sunken -border 2
Christian Stimmingd990ced2007-11-07 18:42:55 +01008810 message $w.f.rt -text [mc "Reset type:"] -aspect 1000
Paul Mackerras6fb735a2006-10-19 10:09:06 +10008811 grid $w.f.rt -sticky w
8812 set resettype mixed
8813 radiobutton $w.f.soft -value soft -variable resettype -justify left \
Christian Stimmingd990ced2007-11-07 18:42:55 +01008814 -text [mc "Soft: Leave working tree and index untouched"]
Paul Mackerras6fb735a2006-10-19 10:09:06 +10008815 grid $w.f.soft -sticky w
8816 radiobutton $w.f.mixed -value mixed -variable resettype -justify left \
Christian Stimmingd990ced2007-11-07 18:42:55 +01008817 -text [mc "Mixed: Leave working tree untouched, reset index"]
Paul Mackerras6fb735a2006-10-19 10:09:06 +10008818 grid $w.f.mixed -sticky w
8819 radiobutton $w.f.hard -value hard -variable resettype -justify left \
Christian Stimmingd990ced2007-11-07 18:42:55 +01008820 -text [mc "Hard: Reset working tree and index\n(discard ALL local changes)"]
Paul Mackerras6fb735a2006-10-19 10:09:06 +10008821 grid $w.f.hard -sticky w
8822 pack $w.f -side top -fill x
Christian Stimmingd990ced2007-11-07 18:42:55 +01008823 button $w.ok -text [mc OK] -command "set confirm_ok 1; destroy $w"
Paul Mackerras6fb735a2006-10-19 10:09:06 +10008824 pack $w.ok -side left -fill x -padx 20 -pady 20
Christian Stimmingd990ced2007-11-07 18:42:55 +01008825 button $w.cancel -text [mc Cancel] -command "destroy $w"
Alexander Gavrilov76f15942008-11-02 21:59:44 +03008826 bind $w <Key-Escape> [list destroy $w]
Paul Mackerras6fb735a2006-10-19 10:09:06 +10008827 pack $w.cancel -side right -fill x -padx 20 -pady 20
8828 bind $w <Visibility> "grab $w; focus $w"
8829 tkwait window $w
8830 if {!$confirm_ok} return
Paul Mackerras706d6c32007-06-26 11:09:49 +10008831 if {[catch {set fd [open \
Paul Mackerras08ba8202008-05-12 10:18:38 +10008832 [list | git reset --$resettype $rowmenuid 2>@1] r]} err]} {
Paul Mackerras6fb735a2006-10-19 10:09:06 +10008833 error_popup $err
8834 } else {
Paul Mackerras706d6c32007-06-26 11:09:49 +10008835 dohidelocalchanges
Paul Mackerrasa137a902007-10-23 21:12:49 +10008836 filerun $fd [list readresetstat $fd]
Christian Stimmingd990ced2007-11-07 18:42:55 +01008837 nowbusy reset [mc "Resetting"]
Paul Mackerras46308ea2008-01-15 22:16:32 +11008838 selbyid $rowmenuid
Paul Mackerras706d6c32007-06-26 11:09:49 +10008839 }
8840}
8841
Paul Mackerrasa137a902007-10-23 21:12:49 +10008842proc readresetstat {fd} {
8843 global mainhead mainheadid showlocalchanges rprogcoord
Paul Mackerras706d6c32007-06-26 11:09:49 +10008844
8845 if {[gets $fd line] >= 0} {
8846 if {[regexp {([0-9]+)% \(([0-9]+)/([0-9]+)\)} $line match p m n]} {
Paul Mackerrasa137a902007-10-23 21:12:49 +10008847 set rprogcoord [expr {1.0 * $m / $n}]
8848 adjustprogress
Paul Mackerras706d6c32007-06-26 11:09:49 +10008849 }
8850 return 1
8851 }
Paul Mackerrasa137a902007-10-23 21:12:49 +10008852 set rprogcoord 0
8853 adjustprogress
Paul Mackerras706d6c32007-06-26 11:09:49 +10008854 notbusy reset
8855 if {[catch {close $fd} err]} {
8856 error_popup $err
8857 }
8858 set oldhead $mainheadid
8859 set newhead [exec git rev-parse HEAD]
8860 if {$newhead ne $oldhead} {
8861 movehead $newhead $mainhead
8862 movedhead $newhead $mainhead
8863 set mainheadid $newhead
Paul Mackerras6fb735a2006-10-19 10:09:06 +10008864 redrawtags $oldhead
Paul Mackerras706d6c32007-06-26 11:09:49 +10008865 redrawtags $newhead
Paul Mackerras6fb735a2006-10-19 10:09:06 +10008866 }
8867 if {$showlocalchanges} {
8868 doshowlocalchanges
8869 }
Paul Mackerras706d6c32007-06-26 11:09:49 +10008870 return 0
Paul Mackerras6fb735a2006-10-19 10:09:06 +10008871}
8872
Paul Mackerras10299152006-08-02 09:52:01 +10008873# context menu for a head
8874proc headmenu {x y id head} {
Paul Mackerras00609462007-06-17 17:08:35 +10008875 global headmenuid headmenuhead headctxmenu mainhead
Paul Mackerras10299152006-08-02 09:52:01 +10008876
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10008877 stopfinding
Paul Mackerras10299152006-08-02 09:52:01 +10008878 set headmenuid $id
8879 set headmenuhead $head
Paul Mackerras00609462007-06-17 17:08:35 +10008880 set state normal
8881 if {$head eq $mainhead} {
8882 set state disabled
8883 }
8884 $headctxmenu entryconfigure 0 -state $state
8885 $headctxmenu entryconfigure 1 -state $state
Paul Mackerras10299152006-08-02 09:52:01 +10008886 tk_popup $headctxmenu $x $y
8887}
8888
8889proc cobranch {} {
Paul Mackerrasc11ff122008-05-26 10:11:33 +10008890 global headmenuid headmenuhead headids
Paul Mackerrascdc84292008-11-18 19:54:14 +11008891 global showlocalchanges
Paul Mackerras10299152006-08-02 09:52:01 +10008892
8893 # check the tree is clean first??
Christian Stimmingd990ced2007-11-07 18:42:55 +01008894 nowbusy checkout [mc "Checking out"]
Paul Mackerras10299152006-08-02 09:52:01 +10008895 update
Paul Mackerras219ea3a2006-09-07 10:21:39 +10008896 dohidelocalchanges
Paul Mackerras10299152006-08-02 09:52:01 +10008897 if {[catch {
Paul Mackerras08ba8202008-05-12 10:18:38 +10008898 set fd [open [list | git checkout $headmenuhead 2>@1] r]
Paul Mackerras10299152006-08-02 09:52:01 +10008899 } err]} {
8900 notbusy checkout
8901 error_popup $err
Paul Mackerras08ba8202008-05-12 10:18:38 +10008902 if {$showlocalchanges} {
8903 dodiffindex
Paul Mackerras10299152006-08-02 09:52:01 +10008904 }
Paul Mackerras08ba8202008-05-12 10:18:38 +10008905 } else {
8906 filerun $fd [list readcheckoutstat $fd $headmenuhead $headmenuid]
Paul Mackerras6fb735a2006-10-19 10:09:06 +10008907 }
Paul Mackerras08ba8202008-05-12 10:18:38 +10008908}
8909
8910proc readcheckoutstat {fd newhead newheadid} {
8911 global mainhead mainheadid headids showlocalchanges progresscoords
Paul Mackerrascdc84292008-11-18 19:54:14 +11008912 global viewmainheadid curview
Paul Mackerras08ba8202008-05-12 10:18:38 +10008913
8914 if {[gets $fd line] >= 0} {
8915 if {[regexp {([0-9]+)% \(([0-9]+)/([0-9]+)\)} $line match p m n]} {
8916 set progresscoords [list 0 [expr {1.0 * $m / $n}]]
8917 adjustprogress
8918 }
8919 return 1
8920 }
8921 set progresscoords {0 0}
8922 adjustprogress
8923 notbusy checkout
8924 if {[catch {close $fd} err]} {
8925 error_popup $err
8926 }
Paul Mackerrasc11ff122008-05-26 10:11:33 +10008927 set oldmainid $mainheadid
Paul Mackerras08ba8202008-05-12 10:18:38 +10008928 set mainhead $newhead
8929 set mainheadid $newheadid
Paul Mackerrascdc84292008-11-18 19:54:14 +11008930 set viewmainheadid($curview) $newheadid
Paul Mackerrasc11ff122008-05-26 10:11:33 +10008931 redrawtags $oldmainid
Paul Mackerras08ba8202008-05-12 10:18:38 +10008932 redrawtags $newheadid
8933 selbyid $newheadid
Paul Mackerras6fb735a2006-10-19 10:09:06 +10008934 if {$showlocalchanges} {
8935 dodiffindex
Paul Mackerras10299152006-08-02 09:52:01 +10008936 }
8937}
8938
8939proc rmbranch {} {
Paul Mackerrase11f1232007-06-16 20:29:25 +10008940 global headmenuid headmenuhead mainhead
Paul Mackerrasb1054ac2007-08-15 10:09:47 +10008941 global idheads
Paul Mackerras10299152006-08-02 09:52:01 +10008942
8943 set head $headmenuhead
8944 set id $headmenuid
Paul Mackerras00609462007-06-17 17:08:35 +10008945 # this check shouldn't be needed any more...
Paul Mackerras10299152006-08-02 09:52:01 +10008946 if {$head eq $mainhead} {
Christian Stimmingd990ced2007-11-07 18:42:55 +01008947 error_popup [mc "Cannot delete the currently checked-out branch"]
Paul Mackerras10299152006-08-02 09:52:01 +10008948 return
8949 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10008950 set dheads [descheads $id]
Paul Mackerrasd7b16112007-08-17 17:57:31 +10008951 if {[llength $dheads] == 1 && $idheads($dheads) eq $head} {
Paul Mackerras10299152006-08-02 09:52:01 +10008952 # the stuff on this branch isn't on any other branch
Christian Stimmingd990ced2007-11-07 18:42:55 +01008953 if {![confirm_popup [mc "The commits on branch %s aren't on any other\
8954 branch.\nReally delete branch %s?" $head $head]]} return
Paul Mackerras10299152006-08-02 09:52:01 +10008955 }
8956 nowbusy rmbranch
8957 update
8958 if {[catch {exec git branch -D $head} err]} {
8959 notbusy rmbranch
8960 error_popup $err
8961 return
8962 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10008963 removehead $id $head
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10008964 removedhead $id $head
Paul Mackerras10299152006-08-02 09:52:01 +10008965 redrawtags $id
8966 notbusy rmbranch
Paul Mackerrase11f1232007-06-16 20:29:25 +10008967 dispneartags 0
Paul Mackerras887c9962007-08-20 19:36:20 +10008968 run refill_reflist
8969}
8970
8971# Display a list of tags and heads
8972proc showrefs {} {
Paul Mackerras9c311b32007-10-04 22:27:13 +10008973 global showrefstop bgcolor fgcolor selectbgcolor
8974 global bglist fglist reflistfilter reflist maincursor
Paul Mackerras887c9962007-08-20 19:36:20 +10008975
8976 set top .showrefs
8977 set showrefstop $top
8978 if {[winfo exists $top]} {
8979 raise $top
8980 refill_reflist
8981 return
8982 }
8983 toplevel $top
Christian Stimmingd990ced2007-11-07 18:42:55 +01008984 wm title $top [mc "Tags and heads: %s" [file tail [pwd]]]
Alexander Gavrilove7d64002008-11-11 23:55:42 +03008985 make_transient $top .
Paul Mackerras887c9962007-08-20 19:36:20 +10008986 text $top.list -background $bgcolor -foreground $fgcolor \
Paul Mackerras9c311b32007-10-04 22:27:13 +10008987 -selectbackground $selectbgcolor -font mainfont \
Paul Mackerras887c9962007-08-20 19:36:20 +10008988 -xscrollcommand "$top.xsb set" -yscrollcommand "$top.ysb set" \
8989 -width 30 -height 20 -cursor $maincursor \
8990 -spacing1 1 -spacing3 1 -state disabled
8991 $top.list tag configure highlight -background $selectbgcolor
8992 lappend bglist $top.list
8993 lappend fglist $top.list
8994 scrollbar $top.ysb -command "$top.list yview" -orient vertical
8995 scrollbar $top.xsb -command "$top.list xview" -orient horizontal
8996 grid $top.list $top.ysb -sticky nsew
8997 grid $top.xsb x -sticky ew
8998 frame $top.f
Paul Mackerrasb039f0a2008-01-06 15:54:46 +11008999 label $top.f.l -text "[mc "Filter"]: "
9000 entry $top.f.e -width 20 -textvariable reflistfilter
Paul Mackerras887c9962007-08-20 19:36:20 +10009001 set reflistfilter "*"
9002 trace add variable reflistfilter write reflistfilter_change
9003 pack $top.f.e -side right -fill x -expand 1
9004 pack $top.f.l -side left
9005 grid $top.f - -sticky ew -pady 2
Paul Mackerrasb039f0a2008-01-06 15:54:46 +11009006 button $top.close -command [list destroy $top] -text [mc "Close"]
Alexander Gavrilov76f15942008-11-02 21:59:44 +03009007 bind $top <Key-Escape> [list destroy $top]
Paul Mackerras887c9962007-08-20 19:36:20 +10009008 grid $top.close -
9009 grid columnconfigure $top 0 -weight 1
9010 grid rowconfigure $top 0 -weight 1
9011 bind $top.list <1> {break}
9012 bind $top.list <B1-Motion> {break}
9013 bind $top.list <ButtonRelease-1> {sel_reflist %W %x %y; break}
9014 set reflist {}
9015 refill_reflist
9016}
9017
9018proc sel_reflist {w x y} {
9019 global showrefstop reflist headids tagids otherrefids
9020
9021 if {![winfo exists $showrefstop]} return
9022 set l [lindex [split [$w index "@$x,$y"] "."] 0]
9023 set ref [lindex $reflist [expr {$l-1}]]
9024 set n [lindex $ref 0]
9025 switch -- [lindex $ref 1] {
9026 "H" {selbyid $headids($n)}
9027 "T" {selbyid $tagids($n)}
9028 "o" {selbyid $otherrefids($n)}
9029 }
9030 $showrefstop.list tag add highlight $l.0 "$l.0 lineend"
9031}
9032
9033proc unsel_reflist {} {
9034 global showrefstop
9035
9036 if {![info exists showrefstop] || ![winfo exists $showrefstop]} return
9037 $showrefstop.list tag remove highlight 0.0 end
9038}
9039
9040proc reflistfilter_change {n1 n2 op} {
9041 global reflistfilter
9042
9043 after cancel refill_reflist
9044 after 200 refill_reflist
9045}
9046
9047proc refill_reflist {} {
9048 global reflist reflistfilter showrefstop headids tagids otherrefids
Paul Mackerrasd375ef92008-10-21 10:18:12 +11009049 global curview
Paul Mackerras887c9962007-08-20 19:36:20 +10009050
9051 if {![info exists showrefstop] || ![winfo exists $showrefstop]} return
9052 set refs {}
9053 foreach n [array names headids] {
9054 if {[string match $reflistfilter $n]} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11009055 if {[commitinview $headids($n) $curview]} {
Paul Mackerras887c9962007-08-20 19:36:20 +10009056 lappend refs [list $n H]
9057 } else {
Paul Mackerrasd375ef92008-10-21 10:18:12 +11009058 interestedin $headids($n) {run refill_reflist}
Paul Mackerras887c9962007-08-20 19:36:20 +10009059 }
9060 }
9061 }
9062 foreach n [array names tagids] {
9063 if {[string match $reflistfilter $n]} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11009064 if {[commitinview $tagids($n) $curview]} {
Paul Mackerras887c9962007-08-20 19:36:20 +10009065 lappend refs [list $n T]
9066 } else {
Paul Mackerrasd375ef92008-10-21 10:18:12 +11009067 interestedin $tagids($n) {run refill_reflist}
Paul Mackerras887c9962007-08-20 19:36:20 +10009068 }
9069 }
9070 }
9071 foreach n [array names otherrefids] {
9072 if {[string match $reflistfilter $n]} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11009073 if {[commitinview $otherrefids($n) $curview]} {
Paul Mackerras887c9962007-08-20 19:36:20 +10009074 lappend refs [list $n o]
9075 } else {
Paul Mackerrasd375ef92008-10-21 10:18:12 +11009076 interestedin $otherrefids($n) {run refill_reflist}
Paul Mackerras887c9962007-08-20 19:36:20 +10009077 }
9078 }
9079 }
9080 set refs [lsort -index 0 $refs]
9081 if {$refs eq $reflist} return
9082
9083 # Update the contents of $showrefstop.list according to the
9084 # differences between $reflist (old) and $refs (new)
9085 $showrefstop.list conf -state normal
9086 $showrefstop.list insert end "\n"
9087 set i 0
9088 set j 0
9089 while {$i < [llength $reflist] || $j < [llength $refs]} {
9090 if {$i < [llength $reflist]} {
9091 if {$j < [llength $refs]} {
9092 set cmp [string compare [lindex $reflist $i 0] \
9093 [lindex $refs $j 0]]
9094 if {$cmp == 0} {
9095 set cmp [string compare [lindex $reflist $i 1] \
9096 [lindex $refs $j 1]]
9097 }
9098 } else {
9099 set cmp -1
9100 }
9101 } else {
9102 set cmp 1
9103 }
9104 switch -- $cmp {
9105 -1 {
9106 $showrefstop.list delete "[expr {$j+1}].0" "[expr {$j+2}].0"
9107 incr i
9108 }
9109 0 {
9110 incr i
9111 incr j
9112 }
9113 1 {
9114 set l [expr {$j + 1}]
9115 $showrefstop.list image create $l.0 -align baseline \
9116 -image reficon-[lindex $refs $j 1] -padx 2
9117 $showrefstop.list insert $l.1 "[lindex $refs $j 0]\n"
9118 incr j
9119 }
9120 }
9121 }
9122 set reflist $refs
9123 # delete last newline
9124 $showrefstop.list delete end-2c end-1c
9125 $showrefstop.list conf -state disabled
Paul Mackerras10299152006-08-02 09:52:01 +10009126}
9127
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10009128# Stuff for finding nearby tags
9129proc getallcommits {} {
Paul Mackerras5cd15b62007-08-30 21:54:17 +10009130 global allcommits nextarc seeds allccache allcwait cachedarcs allcupdate
9131 global idheads idtags idotherrefs allparents tagobjid
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10009132
Paul Mackerrasa69b2d12007-08-13 15:02:02 +10009133 if {![info exists allcommits]} {
Paul Mackerrasa69b2d12007-08-13 15:02:02 +10009134 set nextarc 0
9135 set allcommits 0
9136 set seeds {}
Paul Mackerras5cd15b62007-08-30 21:54:17 +10009137 set allcwait 0
9138 set cachedarcs 0
9139 set allccache [file join [gitdir] "gitk.cache"]
9140 if {![catch {
9141 set f [open $allccache r]
9142 set allcwait 1
9143 getcache $f
9144 }]} return
Paul Mackerrasa69b2d12007-08-13 15:02:02 +10009145 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10009146
Paul Mackerras5cd15b62007-08-30 21:54:17 +10009147 if {$allcwait} {
9148 return
Paul Mackerrase11f1232007-06-16 20:29:25 +10009149 }
Paul Mackerras5cd15b62007-08-30 21:54:17 +10009150 set cmd [list | git rev-list --parents]
9151 set allcupdate [expr {$seeds ne {}}]
9152 if {!$allcupdate} {
9153 set ids "--all"
9154 } else {
9155 set refs [concat [array names idheads] [array names idtags] \
9156 [array names idotherrefs]]
9157 set ids {}
9158 set tagobjs {}
9159 foreach name [array names tagobjid] {
9160 lappend tagobjs $tagobjid($name)
9161 }
9162 foreach id [lsort -unique $refs] {
9163 if {![info exists allparents($id)] &&
9164 [lsearch -exact $tagobjs $id] < 0} {
9165 lappend ids $id
9166 }
9167 }
9168 if {$ids ne {}} {
9169 foreach id $seeds {
9170 lappend ids "^$id"
9171 }
9172 }
9173 }
9174 if {$ids ne {}} {
9175 set fd [open [concat $cmd $ids] r]
9176 fconfigure $fd -blocking 0
9177 incr allcommits
9178 nowbusy allcommits
9179 filerun $fd [list getallclines $fd]
9180 } else {
9181 dispneartags 0
9182 }
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10009183}
9184
Paul Mackerrase11f1232007-06-16 20:29:25 +10009185# Since most commits have 1 parent and 1 child, we group strings of
9186# such commits into "arcs" joining branch/merge points (BMPs), which
9187# are commits that either don't have 1 parent or don't have 1 child.
9188#
9189# arcnos(id) - incoming arcs for BMP, arc we're on for other nodes
9190# arcout(id) - outgoing arcs for BMP
9191# arcids(a) - list of IDs on arc including end but not start
9192# arcstart(a) - BMP ID at start of arc
9193# arcend(a) - BMP ID at end of arc
9194# growing(a) - arc a is still growing
9195# arctags(a) - IDs out of arcids (excluding end) that have tags
9196# archeads(a) - IDs out of arcids (excluding end) that have heads
9197# The start of an arc is at the descendent end, so "incoming" means
9198# coming from descendents, and "outgoing" means going towards ancestors.
Paul Mackerrascec7bec2006-08-02 09:38:10 +10009199
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10009200proc getallclines {fd} {
Paul Mackerras5cd15b62007-08-30 21:54:17 +10009201 global allparents allchildren idtags idheads nextarc
Paul Mackerrase11f1232007-06-16 20:29:25 +10009202 global arcnos arcids arctags arcout arcend arcstart archeads growing
Paul Mackerras5cd15b62007-08-30 21:54:17 +10009203 global seeds allcommits cachedarcs allcupdate
9204
Paul Mackerrase11f1232007-06-16 20:29:25 +10009205 set nid 0
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10009206 while {[incr nid] <= 1000 && [gets $fd line] >= 0} {
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10009207 set id [lindex $line 0]
Paul Mackerrase11f1232007-06-16 20:29:25 +10009208 if {[info exists allparents($id)]} {
9209 # seen it already
9210 continue
9211 }
Paul Mackerras5cd15b62007-08-30 21:54:17 +10009212 set cachedarcs 0
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10009213 set olds [lrange $line 1 end]
9214 set allparents($id) $olds
9215 if {![info exists allchildren($id)]} {
9216 set allchildren($id) {}
Paul Mackerrase11f1232007-06-16 20:29:25 +10009217 set arcnos($id) {}
9218 lappend seeds $id
9219 } else {
9220 set a $arcnos($id)
9221 if {[llength $olds] == 1 && [llength $a] == 1} {
9222 lappend arcids($a) $id
9223 if {[info exists idtags($id)]} {
9224 lappend arctags($a) $id
9225 }
9226 if {[info exists idheads($id)]} {
9227 lappend archeads($a) $id
9228 }
9229 if {[info exists allparents($olds)]} {
9230 # seen parent already
9231 if {![info exists arcout($olds)]} {
9232 splitarc $olds
9233 }
9234 lappend arcids($a) $olds
9235 set arcend($a) $olds
9236 unset growing($a)
9237 }
9238 lappend allchildren($olds) $id
9239 lappend arcnos($olds) $a
9240 continue
9241 }
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10009242 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10009243 foreach a $arcnos($id) {
9244 lappend arcids($a) $id
9245 set arcend($a) $id
9246 unset growing($a)
9247 }
9248
9249 set ao {}
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10009250 foreach p $olds {
9251 lappend allchildren($p) $id
Paul Mackerrase11f1232007-06-16 20:29:25 +10009252 set a [incr nextarc]
9253 set arcstart($a) $id
9254 set archeads($a) {}
9255 set arctags($a) {}
9256 set archeads($a) {}
9257 set arcids($a) {}
9258 lappend ao $a
9259 set growing($a) 1
9260 if {[info exists allparents($p)]} {
9261 # seen it already, may need to make a new branch
9262 if {![info exists arcout($p)]} {
9263 splitarc $p
9264 }
9265 lappend arcids($a) $p
9266 set arcend($a) $p
9267 unset growing($a)
9268 }
9269 lappend arcnos($p) $a
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10009270 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10009271 set arcout($id) $ao
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10009272 }
Paul Mackerrasf3326b62007-06-18 22:39:21 +10009273 if {$nid > 0} {
9274 global cached_dheads cached_dtags cached_atags
9275 catch {unset cached_dheads}
9276 catch {unset cached_dtags}
9277 catch {unset cached_atags}
9278 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10009279 if {![eof $fd]} {
9280 return [expr {$nid >= 1000? 2: 1}]
9281 }
Paul Mackerras5cd15b62007-08-30 21:54:17 +10009282 set cacheok 1
9283 if {[catch {
9284 fconfigure $fd -blocking 1
9285 close $fd
9286 } err]} {
9287 # got an error reading the list of commits
9288 # if we were updating, try rereading the whole thing again
9289 if {$allcupdate} {
9290 incr allcommits -1
9291 dropcache $err
9292 return
9293 }
Christian Stimmingd990ced2007-11-07 18:42:55 +01009294 error_popup "[mc "Error reading commit topology information;\
Paul Mackerras5cd15b62007-08-30 21:54:17 +10009295 branch and preceding/following tag information\
Christian Stimmingd990ced2007-11-07 18:42:55 +01009296 will be incomplete."]\n($err)"
Paul Mackerras5cd15b62007-08-30 21:54:17 +10009297 set cacheok 0
9298 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10009299 if {[incr allcommits -1] == 0} {
9300 notbusy allcommits
Paul Mackerras5cd15b62007-08-30 21:54:17 +10009301 if {$cacheok} {
9302 run savecache
9303 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10009304 }
9305 dispneartags 0
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10009306 return 0
Paul Mackerrase11f1232007-06-16 20:29:25 +10009307}
9308
9309proc recalcarc {a} {
9310 global arctags archeads arcids idtags idheads
9311
9312 set at {}
9313 set ah {}
9314 foreach id [lrange $arcids($a) 0 end-1] {
9315 if {[info exists idtags($id)]} {
9316 lappend at $id
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10009317 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10009318 if {[info exists idheads($id)]} {
9319 lappend ah $id
9320 }
9321 }
9322 set arctags($a) $at
9323 set archeads($a) $ah
9324}
9325
9326proc splitarc {p} {
Paul Mackerras5cd15b62007-08-30 21:54:17 +10009327 global arcnos arcids nextarc arctags archeads idtags idheads
Paul Mackerrase11f1232007-06-16 20:29:25 +10009328 global arcstart arcend arcout allparents growing
9329
9330 set a $arcnos($p)
9331 if {[llength $a] != 1} {
9332 puts "oops splitarc called but [llength $a] arcs already"
9333 return
9334 }
9335 set a [lindex $a 0]
9336 set i [lsearch -exact $arcids($a) $p]
9337 if {$i < 0} {
9338 puts "oops splitarc $p not in arc $a"
9339 return
9340 }
9341 set na [incr nextarc]
9342 if {[info exists arcend($a)]} {
9343 set arcend($na) $arcend($a)
9344 } else {
9345 set l [lindex $allparents([lindex $arcids($a) end]) 0]
9346 set j [lsearch -exact $arcnos($l) $a]
9347 set arcnos($l) [lreplace $arcnos($l) $j $j $na]
9348 }
9349 set tail [lrange $arcids($a) [expr {$i+1}] end]
9350 set arcids($a) [lrange $arcids($a) 0 $i]
9351 set arcend($a) $p
9352 set arcstart($na) $p
9353 set arcout($p) $na
9354 set arcids($na) $tail
9355 if {[info exists growing($a)]} {
9356 set growing($na) 1
9357 unset growing($a)
9358 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10009359
9360 foreach id $tail {
9361 if {[llength $arcnos($id)] == 1} {
9362 set arcnos($id) $na
9363 } else {
9364 set j [lsearch -exact $arcnos($id) $a]
9365 set arcnos($id) [lreplace $arcnos($id) $j $j $na]
9366 }
9367 }
9368
9369 # reconstruct tags and heads lists
9370 if {$arctags($a) ne {} || $archeads($a) ne {}} {
9371 recalcarc $a
9372 recalcarc $na
9373 } else {
9374 set arctags($na) {}
9375 set archeads($na) {}
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10009376 }
9377}
9378
Paul Mackerrase11f1232007-06-16 20:29:25 +10009379# Update things for a new commit added that is a child of one
9380# existing commit. Used when cherry-picking.
9381proc addnewchild {id p} {
Paul Mackerras5cd15b62007-08-30 21:54:17 +10009382 global allparents allchildren idtags nextarc
Paul Mackerrase11f1232007-06-16 20:29:25 +10009383 global arcnos arcids arctags arcout arcend arcstart archeads growing
Paul Mackerras719c2b92007-08-29 22:41:34 +10009384 global seeds allcommits
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10009385
Paul Mackerras3ebba3c2007-10-20 22:10:52 +10009386 if {![info exists allcommits] || ![info exists arcnos($p)]} return
Paul Mackerrase11f1232007-06-16 20:29:25 +10009387 set allparents($id) [list $p]
9388 set allchildren($id) {}
9389 set arcnos($id) {}
9390 lappend seeds $id
Paul Mackerrase11f1232007-06-16 20:29:25 +10009391 lappend allchildren($p) $id
9392 set a [incr nextarc]
9393 set arcstart($a) $id
9394 set archeads($a) {}
9395 set arctags($a) {}
9396 set arcids($a) [list $p]
9397 set arcend($a) $p
9398 if {![info exists arcout($p)]} {
9399 splitarc $p
9400 }
9401 lappend arcnos($p) $a
9402 set arcout($id) [list $a]
9403}
9404
Paul Mackerras5cd15b62007-08-30 21:54:17 +10009405# This implements a cache for the topology information.
9406# The cache saves, for each arc, the start and end of the arc,
9407# the ids on the arc, and the outgoing arcs from the end.
9408proc readcache {f} {
9409 global arcnos arcids arcout arcstart arcend arctags archeads nextarc
9410 global idtags idheads allparents cachedarcs possible_seeds seeds growing
9411 global allcwait
9412
9413 set a $nextarc
9414 set lim $cachedarcs
9415 if {$lim - $a > 500} {
9416 set lim [expr {$a + 500}]
9417 }
9418 if {[catch {
9419 if {$a == $lim} {
9420 # finish reading the cache and setting up arctags, etc.
9421 set line [gets $f]
9422 if {$line ne "1"} {error "bad final version"}
9423 close $f
9424 foreach id [array names idtags] {
9425 if {[info exists arcnos($id)] && [llength $arcnos($id)] == 1 &&
9426 [llength $allparents($id)] == 1} {
9427 set a [lindex $arcnos($id) 0]
9428 if {$arctags($a) eq {}} {
9429 recalcarc $a
9430 }
9431 }
9432 }
9433 foreach id [array names idheads] {
9434 if {[info exists arcnos($id)] && [llength $arcnos($id)] == 1 &&
9435 [llength $allparents($id)] == 1} {
9436 set a [lindex $arcnos($id) 0]
9437 if {$archeads($a) eq {}} {
9438 recalcarc $a
9439 }
9440 }
9441 }
9442 foreach id [lsort -unique $possible_seeds] {
9443 if {$arcnos($id) eq {}} {
9444 lappend seeds $id
9445 }
9446 }
9447 set allcwait 0
9448 } else {
9449 while {[incr a] <= $lim} {
9450 set line [gets $f]
9451 if {[llength $line] != 3} {error "bad line"}
9452 set s [lindex $line 0]
9453 set arcstart($a) $s
9454 lappend arcout($s) $a
9455 if {![info exists arcnos($s)]} {
9456 lappend possible_seeds $s
9457 set arcnos($s) {}
9458 }
9459 set e [lindex $line 1]
9460 if {$e eq {}} {
9461 set growing($a) 1
9462 } else {
9463 set arcend($a) $e
9464 if {![info exists arcout($e)]} {
9465 set arcout($e) {}
9466 }
9467 }
9468 set arcids($a) [lindex $line 2]
9469 foreach id $arcids($a) {
9470 lappend allparents($s) $id
9471 set s $id
9472 lappend arcnos($id) $a
9473 }
9474 if {![info exists allparents($s)]} {
9475 set allparents($s) {}
9476 }
9477 set arctags($a) {}
9478 set archeads($a) {}
9479 }
9480 set nextarc [expr {$a - 1}]
9481 }
9482 } err]} {
9483 dropcache $err
9484 return 0
9485 }
9486 if {!$allcwait} {
9487 getallcommits
9488 }
9489 return $allcwait
9490}
9491
9492proc getcache {f} {
9493 global nextarc cachedarcs possible_seeds
9494
9495 if {[catch {
9496 set line [gets $f]
9497 if {[llength $line] != 2 || [lindex $line 0] ne "1"} {error "bad version"}
9498 # make sure it's an integer
9499 set cachedarcs [expr {int([lindex $line 1])}]
9500 if {$cachedarcs < 0} {error "bad number of arcs"}
9501 set nextarc 0
9502 set possible_seeds {}
9503 run readcache $f
9504 } err]} {
9505 dropcache $err
9506 }
9507 return 0
9508}
9509
9510proc dropcache {err} {
9511 global allcwait nextarc cachedarcs seeds
9512
9513 #puts "dropping cache ($err)"
9514 foreach v {arcnos arcout arcids arcstart arcend growing \
9515 arctags archeads allparents allchildren} {
9516 global $v
9517 catch {unset $v}
9518 }
9519 set allcwait 0
9520 set nextarc 0
9521 set cachedarcs 0
9522 set seeds {}
9523 getallcommits
9524}
9525
9526proc writecache {f} {
9527 global cachearc cachedarcs allccache
9528 global arcstart arcend arcnos arcids arcout
9529
9530 set a $cachearc
9531 set lim $cachedarcs
9532 if {$lim - $a > 1000} {
9533 set lim [expr {$a + 1000}]
9534 }
9535 if {[catch {
9536 while {[incr a] <= $lim} {
9537 if {[info exists arcend($a)]} {
9538 puts $f [list $arcstart($a) $arcend($a) $arcids($a)]
9539 } else {
9540 puts $f [list $arcstart($a) {} $arcids($a)]
9541 }
9542 }
9543 } err]} {
9544 catch {close $f}
9545 catch {file delete $allccache}
9546 #puts "writing cache failed ($err)"
9547 return 0
9548 }
9549 set cachearc [expr {$a - 1}]
9550 if {$a > $cachedarcs} {
9551 puts $f "1"
9552 close $f
9553 return 0
9554 }
9555 return 1
9556}
9557
9558proc savecache {} {
9559 global nextarc cachedarcs cachearc allccache
9560
9561 if {$nextarc == $cachedarcs} return
9562 set cachearc 0
9563 set cachedarcs $nextarc
9564 catch {
9565 set f [open $allccache w]
9566 puts $f [list 1 $cachedarcs]
9567 run writecache $f
9568 }
9569}
9570
Paul Mackerrase11f1232007-06-16 20:29:25 +10009571# Returns 1 if a is an ancestor of b, -1 if b is an ancestor of a,
9572# or 0 if neither is true.
9573proc anc_or_desc {a b} {
9574 global arcout arcstart arcend arcnos cached_isanc
9575
9576 if {$arcnos($a) eq $arcnos($b)} {
9577 # Both are on the same arc(s); either both are the same BMP,
9578 # or if one is not a BMP, the other is also not a BMP or is
9579 # the BMP at end of the arc (and it only has 1 incoming arc).
Paul Mackerras69c0b5d2007-07-04 21:57:04 +10009580 # Or both can be BMPs with no incoming arcs.
9581 if {$a eq $b || $arcnos($a) eq {}} {
Paul Mackerrase11f1232007-06-16 20:29:25 +10009582 return 0
9583 }
9584 # assert {[llength $arcnos($a)] == 1}
9585 set arc [lindex $arcnos($a) 0]
9586 set i [lsearch -exact $arcids($arc) $a]
9587 set j [lsearch -exact $arcids($arc) $b]
9588 if {$i < 0 || $i > $j} {
9589 return 1
9590 } else {
9591 return -1
9592 }
9593 }
9594
9595 if {![info exists arcout($a)]} {
9596 set arc [lindex $arcnos($a) 0]
9597 if {[info exists arcend($arc)]} {
9598 set aend $arcend($arc)
9599 } else {
9600 set aend {}
9601 }
9602 set a $arcstart($arc)
9603 } else {
9604 set aend $a
9605 }
9606 if {![info exists arcout($b)]} {
9607 set arc [lindex $arcnos($b) 0]
9608 if {[info exists arcend($arc)]} {
9609 set bend $arcend($arc)
9610 } else {
9611 set bend {}
9612 }
9613 set b $arcstart($arc)
9614 } else {
9615 set bend $b
9616 }
9617 if {$a eq $bend} {
9618 return 1
9619 }
9620 if {$b eq $aend} {
9621 return -1
9622 }
9623 if {[info exists cached_isanc($a,$bend)]} {
9624 if {$cached_isanc($a,$bend)} {
9625 return 1
9626 }
9627 }
9628 if {[info exists cached_isanc($b,$aend)]} {
9629 if {$cached_isanc($b,$aend)} {
9630 return -1
9631 }
9632 if {[info exists cached_isanc($a,$bend)]} {
9633 return 0
9634 }
9635 }
9636
9637 set todo [list $a $b]
9638 set anc($a) a
9639 set anc($b) b
9640 for {set i 0} {$i < [llength $todo]} {incr i} {
9641 set x [lindex $todo $i]
9642 if {$anc($x) eq {}} {
9643 continue
9644 }
9645 foreach arc $arcnos($x) {
9646 set xd $arcstart($arc)
9647 if {$xd eq $bend} {
9648 set cached_isanc($a,$bend) 1
9649 set cached_isanc($b,$aend) 0
9650 return 1
9651 } elseif {$xd eq $aend} {
9652 set cached_isanc($b,$aend) 1
9653 set cached_isanc($a,$bend) 0
9654 return -1
9655 }
9656 if {![info exists anc($xd)]} {
9657 set anc($xd) $anc($x)
9658 lappend todo $xd
9659 } elseif {$anc($xd) ne $anc($x)} {
9660 set anc($xd) {}
9661 }
9662 }
9663 }
9664 set cached_isanc($a,$bend) 0
9665 set cached_isanc($b,$aend) 0
9666 return 0
9667}
9668
9669# This identifies whether $desc has an ancestor that is
9670# a growing tip of the graph and which is not an ancestor of $anc
9671# and returns 0 if so and 1 if not.
9672# If we subsequently discover a tag on such a growing tip, and that
9673# turns out to be a descendent of $anc (which it could, since we
9674# don't necessarily see children before parents), then $desc
9675# isn't a good choice to display as a descendent tag of
9676# $anc (since it is the descendent of another tag which is
9677# a descendent of $anc). Similarly, $anc isn't a good choice to
9678# display as a ancestor tag of $desc.
9679#
9680proc is_certain {desc anc} {
9681 global arcnos arcout arcstart arcend growing problems
9682
9683 set certain {}
9684 if {[llength $arcnos($anc)] == 1} {
9685 # tags on the same arc are certain
9686 if {$arcnos($desc) eq $arcnos($anc)} {
9687 return 1
9688 }
9689 if {![info exists arcout($anc)]} {
9690 # if $anc is partway along an arc, use the start of the arc instead
9691 set a [lindex $arcnos($anc) 0]
9692 set anc $arcstart($a)
9693 }
9694 }
9695 if {[llength $arcnos($desc)] > 1 || [info exists arcout($desc)]} {
9696 set x $desc
9697 } else {
9698 set a [lindex $arcnos($desc) 0]
9699 set x $arcend($a)
9700 }
9701 if {$x == $anc} {
9702 return 1
9703 }
9704 set anclist [list $x]
9705 set dl($x) 1
9706 set nnh 1
9707 set ngrowanc 0
9708 for {set i 0} {$i < [llength $anclist] && ($nnh > 0 || $ngrowanc > 0)} {incr i} {
9709 set x [lindex $anclist $i]
9710 if {$dl($x)} {
9711 incr nnh -1
9712 }
9713 set done($x) 1
9714 foreach a $arcout($x) {
9715 if {[info exists growing($a)]} {
9716 if {![info exists growanc($x)] && $dl($x)} {
9717 set growanc($x) 1
9718 incr ngrowanc
9719 }
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10009720 } else {
Paul Mackerrase11f1232007-06-16 20:29:25 +10009721 set y $arcend($a)
9722 if {[info exists dl($y)]} {
9723 if {$dl($y)} {
9724 if {!$dl($x)} {
9725 set dl($y) 0
9726 if {![info exists done($y)]} {
9727 incr nnh -1
9728 }
9729 if {[info exists growanc($x)]} {
9730 incr ngrowanc -1
9731 }
9732 set xl [list $y]
9733 for {set k 0} {$k < [llength $xl]} {incr k} {
9734 set z [lindex $xl $k]
9735 foreach c $arcout($z) {
9736 if {[info exists arcend($c)]} {
9737 set v $arcend($c)
9738 if {[info exists dl($v)] && $dl($v)} {
9739 set dl($v) 0
9740 if {![info exists done($v)]} {
9741 incr nnh -1
9742 }
9743 if {[info exists growanc($v)]} {
9744 incr ngrowanc -1
9745 }
9746 lappend xl $v
9747 }
9748 }
9749 }
9750 }
9751 }
9752 }
9753 } elseif {$y eq $anc || !$dl($x)} {
9754 set dl($y) 0
9755 lappend anclist $y
9756 } else {
9757 set dl($y) 1
9758 lappend anclist $y
9759 incr nnh
9760 }
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10009761 }
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10009762 }
9763 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10009764 foreach x [array names growanc] {
9765 if {$dl($x)} {
9766 return 0
9767 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10009768 return 0
Paul Mackerrase11f1232007-06-16 20:29:25 +10009769 }
9770 return 1
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10009771}
9772
Paul Mackerrase11f1232007-06-16 20:29:25 +10009773proc validate_arctags {a} {
9774 global arctags idtags
9775
9776 set i -1
9777 set na $arctags($a)
9778 foreach id $arctags($a) {
9779 incr i
9780 if {![info exists idtags($id)]} {
9781 set na [lreplace $na $i $i]
9782 incr i -1
9783 }
9784 }
9785 set arctags($a) $na
9786}
9787
9788proc validate_archeads {a} {
9789 global archeads idheads
9790
9791 set i -1
9792 set na $archeads($a)
9793 foreach id $archeads($a) {
9794 incr i
9795 if {![info exists idheads($id)]} {
9796 set na [lreplace $na $i $i]
9797 incr i -1
9798 }
9799 }
9800 set archeads($a) $na
9801}
9802
9803# Return the list of IDs that have tags that are descendents of id,
9804# ignoring IDs that are descendents of IDs already reported.
9805proc desctags {id} {
9806 global arcnos arcstart arcids arctags idtags allparents
9807 global growing cached_dtags
9808
9809 if {![info exists allparents($id)]} {
9810 return {}
9811 }
9812 set t1 [clock clicks -milliseconds]
9813 set argid $id
9814 if {[llength $arcnos($id)] == 1 && [llength $allparents($id)] == 1} {
9815 # part-way along an arc; check that arc first
9816 set a [lindex $arcnos($id) 0]
9817 if {$arctags($a) ne {}} {
9818 validate_arctags $a
9819 set i [lsearch -exact $arcids($a) $id]
9820 set tid {}
9821 foreach t $arctags($a) {
9822 set j [lsearch -exact $arcids($a) $t]
9823 if {$j >= $i} break
9824 set tid $t
9825 }
9826 if {$tid ne {}} {
9827 return $tid
9828 }
9829 }
9830 set id $arcstart($a)
9831 if {[info exists idtags($id)]} {
9832 return $id
9833 }
9834 }
9835 if {[info exists cached_dtags($id)]} {
9836 return $cached_dtags($id)
9837 }
9838
9839 set origid $id
9840 set todo [list $id]
9841 set queued($id) 1
9842 set nc 1
9843 for {set i 0} {$i < [llength $todo] && $nc > 0} {incr i} {
9844 set id [lindex $todo $i]
9845 set done($id) 1
9846 set ta [info exists hastaggedancestor($id)]
9847 if {!$ta} {
9848 incr nc -1
9849 }
9850 # ignore tags on starting node
9851 if {!$ta && $i > 0} {
9852 if {[info exists idtags($id)]} {
9853 set tagloc($id) $id
9854 set ta 1
9855 } elseif {[info exists cached_dtags($id)]} {
9856 set tagloc($id) $cached_dtags($id)
9857 set ta 1
9858 }
9859 }
9860 foreach a $arcnos($id) {
9861 set d $arcstart($a)
9862 if {!$ta && $arctags($a) ne {}} {
9863 validate_arctags $a
9864 if {$arctags($a) ne {}} {
9865 lappend tagloc($id) [lindex $arctags($a) end]
9866 }
9867 }
9868 if {$ta || $arctags($a) ne {}} {
9869 set tomark [list $d]
9870 for {set j 0} {$j < [llength $tomark]} {incr j} {
9871 set dd [lindex $tomark $j]
9872 if {![info exists hastaggedancestor($dd)]} {
9873 if {[info exists done($dd)]} {
9874 foreach b $arcnos($dd) {
9875 lappend tomark $arcstart($b)
9876 }
9877 if {[info exists tagloc($dd)]} {
9878 unset tagloc($dd)
9879 }
9880 } elseif {[info exists queued($dd)]} {
9881 incr nc -1
9882 }
9883 set hastaggedancestor($dd) 1
9884 }
9885 }
9886 }
9887 if {![info exists queued($d)]} {
9888 lappend todo $d
9889 set queued($d) 1
9890 if {![info exists hastaggedancestor($d)]} {
9891 incr nc
9892 }
9893 }
9894 }
9895 }
9896 set tags {}
9897 foreach id [array names tagloc] {
9898 if {![info exists hastaggedancestor($id)]} {
9899 foreach t $tagloc($id) {
9900 if {[lsearch -exact $tags $t] < 0} {
9901 lappend tags $t
9902 }
9903 }
9904 }
9905 }
9906 set t2 [clock clicks -milliseconds]
9907 set loopix $i
9908
9909 # remove tags that are descendents of other tags
9910 for {set i 0} {$i < [llength $tags]} {incr i} {
9911 set a [lindex $tags $i]
9912 for {set j 0} {$j < $i} {incr j} {
9913 set b [lindex $tags $j]
9914 set r [anc_or_desc $a $b]
9915 if {$r == 1} {
9916 set tags [lreplace $tags $j $j]
9917 incr j -1
9918 incr i -1
9919 } elseif {$r == -1} {
9920 set tags [lreplace $tags $i $i]
9921 incr i -1
9922 break
9923 }
9924 }
9925 }
9926
9927 if {[array names growing] ne {}} {
9928 # graph isn't finished, need to check if any tag could get
9929 # eclipsed by another tag coming later. Simply ignore any
9930 # tags that could later get eclipsed.
9931 set ctags {}
9932 foreach t $tags {
9933 if {[is_certain $t $origid]} {
9934 lappend ctags $t
9935 }
9936 }
9937 if {$tags eq $ctags} {
9938 set cached_dtags($origid) $tags
9939 } else {
9940 set tags $ctags
9941 }
9942 } else {
9943 set cached_dtags($origid) $tags
9944 }
9945 set t3 [clock clicks -milliseconds]
9946 if {0 && $t3 - $t1 >= 100} {
9947 puts "iterating descendents ($loopix/[llength $todo] nodes) took\
9948 [expr {$t2-$t1}]+[expr {$t3-$t2}]ms, $nc candidates left"
9949 }
9950 return $tags
9951}
9952
9953proc anctags {id} {
9954 global arcnos arcids arcout arcend arctags idtags allparents
9955 global growing cached_atags
9956
9957 if {![info exists allparents($id)]} {
9958 return {}
9959 }
9960 set t1 [clock clicks -milliseconds]
9961 set argid $id
9962 if {[llength $arcnos($id)] == 1 && [llength $allparents($id)] == 1} {
9963 # part-way along an arc; check that arc first
9964 set a [lindex $arcnos($id) 0]
9965 if {$arctags($a) ne {}} {
9966 validate_arctags $a
9967 set i [lsearch -exact $arcids($a) $id]
9968 foreach t $arctags($a) {
9969 set j [lsearch -exact $arcids($a) $t]
9970 if {$j > $i} {
9971 return $t
9972 }
9973 }
9974 }
9975 if {![info exists arcend($a)]} {
9976 return {}
9977 }
9978 set id $arcend($a)
9979 if {[info exists idtags($id)]} {
9980 return $id
9981 }
9982 }
9983 if {[info exists cached_atags($id)]} {
9984 return $cached_atags($id)
9985 }
9986
9987 set origid $id
9988 set todo [list $id]
9989 set queued($id) 1
9990 set taglist {}
9991 set nc 1
9992 for {set i 0} {$i < [llength $todo] && $nc > 0} {incr i} {
9993 set id [lindex $todo $i]
9994 set done($id) 1
9995 set td [info exists hastaggeddescendent($id)]
9996 if {!$td} {
9997 incr nc -1
9998 }
9999 # ignore tags on starting node
10000 if {!$td && $i > 0} {
10001 if {[info exists idtags($id)]} {
10002 set tagloc($id) $id
10003 set td 1
10004 } elseif {[info exists cached_atags($id)]} {
10005 set tagloc($id) $cached_atags($id)
10006 set td 1
10007 }
10008 }
10009 foreach a $arcout($id) {
10010 if {!$td && $arctags($a) ne {}} {
10011 validate_arctags $a
10012 if {$arctags($a) ne {}} {
10013 lappend tagloc($id) [lindex $arctags($a) 0]
10014 }
10015 }
10016 if {![info exists arcend($a)]} continue
10017 set d $arcend($a)
10018 if {$td || $arctags($a) ne {}} {
10019 set tomark [list $d]
10020 for {set j 0} {$j < [llength $tomark]} {incr j} {
10021 set dd [lindex $tomark $j]
10022 if {![info exists hastaggeddescendent($dd)]} {
10023 if {[info exists done($dd)]} {
10024 foreach b $arcout($dd) {
10025 if {[info exists arcend($b)]} {
10026 lappend tomark $arcend($b)
10027 }
10028 }
10029 if {[info exists tagloc($dd)]} {
10030 unset tagloc($dd)
10031 }
10032 } elseif {[info exists queued($dd)]} {
10033 incr nc -1
10034 }
10035 set hastaggeddescendent($dd) 1
10036 }
10037 }
10038 }
10039 if {![info exists queued($d)]} {
10040 lappend todo $d
10041 set queued($d) 1
10042 if {![info exists hastaggeddescendent($d)]} {
10043 incr nc
10044 }
10045 }
10046 }
10047 }
10048 set t2 [clock clicks -milliseconds]
10049 set loopix $i
10050 set tags {}
10051 foreach id [array names tagloc] {
10052 if {![info exists hastaggeddescendent($id)]} {
10053 foreach t $tagloc($id) {
10054 if {[lsearch -exact $tags $t] < 0} {
10055 lappend tags $t
10056 }
10057 }
10058 }
10059 }
10060
10061 # remove tags that are ancestors of other tags
10062 for {set i 0} {$i < [llength $tags]} {incr i} {
10063 set a [lindex $tags $i]
10064 for {set j 0} {$j < $i} {incr j} {
10065 set b [lindex $tags $j]
10066 set r [anc_or_desc $a $b]
10067 if {$r == -1} {
10068 set tags [lreplace $tags $j $j]
10069 incr j -1
10070 incr i -1
10071 } elseif {$r == 1} {
10072 set tags [lreplace $tags $i $i]
10073 incr i -1
10074 break
10075 }
10076 }
10077 }
10078
10079 if {[array names growing] ne {}} {
10080 # graph isn't finished, need to check if any tag could get
10081 # eclipsed by another tag coming later. Simply ignore any
10082 # tags that could later get eclipsed.
10083 set ctags {}
10084 foreach t $tags {
10085 if {[is_certain $origid $t]} {
10086 lappend ctags $t
10087 }
10088 }
10089 if {$tags eq $ctags} {
10090 set cached_atags($origid) $tags
10091 } else {
10092 set tags $ctags
10093 }
10094 } else {
10095 set cached_atags($origid) $tags
10096 }
10097 set t3 [clock clicks -milliseconds]
10098 if {0 && $t3 - $t1 >= 100} {
10099 puts "iterating ancestors ($loopix/[llength $todo] nodes) took\
10100 [expr {$t2-$t1}]+[expr {$t3-$t2}]ms, $nc candidates left"
10101 }
10102 return $tags
10103}
10104
10105# Return the list of IDs that have heads that are descendents of id,
10106# including id itself if it has a head.
10107proc descheads {id} {
10108 global arcnos arcstart arcids archeads idheads cached_dheads
10109 global allparents
10110
10111 if {![info exists allparents($id)]} {
10112 return {}
10113 }
Paul Mackerrasf3326b62007-06-18 22:39:21 +100010114 set aret {}
Paul Mackerrase11f1232007-06-16 20:29:25 +100010115 if {[llength $arcnos($id)] == 1 && [llength $allparents($id)] == 1} {
10116 # part-way along an arc; check it first
10117 set a [lindex $arcnos($id) 0]
10118 if {$archeads($a) ne {}} {
10119 validate_archeads $a
10120 set i [lsearch -exact $arcids($a) $id]
10121 foreach t $archeads($a) {
10122 set j [lsearch -exact $arcids($a) $t]
10123 if {$j > $i} break
Paul Mackerrasf3326b62007-06-18 22:39:21 +100010124 lappend aret $t
Paul Mackerrase11f1232007-06-16 20:29:25 +100010125 }
10126 }
10127 set id $arcstart($a)
10128 }
10129 set origid $id
10130 set todo [list $id]
10131 set seen($id) 1
Paul Mackerrasf3326b62007-06-18 22:39:21 +100010132 set ret {}
Paul Mackerrase11f1232007-06-16 20:29:25 +100010133 for {set i 0} {$i < [llength $todo]} {incr i} {
10134 set id [lindex $todo $i]
10135 if {[info exists cached_dheads($id)]} {
10136 set ret [concat $ret $cached_dheads($id)]
10137 } else {
10138 if {[info exists idheads($id)]} {
10139 lappend ret $id
10140 }
10141 foreach a $arcnos($id) {
10142 if {$archeads($a) ne {}} {
Paul Mackerras706d6c32007-06-26 11:09:49 +100010143 validate_archeads $a
10144 if {$archeads($a) ne {}} {
10145 set ret [concat $ret $archeads($a)]
10146 }
Paul Mackerrase11f1232007-06-16 20:29:25 +100010147 }
10148 set d $arcstart($a)
10149 if {![info exists seen($d)]} {
10150 lappend todo $d
10151 set seen($d) 1
10152 }
10153 }
10154 }
10155 }
10156 set ret [lsort -unique $ret]
10157 set cached_dheads($origid) $ret
Paul Mackerrasf3326b62007-06-18 22:39:21 +100010158 return [concat $ret $aret]
Paul Mackerrase11f1232007-06-16 20:29:25 +100010159}
10160
Paul Mackerrasceadfe92006-08-08 20:55:36 +100010161proc addedtag {id} {
Paul Mackerrase11f1232007-06-16 20:29:25 +100010162 global arcnos arcout cached_dtags cached_atags
Paul Mackerrasceadfe92006-08-08 20:55:36 +100010163
Paul Mackerrase11f1232007-06-16 20:29:25 +100010164 if {![info exists arcnos($id)]} return
10165 if {![info exists arcout($id)]} {
10166 recalcarc [lindex $arcnos($id) 0]
Paul Mackerrasceadfe92006-08-08 20:55:36 +100010167 }
Paul Mackerrase11f1232007-06-16 20:29:25 +100010168 catch {unset cached_dtags}
10169 catch {unset cached_atags}
Paul Mackerrasceadfe92006-08-08 20:55:36 +100010170}
10171
Paul Mackerrasca6d8f52006-08-06 21:08:05 +100010172proc addedhead {hid head} {
Paul Mackerrase11f1232007-06-16 20:29:25 +100010173 global arcnos arcout cached_dheads
Paul Mackerrasca6d8f52006-08-06 21:08:05 +100010174
Paul Mackerrase11f1232007-06-16 20:29:25 +100010175 if {![info exists arcnos($hid)]} return
10176 if {![info exists arcout($hid)]} {
10177 recalcarc [lindex $arcnos($hid) 0]
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +100010178 }
Paul Mackerrase11f1232007-06-16 20:29:25 +100010179 catch {unset cached_dheads}
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +100010180}
10181
Paul Mackerrasca6d8f52006-08-06 21:08:05 +100010182proc removedhead {hid head} {
Paul Mackerrase11f1232007-06-16 20:29:25 +100010183 global cached_dheads
Paul Mackerrasca6d8f52006-08-06 21:08:05 +100010184
Paul Mackerrase11f1232007-06-16 20:29:25 +100010185 catch {unset cached_dheads}
Paul Mackerras10299152006-08-02 09:52:01 +100010186}
10187
Paul Mackerrase11f1232007-06-16 20:29:25 +100010188proc movedhead {hid head} {
10189 global arcnos arcout cached_dheads
Paul Mackerrasca6d8f52006-08-06 21:08:05 +100010190
Paul Mackerrase11f1232007-06-16 20:29:25 +100010191 if {![info exists arcnos($hid)]} return
10192 if {![info exists arcout($hid)]} {
10193 recalcarc [lindex $arcnos($hid) 0]
Paul Mackerrasca6d8f52006-08-06 21:08:05 +100010194 }
Paul Mackerrase11f1232007-06-16 20:29:25 +100010195 catch {unset cached_dheads}
Paul Mackerrasca6d8f52006-08-06 21:08:05 +100010196}
10197
Paul Mackerrascec7bec2006-08-02 09:38:10 +100010198proc changedrefs {} {
Paul Mackerrase11f1232007-06-16 20:29:25 +100010199 global cached_dheads cached_dtags cached_atags
10200 global arctags archeads arcnos arcout idheads idtags
Paul Mackerrascec7bec2006-08-02 09:38:10 +100010201
Paul Mackerrase11f1232007-06-16 20:29:25 +100010202 foreach id [concat [array names idheads] [array names idtags]] {
10203 if {[info exists arcnos($id)] && ![info exists arcout($id)]} {
10204 set a [lindex $arcnos($id) 0]
10205 if {![info exists donearc($a)]} {
10206 recalcarc $a
10207 set donearc($a) 1
10208 }
Paul Mackerrascec7bec2006-08-02 09:38:10 +100010209 }
10210 }
Paul Mackerrase11f1232007-06-16 20:29:25 +100010211 catch {unset cached_dtags}
10212 catch {unset cached_atags}
10213 catch {unset cached_dheads}
Paul Mackerrascec7bec2006-08-02 09:38:10 +100010214}
10215
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +100010216proc rereadrefs {} {
Paul Mackerrasfc2a2562007-12-26 23:03:43 +110010217 global idtags idheads idotherrefs mainheadid
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +100010218
10219 set refids [concat [array names idtags] \
10220 [array names idheads] [array names idotherrefs]]
10221 foreach id $refids {
10222 if {![info exists ref($id)]} {
10223 set ref($id) [listrefs $id]
10224 }
10225 }
Paul Mackerrasfc2a2562007-12-26 23:03:43 +110010226 set oldmainhead $mainheadid
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +100010227 readrefs
Paul Mackerrascec7bec2006-08-02 09:38:10 +100010228 changedrefs
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +100010229 set refids [lsort -unique [concat $refids [array names idtags] \
10230 [array names idheads] [array names idotherrefs]]]
10231 foreach id $refids {
10232 set v [listrefs $id]
Paul Mackerrasc11ff122008-05-26 10:11:33 +100010233 if {![info exists ref($id)] || $ref($id) != $v} {
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +100010234 redrawtags $id
10235 }
10236 }
Paul Mackerrasc11ff122008-05-26 10:11:33 +100010237 if {$oldmainhead ne $mainheadid} {
10238 redrawtags $oldmainhead
10239 redrawtags $mainheadid
10240 }
Paul Mackerras887c9962007-08-20 19:36:20 +100010241 run refill_reflist
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +100010242}
10243
Junio C Hamano2e1ded42006-06-11 09:50:47 -070010244proc listrefs {id} {
10245 global idtags idheads idotherrefs
10246
10247 set x {}
10248 if {[info exists idtags($id)]} {
10249 set x $idtags($id)
10250 }
10251 set y {}
10252 if {[info exists idheads($id)]} {
10253 set y $idheads($id)
10254 }
10255 set z {}
10256 if {[info exists idotherrefs($id)]} {
10257 set z $idotherrefs($id)
10258 }
10259 return [list $x $y $z]
10260}
10261
Paul Mackerras106288c2005-08-19 23:11:39 +100010262proc showtag {tag isnew} {
Paul Mackerras62d3ea62006-09-11 10:36:53 +100010263 global ctext tagcontents tagids linknum tagobjid
Paul Mackerras106288c2005-08-19 23:11:39 +100010264
10265 if {$isnew} {
10266 addtohistory [list showtag $tag 0]
10267 }
10268 $ctext conf -state normal
Paul Mackerras3ea06f92006-05-24 10:16:03 +100010269 clear_ctext
Paul Mackerras32f1b3e2007-09-28 21:27:39 +100010270 settabs 0
Paul Mackerras106288c2005-08-19 23:11:39 +100010271 set linknum 0
Paul Mackerras62d3ea62006-09-11 10:36:53 +100010272 if {![info exists tagcontents($tag)]} {
10273 catch {
10274 set tagcontents($tag) [exec git cat-file tag $tagobjid($tag)]
10275 }
10276 }
Paul Mackerras106288c2005-08-19 23:11:39 +100010277 if {[info exists tagcontents($tag)]} {
10278 set text $tagcontents($tag)
10279 } else {
Christian Stimmingd990ced2007-11-07 18:42:55 +010010280 set text "[mc "Tag"]: $tag\n[mc "Id"]: $tagids($tag)"
Paul Mackerras106288c2005-08-19 23:11:39 +100010281 }
Sergey Vlasovf1b86292006-05-15 19:13:14 +040010282 appendwithlinks $text {}
Paul Mackerras106288c2005-08-19 23:11:39 +100010283 $ctext conf -state disabled
Paul Mackerras7fcceed2006-04-27 19:21:49 +100010284 init_flist {}
Paul Mackerras106288c2005-08-19 23:11:39 +100010285}
10286
Paul Mackerras1d10f362005-05-15 12:55:47 +000010287proc doquit {} {
10288 global stopped
Thomas Arcila314f5de2008-03-24 12:55:36 +010010289 global gitktmpdir
10290
Paul Mackerras1d10f362005-05-15 12:55:47 +000010291 set stopped 100
Mark Levedahlb6047c52007-02-08 22:22:24 -050010292 savestuff .
Paul Mackerras1d10f362005-05-15 12:55:47 +000010293 destroy .
Thomas Arcila314f5de2008-03-24 12:55:36 +010010294
10295 if {[info exists gitktmpdir]} {
10296 catch {file delete -force $gitktmpdir}
10297 }
Paul Mackerras1d10f362005-05-15 12:55:47 +000010298}
10299
Paul Mackerras9a7558f2007-10-06 20:16:06 +100010300proc mkfontdisp {font top which} {
10301 global fontattr fontpref $font
10302
10303 set fontpref($font) [set $font]
10304 button $top.${font}but -text $which -font optionfont \
10305 -command [list choosefont $font $which]
10306 label $top.$font -relief flat -font $font \
10307 -text $fontattr($font,family) -justify left
10308 grid x $top.${font}but $top.$font -sticky w
10309}
10310
10311proc choosefont {font which} {
10312 global fontparam fontlist fonttop fontattr
Alexander Gavrilov84a76f12008-11-02 21:59:45 +030010313 global prefstop
Paul Mackerras9a7558f2007-10-06 20:16:06 +100010314
10315 set fontparam(which) $which
10316 set fontparam(font) $font
10317 set fontparam(family) [font actual $font -family]
10318 set fontparam(size) $fontattr($font,size)
10319 set fontparam(weight) $fontattr($font,weight)
10320 set fontparam(slant) $fontattr($font,slant)
10321 set top .gitkfont
10322 set fonttop $top
10323 if {![winfo exists $top]} {
10324 font create sample
10325 eval font config sample [font actual $font]
10326 toplevel $top
Alexander Gavrilove7d64002008-11-11 23:55:42 +030010327 make_transient $top $prefstop
Christian Stimmingd990ced2007-11-07 18:42:55 +010010328 wm title $top [mc "Gitk font chooser"]
Paul Mackerrasb039f0a2008-01-06 15:54:46 +110010329 label $top.l -textvariable fontparam(which)
Paul Mackerras9a7558f2007-10-06 20:16:06 +100010330 pack $top.l -side top
10331 set fontlist [lsort [font families]]
10332 frame $top.f
10333 listbox $top.f.fam -listvariable fontlist \
10334 -yscrollcommand [list $top.f.sb set]
10335 bind $top.f.fam <<ListboxSelect>> selfontfam
10336 scrollbar $top.f.sb -command [list $top.f.fam yview]
10337 pack $top.f.sb -side right -fill y
10338 pack $top.f.fam -side left -fill both -expand 1
10339 pack $top.f -side top -fill both -expand 1
10340 frame $top.g
10341 spinbox $top.g.size -from 4 -to 40 -width 4 \
10342 -textvariable fontparam(size) \
10343 -validatecommand {string is integer -strict %s}
10344 checkbutton $top.g.bold -padx 5 \
Christian Stimmingd990ced2007-11-07 18:42:55 +010010345 -font {{Times New Roman} 12 bold} -text [mc "B"] -indicatoron 0 \
Paul Mackerras9a7558f2007-10-06 20:16:06 +100010346 -variable fontparam(weight) -onvalue bold -offvalue normal
10347 checkbutton $top.g.ital -padx 5 \
Christian Stimmingd990ced2007-11-07 18:42:55 +010010348 -font {{Times New Roman} 12 italic} -text [mc "I"] -indicatoron 0 \
Paul Mackerras9a7558f2007-10-06 20:16:06 +100010349 -variable fontparam(slant) -onvalue italic -offvalue roman
10350 pack $top.g.size $top.g.bold $top.g.ital -side left
10351 pack $top.g -side top
10352 canvas $top.c -width 150 -height 50 -border 2 -relief sunk \
10353 -background white
10354 $top.c create text 100 25 -anchor center -text $which -font sample \
10355 -fill black -tags text
10356 bind $top.c <Configure> [list centertext $top.c]
10357 pack $top.c -side top -fill x
10358 frame $top.buts
Paul Mackerrasb039f0a2008-01-06 15:54:46 +110010359 button $top.buts.ok -text [mc "OK"] -command fontok -default active
10360 button $top.buts.can -text [mc "Cancel"] -command fontcan -default normal
Alexander Gavrilov76f15942008-11-02 21:59:44 +030010361 bind $top <Key-Return> fontok
10362 bind $top <Key-Escape> fontcan
Paul Mackerras9a7558f2007-10-06 20:16:06 +100010363 grid $top.buts.ok $top.buts.can
10364 grid columnconfigure $top.buts 0 -weight 1 -uniform a
10365 grid columnconfigure $top.buts 1 -weight 1 -uniform a
10366 pack $top.buts -side bottom -fill x
10367 trace add variable fontparam write chg_fontparam
10368 } else {
10369 raise $top
10370 $top.c itemconf text -text $which
10371 }
10372 set i [lsearch -exact $fontlist $fontparam(family)]
10373 if {$i >= 0} {
10374 $top.f.fam selection set $i
10375 $top.f.fam see $i
10376 }
10377}
10378
10379proc centertext {w} {
10380 $w coords text [expr {[winfo width $w] / 2}] [expr {[winfo height $w] / 2}]
10381}
10382
10383proc fontok {} {
10384 global fontparam fontpref prefstop
10385
10386 set f $fontparam(font)
10387 set fontpref($f) [list $fontparam(family) $fontparam(size)]
10388 if {$fontparam(weight) eq "bold"} {
10389 lappend fontpref($f) "bold"
10390 }
10391 if {$fontparam(slant) eq "italic"} {
10392 lappend fontpref($f) "italic"
10393 }
10394 set w $prefstop.$f
10395 $w conf -text $fontparam(family) -font $fontpref($f)
10396
10397 fontcan
10398}
10399
10400proc fontcan {} {
10401 global fonttop fontparam
10402
10403 if {[info exists fonttop]} {
10404 catch {destroy $fonttop}
10405 catch {font delete sample}
10406 unset fonttop
10407 unset fontparam
10408 }
10409}
10410
10411proc selfontfam {} {
10412 global fonttop fontparam
10413
10414 set i [$fonttop.f.fam curselection]
10415 if {$i ne {}} {
10416 set fontparam(family) [$fonttop.f.fam get $i]
10417 }
10418}
10419
10420proc chg_fontparam {v sub op} {
10421 global fontparam
10422
10423 font config sample -$sub $fontparam($sub)
10424}
10425
Paul Mackerras712fcc02005-11-30 09:28:16 +110010426proc doprefs {} {
Paul Mackerras8d73b242007-10-06 20:22:00 +100010427 global maxwidth maxgraphpct
Paul Mackerras219ea3a2006-09-07 10:21:39 +100010428 global oldprefs prefstop showneartags showlocalchanges
Guillermo S. Romero5497f7a2009-10-15 18:51:49 +020010429 global uicolor bgcolor fgcolor ctext diffcolors selectbgcolor markbgcolor
Paul Mackerras39ee47e2008-10-15 22:23:03 +110010430 global tabstop limitdiffs autoselect extdifftool perfile_attrs
Thomas Rastffe15292009-08-03 23:53:36 +020010431 global hideremotes
Paul Mackerras232475d2005-11-15 10:34:03 +110010432
Paul Mackerras712fcc02005-11-30 09:28:16 +110010433 set top .gitkprefs
10434 set prefstop $top
10435 if {[winfo exists $top]} {
10436 raise $top
10437 return
Paul Mackerras757f17b2005-11-21 09:56:07 +110010438 }
Paul Mackerras3de07112007-10-23 22:40:50 +100010439 foreach v {maxwidth maxgraphpct showneartags showlocalchanges \
Thomas Rastffe15292009-08-03 23:53:36 +020010440 limitdiffs tabstop perfile_attrs hideremotes} {
Paul Mackerras712fcc02005-11-30 09:28:16 +110010441 set oldprefs($v) [set $v]
Paul Mackerras232475d2005-11-15 10:34:03 +110010442 }
Paul Mackerras712fcc02005-11-30 09:28:16 +110010443 toplevel $top
Christian Stimmingd990ced2007-11-07 18:42:55 +010010444 wm title $top [mc "Gitk preferences"]
Alexander Gavrilove7d64002008-11-11 23:55:42 +030010445 make_transient $top .
Christian Stimmingd990ced2007-11-07 18:42:55 +010010446 label $top.ldisp -text [mc "Commit list display options"]
Paul Mackerras712fcc02005-11-30 09:28:16 +110010447 grid $top.ldisp - -sticky w -pady 10
10448 label $top.spacer -text " "
Christian Stimmingd990ced2007-11-07 18:42:55 +010010449 label $top.maxwidthl -text [mc "Maximum graph width (lines)"] \
Paul Mackerras712fcc02005-11-30 09:28:16 +110010450 -font optionfont
10451 spinbox $top.maxwidth -from 0 -to 100 -width 4 -textvariable maxwidth
10452 grid $top.spacer $top.maxwidthl $top.maxwidth -sticky w
Christian Stimmingd990ced2007-11-07 18:42:55 +010010453 label $top.maxpctl -text [mc "Maximum graph width (% of pane)"] \
Paul Mackerras712fcc02005-11-30 09:28:16 +110010454 -font optionfont
10455 spinbox $top.maxpct -from 1 -to 100 -width 4 -textvariable maxgraphpct
10456 grid x $top.maxpctl $top.maxpct -sticky w
Johannes Sixtadcbec12008-12-02 21:42:16 +010010457 checkbutton $top.showlocal -text [mc "Show local changes"] \
10458 -font optionfont -variable showlocalchanges
Paul Mackerras219ea3a2006-09-07 10:21:39 +100010459 grid x $top.showlocal -sticky w
Johannes Sixtadcbec12008-12-02 21:42:16 +010010460 checkbutton $top.autoselect -text [mc "Auto-select SHA1"] \
10461 -font optionfont -variable autoselect
Jeff King95293b52008-03-06 06:49:25 -050010462 grid x $top.autoselect -sticky w
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +100010463
Christian Stimmingd990ced2007-11-07 18:42:55 +010010464 label $top.ddisp -text [mc "Diff display options"]
Paul Mackerras712fcc02005-11-30 09:28:16 +110010465 grid $top.ddisp - -sticky w -pady 10
Christian Stimmingd990ced2007-11-07 18:42:55 +010010466 label $top.tabstopl -text [mc "Tab spacing"] -font optionfont
Paul Mackerras94503912007-10-23 10:33:38 +100010467 spinbox $top.tabstop -from 1 -to 20 -width 4 -textvariable tabstop
10468 grid x $top.tabstopl $top.tabstop -sticky w
Johannes Sixtadcbec12008-12-02 21:42:16 +010010469 checkbutton $top.ntag -text [mc "Display nearby tags"] \
10470 -font optionfont -variable showneartags
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +100010471 grid x $top.ntag -sticky w
Thomas Rastffe15292009-08-03 23:53:36 +020010472 checkbutton $top.hideremotes -text [mc "Hide remote refs"] \
10473 -font optionfont -variable hideremotes
10474 grid x $top.hideremotes -sticky w
Johannes Sixtadcbec12008-12-02 21:42:16 +010010475 checkbutton $top.ldiff -text [mc "Limit diffs to listed paths"] \
10476 -font optionfont -variable limitdiffs
Paul Mackerras7a39a172007-10-23 10:15:11 +100010477 grid x $top.ldiff -sticky w
Johannes Sixtadcbec12008-12-02 21:42:16 +010010478 checkbutton $top.lattr -text [mc "Support per-file encodings"] \
10479 -font optionfont -variable perfile_attrs
Paul Mackerras39ee47e2008-10-15 22:23:03 +110010480 grid x $top.lattr -sticky w
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +100010481
Thomas Arcila314f5de2008-03-24 12:55:36 +010010482 entry $top.extdifft -textvariable extdifftool
10483 frame $top.extdifff
10484 label $top.extdifff.l -text [mc "External diff tool" ] -font optionfont \
10485 -padx 10
10486 button $top.extdifff.b -text [mc "Choose..."] -font optionfont \
10487 -command choose_extdiff
10488 pack $top.extdifff.l $top.extdifff.b -side left
10489 grid x $top.extdifff $top.extdifft -sticky w
10490
Christian Stimmingd990ced2007-11-07 18:42:55 +010010491 label $top.cdisp -text [mc "Colors: press to choose"]
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +100010492 grid $top.cdisp - -sticky w -pady 10
Guillermo S. Romero5497f7a2009-10-15 18:51:49 +020010493 label $top.ui -padx 40 -relief sunk -background $uicolor
10494 button $top.uibut -text [mc "Interface"] -font optionfont \
10495 -command [list choosecolor uicolor {} $top.ui [mc "interface"] setui]
10496 grid x $top.uibut $top.ui -sticky w
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +100010497 label $top.bg -padx 40 -relief sunk -background $bgcolor
Christian Stimmingd990ced2007-11-07 18:42:55 +010010498 button $top.bgbut -text [mc "Background"] -font optionfont \
Christian Stimming968b0162008-12-06 20:48:30 +010010499 -command [list choosecolor bgcolor {} $top.bg [mc "background"] setbg]
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +100010500 grid x $top.bgbut $top.bg -sticky w
10501 label $top.fg -padx 40 -relief sunk -background $fgcolor
Christian Stimmingd990ced2007-11-07 18:42:55 +010010502 button $top.fgbut -text [mc "Foreground"] -font optionfont \
Christian Stimming968b0162008-12-06 20:48:30 +010010503 -command [list choosecolor fgcolor {} $top.fg [mc "foreground"] setfg]
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +100010504 grid x $top.fgbut $top.fg -sticky w
10505 label $top.diffold -padx 40 -relief sunk -background [lindex $diffcolors 0]
Christian Stimmingd990ced2007-11-07 18:42:55 +010010506 button $top.diffoldbut -text [mc "Diff: old lines"] -font optionfont \
Christian Stimming968b0162008-12-06 20:48:30 +010010507 -command [list choosecolor diffcolors 0 $top.diffold [mc "diff old lines"] \
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +100010508 [list $ctext tag conf d0 -foreground]]
10509 grid x $top.diffoldbut $top.diffold -sticky w
10510 label $top.diffnew -padx 40 -relief sunk -background [lindex $diffcolors 1]
Christian Stimmingd990ced2007-11-07 18:42:55 +010010511 button $top.diffnewbut -text [mc "Diff: new lines"] -font optionfont \
Christian Stimming968b0162008-12-06 20:48:30 +010010512 -command [list choosecolor diffcolors 1 $top.diffnew [mc "diff new lines"] \
Paul Mackerras8b07dca2008-11-02 22:34:47 +110010513 [list $ctext tag conf dresult -foreground]]
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +100010514 grid x $top.diffnewbut $top.diffnew -sticky w
10515 label $top.hunksep -padx 40 -relief sunk -background [lindex $diffcolors 2]
Christian Stimmingd990ced2007-11-07 18:42:55 +010010516 button $top.hunksepbut -text [mc "Diff: hunk header"] -font optionfont \
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +100010517 -command [list choosecolor diffcolors 2 $top.hunksep \
Christian Stimming968b0162008-12-06 20:48:30 +010010518 [mc "diff hunk header"] \
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +100010519 [list $ctext tag conf hunksep -foreground]]
10520 grid x $top.hunksepbut $top.hunksep -sticky w
Paul Mackerrase3e901b2008-10-27 22:37:21 +110010521 label $top.markbgsep -padx 40 -relief sunk -background $markbgcolor
10522 button $top.markbgbut -text [mc "Marked line bg"] -font optionfont \
10523 -command [list choosecolor markbgcolor {} $top.markbgsep \
10524 [mc "marked line background"] \
10525 [list $ctext tag conf omark -background]]
10526 grid x $top.markbgbut $top.markbgsep -sticky w
Mark Levedahl60378c02007-05-20 12:12:48 -040010527 label $top.selbgsep -padx 40 -relief sunk -background $selectbgcolor
Christian Stimmingd990ced2007-11-07 18:42:55 +010010528 button $top.selbgbut -text [mc "Select bg"] -font optionfont \
Christian Stimming968b0162008-12-06 20:48:30 +010010529 -command [list choosecolor selectbgcolor {} $top.selbgsep [mc "background"] setselbg]
Mark Levedahl60378c02007-05-20 12:12:48 -040010530 grid x $top.selbgbut $top.selbgsep -sticky w
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +100010531
Christian Stimmingd990ced2007-11-07 18:42:55 +010010532 label $top.cfont -text [mc "Fonts: press to choose"]
Paul Mackerras9a7558f2007-10-06 20:16:06 +100010533 grid $top.cfont - -sticky w -pady 10
Christian Stimmingd990ced2007-11-07 18:42:55 +010010534 mkfontdisp mainfont $top [mc "Main font"]
10535 mkfontdisp textfont $top [mc "Diff display font"]
10536 mkfontdisp uifont $top [mc "User interface font"]
Paul Mackerras9a7558f2007-10-06 20:16:06 +100010537
Paul Mackerras712fcc02005-11-30 09:28:16 +110010538 frame $top.buts
Christian Stimmingd990ced2007-11-07 18:42:55 +010010539 button $top.buts.ok -text [mc "OK"] -command prefsok -default active
Christian Stimmingd990ced2007-11-07 18:42:55 +010010540 button $top.buts.can -text [mc "Cancel"] -command prefscan -default normal
Alexander Gavrilov76f15942008-11-02 21:59:44 +030010541 bind $top <Key-Return> prefsok
10542 bind $top <Key-Escape> prefscan
Paul Mackerras712fcc02005-11-30 09:28:16 +110010543 grid $top.buts.ok $top.buts.can
10544 grid columnconfigure $top.buts 0 -weight 1 -uniform a
10545 grid columnconfigure $top.buts 1 -weight 1 -uniform a
10546 grid $top.buts - - -pady 10 -sticky ew
Eygene Ryabinkin3a950e92007-03-27 14:36:59 +040010547 bind $top <Visibility> "focus $top.buts.ok"
Paul Mackerras712fcc02005-11-30 09:28:16 +110010548}
10549
Thomas Arcila314f5de2008-03-24 12:55:36 +010010550proc choose_extdiff {} {
10551 global extdifftool
10552
Michele Ballabiob56e0a92009-03-30 21:17:25 +020010553 set prog [tk_getOpenFile -title [mc "External diff tool"] -multiple false]
Thomas Arcila314f5de2008-03-24 12:55:36 +010010554 if {$prog ne {}} {
10555 set extdifftool $prog
10556 }
10557}
10558
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +100010559proc choosecolor {v vi w x cmd} {
10560 global $v
10561
10562 set c [tk_chooseColor -initialcolor [lindex [set $v] $vi] \
Christian Stimmingd990ced2007-11-07 18:42:55 +010010563 -title [mc "Gitk: choose color for %s" $x]]
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +100010564 if {$c eq {}} return
10565 $w conf -background $c
10566 lset $v $vi $c
10567 eval $cmd $c
10568}
10569
Mark Levedahl60378c02007-05-20 12:12:48 -040010570proc setselbg {c} {
10571 global bglist cflist
10572 foreach w $bglist {
10573 $w configure -selectbackground $c
10574 }
10575 $cflist tag configure highlight \
10576 -background [$cflist cget -selectbackground]
10577 allcanvs itemconf secsel -fill $c
10578}
10579
Guillermo S. Romero5497f7a2009-10-15 18:51:49 +020010580proc setui {c} {
10581 tk_setPalette $c
10582}
10583
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +100010584proc setbg {c} {
10585 global bglist
10586
10587 foreach w $bglist {
10588 $w conf -background $c
10589 }
10590}
10591
10592proc setfg {c} {
10593 global fglist canv
10594
10595 foreach w $fglist {
10596 $w conf -foreground $c
10597 }
10598 allcanvs itemconf text -fill $c
10599 $canv itemconf circle -outline $c
Paul Mackerrasb9fdba72009-04-09 09:34:46 +100010600 $canv itemconf markid -outline $c
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +100010601}
10602
Paul Mackerras712fcc02005-11-30 09:28:16 +110010603proc prefscan {} {
Paul Mackerras94503912007-10-23 10:33:38 +100010604 global oldprefs prefstop
Paul Mackerras712fcc02005-11-30 09:28:16 +110010605
Paul Mackerras3de07112007-10-23 22:40:50 +100010606 foreach v {maxwidth maxgraphpct showneartags showlocalchanges \
Thomas Rastffe15292009-08-03 23:53:36 +020010607 limitdiffs tabstop perfile_attrs hideremotes} {
Paul Mackerras94503912007-10-23 10:33:38 +100010608 global $v
Paul Mackerras712fcc02005-11-30 09:28:16 +110010609 set $v $oldprefs($v)
10610 }
10611 catch {destroy $prefstop}
10612 unset prefstop
Paul Mackerras9a7558f2007-10-06 20:16:06 +100010613 fontcan
Paul Mackerras712fcc02005-11-30 09:28:16 +110010614}
10615
10616proc prefsok {} {
10617 global maxwidth maxgraphpct
Paul Mackerras219ea3a2006-09-07 10:21:39 +100010618 global oldprefs prefstop showneartags showlocalchanges
Paul Mackerras9a7558f2007-10-06 20:16:06 +100010619 global fontpref mainfont textfont uifont
Paul Mackerras39ee47e2008-10-15 22:23:03 +110010620 global limitdiffs treediffs perfile_attrs
Thomas Rastffe15292009-08-03 23:53:36 +020010621 global hideremotes
Paul Mackerras712fcc02005-11-30 09:28:16 +110010622
10623 catch {destroy $prefstop}
10624 unset prefstop
Paul Mackerras9a7558f2007-10-06 20:16:06 +100010625 fontcan
10626 set fontchanged 0
10627 if {$mainfont ne $fontpref(mainfont)} {
10628 set mainfont $fontpref(mainfont)
10629 parsefont mainfont $mainfont
10630 eval font configure mainfont [fontflags mainfont]
10631 eval font configure mainfontbold [fontflags mainfont 1]
10632 setcoords
10633 set fontchanged 1
10634 }
10635 if {$textfont ne $fontpref(textfont)} {
10636 set textfont $fontpref(textfont)
10637 parsefont textfont $textfont
10638 eval font configure textfont [fontflags textfont]
10639 eval font configure textfontbold [fontflags textfont 1]
10640 }
10641 if {$uifont ne $fontpref(uifont)} {
10642 set uifont $fontpref(uifont)
10643 parsefont uifont $uifont
10644 eval font configure uifont [fontflags uifont]
10645 }
Paul Mackerras32f1b3e2007-09-28 21:27:39 +100010646 settabs
Paul Mackerras219ea3a2006-09-07 10:21:39 +100010647 if {$showlocalchanges != $oldprefs(showlocalchanges)} {
10648 if {$showlocalchanges} {
10649 doshowlocalchanges
10650 } else {
10651 dohidelocalchanges
10652 }
10653 }
Paul Mackerras39ee47e2008-10-15 22:23:03 +110010654 if {$limitdiffs != $oldprefs(limitdiffs) ||
10655 ($perfile_attrs && !$oldprefs(perfile_attrs))} {
10656 # treediffs elements are limited by path;
10657 # won't have encodings cached if perfile_attrs was just turned on
Paul Mackerras74a40c72007-10-24 10:16:56 +100010658 catch {unset treediffs}
10659 }
Paul Mackerras9a7558f2007-10-06 20:16:06 +100010660 if {$fontchanged || $maxwidth != $oldprefs(maxwidth)
Paul Mackerras712fcc02005-11-30 09:28:16 +110010661 || $maxgraphpct != $oldprefs(maxgraphpct)} {
10662 redisplay
Paul Mackerras7a39a172007-10-23 10:15:11 +100010663 } elseif {$showneartags != $oldprefs(showneartags) ||
10664 $limitdiffs != $oldprefs(limitdiffs)} {
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +100010665 reselectline
Paul Mackerras712fcc02005-11-30 09:28:16 +110010666 }
Thomas Rastffe15292009-08-03 23:53:36 +020010667 if {$hideremotes != $oldprefs(hideremotes)} {
10668 rereadrefs
10669 }
Paul Mackerras712fcc02005-11-30 09:28:16 +110010670}
10671
10672proc formatdate {d} {
Arjen Laarhovene8b5f4b2007-08-14 22:02:04 +020010673 global datetimeformat
Paul Mackerras219ea3a2006-09-07 10:21:39 +100010674 if {$d ne {}} {
Arjen Laarhovene8b5f4b2007-08-14 22:02:04 +020010675 set d [clock format $d -format $datetimeformat]
Paul Mackerras219ea3a2006-09-07 10:21:39 +100010676 }
10677 return $d
Paul Mackerras232475d2005-11-15 10:34:03 +110010678}
10679
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +110010680# This list of encoding names and aliases is distilled from
10681# http://www.iana.org/assignments/character-sets.
10682# Not all of them are supported by Tcl.
10683set encoding_aliases {
10684 { ANSI_X3.4-1968 iso-ir-6 ANSI_X3.4-1986 ISO_646.irv:1991 ASCII
10685 ISO646-US US-ASCII us IBM367 cp367 csASCII }
10686 { ISO-10646-UTF-1 csISO10646UTF1 }
10687 { ISO_646.basic:1983 ref csISO646basic1983 }
10688 { INVARIANT csINVARIANT }
10689 { ISO_646.irv:1983 iso-ir-2 irv csISO2IntlRefVersion }
10690 { BS_4730 iso-ir-4 ISO646-GB gb uk csISO4UnitedKingdom }
10691 { NATS-SEFI iso-ir-8-1 csNATSSEFI }
10692 { NATS-SEFI-ADD iso-ir-8-2 csNATSSEFIADD }
10693 { NATS-DANO iso-ir-9-1 csNATSDANO }
10694 { NATS-DANO-ADD iso-ir-9-2 csNATSDANOADD }
10695 { SEN_850200_B iso-ir-10 FI ISO646-FI ISO646-SE se csISO10Swedish }
10696 { SEN_850200_C iso-ir-11 ISO646-SE2 se2 csISO11SwedishForNames }
10697 { KS_C_5601-1987 iso-ir-149 KS_C_5601-1989 KSC_5601 korean csKSC56011987 }
10698 { ISO-2022-KR csISO2022KR }
10699 { EUC-KR csEUCKR }
10700 { ISO-2022-JP csISO2022JP }
10701 { ISO-2022-JP-2 csISO2022JP2 }
10702 { JIS_C6220-1969-jp JIS_C6220-1969 iso-ir-13 katakana x0201-7
10703 csISO13JISC6220jp }
10704 { JIS_C6220-1969-ro iso-ir-14 jp ISO646-JP csISO14JISC6220ro }
10705 { IT iso-ir-15 ISO646-IT csISO15Italian }
10706 { PT iso-ir-16 ISO646-PT csISO16Portuguese }
10707 { ES iso-ir-17 ISO646-ES csISO17Spanish }
10708 { greek7-old iso-ir-18 csISO18Greek7Old }
10709 { latin-greek iso-ir-19 csISO19LatinGreek }
10710 { DIN_66003 iso-ir-21 de ISO646-DE csISO21German }
10711 { NF_Z_62-010_(1973) iso-ir-25 ISO646-FR1 csISO25French }
10712 { Latin-greek-1 iso-ir-27 csISO27LatinGreek1 }
10713 { ISO_5427 iso-ir-37 csISO5427Cyrillic }
10714 { JIS_C6226-1978 iso-ir-42 csISO42JISC62261978 }
10715 { BS_viewdata iso-ir-47 csISO47BSViewdata }
10716 { INIS iso-ir-49 csISO49INIS }
10717 { INIS-8 iso-ir-50 csISO50INIS8 }
10718 { INIS-cyrillic iso-ir-51 csISO51INISCyrillic }
10719 { ISO_5427:1981 iso-ir-54 ISO5427Cyrillic1981 }
10720 { ISO_5428:1980 iso-ir-55 csISO5428Greek }
10721 { GB_1988-80 iso-ir-57 cn ISO646-CN csISO57GB1988 }
10722 { GB_2312-80 iso-ir-58 chinese csISO58GB231280 }
10723 { NS_4551-1 iso-ir-60 ISO646-NO no csISO60DanishNorwegian
10724 csISO60Norwegian1 }
10725 { NS_4551-2 ISO646-NO2 iso-ir-61 no2 csISO61Norwegian2 }
10726 { NF_Z_62-010 iso-ir-69 ISO646-FR fr csISO69French }
10727 { videotex-suppl iso-ir-70 csISO70VideotexSupp1 }
10728 { PT2 iso-ir-84 ISO646-PT2 csISO84Portuguese2 }
10729 { ES2 iso-ir-85 ISO646-ES2 csISO85Spanish2 }
10730 { MSZ_7795.3 iso-ir-86 ISO646-HU hu csISO86Hungarian }
10731 { JIS_C6226-1983 iso-ir-87 x0208 JIS_X0208-1983 csISO87JISX0208 }
10732 { greek7 iso-ir-88 csISO88Greek7 }
10733 { ASMO_449 ISO_9036 arabic7 iso-ir-89 csISO89ASMO449 }
10734 { iso-ir-90 csISO90 }
10735 { JIS_C6229-1984-a iso-ir-91 jp-ocr-a csISO91JISC62291984a }
10736 { JIS_C6229-1984-b iso-ir-92 ISO646-JP-OCR-B jp-ocr-b
10737 csISO92JISC62991984b }
10738 { JIS_C6229-1984-b-add iso-ir-93 jp-ocr-b-add csISO93JIS62291984badd }
10739 { JIS_C6229-1984-hand iso-ir-94 jp-ocr-hand csISO94JIS62291984hand }
10740 { JIS_C6229-1984-hand-add iso-ir-95 jp-ocr-hand-add
10741 csISO95JIS62291984handadd }
10742 { JIS_C6229-1984-kana iso-ir-96 csISO96JISC62291984kana }
10743 { ISO_2033-1983 iso-ir-98 e13b csISO2033 }
10744 { ANSI_X3.110-1983 iso-ir-99 CSA_T500-1983 NAPLPS csISO99NAPLPS }
10745 { ISO_8859-1:1987 iso-ir-100 ISO_8859-1 ISO-8859-1 latin1 l1 IBM819
10746 CP819 csISOLatin1 }
10747 { ISO_8859-2:1987 iso-ir-101 ISO_8859-2 ISO-8859-2 latin2 l2 csISOLatin2 }
10748 { T.61-7bit iso-ir-102 csISO102T617bit }
10749 { T.61-8bit T.61 iso-ir-103 csISO103T618bit }
10750 { ISO_8859-3:1988 iso-ir-109 ISO_8859-3 ISO-8859-3 latin3 l3 csISOLatin3 }
10751 { ISO_8859-4:1988 iso-ir-110 ISO_8859-4 ISO-8859-4 latin4 l4 csISOLatin4 }
10752 { ECMA-cyrillic iso-ir-111 KOI8-E csISO111ECMACyrillic }
10753 { CSA_Z243.4-1985-1 iso-ir-121 ISO646-CA csa7-1 ca csISO121Canadian1 }
10754 { CSA_Z243.4-1985-2 iso-ir-122 ISO646-CA2 csa7-2 csISO122Canadian2 }
10755 { CSA_Z243.4-1985-gr iso-ir-123 csISO123CSAZ24341985gr }
10756 { ISO_8859-6:1987 iso-ir-127 ISO_8859-6 ISO-8859-6 ECMA-114 ASMO-708
10757 arabic csISOLatinArabic }
10758 { ISO_8859-6-E csISO88596E ISO-8859-6-E }
10759 { ISO_8859-6-I csISO88596I ISO-8859-6-I }
10760 { ISO_8859-7:1987 iso-ir-126 ISO_8859-7 ISO-8859-7 ELOT_928 ECMA-118
10761 greek greek8 csISOLatinGreek }
10762 { T.101-G2 iso-ir-128 csISO128T101G2 }
10763 { ISO_8859-8:1988 iso-ir-138 ISO_8859-8 ISO-8859-8 hebrew
10764 csISOLatinHebrew }
10765 { ISO_8859-8-E csISO88598E ISO-8859-8-E }
10766 { ISO_8859-8-I csISO88598I ISO-8859-8-I }
10767 { CSN_369103 iso-ir-139 csISO139CSN369103 }
10768 { JUS_I.B1.002 iso-ir-141 ISO646-YU js yu csISO141JUSIB1002 }
10769 { ISO_6937-2-add iso-ir-142 csISOTextComm }
10770 { IEC_P27-1 iso-ir-143 csISO143IECP271 }
10771 { ISO_8859-5:1988 iso-ir-144 ISO_8859-5 ISO-8859-5 cyrillic
10772 csISOLatinCyrillic }
10773 { JUS_I.B1.003-serb iso-ir-146 serbian csISO146Serbian }
10774 { JUS_I.B1.003-mac macedonian iso-ir-147 csISO147Macedonian }
10775 { ISO_8859-9:1989 iso-ir-148 ISO_8859-9 ISO-8859-9 latin5 l5 csISOLatin5 }
10776 { greek-ccitt iso-ir-150 csISO150 csISO150GreekCCITT }
10777 { NC_NC00-10:81 cuba iso-ir-151 ISO646-CU csISO151Cuba }
10778 { ISO_6937-2-25 iso-ir-152 csISO6937Add }
10779 { GOST_19768-74 ST_SEV_358-88 iso-ir-153 csISO153GOST1976874 }
10780 { ISO_8859-supp iso-ir-154 latin1-2-5 csISO8859Supp }
10781 { ISO_10367-box iso-ir-155 csISO10367Box }
10782 { ISO-8859-10 iso-ir-157 l6 ISO_8859-10:1992 csISOLatin6 latin6 }
10783 { latin-lap lap iso-ir-158 csISO158Lap }
10784 { JIS_X0212-1990 x0212 iso-ir-159 csISO159JISX02121990 }
10785 { DS_2089 DS2089 ISO646-DK dk csISO646Danish }
10786 { us-dk csUSDK }
10787 { dk-us csDKUS }
10788 { JIS_X0201 X0201 csHalfWidthKatakana }
10789 { KSC5636 ISO646-KR csKSC5636 }
10790 { ISO-10646-UCS-2 csUnicode }
10791 { ISO-10646-UCS-4 csUCS4 }
10792 { DEC-MCS dec csDECMCS }
10793 { hp-roman8 roman8 r8 csHPRoman8 }
10794 { macintosh mac csMacintosh }
10795 { IBM037 cp037 ebcdic-cp-us ebcdic-cp-ca ebcdic-cp-wt ebcdic-cp-nl
10796 csIBM037 }
10797 { IBM038 EBCDIC-INT cp038 csIBM038 }
10798 { IBM273 CP273 csIBM273 }
10799 { IBM274 EBCDIC-BE CP274 csIBM274 }
10800 { IBM275 EBCDIC-BR cp275 csIBM275 }
10801 { IBM277 EBCDIC-CP-DK EBCDIC-CP-NO csIBM277 }
10802 { IBM278 CP278 ebcdic-cp-fi ebcdic-cp-se csIBM278 }
10803 { IBM280 CP280 ebcdic-cp-it csIBM280 }
10804 { IBM281 EBCDIC-JP-E cp281 csIBM281 }
10805 { IBM284 CP284 ebcdic-cp-es csIBM284 }
10806 { IBM285 CP285 ebcdic-cp-gb csIBM285 }
10807 { IBM290 cp290 EBCDIC-JP-kana csIBM290 }
10808 { IBM297 cp297 ebcdic-cp-fr csIBM297 }
10809 { IBM420 cp420 ebcdic-cp-ar1 csIBM420 }
10810 { IBM423 cp423 ebcdic-cp-gr csIBM423 }
10811 { IBM424 cp424 ebcdic-cp-he csIBM424 }
10812 { IBM437 cp437 437 csPC8CodePage437 }
10813 { IBM500 CP500 ebcdic-cp-be ebcdic-cp-ch csIBM500 }
10814 { IBM775 cp775 csPC775Baltic }
10815 { IBM850 cp850 850 csPC850Multilingual }
10816 { IBM851 cp851 851 csIBM851 }
10817 { IBM852 cp852 852 csPCp852 }
10818 { IBM855 cp855 855 csIBM855 }
10819 { IBM857 cp857 857 csIBM857 }
10820 { IBM860 cp860 860 csIBM860 }
10821 { IBM861 cp861 861 cp-is csIBM861 }
10822 { IBM862 cp862 862 csPC862LatinHebrew }
10823 { IBM863 cp863 863 csIBM863 }
10824 { IBM864 cp864 csIBM864 }
10825 { IBM865 cp865 865 csIBM865 }
10826 { IBM866 cp866 866 csIBM866 }
10827 { IBM868 CP868 cp-ar csIBM868 }
10828 { IBM869 cp869 869 cp-gr csIBM869 }
10829 { IBM870 CP870 ebcdic-cp-roece ebcdic-cp-yu csIBM870 }
10830 { IBM871 CP871 ebcdic-cp-is csIBM871 }
10831 { IBM880 cp880 EBCDIC-Cyrillic csIBM880 }
10832 { IBM891 cp891 csIBM891 }
10833 { IBM903 cp903 csIBM903 }
10834 { IBM904 cp904 904 csIBBM904 }
10835 { IBM905 CP905 ebcdic-cp-tr csIBM905 }
10836 { IBM918 CP918 ebcdic-cp-ar2 csIBM918 }
10837 { IBM1026 CP1026 csIBM1026 }
10838 { EBCDIC-AT-DE csIBMEBCDICATDE }
10839 { EBCDIC-AT-DE-A csEBCDICATDEA }
10840 { EBCDIC-CA-FR csEBCDICCAFR }
10841 { EBCDIC-DK-NO csEBCDICDKNO }
10842 { EBCDIC-DK-NO-A csEBCDICDKNOA }
10843 { EBCDIC-FI-SE csEBCDICFISE }
10844 { EBCDIC-FI-SE-A csEBCDICFISEA }
10845 { EBCDIC-FR csEBCDICFR }
10846 { EBCDIC-IT csEBCDICIT }
10847 { EBCDIC-PT csEBCDICPT }
10848 { EBCDIC-ES csEBCDICES }
10849 { EBCDIC-ES-A csEBCDICESA }
10850 { EBCDIC-ES-S csEBCDICESS }
10851 { EBCDIC-UK csEBCDICUK }
10852 { EBCDIC-US csEBCDICUS }
10853 { UNKNOWN-8BIT csUnknown8BiT }
10854 { MNEMONIC csMnemonic }
10855 { MNEM csMnem }
10856 { VISCII csVISCII }
10857 { VIQR csVIQR }
10858 { KOI8-R csKOI8R }
10859 { IBM00858 CCSID00858 CP00858 PC-Multilingual-850+euro }
10860 { IBM00924 CCSID00924 CP00924 ebcdic-Latin9--euro }
10861 { IBM01140 CCSID01140 CP01140 ebcdic-us-37+euro }
10862 { IBM01141 CCSID01141 CP01141 ebcdic-de-273+euro }
10863 { IBM01142 CCSID01142 CP01142 ebcdic-dk-277+euro ebcdic-no-277+euro }
10864 { IBM01143 CCSID01143 CP01143 ebcdic-fi-278+euro ebcdic-se-278+euro }
10865 { IBM01144 CCSID01144 CP01144 ebcdic-it-280+euro }
10866 { IBM01145 CCSID01145 CP01145 ebcdic-es-284+euro }
10867 { IBM01146 CCSID01146 CP01146 ebcdic-gb-285+euro }
10868 { IBM01147 CCSID01147 CP01147 ebcdic-fr-297+euro }
10869 { IBM01148 CCSID01148 CP01148 ebcdic-international-500+euro }
10870 { IBM01149 CCSID01149 CP01149 ebcdic-is-871+euro }
10871 { IBM1047 IBM-1047 }
10872 { PTCP154 csPTCP154 PT154 CP154 Cyrillic-Asian }
10873 { Amiga-1251 Ami1251 Amiga1251 Ami-1251 }
10874 { UNICODE-1-1 csUnicode11 }
10875 { CESU-8 csCESU-8 }
10876 { BOCU-1 csBOCU-1 }
10877 { UNICODE-1-1-UTF-7 csUnicode11UTF7 }
10878 { ISO-8859-14 iso-ir-199 ISO_8859-14:1998 ISO_8859-14 latin8 iso-celtic
10879 l8 }
10880 { ISO-8859-15 ISO_8859-15 Latin-9 }
10881 { ISO-8859-16 iso-ir-226 ISO_8859-16:2001 ISO_8859-16 latin10 l10 }
10882 { GBK CP936 MS936 windows-936 }
10883 { JIS_Encoding csJISEncoding }
Alexander Gavrilov09c70292008-10-13 12:12:31 +040010884 { Shift_JIS MS_Kanji csShiftJIS ShiftJIS Shift-JIS }
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +110010885 { Extended_UNIX_Code_Packed_Format_for_Japanese csEUCPkdFmtJapanese
10886 EUC-JP }
10887 { Extended_UNIX_Code_Fixed_Width_for_Japanese csEUCFixWidJapanese }
10888 { ISO-10646-UCS-Basic csUnicodeASCII }
10889 { ISO-10646-Unicode-Latin1 csUnicodeLatin1 ISO-10646 }
10890 { ISO-Unicode-IBM-1261 csUnicodeIBM1261 }
10891 { ISO-Unicode-IBM-1268 csUnicodeIBM1268 }
10892 { ISO-Unicode-IBM-1276 csUnicodeIBM1276 }
10893 { ISO-Unicode-IBM-1264 csUnicodeIBM1264 }
10894 { ISO-Unicode-IBM-1265 csUnicodeIBM1265 }
10895 { ISO-8859-1-Windows-3.0-Latin-1 csWindows30Latin1 }
10896 { ISO-8859-1-Windows-3.1-Latin-1 csWindows31Latin1 }
10897 { ISO-8859-2-Windows-Latin-2 csWindows31Latin2 }
10898 { ISO-8859-9-Windows-Latin-5 csWindows31Latin5 }
10899 { Adobe-Standard-Encoding csAdobeStandardEncoding }
10900 { Ventura-US csVenturaUS }
10901 { Ventura-International csVenturaInternational }
10902 { PC8-Danish-Norwegian csPC8DanishNorwegian }
10903 { PC8-Turkish csPC8Turkish }
10904 { IBM-Symbols csIBMSymbols }
10905 { IBM-Thai csIBMThai }
10906 { HP-Legal csHPLegal }
10907 { HP-Pi-font csHPPiFont }
10908 { HP-Math8 csHPMath8 }
10909 { Adobe-Symbol-Encoding csHPPSMath }
10910 { HP-DeskTop csHPDesktop }
10911 { Ventura-Math csVenturaMath }
10912 { Microsoft-Publishing csMicrosoftPublishing }
10913 { Windows-31J csWindows31J }
10914 { GB2312 csGB2312 }
10915 { Big5 csBig5 }
10916}
10917
10918proc tcl_encoding {enc} {
Paul Mackerras39ee47e2008-10-15 22:23:03 +110010919 global encoding_aliases tcl_encoding_cache
10920 if {[info exists tcl_encoding_cache($enc)]} {
10921 return $tcl_encoding_cache($enc)
10922 }
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +110010923 set names [encoding names]
10924 set lcnames [string tolower $names]
10925 set enc [string tolower $enc]
10926 set i [lsearch -exact $lcnames $enc]
10927 if {$i < 0} {
10928 # look for "isonnn" instead of "iso-nnn" or "iso_nnn"
Alexander Gavrilov09c70292008-10-13 12:12:31 +040010929 if {[regsub {^(iso|cp|ibm|jis)[-_]} $enc {\1} encx]} {
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +110010930 set i [lsearch -exact $lcnames $encx]
10931 }
10932 }
10933 if {$i < 0} {
10934 foreach l $encoding_aliases {
10935 set ll [string tolower $l]
10936 if {[lsearch -exact $ll $enc] < 0} continue
10937 # look through the aliases for one that tcl knows about
10938 foreach e $ll {
10939 set i [lsearch -exact $lcnames $e]
10940 if {$i < 0} {
Alexander Gavrilov09c70292008-10-13 12:12:31 +040010941 if {[regsub {^(iso|cp|ibm|jis)[-_]} $e {\1} ex]} {
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +110010942 set i [lsearch -exact $lcnames $ex]
10943 }
10944 }
10945 if {$i >= 0} break
10946 }
10947 break
10948 }
10949 }
Paul Mackerras39ee47e2008-10-15 22:23:03 +110010950 set tclenc {}
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +110010951 if {$i >= 0} {
Paul Mackerras39ee47e2008-10-15 22:23:03 +110010952 set tclenc [lindex $names $i]
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +110010953 }
Paul Mackerras39ee47e2008-10-15 22:23:03 +110010954 set tcl_encoding_cache($enc) $tclenc
10955 return $tclenc
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +110010956}
10957
Alexander Gavrilov09c70292008-10-13 12:12:31 +040010958proc gitattr {path attr default} {
Paul Mackerras39ee47e2008-10-15 22:23:03 +110010959 global path_attr_cache
10960 if {[info exists path_attr_cache($attr,$path)]} {
10961 set r $path_attr_cache($attr,$path)
10962 } else {
10963 set r "unspecified"
10964 if {![catch {set line [exec git check-attr $attr -- $path]}]} {
Johannes Sixt097e1112009-07-21 10:09:48 +020010965 regexp "(.*): $attr: (.*)" $line m f r
Alexander Gavrilov09c70292008-10-13 12:12:31 +040010966 }
Alexander Gavrilov4db09302008-10-13 12:12:33 +040010967 set path_attr_cache($attr,$path) $r
Paul Mackerras39ee47e2008-10-15 22:23:03 +110010968 }
10969 if {$r eq "unspecified"} {
10970 return $default
10971 }
10972 return $r
Alexander Gavrilov09c70292008-10-13 12:12:31 +040010973}
10974
Alexander Gavrilov4db09302008-10-13 12:12:33 +040010975proc cache_gitattr {attr pathlist} {
Paul Mackerras39ee47e2008-10-15 22:23:03 +110010976 global path_attr_cache
10977 set newlist {}
10978 foreach path $pathlist {
10979 if {![info exists path_attr_cache($attr,$path)]} {
10980 lappend newlist $path
Alexander Gavrilov4db09302008-10-13 12:12:33 +040010981 }
Paul Mackerras39ee47e2008-10-15 22:23:03 +110010982 }
10983 set lim 1000
10984 if {[tk windowingsystem] == "win32"} {
10985 # windows has a 32k limit on the arguments to a command...
10986 set lim 30
10987 }
10988 while {$newlist ne {}} {
10989 set head [lrange $newlist 0 [expr {$lim - 1}]]
10990 set newlist [lrange $newlist $lim end]
10991 if {![catch {set rlist [eval exec git check-attr $attr -- $head]}]} {
10992 foreach row [split $rlist "\n"] {
Johannes Sixt097e1112009-07-21 10:09:48 +020010993 if {[regexp "(.*): $attr: (.*)" $row m path value]} {
Paul Mackerras39ee47e2008-10-15 22:23:03 +110010994 if {[string index $path 0] eq "\""} {
10995 set path [encoding convertfrom [lindex $path 0]]
10996 }
10997 set path_attr_cache($attr,$path) $value
Alexander Gavrilov4db09302008-10-13 12:12:33 +040010998 }
Paul Mackerras39ee47e2008-10-15 22:23:03 +110010999 }
Alexander Gavrilov4db09302008-10-13 12:12:33 +040011000 }
Paul Mackerras39ee47e2008-10-15 22:23:03 +110011001 }
Alexander Gavrilov4db09302008-10-13 12:12:33 +040011002}
11003
Alexander Gavrilov09c70292008-10-13 12:12:31 +040011004proc get_path_encoding {path} {
Paul Mackerras39ee47e2008-10-15 22:23:03 +110011005 global gui_encoding perfile_attrs
11006 set tcl_enc $gui_encoding
11007 if {$path ne {} && $perfile_attrs} {
11008 set enc2 [tcl_encoding [gitattr $path encoding $tcl_enc]]
11009 if {$enc2 ne {}} {
11010 set tcl_enc $enc2
Alexander Gavrilov09c70292008-10-13 12:12:31 +040011011 }
Paul Mackerras39ee47e2008-10-15 22:23:03 +110011012 }
11013 return $tcl_enc
Alexander Gavrilov09c70292008-10-13 12:12:31 +040011014}
11015
Paul Mackerras5d7589d2007-10-20 21:21:03 +100011016# First check that Tcl/Tk is recent enough
11017if {[catch {package require Tk 8.4} err]} {
Christian Stimmingd990ced2007-11-07 18:42:55 +010011018 show_error {} . [mc "Sorry, gitk cannot run with this version of Tcl/Tk.\n\
11019 Gitk requires at least Tcl/Tk 8.4."]
Paul Mackerras5d7589d2007-10-20 21:21:03 +100011020 exit 1
11021}
11022
Paul Mackerras1d10f362005-05-15 12:55:47 +000011023# defaults...
Timo Hirvonen8974c6f2006-05-24 10:57:40 +030011024set wrcomcmd "git diff-tree --stdin -p --pretty"
Junio C Hamano671bc152005-11-27 16:12:51 -080011025
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +110011026set gitencoding {}
Junio C Hamano671bc152005-11-27 16:12:51 -080011027catch {
Paul Mackerras27cb61c2007-02-15 08:54:34 +110011028 set gitencoding [exec git config --get i18n.commitencoding]
Junio C Hamano671bc152005-11-27 16:12:51 -080011029}
Alexander Gavrilov590915d2008-11-09 18:06:07 +030011030catch {
11031 set gitencoding [exec git config --get i18n.logoutputencoding]
11032}
Junio C Hamano671bc152005-11-27 16:12:51 -080011033if {$gitencoding == ""} {
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +110011034 set gitencoding "utf-8"
11035}
11036set tclencoding [tcl_encoding $gitencoding]
11037if {$tclencoding == {}} {
11038 puts stderr "Warning: encoding $gitencoding is not supported by Tcl/Tk"
Junio C Hamano671bc152005-11-27 16:12:51 -080011039}
Paul Mackerras1d10f362005-05-15 12:55:47 +000011040
Alexander Gavrilov09c70292008-10-13 12:12:31 +040011041set gui_encoding [encoding system]
11042catch {
Paul Mackerras39ee47e2008-10-15 22:23:03 +110011043 set enc [exec git config --get gui.encoding]
11044 if {$enc ne {}} {
11045 set tclenc [tcl_encoding $enc]
11046 if {$tclenc ne {}} {
11047 set gui_encoding $tclenc
11048 } else {
11049 puts stderr "Warning: encoding $enc is not supported by Tcl/Tk"
11050 }
11051 }
Alexander Gavrilov09c70292008-10-13 12:12:31 +040011052}
11053
Daniel A. Steffen5fdcbb12009-03-23 12:17:38 +010011054if {[tk windowingsystem] eq "aqua"} {
11055 set mainfont {{Lucida Grande} 9}
11056 set textfont {Monaco 9}
11057 set uifont {{Lucida Grande} 9 bold}
11058} else {
11059 set mainfont {Helvetica 9}
11060 set textfont {Courier 9}
11061 set uifont {Helvetica 9 bold}
11062}
Mark Levedahl7e12f1a2007-05-20 11:45:50 -040011063set tabstop 8
Paul Mackerrasb74fd572005-07-16 07:46:13 -040011064set findmergefiles 0
Paul Mackerras8d858d12005-08-05 09:52:16 +100011065set maxgraphpct 50
Paul Mackerrasf6075eb2005-08-18 09:30:10 +100011066set maxwidth 16
Paul Mackerras232475d2005-11-15 10:34:03 +110011067set revlistorder 0
Paul Mackerras757f17b2005-11-21 09:56:07 +110011068set fastdate 0
Paul Mackerras6e8c8702007-07-31 21:03:06 +100011069set uparrowlen 5
11070set downarrowlen 5
11071set mingaplen 100
Paul Mackerrasf8b28a42006-05-01 09:50:57 +100011072set cmitmode "patch"
Sergey Vlasovf1b86292006-05-15 19:13:14 +040011073set wrapcomment "none"
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +100011074set showneartags 1
Thomas Rastffe15292009-08-03 23:53:36 +020011075set hideremotes 0
Paul Mackerras0a4dd8b2007-06-16 21:21:57 +100011076set maxrefs 20
Paul Mackerras322a8cc2006-10-15 18:03:46 +100011077set maxlinelen 200
Paul Mackerras219ea3a2006-09-07 10:21:39 +100011078set showlocalchanges 1
Paul Mackerras7a39a172007-10-23 10:15:11 +100011079set limitdiffs 1
Arjen Laarhovene8b5f4b2007-08-14 22:02:04 +020011080set datetimeformat "%Y-%m-%d %H:%M:%S"
Jeff King95293b52008-03-06 06:49:25 -050011081set autoselect 1
Paul Mackerras39ee47e2008-10-15 22:23:03 +110011082set perfile_attrs 0
Paul Mackerras1d10f362005-05-15 12:55:47 +000011083
Daniel A. Steffen5fdcbb12009-03-23 12:17:38 +010011084if {[tk windowingsystem] eq "aqua"} {
11085 set extdifftool "opendiff"
11086} else {
11087 set extdifftool "meld"
11088}
Thomas Arcila314f5de2008-03-24 12:55:36 +010011089
Paul Mackerras1d10f362005-05-15 12:55:47 +000011090set colors {green red blue magenta darkgrey brown orange}
Guillermo S. Romero5497f7a2009-10-15 18:51:49 +020011091set uicolor grey85
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +100011092set bgcolor white
11093set fgcolor black
11094set diffcolors {red "#00a000" blue}
Steffen Prohaska890fae72007-08-12 12:05:46 +020011095set diffcontext 3
Steffen Prohaskab9b86002008-01-17 23:42:55 +010011096set ignorespace 0
Mark Levedahl60378c02007-05-20 12:12:48 -040011097set selectbgcolor gray85
Paul Mackerrase3e901b2008-10-27 22:37:21 +110011098set markbgcolor "#e0e0ff"
Paul Mackerras1d10f362005-05-15 12:55:47 +000011099
Paul Mackerrasc11ff122008-05-26 10:11:33 +100011100set circlecolors {white blue gray blue blue}
11101
Paul Mackerrasd277e892008-09-21 18:11:37 -050011102# button for popping up context menus
11103if {[tk windowingsystem] eq "aqua"} {
11104 set ctxbut <Button-2>
11105} else {
11106 set ctxbut <Button-3>
11107}
11108
Christian Stimming663c3aa2007-11-07 18:40:59 +010011109## For msgcat loading, first locate the installation location.
11110if { [info exists ::env(GITK_MSGSDIR)] } {
11111 ## Msgsdir was manually set in the environment.
11112 set gitk_msgsdir $::env(GITK_MSGSDIR)
11113} else {
11114 ## Let's guess the prefix from argv0.
11115 set gitk_prefix [file dirname [file dirname [file normalize $argv0]]]
11116 set gitk_libdir [file join $gitk_prefix share gitk lib]
11117 set gitk_msgsdir [file join $gitk_libdir msgs]
11118 unset gitk_prefix
11119}
11120
11121## Internationalization (i18n) through msgcat and gettext. See
11122## http://www.gnu.org/software/gettext/manual/html_node/Tcl.html
11123package require msgcat
11124namespace import ::msgcat::mc
11125## And eventually load the actual message catalog
11126::msgcat::mcload $gitk_msgsdir
11127
Paul Mackerras1d10f362005-05-15 12:55:47 +000011128catch {source ~/.gitk}
11129
Paul Mackerras712fcc02005-11-30 09:28:16 +110011130font create optionfont -family sans-serif -size -12
Paul Mackerras17386062005-05-18 22:51:00 +000011131
Paul Mackerras0ed1dd32007-10-06 18:27:37 +100011132parsefont mainfont $mainfont
11133eval font create mainfont [fontflags mainfont]
11134eval font create mainfontbold [fontflags mainfont 1]
11135
11136parsefont textfont $textfont
11137eval font create textfont [fontflags textfont]
11138eval font create textfontbold [fontflags textfont 1]
11139
11140parsefont uifont $uifont
11141eval font create uifont [fontflags uifont]
Paul Mackerras1db95b02005-05-09 04:08:39 +000011142
Guillermo S. Romero5497f7a2009-10-15 18:51:49 +020011143tk_setPalette $uicolor
11144
Paul Mackerrasb039f0a2008-01-06 15:54:46 +110011145setoptions
11146
Paul Mackerrasaa81d972006-02-28 11:27:12 +110011147# check that we can find a .git directory somewhere...
Alex Riesen6c87d602007-07-29 22:29:45 +020011148if {[catch {set gitdir [gitdir]}]} {
Christian Stimmingd990ced2007-11-07 18:42:55 +010011149 show_error {} . [mc "Cannot find a git repository here."]
Alex Riesen6c87d602007-07-29 22:29:45 +020011150 exit 1
11151}
Paul Mackerrasaa81d972006-02-28 11:27:12 +110011152if {![file isdirectory $gitdir]} {
Christian Stimmingd990ced2007-11-07 18:42:55 +010011153 show_error {} . [mc "Cannot find the git directory \"%s\"." $gitdir]
Paul Mackerrasaa81d972006-02-28 11:27:12 +110011154 exit 1
11155}
11156
Alexander Gavrilov39816d62008-08-23 12:27:44 +040011157set selecthead {}
11158set selectheadid {}
11159
Paul Mackerrascdaee5d2007-07-12 22:29:49 +100011160set revtreeargs {}
Paul Mackerras098dd8a2006-05-03 09:32:53 +100011161set cmdline_files {}
Paul Mackerrascdaee5d2007-07-12 22:29:49 +100011162set i 0
Yann Dirson2d480852008-02-21 21:23:31 +010011163set revtreeargscmd {}
Paul Mackerrascdaee5d2007-07-12 22:29:49 +100011164foreach arg $argv {
Yann Dirson2d480852008-02-21 21:23:31 +010011165 switch -glob -- $arg {
Paul Mackerras6ebedab2007-07-13 13:45:55 +100011166 "" { }
Paul Mackerrascdaee5d2007-07-12 22:29:49 +100011167 "--" {
11168 set cmdline_files [lrange $argv [expr {$i + 1}] end]
11169 break
11170 }
Alexander Gavrilov39816d62008-08-23 12:27:44 +040011171 "--select-commit=*" {
11172 set selecthead [string range $arg 16 end]
11173 }
Yann Dirson2d480852008-02-21 21:23:31 +010011174 "--argscmd=*" {
11175 set revtreeargscmd [string range $arg 10 end]
11176 }
Paul Mackerrascdaee5d2007-07-12 22:29:49 +100011177 default {
11178 lappend revtreeargs $arg
11179 }
11180 }
11181 incr i
11182}
11183
Alexander Gavrilov39816d62008-08-23 12:27:44 +040011184if {$selecthead eq "HEAD"} {
11185 set selecthead {}
11186}
11187
Paul Mackerrascdaee5d2007-07-12 22:29:49 +100011188if {$i >= [llength $argv] && $revtreeargs ne {}} {
Paul Mackerras3ed31a82008-04-26 16:00:00 +100011189 # no -- on command line, but some arguments (other than --argscmd)
Paul Mackerras098dd8a2006-05-03 09:32:53 +100011190 if {[catch {
Timo Hirvonen8974c6f2006-05-24 10:57:40 +030011191 set f [eval exec git rev-parse --no-revs --no-flags $revtreeargs]
Paul Mackerras098dd8a2006-05-03 09:32:53 +100011192 set cmdline_files [split $f "\n"]
11193 set n [llength $cmdline_files]
11194 set revtreeargs [lrange $revtreeargs 0 end-$n]
Paul Mackerrascdaee5d2007-07-12 22:29:49 +100011195 # Unfortunately git rev-parse doesn't produce an error when
11196 # something is both a revision and a filename. To be consistent
11197 # with git log and git rev-list, check revtreeargs for filenames.
11198 foreach arg $revtreeargs {
11199 if {[file exists $arg]} {
Christian Stimmingd990ced2007-11-07 18:42:55 +010011200 show_error {} . [mc "Ambiguous argument '%s': both revision\
11201 and filename" $arg]
Paul Mackerrascdaee5d2007-07-12 22:29:49 +100011202 exit 1
11203 }
11204 }
Paul Mackerras098dd8a2006-05-03 09:32:53 +100011205 } err]} {
11206 # unfortunately we get both stdout and stderr in $err,
11207 # so look for "fatal:".
11208 set i [string first "fatal:" $err]
11209 if {$i > 0} {
Junio C Hamanob5e09632006-05-26 00:07:15 -070011210 set err [string range $err [expr {$i + 6}] end]
Paul Mackerras098dd8a2006-05-03 09:32:53 +100011211 }
Christian Stimmingd990ced2007-11-07 18:42:55 +010011212 show_error {} . "[mc "Bad arguments to gitk:"]\n$err"
Paul Mackerras098dd8a2006-05-03 09:32:53 +100011213 exit 1
11214 }
11215}
11216
Paul Mackerras219ea3a2006-09-07 10:21:39 +100011217set nullid "0000000000000000000000000000000000000000"
Paul Mackerras8f489362007-07-13 19:49:37 +100011218set nullid2 "0000000000000000000000000000000000000001"
Thomas Arcila314f5de2008-03-24 12:55:36 +010011219set nullfile "/dev/null"
Paul Mackerras8f489362007-07-13 19:49:37 +100011220
Paul Mackerras32f1b3e2007-09-28 21:27:39 +100011221set have_tk85 [expr {[package vcompare $tk_version "8.5"] >= 0}]
Pat Thoyts194bbf62009-05-18 22:46:01 +010011222set git_version [join [lrange [split [lindex [exec git version] end] .] 0 2] .]
Paul Mackerras219ea3a2006-09-07 10:21:39 +100011223
Paul Mackerras7eb3cb92007-06-17 14:45:00 +100011224set runq {}
Paul Mackerrasd6982062005-08-06 22:06:06 +100011225set history {}
11226set historyindex 0
Paul Mackerras908c3582006-05-20 09:38:11 +100011227set fh_serial 0
Paul Mackerras908c3582006-05-20 09:38:11 +100011228set nhl_names {}
Paul Mackerras63b79192006-05-20 21:31:52 +100011229set highlight_paths {}
Paul Mackerras687c8762007-09-22 12:49:33 +100011230set findpattern {}
Paul Mackerras1902c272006-05-25 21:25:13 +100011231set searchdirn -forwards
Paul Mackerras28593d32008-11-13 23:01:46 +110011232set boldids {}
11233set boldnameids {}
Paul Mackerrasa8d610a2007-04-19 11:39:12 +100011234set diffelide {0 0}
Paul Mackerras4fb0fa12007-07-04 19:43:51 +100011235set markingmatches 0
Paul Mackerras97645682007-08-23 22:24:38 +100011236set linkentercount 0
Paul Mackerras03800812007-08-29 21:45:21 +100011237set need_redisplay 0
11238set nrows_drawn 0
Paul Mackerras32f1b3e2007-09-28 21:27:39 +100011239set firsttabstop 0
Paul Mackerras9f1afe02006-02-19 22:44:47 +110011240
Paul Mackerras50b44ec2006-04-04 10:16:22 +100011241set nextviewnum 1
11242set curview 0
Paul Mackerrasa90a6d22006-04-25 17:12:46 +100011243set selectedview 0
Christian Stimmingb007ee22007-11-07 18:44:35 +010011244set selectedhlview [mc "None"]
11245set highlight_related [mc "None"]
Paul Mackerras687c8762007-09-22 12:49:33 +100011246set highlight_files {}
Paul Mackerras50b44ec2006-04-04 10:16:22 +100011247set viewfiles(0) {}
Paul Mackerrasa90a6d22006-04-25 17:12:46 +100011248set viewperm(0) 0
Paul Mackerras098dd8a2006-05-03 09:32:53 +100011249set viewargs(0) {}
Yann Dirson2d480852008-02-21 21:23:31 +010011250set viewargscmd(0) {}
Paul Mackerras50b44ec2006-04-04 10:16:22 +100011251
Paul Mackerras94b4a692008-05-20 20:51:06 +100011252set selectedline {}
Paul Mackerras6df74032008-05-11 22:13:02 +100011253set numcommits 0
Paul Mackerras7fcc92b2007-12-03 10:33:01 +110011254set loginstance 0
Paul Mackerras098dd8a2006-05-03 09:32:53 +100011255set cmdlineok 0
Paul Mackerras1db95b02005-05-09 04:08:39 +000011256set stopped 0
Paul Mackerras1db95b02005-05-09 04:08:39 +000011257set stuffsaved 0
Paul Mackerras74daedb2005-06-27 19:27:32 +100011258set patchnum 0
Paul Mackerras219ea3a2006-09-07 10:21:39 +100011259set lserial 0
David Aguilarcb8329a2008-03-10 03:54:56 -070011260set isworktree [expr {[exec git rev-parse --is-inside-work-tree] == "true"}]
Paul Mackerras1db95b02005-05-09 04:08:39 +000011261setcoords
Paul Mackerrasd94f8cd2006-04-06 10:18:23 +100011262makewindow
Giuseppe Bilotta37871b72009-03-19 01:54:17 -070011263catch {
11264 image create photo gitlogo -width 16 -height 16
11265
11266 image create photo gitlogominus -width 4 -height 2
11267 gitlogominus put #C00000 -to 0 0 4 2
11268 gitlogo copy gitlogominus -to 1 5
11269 gitlogo copy gitlogominus -to 6 5
11270 gitlogo copy gitlogominus -to 11 5
11271 image delete gitlogominus
11272
11273 image create photo gitlogoplus -width 4 -height 4
11274 gitlogoplus put #008000 -to 1 0 3 4
11275 gitlogoplus put #008000 -to 0 1 4 3
11276 gitlogo copy gitlogoplus -to 1 9
11277 gitlogo copy gitlogoplus -to 6 9
11278 gitlogo copy gitlogoplus -to 11 9
11279 image delete gitlogoplus
11280
Stephen Boydd38d7d42009-03-19 01:54:18 -070011281 image create photo gitlogo32 -width 32 -height 32
11282 gitlogo32 copy gitlogo -zoom 2 2
11283
11284 wm iconphoto . -default gitlogo gitlogo32
Giuseppe Bilotta37871b72009-03-19 01:54:17 -070011285}
Paul Mackerras0eafba12007-07-23 21:35:03 +100011286# wait for the window to become visible
11287tkwait visibility .
Doug Maxey6c283322006-12-10 14:31:46 -060011288wm title . "[file tail $argv0]: [file tail [pwd]]"
Pat Thoyts478afad2009-04-15 17:14:03 +010011289update
Paul Mackerras887fe3c2005-05-21 07:35:37 +000011290readrefs
Paul Mackerrasa8aaf192006-04-23 22:45:55 +100011291
Yann Dirson2d480852008-02-21 21:23:31 +010011292if {$cmdline_files ne {} || $revtreeargs ne {} || $revtreeargscmd ne {}} {
Paul Mackerras50b44ec2006-04-04 10:16:22 +100011293 # create a view for the files/dirs specified on the command line
11294 set curview 1
Paul Mackerrasa90a6d22006-04-25 17:12:46 +100011295 set selectedview 1
Paul Mackerras50b44ec2006-04-04 10:16:22 +100011296 set nextviewnum 2
Christian Stimmingd990ced2007-11-07 18:42:55 +010011297 set viewname(1) [mc "Command line"]
Paul Mackerras50b44ec2006-04-04 10:16:22 +100011298 set viewfiles(1) $cmdline_files
Paul Mackerras098dd8a2006-05-03 09:32:53 +100011299 set viewargs(1) $revtreeargs
Yann Dirson2d480852008-02-21 21:23:31 +010011300 set viewargscmd(1) $revtreeargscmd
Paul Mackerrasa90a6d22006-04-25 17:12:46 +100011301 set viewperm(1) 0
Paul Mackerras3ed31a82008-04-26 16:00:00 +100011302 set vdatemode(1) 0
Paul Mackerrasda7c24d2006-05-02 11:15:29 +100011303 addviewmenu 1
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +110011304 .bar.view entryconf [mca "Edit view..."] -state normal
11305 .bar.view entryconf [mca "Delete view"] -state normal
Paul Mackerras50b44ec2006-04-04 10:16:22 +100011306}
Paul Mackerrasa90a6d22006-04-25 17:12:46 +100011307
11308if {[info exists permviews]} {
11309 foreach v $permviews {
11310 set n $nextviewnum
11311 incr nextviewnum
11312 set viewname($n) [lindex $v 0]
11313 set viewfiles($n) [lindex $v 1]
Paul Mackerras098dd8a2006-05-03 09:32:53 +100011314 set viewargs($n) [lindex $v 2]
Yann Dirson2d480852008-02-21 21:23:31 +010011315 set viewargscmd($n) [lindex $v 3]
Paul Mackerrasa90a6d22006-04-25 17:12:46 +100011316 set viewperm($n) 1
Paul Mackerrasda7c24d2006-05-02 11:15:29 +100011317 addviewmenu $n
Paul Mackerrasa90a6d22006-04-25 17:12:46 +100011318 }
11319}
Johannes Sixte4df5192008-12-18 08:30:49 +010011320
11321if {[tk windowingsystem] eq "win32"} {
11322 focus -force .
11323}
11324
Alexander Gavrilov567c34e2008-07-26 20:13:45 +040011325getcommits {}