blob: 0dcfbf1b4afb5e1e1149ad80c259cc09820eab80 [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" -
Paul Mackerras29582282008-11-18 19:44:20 +1100190 "-S*" - "--pickaxe-all" - "--pickaxe-regex" {
191 # These mean that we get a subset of the commits
Paul Mackerrasee66e082008-05-09 10:14:07 +1000192 set filtered 1
193 lappend glflags $arg
194 }
Paul Mackerrasee66e082008-05-09 10:14:07 +1000195 "-n" {
Paul Mackerras29582282008-11-18 19:44:20 +1100196 # This appears to be the only one that has a value as a
197 # separate word following it
Paul Mackerrasee66e082008-05-09 10:14:07 +1000198 set filtered 1
199 set nextisval 1
200 lappend glflags $arg
201 }
Paul Mackerras6e7e87c2008-12-02 09:17:46 +1100202 "--not" - "--all" {
Paul Mackerrasee66e082008-05-09 10:14:07 +1000203 lappend revargs $arg
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000204 }
205 "--merge" {
206 set vmergeonly($n) 1
Paul Mackerrasee66e082008-05-09 10:14:07 +1000207 # git rev-parse doesn't understand --merge
208 lappend revargs --gitk-symmetric-diff-marker MERGE_HEAD...HEAD
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000209 }
Paul Mackerrasee66e082008-05-09 10:14:07 +1000210 "-*" {
Paul Mackerras29582282008-11-18 19:44:20 +1100211 # Other flag arguments including -<n>
Paul Mackerrasee66e082008-05-09 10:14:07 +1000212 if {[string is digit -strict [string range $arg 1 end]]} {
213 set filtered 1
214 } else {
215 # a flag argument that we don't recognize;
216 # that means we can't optimize
217 set allknown 0
218 }
219 lappend glflags $arg
220 }
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000221 default {
Paul Mackerras29582282008-11-18 19:44:20 +1100222 # Non-flag arguments specify commits or ranges of commits
Paul Mackerrasee66e082008-05-09 10:14:07 +1000223 if {[string match "*...*" $arg]} {
224 lappend revargs --gitk-symmetric-diff-marker
225 }
226 lappend revargs $arg
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000227 }
228 }
229 }
Paul Mackerrasee66e082008-05-09 10:14:07 +1000230 set vdflags($n) $diffargs
231 set vflags($n) $glflags
232 set vrevs($n) $revargs
233 set vfiltered($n) $filtered
234 set vorigargs($n) $origargs
235 return $allknown
236}
237
238proc parseviewrevs {view revs} {
239 global vposids vnegids
240
241 if {$revs eq {}} {
242 set revs HEAD
243 }
244 if {[catch {set ids [eval exec git rev-parse $revs]} err]} {
245 # we get stdout followed by stderr in $err
246 # for an unknown rev, git rev-parse echoes it and then errors out
247 set errlines [split $err "\n"]
248 set badrev {}
249 for {set l 0} {$l < [llength $errlines]} {incr l} {
250 set line [lindex $errlines $l]
251 if {!([string length $line] == 40 && [string is xdigit $line])} {
252 if {[string match "fatal:*" $line]} {
253 if {[string match "fatal: ambiguous argument*" $line]
254 && $badrev ne {}} {
255 if {[llength $badrev] == 1} {
256 set err "unknown revision $badrev"
257 } else {
258 set err "unknown revisions: [join $badrev ", "]"
259 }
260 } else {
261 set err [join [lrange $errlines $l end] "\n"]
262 }
263 break
264 }
265 lappend badrev $line
266 }
267 }
Christian Stimming3945d2c2008-09-12 11:39:43 +0200268 error_popup "[mc "Error parsing revisions:"] $err"
Paul Mackerrasee66e082008-05-09 10:14:07 +1000269 return {}
270 }
271 set ret {}
272 set pos {}
273 set neg {}
274 set sdm 0
275 foreach id [split $ids "\n"] {
276 if {$id eq "--gitk-symmetric-diff-marker"} {
277 set sdm 4
278 } elseif {[string match "^*" $id]} {
279 if {$sdm != 1} {
280 lappend ret $id
281 if {$sdm == 3} {
282 set sdm 0
283 }
284 }
285 lappend neg [string range $id 1 end]
286 } else {
287 if {$sdm != 2} {
288 lappend ret $id
289 } else {
290 lset ret end [lindex $ret end]...$id
291 }
292 lappend pos $id
293 }
294 incr sdm -1
295 }
296 set vposids($view) $pos
297 set vnegids($view) $neg
298 return $ret
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000299}
300
Paul Mackerrasf9e0b6f2008-03-04 21:14:17 +1100301# Start off a git log process and arrange to read its output
Paul Mackerrasda7c24d2006-05-02 11:15:29 +1000302proc start_rev_list {view} {
Paul Mackerras6df74032008-05-11 22:13:02 +1000303 global startmsecs commitidx viewcomplete curview
Alexander Gavrilove439e092008-07-13 16:40:47 +0400304 global tclencoding
Paul Mackerrasee66e082008-05-09 10:14:07 +1000305 global viewargs viewargscmd viewfiles vfilelimit
Paul Mackerrasd375ef92008-10-21 10:18:12 +1100306 global showlocalchanges
Alexander Gavrilove439e092008-07-13 16:40:47 +0400307 global viewactive viewinstances vmergeonly
Paul Mackerrascdc84292008-11-18 19:54:14 +1100308 global mainheadid viewmainheadid viewmainheadid_orig
Paul Mackerrasee66e082008-05-09 10:14:07 +1000309 global vcanopt vflags vrevs vorigargs
Paul Mackerras38ad0912005-12-01 22:42:46 +1100310
311 set startmsecs [clock clicks -milliseconds]
Paul Mackerrasda7c24d2006-05-02 11:15:29 +1000312 set commitidx($view) 0
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000313 # these are set this way for the error exits
314 set viewcomplete($view) 1
315 set viewactive($view) 0
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100316 varcinit $view
317
Yann Dirson2d480852008-02-21 21:23:31 +0100318 set args $viewargs($view)
319 if {$viewargscmd($view) ne {}} {
320 if {[catch {
321 set str [exec sh -c $viewargscmd($view)]
322 } err]} {
Christian Stimming3945d2c2008-09-12 11:39:43 +0200323 error_popup "[mc "Error executing --argscmd command:"] $err"
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000324 return 0
Yann Dirson2d480852008-02-21 21:23:31 +0100325 }
326 set args [concat $args [split $str "\n"]]
327 }
Paul Mackerrasee66e082008-05-09 10:14:07 +1000328 set vcanopt($view) [parseviewargs $view $args]
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000329
330 set files $viewfiles($view)
331 if {$vmergeonly($view)} {
332 set files [unmerged_files $files]
333 if {$files eq {}} {
334 global nr_unmerged
335 if {$nr_unmerged == 0} {
336 error_popup [mc "No files selected: --merge specified but\
337 no files are unmerged."]
338 } else {
339 error_popup [mc "No files selected: --merge specified but\
340 no unmerged files are within file limit."]
341 }
342 return 0
343 }
344 }
345 set vfilelimit($view) $files
346
Paul Mackerrasee66e082008-05-09 10:14:07 +1000347 if {$vcanopt($view)} {
348 set revs [parseviewrevs $view $vrevs($view)]
349 if {$revs eq {}} {
350 return 0
351 }
352 set args [concat $vflags($view) $revs]
353 } else {
354 set args $vorigargs($view)
355 }
356
Paul Mackerras418c4c72006-02-07 09:10:18 +1100357 if {[catch {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100358 set fd [open [concat | git log --no-color -z --pretty=raw --parents \
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000359 --boundary $args "--" $files] r]
Paul Mackerras418c4c72006-02-07 09:10:18 +1100360 } err]} {
Paul Mackerras00abadb2007-12-20 10:25:50 +1100361 error_popup "[mc "Error executing git log:"] $err"
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000362 return 0
Paul Mackerras38ad0912005-12-01 22:42:46 +1100363 }
Alexander Gavrilove439e092008-07-13 16:40:47 +0400364 set i [reg_instance $fd]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100365 set viewinstances($view) [list $i]
Paul Mackerrascdc84292008-11-18 19:54:14 +1100366 set viewmainheadid($view) $mainheadid
367 set viewmainheadid_orig($view) $mainheadid
368 if {$files ne {} && $mainheadid ne {}} {
369 get_viewmainhead $view
370 }
371 if {$showlocalchanges && $viewmainheadid($view) ne {}} {
372 interestedin $viewmainheadid($view) dodiffindex
Paul Mackerras3e6b8932007-09-15 09:33:39 +1000373 }
Mark Levedahl86da5b62007-07-17 18:42:04 -0400374 fconfigure $fd -blocking 0 -translation lf -eofchar {}
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +1100375 if {$tclencoding != {}} {
Paul Mackerrasda7c24d2006-05-02 11:15:29 +1000376 fconfigure $fd -encoding $tclencoding
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +1100377 }
Paul Mackerrasf806f0f2008-02-24 12:16:56 +1100378 filerun $fd [list getcommitlines $fd $i $view 0]
Christian Stimmingd990ced2007-11-07 18:42:55 +0100379 nowbusy $view [mc "Reading"]
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000380 set viewcomplete($view) 0
381 set viewactive($view) 1
382 return 1
Paul Mackerras38ad0912005-12-01 22:42:46 +1100383}
384
Alexander Gavrilove2f90ee2008-07-12 16:09:28 +0400385proc stop_instance {inst} {
386 global commfd leftover
387
388 set fd $commfd($inst)
389 catch {
390 set pid [pid $fd]
Alexander Gavrilovb6326e92008-07-15 00:35:42 +0400391
392 if {$::tcl_platform(platform) eq {windows}} {
393 exec kill -f $pid
394 } else {
395 exec kill $pid
396 }
Alexander Gavrilove2f90ee2008-07-12 16:09:28 +0400397 }
398 catch {close $fd}
399 nukefile $fd
400 unset commfd($inst)
401 unset leftover($inst)
402}
403
404proc stop_backends {} {
405 global commfd
406
407 foreach inst [array names commfd] {
408 stop_instance $inst
409 }
410}
411
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100412proc stop_rev_list {view} {
Alexander Gavrilove2f90ee2008-07-12 16:09:28 +0400413 global viewinstances
Paul Mackerras22626ef2006-04-17 09:56:02 +1000414
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100415 foreach inst $viewinstances($view) {
Alexander Gavrilove2f90ee2008-07-12 16:09:28 +0400416 stop_instance $inst
Paul Mackerras22626ef2006-04-17 09:56:02 +1000417 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100418 set viewinstances($view) {}
Paul Mackerras22626ef2006-04-17 09:56:02 +1000419}
420
Alexander Gavrilov567c34e2008-07-26 20:13:45 +0400421proc reset_pending_select {selid} {
Alexander Gavrilov39816d62008-08-23 12:27:44 +0400422 global pending_select mainheadid selectheadid
Alexander Gavrilov567c34e2008-07-26 20:13:45 +0400423
424 if {$selid ne {}} {
425 set pending_select $selid
Alexander Gavrilov39816d62008-08-23 12:27:44 +0400426 } elseif {$selectheadid ne {}} {
427 set pending_select $selectheadid
Alexander Gavrilov567c34e2008-07-26 20:13:45 +0400428 } else {
429 set pending_select $mainheadid
430 }
431}
432
433proc getcommits {selid} {
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000434 global canv curview need_redisplay viewactive
Sven Verdoolaegeb5c2f302005-11-29 22:15:51 +0100435
Paul Mackerrasda7c24d2006-05-02 11:15:29 +1000436 initlayout
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000437 if {[start_rev_list $curview]} {
Alexander Gavrilov567c34e2008-07-26 20:13:45 +0400438 reset_pending_select $selid
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000439 show_status [mc "Reading commits..."]
440 set need_redisplay 1
441 } else {
442 show_status [mc "No commits selected"]
443 }
Paul Mackerras1d10f362005-05-15 12:55:47 +0000444}
445
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100446proc updatecommits {} {
Paul Mackerrasee66e082008-05-09 10:14:07 +1000447 global curview vcanopt vorigargs vfilelimit viewinstances
Alexander Gavrilove439e092008-07-13 16:40:47 +0400448 global viewactive viewcomplete tclencoding
449 global startmsecs showneartags showlocalchanges
Paul Mackerrascdc84292008-11-18 19:54:14 +1100450 global mainheadid viewmainheadid viewmainheadid_orig pending_select
Paul Mackerras92e22ca2008-03-11 22:21:39 +1100451 global isworktree
Paul Mackerrasee66e082008-05-09 10:14:07 +1000452 global varcid vposids vnegids vflags vrevs
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100453
Paul Mackerras92e22ca2008-03-11 22:21:39 +1100454 set isworktree [expr {[exec git rev-parse --is-inside-work-tree] == "true"}]
Paul Mackerrasfc2a2562007-12-26 23:03:43 +1100455 rereadrefs
Paul Mackerrascdc84292008-11-18 19:54:14 +1100456 set view $curview
457 if {$mainheadid ne $viewmainheadid_orig($view)} {
458 if {$showlocalchanges} {
Paul Mackerraseb5f8c92007-12-29 21:13:34 +1100459 dohidelocalchanges
460 }
Paul Mackerrascdc84292008-11-18 19:54:14 +1100461 set viewmainheadid($view) $mainheadid
462 set viewmainheadid_orig($view) $mainheadid
463 if {$vfilelimit($view) ne {}} {
464 get_viewmainhead $view
Paul Mackerraseb5f8c92007-12-29 21:13:34 +1100465 }
466 }
Paul Mackerrascdc84292008-11-18 19:54:14 +1100467 if {$showlocalchanges} {
468 doshowlocalchanges
469 }
Paul Mackerrasee66e082008-05-09 10:14:07 +1000470 if {$vcanopt($view)} {
471 set oldpos $vposids($view)
472 set oldneg $vnegids($view)
473 set revs [parseviewrevs $view $vrevs($view)]
474 if {$revs eq {}} {
475 return
476 }
477 # note: getting the delta when negative refs change is hard,
478 # and could require multiple git log invocations, so in that
479 # case we ask git log for all the commits (not just the delta)
480 if {$oldneg eq $vnegids($view)} {
481 set newrevs {}
482 set npos 0
483 # take out positive refs that we asked for before or
484 # that we have already seen
485 foreach rev $revs {
486 if {[string length $rev] == 40} {
487 if {[lsearch -exact $oldpos $rev] < 0
488 && ![info exists varcid($view,$rev)]} {
489 lappend newrevs $rev
490 incr npos
491 }
492 } else {
493 lappend $newrevs $rev
494 }
495 }
496 if {$npos == 0} return
497 set revs $newrevs
498 set vposids($view) [lsort -unique [concat $oldpos $vposids($view)]]
499 }
500 set args [concat $vflags($view) $revs --not $oldpos]
501 } else {
502 set args $vorigargs($view)
503 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100504 if {[catch {
505 set fd [open [concat | git log --no-color -z --pretty=raw --parents \
Paul Mackerrasee66e082008-05-09 10:14:07 +1000506 --boundary $args "--" $vfilelimit($view)] r]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100507 } err]} {
Christian Stimming3945d2c2008-09-12 11:39:43 +0200508 error_popup "[mc "Error executing git log:"] $err"
Paul Mackerrasee66e082008-05-09 10:14:07 +1000509 return
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100510 }
511 if {$viewactive($view) == 0} {
512 set startmsecs [clock clicks -milliseconds]
513 }
Alexander Gavrilove439e092008-07-13 16:40:47 +0400514 set i [reg_instance $fd]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100515 lappend viewinstances($view) $i
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100516 fconfigure $fd -blocking 0 -translation lf -eofchar {}
517 if {$tclencoding != {}} {
518 fconfigure $fd -encoding $tclencoding
519 }
Paul Mackerrasf806f0f2008-02-24 12:16:56 +1100520 filerun $fd [list getcommitlines $fd $i $view 1]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100521 incr viewactive($view)
522 set viewcomplete($view) 0
Alexander Gavrilov567c34e2008-07-26 20:13:45 +0400523 reset_pending_select {}
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100524 nowbusy $view "Reading"
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100525 if {$showneartags} {
526 getallcommits
527 }
528}
529
530proc reloadcommits {} {
531 global curview viewcomplete selectedline currentid thickerline
532 global showneartags treediffs commitinterest cached_commitrow
Paul Mackerras6df74032008-05-11 22:13:02 +1000533 global targetid
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100534
Alexander Gavrilov567c34e2008-07-26 20:13:45 +0400535 set selid {}
536 if {$selectedline ne {}} {
537 set selid $currentid
538 }
539
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100540 if {!$viewcomplete($curview)} {
541 stop_rev_list $curview
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100542 }
543 resetvarcs $curview
Paul Mackerras94b4a692008-05-20 20:51:06 +1000544 set selectedline {}
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100545 catch {unset currentid}
546 catch {unset thickerline}
547 catch {unset treediffs}
548 readrefs
549 changedrefs
550 if {$showneartags} {
551 getallcommits
552 }
553 clear_display
554 catch {unset commitinterest}
555 catch {unset cached_commitrow}
Paul Mackerras42a671f2008-01-02 09:59:39 +1100556 catch {unset targetid}
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100557 setcanvscroll
Alexander Gavrilov567c34e2008-07-26 20:13:45 +0400558 getcommits $selid
Paul Mackerrase7297a12008-01-15 22:30:40 +1100559 return 0
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100560}
561
Paul Mackerras6e8c8702007-07-31 21:03:06 +1000562# This makes a string representation of a positive integer which
563# sorts as a string in numerical order
564proc strrep {n} {
565 if {$n < 16} {
566 return [format "%x" $n]
567 } elseif {$n < 256} {
568 return [format "x%.2x" $n]
569 } elseif {$n < 65536} {
570 return [format "y%.4x" $n]
571 }
572 return [format "z%.8x" $n]
573}
574
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100575# Procedures used in reordering commits from git log (without
576# --topo-order) into the order for display.
577
578proc varcinit {view} {
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100579 global varcstart vupptr vdownptr vleftptr vbackptr varctok varcrow
580 global vtokmod varcmod vrowmod varcix vlastins
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100581
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100582 set varcstart($view) {{}}
583 set vupptr($view) {0}
584 set vdownptr($view) {0}
585 set vleftptr($view) {0}
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100586 set vbackptr($view) {0}
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100587 set varctok($view) {{}}
588 set varcrow($view) {{}}
589 set vtokmod($view) {}
590 set varcmod($view) 0
Paul Mackerrase5b37ac2007-12-12 18:13:51 +1100591 set vrowmod($view) 0
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100592 set varcix($view) {{}}
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100593 set vlastins($view) {0}
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100594}
595
596proc resetvarcs {view} {
597 global varcid varccommits parents children vseedcount ordertok
598
599 foreach vid [array names varcid $view,*] {
600 unset varcid($vid)
601 unset children($vid)
602 unset parents($vid)
603 }
604 # some commits might have children but haven't been seen yet
605 foreach vid [array names children $view,*] {
606 unset children($vid)
607 }
608 foreach va [array names varccommits $view,*] {
609 unset varccommits($va)
610 }
611 foreach vd [array names vseedcount $view,*] {
612 unset vseedcount($vd)
613 }
Paul Mackerras9257d8f2007-12-11 10:45:38 +1100614 catch {unset ordertok}
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100615}
616
Paul Mackerras468bcae2008-03-03 10:19:35 +1100617# returns a list of the commits with no children
618proc seeds {v} {
619 global vdownptr vleftptr varcstart
620
621 set ret {}
622 set a [lindex $vdownptr($v) 0]
623 while {$a != 0} {
624 lappend ret [lindex $varcstart($v) $a]
625 set a [lindex $vleftptr($v) $a]
626 }
627 return $ret
628}
629
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100630proc newvarc {view id} {
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000631 global varcid varctok parents children vdatemode
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100632 global vupptr vdownptr vleftptr vbackptr varcrow varcix varcstart
633 global commitdata commitinfo vseedcount varccommits vlastins
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100634
635 set a [llength $varctok($view)]
636 set vid $view,$id
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000637 if {[llength $children($vid)] == 0 || $vdatemode($view)} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100638 if {![info exists commitinfo($id)]} {
639 parsecommit $id $commitdata($id) 1
640 }
641 set cdate [lindex $commitinfo($id) 4]
642 if {![string is integer -strict $cdate]} {
643 set cdate 0
644 }
645 if {![info exists vseedcount($view,$cdate)]} {
646 set vseedcount($view,$cdate) -1
647 }
648 set c [incr vseedcount($view,$cdate)]
649 set cdate [expr {$cdate ^ 0xffffffff}]
650 set tok "s[strrep $cdate][strrep $c]"
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100651 } else {
652 set tok {}
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100653 }
654 set ka 0
655 if {[llength $children($vid)] > 0} {
656 set kid [lindex $children($vid) end]
657 set k $varcid($view,$kid)
658 if {[string compare [lindex $varctok($view) $k] $tok] > 0} {
659 set ki $kid
660 set ka $k
661 set tok [lindex $varctok($view) $k]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100662 }
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100663 }
664 if {$ka != 0} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100665 set i [lsearch -exact $parents($view,$ki) $id]
666 set j [expr {[llength $parents($view,$ki)] - 1 - $i}]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100667 append tok [strrep $j]
668 }
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100669 set c [lindex $vlastins($view) $ka]
670 if {$c == 0 || [string compare $tok [lindex $varctok($view) $c]] < 0} {
671 set c $ka
672 set b [lindex $vdownptr($view) $ka]
673 } else {
674 set b [lindex $vleftptr($view) $c]
675 }
676 while {$b != 0 && [string compare $tok [lindex $varctok($view) $b]] >= 0} {
677 set c $b
678 set b [lindex $vleftptr($view) $c]
679 }
680 if {$c == $ka} {
681 lset vdownptr($view) $ka $a
682 lappend vbackptr($view) 0
683 } else {
684 lset vleftptr($view) $c $a
685 lappend vbackptr($view) $c
686 }
687 lset vlastins($view) $ka $a
688 lappend vupptr($view) $ka
689 lappend vleftptr($view) $b
690 if {$b != 0} {
691 lset vbackptr($view) $b $a
692 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100693 lappend varctok($view) $tok
694 lappend varcstart($view) $id
695 lappend vdownptr($view) 0
696 lappend varcrow($view) {}
697 lappend varcix($view) {}
Paul Mackerrase5b37ac2007-12-12 18:13:51 +1100698 set varccommits($view,$a) {}
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100699 lappend vlastins($view) 0
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100700 return $a
701}
702
703proc splitvarc {p v} {
Paul Mackerras52b8ea92009-03-02 09:38:17 +1100704 global varcid varcstart varccommits varctok vtokmod
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100705 global vupptr vdownptr vleftptr vbackptr varcix varcrow vlastins
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100706
707 set oa $varcid($v,$p)
Paul Mackerras52b8ea92009-03-02 09:38:17 +1100708 set otok [lindex $varctok($v) $oa]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100709 set ac $varccommits($v,$oa)
710 set i [lsearch -exact $varccommits($v,$oa) $p]
711 if {$i <= 0} return
712 set na [llength $varctok($v)]
713 # "%" sorts before "0"...
Paul Mackerras52b8ea92009-03-02 09:38:17 +1100714 set tok "$otok%[strrep $i]"
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100715 lappend varctok($v) $tok
716 lappend varcrow($v) {}
717 lappend varcix($v) {}
718 set varccommits($v,$oa) [lrange $ac 0 [expr {$i - 1}]]
719 set varccommits($v,$na) [lrange $ac $i end]
720 lappend varcstart($v) $p
721 foreach id $varccommits($v,$na) {
722 set varcid($v,$id) $na
723 }
724 lappend vdownptr($v) [lindex $vdownptr($v) $oa]
Paul Mackerras841ea822008-02-18 10:44:33 +1100725 lappend vlastins($v) [lindex $vlastins($v) $oa]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100726 lset vdownptr($v) $oa $na
Paul Mackerras841ea822008-02-18 10:44:33 +1100727 lset vlastins($v) $oa 0
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100728 lappend vupptr($v) $oa
729 lappend vleftptr($v) 0
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100730 lappend vbackptr($v) 0
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100731 for {set b [lindex $vdownptr($v) $na]} {$b != 0} {set b [lindex $vleftptr($v) $b]} {
732 lset vupptr($v) $b $na
733 }
Paul Mackerras52b8ea92009-03-02 09:38:17 +1100734 if {[string compare $otok $vtokmod($v)] <= 0} {
735 modify_arc $v $oa
736 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100737}
738
739proc renumbervarc {a v} {
740 global parents children varctok varcstart varccommits
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000741 global vupptr vdownptr vleftptr vbackptr vlastins varcid vtokmod vdatemode
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100742
743 set t1 [clock clicks -milliseconds]
744 set todo {}
745 set isrelated($a) 1
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100746 set kidchanged($a) 1
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100747 set ntot 0
748 while {$a != 0} {
749 if {[info exists isrelated($a)]} {
750 lappend todo $a
751 set id [lindex $varccommits($v,$a) end]
752 foreach p $parents($v,$id) {
753 if {[info exists varcid($v,$p)]} {
754 set isrelated($varcid($v,$p)) 1
755 }
756 }
757 }
758 incr ntot
759 set b [lindex $vdownptr($v) $a]
760 if {$b == 0} {
761 while {$a != 0} {
762 set b [lindex $vleftptr($v) $a]
763 if {$b != 0} break
764 set a [lindex $vupptr($v) $a]
765 }
766 }
767 set a $b
768 }
769 foreach a $todo {
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100770 if {![info exists kidchanged($a)]} continue
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100771 set id [lindex $varcstart($v) $a]
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100772 if {[llength $children($v,$id)] > 1} {
773 set children($v,$id) [lsort -command [list vtokcmp $v] \
774 $children($v,$id)]
775 }
776 set oldtok [lindex $varctok($v) $a]
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000777 if {!$vdatemode($v)} {
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100778 set tok {}
779 } else {
780 set tok $oldtok
781 }
782 set ka 0
Paul Mackerrasc8c9f3d2008-01-06 13:54:58 +1100783 set kid [last_real_child $v,$id]
784 if {$kid ne {}} {
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100785 set k $varcid($v,$kid)
786 if {[string compare [lindex $varctok($v) $k] $tok] > 0} {
787 set ki $kid
788 set ka $k
789 set tok [lindex $varctok($v) $k]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100790 }
791 }
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100792 if {$ka != 0} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100793 set i [lsearch -exact $parents($v,$ki) $id]
794 set j [expr {[llength $parents($v,$ki)] - 1 - $i}]
795 append tok [strrep $j]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100796 }
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100797 if {$tok eq $oldtok} {
798 continue
799 }
800 set id [lindex $varccommits($v,$a) end]
801 foreach p $parents($v,$id) {
802 if {[info exists varcid($v,$p)]} {
803 set kidchanged($varcid($v,$p)) 1
804 } else {
805 set sortkids($p) 1
806 }
807 }
808 lset varctok($v) $a $tok
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100809 set b [lindex $vupptr($v) $a]
810 if {$b != $ka} {
Paul Mackerras9257d8f2007-12-11 10:45:38 +1100811 if {[string compare [lindex $varctok($v) $ka] $vtokmod($v)] < 0} {
812 modify_arc $v $ka
Paul Mackerras38dfe932007-12-06 20:50:31 +1100813 }
Paul Mackerras9257d8f2007-12-11 10:45:38 +1100814 if {[string compare [lindex $varctok($v) $b] $vtokmod($v)] < 0} {
815 modify_arc $v $b
Paul Mackerras38dfe932007-12-06 20:50:31 +1100816 }
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100817 set c [lindex $vbackptr($v) $a]
818 set d [lindex $vleftptr($v) $a]
819 if {$c == 0} {
820 lset vdownptr($v) $b $d
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100821 } else {
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100822 lset vleftptr($v) $c $d
823 }
824 if {$d != 0} {
825 lset vbackptr($v) $d $c
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100826 }
Paul Mackerras841ea822008-02-18 10:44:33 +1100827 if {[lindex $vlastins($v) $b] == $a} {
828 lset vlastins($v) $b $c
829 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100830 lset vupptr($v) $a $ka
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100831 set c [lindex $vlastins($v) $ka]
832 if {$c == 0 || \
833 [string compare $tok [lindex $varctok($v) $c]] < 0} {
834 set c $ka
835 set b [lindex $vdownptr($v) $ka]
836 } else {
837 set b [lindex $vleftptr($v) $c]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100838 }
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100839 while {$b != 0 && \
840 [string compare $tok [lindex $varctok($v) $b]] >= 0} {
841 set c $b
842 set b [lindex $vleftptr($v) $c]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100843 }
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100844 if {$c == $ka} {
845 lset vdownptr($v) $ka $a
846 lset vbackptr($v) $a 0
847 } else {
848 lset vleftptr($v) $c $a
849 lset vbackptr($v) $a $c
850 }
851 lset vleftptr($v) $a $b
852 if {$b != 0} {
853 lset vbackptr($v) $b $a
854 }
855 lset vlastins($v) $ka $a
856 }
857 }
858 foreach id [array names sortkids] {
859 if {[llength $children($v,$id)] > 1} {
860 set children($v,$id) [lsort -command [list vtokcmp $v] \
861 $children($v,$id)]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100862 }
863 }
864 set t2 [clock clicks -milliseconds]
865 #puts "renumbervarc did [llength $todo] of $ntot arcs in [expr {$t2-$t1}]ms"
866}
867
Paul Mackerrasf806f0f2008-02-24 12:16:56 +1100868# Fix up the graph after we have found out that in view $v,
869# $p (a commit that we have already seen) is actually the parent
870# of the last commit in arc $a.
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100871proc fix_reversal {p a v} {
Paul Mackerras24f7a662007-12-19 09:35:33 +1100872 global varcid varcstart varctok vupptr
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100873
874 set pa $varcid($v,$p)
875 if {$p ne [lindex $varcstart($v) $pa]} {
876 splitvarc $p $v
877 set pa $varcid($v,$p)
878 }
Paul Mackerras24f7a662007-12-19 09:35:33 +1100879 # seeds always need to be renumbered
880 if {[lindex $vupptr($v) $pa] == 0 ||
881 [string compare [lindex $varctok($v) $a] \
882 [lindex $varctok($v) $pa]] > 0} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100883 renumbervarc $pa $v
884 }
885}
886
887proc insertrow {id p v} {
Paul Mackerrasb8a938c2008-02-13 22:12:31 +1100888 global cmitlisted children parents varcid varctok vtokmod
889 global varccommits ordertok commitidx numcommits curview
890 global targetid targetrow
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100891
Paul Mackerrasb8a938c2008-02-13 22:12:31 +1100892 readcommit $id
893 set vid $v,$id
894 set cmitlisted($vid) 1
895 set children($vid) {}
896 set parents($vid) [list $p]
897 set a [newvarc $v $id]
898 set varcid($vid) $a
899 if {[string compare [lindex $varctok($v) $a] $vtokmod($v)] < 0} {
900 modify_arc $v $a
901 }
902 lappend varccommits($v,$a) $id
903 set vp $v,$p
904 if {[llength [lappend children($vp) $id]] > 1} {
905 set children($vp) [lsort -command [list vtokcmp $v] $children($vp)]
906 catch {unset ordertok}
907 }
908 fix_reversal $p $a $v
909 incr commitidx($v)
910 if {$v == $curview} {
911 set numcommits $commitidx($v)
912 setcanvscroll
913 if {[info exists targetid]} {
914 if {![comes_before $targetid $p]} {
915 incr targetrow
916 }
917 }
918 }
919}
920
921proc insertfakerow {id p} {
922 global varcid varccommits parents children cmitlisted
923 global commitidx varctok vtokmod targetid targetrow curview numcommits
924
925 set v $curview
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100926 set a $varcid($v,$p)
927 set i [lsearch -exact $varccommits($v,$a) $p]
928 if {$i < 0} {
Paul Mackerrasb8a938c2008-02-13 22:12:31 +1100929 puts "oops: insertfakerow can't find [shortids $p] on arc $a"
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100930 return
931 }
932 set children($v,$id) {}
933 set parents($v,$id) [list $p]
934 set varcid($v,$id) $a
Paul Mackerras9257d8f2007-12-11 10:45:38 +1100935 lappend children($v,$p) $id
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100936 set cmitlisted($v,$id) 1
Paul Mackerrasb8a938c2008-02-13 22:12:31 +1100937 set numcommits [incr commitidx($v)]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100938 # note we deliberately don't update varcstart($v) even if $i == 0
939 set varccommits($v,$a) [linsert $varccommits($v,$a) $i $id]
Paul Mackerrasc9cfdc92008-03-04 21:32:38 +1100940 modify_arc $v $a $i
Paul Mackerras42a671f2008-01-02 09:59:39 +1100941 if {[info exists targetid]} {
942 if {![comes_before $targetid $p]} {
943 incr targetrow
944 }
945 }
Paul Mackerrasb8a938c2008-02-13 22:12:31 +1100946 setcanvscroll
Paul Mackerras9257d8f2007-12-11 10:45:38 +1100947 drawvisible
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100948}
949
Paul Mackerrasb8a938c2008-02-13 22:12:31 +1100950proc removefakerow {id} {
Paul Mackerras9257d8f2007-12-11 10:45:38 +1100951 global varcid varccommits parents children commitidx
Paul Mackerrasfc2a2562007-12-26 23:03:43 +1100952 global varctok vtokmod cmitlisted currentid selectedline
Paul Mackerrasb8a938c2008-02-13 22:12:31 +1100953 global targetid curview numcommits
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100954
Paul Mackerrasb8a938c2008-02-13 22:12:31 +1100955 set v $curview
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100956 if {[llength $parents($v,$id)] != 1} {
Paul Mackerrasb8a938c2008-02-13 22:12:31 +1100957 puts "oops: removefakerow [shortids $id] has [llength $parents($v,$id)] parents"
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100958 return
959 }
960 set p [lindex $parents($v,$id) 0]
961 set a $varcid($v,$id)
962 set i [lsearch -exact $varccommits($v,$a) $id]
963 if {$i < 0} {
Paul Mackerrasb8a938c2008-02-13 22:12:31 +1100964 puts "oops: removefakerow can't find [shortids $id] on arc $a"
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100965 return
966 }
967 unset varcid($v,$id)
968 set varccommits($v,$a) [lreplace $varccommits($v,$a) $i $i]
969 unset parents($v,$id)
970 unset children($v,$id)
971 unset cmitlisted($v,$id)
Paul Mackerrasb8a938c2008-02-13 22:12:31 +1100972 set numcommits [incr commitidx($v) -1]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100973 set j [lsearch -exact $children($v,$p) $id]
974 if {$j >= 0} {
975 set children($v,$p) [lreplace $children($v,$p) $j $j]
976 }
Paul Mackerrasc9cfdc92008-03-04 21:32:38 +1100977 modify_arc $v $a $i
Paul Mackerrasfc2a2562007-12-26 23:03:43 +1100978 if {[info exist currentid] && $id eq $currentid} {
979 unset currentid
Paul Mackerras94b4a692008-05-20 20:51:06 +1000980 set selectedline {}
Paul Mackerrasfc2a2562007-12-26 23:03:43 +1100981 }
Paul Mackerras42a671f2008-01-02 09:59:39 +1100982 if {[info exists targetid] && $targetid eq $id} {
983 set targetid $p
984 }
Paul Mackerrasb8a938c2008-02-13 22:12:31 +1100985 setcanvscroll
Paul Mackerras9257d8f2007-12-11 10:45:38 +1100986 drawvisible
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100987}
988
Paul Mackerrasc8c9f3d2008-01-06 13:54:58 +1100989proc first_real_child {vp} {
990 global children nullid nullid2
991
992 foreach id $children($vp) {
993 if {$id ne $nullid && $id ne $nullid2} {
994 return $id
995 }
996 }
997 return {}
998}
999
1000proc last_real_child {vp} {
1001 global children nullid nullid2
1002
1003 set kids $children($vp)
1004 for {set i [llength $kids]} {[incr i -1] >= 0} {} {
1005 set id [lindex $kids $i]
1006 if {$id ne $nullid && $id ne $nullid2} {
1007 return $id
1008 }
1009 }
1010 return {}
1011}
1012
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001013proc vtokcmp {v a b} {
1014 global varctok varcid
1015
1016 return [string compare [lindex $varctok($v) $varcid($v,$a)] \
1017 [lindex $varctok($v) $varcid($v,$b)]]
1018}
1019
Paul Mackerrasc9cfdc92008-03-04 21:32:38 +11001020# This assumes that if lim is not given, the caller has checked that
1021# arc a's token is less than $vtokmod($v)
Paul Mackerrase5b37ac2007-12-12 18:13:51 +11001022proc modify_arc {v a {lim {}}} {
1023 global varctok vtokmod varcmod varcrow vupptr curview vrowmod varccommits
Paul Mackerras9257d8f2007-12-11 10:45:38 +11001024
Paul Mackerrasc9cfdc92008-03-04 21:32:38 +11001025 if {$lim ne {}} {
1026 set c [string compare [lindex $varctok($v) $a] $vtokmod($v)]
1027 if {$c > 0} return
1028 if {$c == 0} {
1029 set r [lindex $varcrow($v) $a]
1030 if {$r ne {} && $vrowmod($v) <= $r + $lim} return
1031 }
1032 }
Paul Mackerras9257d8f2007-12-11 10:45:38 +11001033 set vtokmod($v) [lindex $varctok($v) $a]
1034 set varcmod($v) $a
1035 if {$v == $curview} {
1036 while {$a != 0 && [lindex $varcrow($v) $a] eq {}} {
1037 set a [lindex $vupptr($v) $a]
Paul Mackerrase5b37ac2007-12-12 18:13:51 +11001038 set lim {}
Paul Mackerras9257d8f2007-12-11 10:45:38 +11001039 }
Paul Mackerrase5b37ac2007-12-12 18:13:51 +11001040 set r 0
1041 if {$a != 0} {
1042 if {$lim eq {}} {
1043 set lim [llength $varccommits($v,$a)]
1044 }
1045 set r [expr {[lindex $varcrow($v) $a] + $lim}]
1046 }
1047 set vrowmod($v) $r
Paul Mackerras0c278862007-12-11 20:09:53 +11001048 undolayout $r
Paul Mackerras9257d8f2007-12-11 10:45:38 +11001049 }
1050}
1051
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001052proc update_arcrows {v} {
Paul Mackerrase5b37ac2007-12-12 18:13:51 +11001053 global vtokmod varcmod vrowmod varcrow commitidx currentid selectedline
Paul Mackerras24f7a662007-12-19 09:35:33 +11001054 global varcid vrownum varcorder varcix varccommits
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001055 global vupptr vdownptr vleftptr varctok
Paul Mackerras24f7a662007-12-19 09:35:33 +11001056 global displayorder parentlist curview cached_commitrow
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001057
Paul Mackerrasc9cfdc92008-03-04 21:32:38 +11001058 if {$vrowmod($v) == $commitidx($v)} return
1059 if {$v == $curview} {
1060 if {[llength $displayorder] > $vrowmod($v)} {
1061 set displayorder [lrange $displayorder 0 [expr {$vrowmod($v) - 1}]]
1062 set parentlist [lrange $parentlist 0 [expr {$vrowmod($v) - 1}]]
1063 }
1064 catch {unset cached_commitrow}
1065 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001066 set narctot [expr {[llength $varctok($v)] - 1}]
1067 set a $varcmod($v)
1068 while {$a != 0 && [lindex $varcix($v) $a] eq {}} {
1069 # go up the tree until we find something that has a row number,
1070 # or we get to a seed
1071 set a [lindex $vupptr($v) $a]
1072 }
1073 if {$a == 0} {
1074 set a [lindex $vdownptr($v) 0]
1075 if {$a == 0} return
1076 set vrownum($v) {0}
1077 set varcorder($v) [list $a]
1078 lset varcix($v) $a 0
1079 lset varcrow($v) $a 0
1080 set arcn 0
1081 set row 0
1082 } else {
1083 set arcn [lindex $varcix($v) $a]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001084 if {[llength $vrownum($v)] > $arcn + 1} {
1085 set vrownum($v) [lrange $vrownum($v) 0 $arcn]
1086 set varcorder($v) [lrange $varcorder($v) 0 $arcn]
1087 }
1088 set row [lindex $varcrow($v) $a]
1089 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001090 while {1} {
1091 set p $a
1092 incr row [llength $varccommits($v,$a)]
1093 # go down if possible
1094 set b [lindex $vdownptr($v) $a]
1095 if {$b == 0} {
1096 # if not, go left, or go up until we can go left
1097 while {$a != 0} {
1098 set b [lindex $vleftptr($v) $a]
1099 if {$b != 0} break
1100 set a [lindex $vupptr($v) $a]
1101 }
1102 if {$a == 0} break
1103 }
1104 set a $b
1105 incr arcn
1106 lappend vrownum($v) $row
1107 lappend varcorder($v) $a
1108 lset varcix($v) $a $arcn
1109 lset varcrow($v) $a $row
1110 }
Paul Mackerrase5b37ac2007-12-12 18:13:51 +11001111 set vtokmod($v) [lindex $varctok($v) $p]
1112 set varcmod($v) $p
1113 set vrowmod($v) $row
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001114 if {[info exists currentid]} {
1115 set selectedline [rowofcommit $currentid]
1116 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001117}
1118
1119# Test whether view $v contains commit $id
1120proc commitinview {id v} {
1121 global varcid
1122
1123 return [info exists varcid($v,$id)]
1124}
1125
1126# Return the row number for commit $id in the current view
1127proc rowofcommit {id} {
1128 global varcid varccommits varcrow curview cached_commitrow
Paul Mackerras9257d8f2007-12-11 10:45:38 +11001129 global varctok vtokmod
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001130
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001131 set v $curview
1132 if {![info exists varcid($v,$id)]} {
1133 puts "oops rowofcommit no arc for [shortids $id]"
1134 return {}
1135 }
1136 set a $varcid($v,$id)
Paul Mackerrasfc2a2562007-12-26 23:03:43 +11001137 if {[string compare [lindex $varctok($v) $a] $vtokmod($v)] >= 0} {
Paul Mackerras9257d8f2007-12-11 10:45:38 +11001138 update_arcrows $v
1139 }
Paul Mackerras31c0eaa2007-12-30 22:41:14 +11001140 if {[info exists cached_commitrow($id)]} {
1141 return $cached_commitrow($id)
1142 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001143 set i [lsearch -exact $varccommits($v,$a) $id]
1144 if {$i < 0} {
1145 puts "oops didn't find commit [shortids $id] in arc $a"
1146 return {}
1147 }
1148 incr i [lindex $varcrow($v) $a]
1149 set cached_commitrow($id) $i
1150 return $i
1151}
1152
Paul Mackerras42a671f2008-01-02 09:59:39 +11001153# Returns 1 if a is on an earlier row than b, otherwise 0
1154proc comes_before {a b} {
1155 global varcid varctok curview
1156
1157 set v $curview
1158 if {$a eq $b || ![info exists varcid($v,$a)] || \
1159 ![info exists varcid($v,$b)]} {
1160 return 0
1161 }
1162 if {$varcid($v,$a) != $varcid($v,$b)} {
1163 return [expr {[string compare [lindex $varctok($v) $varcid($v,$a)] \
1164 [lindex $varctok($v) $varcid($v,$b)]] < 0}]
1165 }
1166 return [expr {[rowofcommit $a] < [rowofcommit $b]}]
1167}
1168
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001169proc bsearch {l elt} {
1170 if {[llength $l] == 0 || $elt <= [lindex $l 0]} {
1171 return 0
1172 }
1173 set lo 0
1174 set hi [llength $l]
1175 while {$hi - $lo > 1} {
1176 set mid [expr {int(($lo + $hi) / 2)}]
1177 set t [lindex $l $mid]
1178 if {$elt < $t} {
1179 set hi $mid
1180 } elseif {$elt > $t} {
1181 set lo $mid
1182 } else {
1183 return $mid
1184 }
1185 }
1186 return $lo
1187}
1188
1189# Make sure rows $start..$end-1 are valid in displayorder and parentlist
1190proc make_disporder {start end} {
1191 global vrownum curview commitidx displayorder parentlist
Paul Mackerrase5b37ac2007-12-12 18:13:51 +11001192 global varccommits varcorder parents vrowmod varcrow
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001193 global d_valid_start d_valid_end
1194
Paul Mackerrase5b37ac2007-12-12 18:13:51 +11001195 if {$end > $vrowmod($curview)} {
Paul Mackerras9257d8f2007-12-11 10:45:38 +11001196 update_arcrows $curview
1197 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001198 set ai [bsearch $vrownum($curview) $start]
1199 set start [lindex $vrownum($curview) $ai]
1200 set narc [llength $vrownum($curview)]
1201 for {set r $start} {$ai < $narc && $r < $end} {incr ai} {
1202 set a [lindex $varcorder($curview) $ai]
1203 set l [llength $displayorder]
1204 set al [llength $varccommits($curview,$a)]
1205 if {$l < $r + $al} {
1206 if {$l < $r} {
1207 set pad [ntimes [expr {$r - $l}] {}]
1208 set displayorder [concat $displayorder $pad]
1209 set parentlist [concat $parentlist $pad]
1210 } elseif {$l > $r} {
1211 set displayorder [lrange $displayorder 0 [expr {$r - 1}]]
1212 set parentlist [lrange $parentlist 0 [expr {$r - 1}]]
1213 }
1214 foreach id $varccommits($curview,$a) {
1215 lappend displayorder $id
1216 lappend parentlist $parents($curview,$id)
1217 }
Paul Mackerras17529cf92008-01-12 21:46:31 +11001218 } elseif {[lindex $displayorder [expr {$r + $al - 1}]] eq {}} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001219 set i $r
1220 foreach id $varccommits($curview,$a) {
1221 lset displayorder $i $id
1222 lset parentlist $i $parents($curview,$id)
1223 incr i
1224 }
1225 }
1226 incr r $al
1227 }
1228}
1229
1230proc commitonrow {row} {
1231 global displayorder
1232
1233 set id [lindex $displayorder $row]
1234 if {$id eq {}} {
1235 make_disporder $row [expr {$row + 1}]
1236 set id [lindex $displayorder $row]
1237 }
1238 return $id
1239}
1240
1241proc closevarcs {v} {
1242 global varctok varccommits varcid parents children
Paul Mackerrasd375ef92008-10-21 10:18:12 +11001243 global cmitlisted commitidx vtokmod
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001244
1245 set missing_parents 0
1246 set scripts {}
1247 set narcs [llength $varctok($v)]
1248 for {set a 1} {$a < $narcs} {incr a} {
1249 set id [lindex $varccommits($v,$a) end]
1250 foreach p $parents($v,$id) {
1251 if {[info exists varcid($v,$p)]} continue
1252 # add p as a new commit
1253 incr missing_parents
1254 set cmitlisted($v,$p) 0
1255 set parents($v,$p) {}
1256 if {[llength $children($v,$p)] == 1 &&
1257 [llength $parents($v,$id)] == 1} {
1258 set b $a
1259 } else {
1260 set b [newvarc $v $p]
1261 }
1262 set varcid($v,$p) $b
Paul Mackerras9257d8f2007-12-11 10:45:38 +11001263 if {[string compare [lindex $varctok($v) $b] $vtokmod($v)] < 0} {
1264 modify_arc $v $b
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001265 }
Paul Mackerrase5b37ac2007-12-12 18:13:51 +11001266 lappend varccommits($v,$b) $p
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001267 incr commitidx($v)
Paul Mackerrasd375ef92008-10-21 10:18:12 +11001268 set scripts [check_interest $p $scripts]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001269 }
1270 }
1271 if {$missing_parents > 0} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001272 foreach s $scripts {
1273 eval $s
1274 }
1275 }
1276}
1277
Paul Mackerrasf806f0f2008-02-24 12:16:56 +11001278# Use $rwid as a substitute for $id, i.e. reparent $id's children to $rwid
1279# Assumes we already have an arc for $rwid.
1280proc rewrite_commit {v id rwid} {
1281 global children parents varcid varctok vtokmod varccommits
1282
1283 foreach ch $children($v,$id) {
1284 # make $rwid be $ch's parent in place of $id
1285 set i [lsearch -exact $parents($v,$ch) $id]
1286 if {$i < 0} {
1287 puts "oops rewrite_commit didn't find $id in parent list for $ch"
1288 }
1289 set parents($v,$ch) [lreplace $parents($v,$ch) $i $i $rwid]
1290 # add $ch to $rwid's children and sort the list if necessary
1291 if {[llength [lappend children($v,$rwid) $ch]] > 1} {
1292 set children($v,$rwid) [lsort -command [list vtokcmp $v] \
1293 $children($v,$rwid)]
1294 }
1295 # fix the graph after joining $id to $rwid
1296 set a $varcid($v,$ch)
1297 fix_reversal $rwid $a $v
Paul Mackerrasc9cfdc92008-03-04 21:32:38 +11001298 # parentlist is wrong for the last element of arc $a
1299 # even if displayorder is right, hence the 3rd arg here
1300 modify_arc $v $a [expr {[llength $varccommits($v,$a)] - 1}]
Paul Mackerrasf806f0f2008-02-24 12:16:56 +11001301 }
1302}
1303
Paul Mackerrasd375ef92008-10-21 10:18:12 +11001304# Mechanism for registering a command to be executed when we come
1305# across a particular commit. To handle the case when only the
1306# prefix of the commit is known, the commitinterest array is now
1307# indexed by the first 4 characters of the ID. Each element is a
1308# list of id, cmd pairs.
1309proc interestedin {id cmd} {
1310 global commitinterest
1311
1312 lappend commitinterest([string range $id 0 3]) $id $cmd
1313}
1314
1315proc check_interest {id scripts} {
1316 global commitinterest
1317
1318 set prefix [string range $id 0 3]
1319 if {[info exists commitinterest($prefix)]} {
1320 set newlist {}
1321 foreach {i script} $commitinterest($prefix) {
1322 if {[string match "$i*" $id]} {
1323 lappend scripts [string map [list "%I" $id "%P" $i] $script]
1324 } else {
1325 lappend newlist $i $script
1326 }
1327 }
1328 if {$newlist ne {}} {
1329 set commitinterest($prefix) $newlist
1330 } else {
1331 unset commitinterest($prefix)
1332 }
1333 }
1334 return $scripts
1335}
1336
Paul Mackerrasf806f0f2008-02-24 12:16:56 +11001337proc getcommitlines {fd inst view updating} {
Paul Mackerrasd375ef92008-10-21 10:18:12 +11001338 global cmitlisted leftover
Paul Mackerras3ed31a82008-04-26 16:00:00 +10001339 global commitidx commitdata vdatemode
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001340 global parents children curview hlview
Paul Mackerras468bcae2008-03-03 10:19:35 +11001341 global idpending ordertok
Paul Mackerras3ed31a82008-04-26 16:00:00 +10001342 global varccommits varcid varctok vtokmod vfilelimit
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +00001343
Paul Mackerrasd1e46752006-08-16 20:02:32 +10001344 set stuff [read $fd 500000]
Paul Mackerras005a2f42007-07-26 22:36:39 +10001345 # git log doesn't terminate the last commit with a null...
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001346 if {$stuff == {} && $leftover($inst) ne {} && [eof $fd]} {
Paul Mackerras005a2f42007-07-26 22:36:39 +10001347 set stuff "\0"
1348 }
Paul Mackerrasb490a992005-06-22 10:25:38 +10001349 if {$stuff == {}} {
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10001350 if {![eof $fd]} {
1351 return 1
1352 }
Paul Mackerras6df74032008-05-11 22:13:02 +10001353 global commfd viewcomplete viewactive viewname
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001354 global viewinstances
1355 unset commfd($inst)
1356 set i [lsearch -exact $viewinstances($view) $inst]
1357 if {$i >= 0} {
1358 set viewinstances($view) [lreplace $viewinstances($view) $i $i]
Paul Mackerrasb0cdca92007-08-23 19:35:51 +10001359 }
Paul Mackerrasf0654862005-07-18 14:29:03 -04001360 # set it blocking so we wait for the process to terminate
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10001361 fconfigure $fd -blocking 1
Paul Mackerras098dd8a2006-05-03 09:32:53 +10001362 if {[catch {close $fd} err]} {
1363 set fv {}
1364 if {$view != $curview} {
1365 set fv " for the \"$viewname($view)\" view"
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10001366 }
Paul Mackerras098dd8a2006-05-03 09:32:53 +10001367 if {[string range $err 0 4] == "usage"} {
1368 set err "Gitk: error reading commits$fv:\
Paul Mackerrasf9e0b6f2008-03-04 21:14:17 +11001369 bad arguments to git log."
Paul Mackerras098dd8a2006-05-03 09:32:53 +10001370 if {$viewname($view) eq "Command line"} {
1371 append err \
Paul Mackerrasf9e0b6f2008-03-04 21:14:17 +11001372 " (Note: arguments to gitk are passed to git log\
Paul Mackerras098dd8a2006-05-03 09:32:53 +10001373 to allow selection of commits to be displayed.)"
1374 }
1375 } else {
1376 set err "Error reading commits$fv: $err"
1377 }
1378 error_popup $err
Paul Mackerras1d10f362005-05-15 12:55:47 +00001379 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001380 if {[incr viewactive($view) -1] <= 0} {
1381 set viewcomplete($view) 1
1382 # Check if we have seen any ids listed as parents that haven't
1383 # appeared in the list
1384 closevarcs $view
1385 notbusy $view
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001386 }
Paul Mackerras098dd8a2006-05-03 09:32:53 +10001387 if {$view == $curview} {
Paul Mackerrasac1276a2008-03-03 10:11:08 +11001388 run chewcommits
Paul Mackerras9a40c502005-05-12 23:46:16 +00001389 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10001390 return 0
Paul Mackerras9a40c502005-05-12 23:46:16 +00001391 }
Paul Mackerrasb490a992005-06-22 10:25:38 +10001392 set start 0
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11001393 set gotsome 0
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001394 set scripts {}
Paul Mackerrasb490a992005-06-22 10:25:38 +10001395 while 1 {
1396 set i [string first "\0" $stuff $start]
1397 if {$i < 0} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001398 append leftover($inst) [string range $stuff $start end]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11001399 break
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +00001400 }
Paul Mackerrasb490a992005-06-22 10:25:38 +10001401 if {$start == 0} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001402 set cmit $leftover($inst)
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11001403 append cmit [string range $stuff 0 [expr {$i - 1}]]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001404 set leftover($inst) {}
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11001405 } else {
1406 set cmit [string range $stuff $start [expr {$i - 1}]]
Paul Mackerrasb490a992005-06-22 10:25:38 +10001407 }
1408 set start [expr {$i + 1}]
Paul Mackerrase5ea7012005-08-18 20:40:39 +10001409 set j [string first "\n" $cmit]
1410 set ok 0
Paul Mackerras16c1ff92006-03-30 18:43:51 +11001411 set listed 1
Paul Mackerrasc961b222007-07-09 22:45:47 +10001412 if {$j >= 0 && [string match "commit *" $cmit]} {
1413 set ids [string range $cmit 7 [expr {$j - 1}]]
Linus Torvalds1407ade2008-02-09 14:02:07 -08001414 if {[string match {[-^<>]*} $ids]} {
Paul Mackerrasc961b222007-07-09 22:45:47 +10001415 switch -- [string index $ids 0] {
1416 "-" {set listed 0}
Linus Torvalds1407ade2008-02-09 14:02:07 -08001417 "^" {set listed 2}
1418 "<" {set listed 3}
1419 ">" {set listed 4}
Paul Mackerrasc961b222007-07-09 22:45:47 +10001420 }
Paul Mackerras16c1ff92006-03-30 18:43:51 +11001421 set ids [string range $ids 1 end]
1422 }
Paul Mackerrase5ea7012005-08-18 20:40:39 +10001423 set ok 1
1424 foreach id $ids {
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11001425 if {[string length $id] != 40} {
Paul Mackerrase5ea7012005-08-18 20:40:39 +10001426 set ok 0
1427 break
1428 }
1429 }
1430 }
1431 if {!$ok} {
Paul Mackerras7e952e72005-06-27 20:04:26 +10001432 set shortcmit $cmit
1433 if {[string length $shortcmit] > 80} {
1434 set shortcmit "[string range $shortcmit 0 80]..."
1435 }
Christian Stimmingd990ced2007-11-07 18:42:55 +01001436 error_popup "[mc "Can't parse git log output:"] {$shortcmit}"
Paul Mackerrasb490a992005-06-22 10:25:38 +10001437 exit 1
1438 }
Paul Mackerrase5ea7012005-08-18 20:40:39 +10001439 set id [lindex $ids 0]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001440 set vid $view,$id
Paul Mackerrasf806f0f2008-02-24 12:16:56 +11001441
1442 if {!$listed && $updating && ![info exists varcid($vid)] &&
Paul Mackerras3ed31a82008-04-26 16:00:00 +10001443 $vfilelimit($view) ne {}} {
Paul Mackerrasf806f0f2008-02-24 12:16:56 +11001444 # git log doesn't rewrite parents for unlisted commits
1445 # when doing path limiting, so work around that here
1446 # by working out the rewritten parent with git rev-list
1447 # and if we already know about it, using the rewritten
1448 # parent as a substitute parent for $id's children.
1449 if {![catch {
1450 set rwid [exec git rev-list --first-parent --max-count=1 \
Paul Mackerras3ed31a82008-04-26 16:00:00 +10001451 $id -- $vfilelimit($view)]
Paul Mackerrasf806f0f2008-02-24 12:16:56 +11001452 }]} {
1453 if {$rwid ne {} && [info exists varcid($view,$rwid)]} {
1454 # use $rwid in place of $id
1455 rewrite_commit $view $id $rwid
1456 continue
1457 }
1458 }
1459 }
1460
Paul Mackerrasf1bf4ee2008-02-16 17:47:31 +11001461 set a 0
1462 if {[info exists varcid($vid)]} {
1463 if {$cmitlisted($vid) || !$listed} continue
1464 set a $varcid($vid)
1465 }
Paul Mackerras16c1ff92006-03-30 18:43:51 +11001466 if {$listed} {
1467 set olds [lrange $ids 1 end]
Paul Mackerras16c1ff92006-03-30 18:43:51 +11001468 } else {
1469 set olds {}
1470 }
Paul Mackerrasf7a3e8d2006-03-18 10:04:48 +11001471 set commitdata($id) [string range $cmit [expr {$j + 1}] end]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001472 set cmitlisted($vid) $listed
1473 set parents($vid) $olds
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001474 if {![info exists children($vid)]} {
1475 set children($vid) {}
Paul Mackerrasf1bf4ee2008-02-16 17:47:31 +11001476 } elseif {$a == 0 && [llength $children($vid)] == 1} {
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +11001477 set k [lindex $children($vid) 0]
1478 if {[llength $parents($view,$k)] == 1 &&
Paul Mackerras3ed31a82008-04-26 16:00:00 +10001479 (!$vdatemode($view) ||
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +11001480 $varcid($view,$k) == [llength $varctok($view)] - 1)} {
1481 set a $varcid($view,$k)
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001482 }
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10001483 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001484 if {$a == 0} {
1485 # new arc
1486 set a [newvarc $view $id]
1487 }
Paul Mackerrase5b37ac2007-12-12 18:13:51 +11001488 if {[string compare [lindex $varctok($view) $a] $vtokmod($view)] < 0} {
1489 modify_arc $view $a
1490 }
Paul Mackerrasf1bf4ee2008-02-16 17:47:31 +11001491 if {![info exists varcid($vid)]} {
1492 set varcid($vid) $a
1493 lappend varccommits($view,$a) $id
1494 incr commitidx($view)
1495 }
Paul Mackerrase5b37ac2007-12-12 18:13:51 +11001496
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001497 set i 0
1498 foreach p $olds {
1499 if {$i == 0 || [lsearch -exact $olds $p] >= $i} {
1500 set vp $view,$p
1501 if {[llength [lappend children($vp) $id]] > 1 &&
1502 [vtokcmp $view [lindex $children($vp) end-1] $id] > 0} {
1503 set children($vp) [lsort -command [list vtokcmp $view] \
1504 $children($vp)]
Paul Mackerras9257d8f2007-12-11 10:45:38 +11001505 catch {unset ordertok}
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001506 }
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +11001507 if {[info exists varcid($view,$p)]} {
1508 fix_reversal $p $a $view
1509 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001510 }
1511 incr i
1512 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001513
Paul Mackerrasd375ef92008-10-21 10:18:12 +11001514 set scripts [check_interest $id $scripts]
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11001515 set gotsome 1
Paul Mackerras9f1afe02006-02-19 22:44:47 +11001516 }
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11001517 if {$gotsome} {
Paul Mackerrasac1276a2008-03-03 10:11:08 +11001518 global numcommits hlview
1519
1520 if {$view == $curview} {
1521 set numcommits $commitidx($view)
1522 run chewcommits
1523 }
1524 if {[info exists hlview] && $view == $hlview} {
1525 # we never actually get here...
1526 run vhighlightmore
1527 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001528 foreach s $scripts {
1529 eval $s
1530 }
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11001531 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10001532 return 2
Paul Mackerrascfb45632005-05-31 12:14:42 +00001533}
1534
Paul Mackerrasac1276a2008-03-03 10:11:08 +11001535proc chewcommits {} {
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10001536 global curview hlview viewcomplete
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001537 global pending_select
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +00001538
Paul Mackerrasac1276a2008-03-03 10:11:08 +11001539 layoutmore
1540 if {$viewcomplete($curview)} {
1541 global commitidx varctok
1542 global numcommits startmsecs
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10001543
Paul Mackerrasac1276a2008-03-03 10:11:08 +11001544 if {[info exists pending_select]} {
Alexander Gavrilov835e62a2008-07-26 20:15:54 +04001545 update
1546 reset_pending_select {}
1547
1548 if {[commitinview $pending_select $curview]} {
1549 selectline [rowofcommit $pending_select] 1
1550 } else {
1551 set row [first_real_row]
1552 selectline $row 1
1553 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10001554 }
Paul Mackerrasac1276a2008-03-03 10:11:08 +11001555 if {$commitidx($curview) > 0} {
1556 #set ms [expr {[clock clicks -milliseconds] - $startmsecs}]
1557 #puts "overall $ms ms for $numcommits commits"
1558 #puts "[llength $varctok($view)] arcs, $commitidx($view) commits"
1559 } else {
1560 show_status [mc "No commits selected"]
1561 }
1562 notbusy layout
Paul Mackerrasb6645502005-08-11 09:56:23 +10001563 }
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10001564 return 0
Paul Mackerras1db95b02005-05-09 04:08:39 +00001565}
1566
Alexander Gavrilov590915d2008-11-09 18:06:07 +03001567proc do_readcommit {id} {
1568 global tclencoding
1569
1570 # Invoke git-log to handle automatic encoding conversion
1571 set fd [open [concat | git log --no-color --pretty=raw -1 $id] r]
1572 # Read the results using i18n.logoutputencoding
1573 fconfigure $fd -translation lf -eofchar {}
1574 if {$tclencoding != {}} {
1575 fconfigure $fd -encoding $tclencoding
1576 }
1577 set contents [read $fd]
1578 close $fd
1579 # Remove the heading line
1580 regsub {^commit [0-9a-f]+\n} $contents {} contents
1581
1582 return $contents
1583}
1584
Paul Mackerras1db95b02005-05-09 04:08:39 +00001585proc readcommit {id} {
Alexander Gavrilov590915d2008-11-09 18:06:07 +03001586 if {[catch {set contents [do_readcommit $id]}]} return
1587 parsecommit $id $contents 1
Paul Mackerrasb490a992005-06-22 10:25:38 +10001588}
1589
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11001590proc parsecommit {id contents listed} {
Sven Verdoolaegeb5c2f302005-11-29 22:15:51 +01001591 global commitinfo cdate
1592
1593 set inhdr 1
1594 set comment {}
1595 set headline {}
1596 set auname {}
1597 set audate {}
1598 set comname {}
1599 set comdate {}
Paul Mackerras232475d2005-11-15 10:34:03 +11001600 set hdrend [string first "\n\n" $contents]
1601 if {$hdrend < 0} {
1602 # should never happen...
1603 set hdrend [string length $contents]
1604 }
1605 set header [string range $contents 0 [expr {$hdrend - 1}]]
1606 set comment [string range $contents [expr {$hdrend + 2}] end]
1607 foreach line [split $header "\n"] {
Kevin Ballard61f57cb2008-12-18 01:26:48 -08001608 set line [split $line " "]
Paul Mackerras232475d2005-11-15 10:34:03 +11001609 set tag [lindex $line 0]
1610 if {$tag == "author"} {
1611 set audate [lindex $line end-1]
Kevin Ballard61f57cb2008-12-18 01:26:48 -08001612 set auname [join [lrange $line 1 end-2] " "]
Paul Mackerras232475d2005-11-15 10:34:03 +11001613 } elseif {$tag == "committer"} {
1614 set comdate [lindex $line end-1]
Kevin Ballard61f57cb2008-12-18 01:26:48 -08001615 set comname [join [lrange $line 1 end-2] " "]
Paul Mackerras1db95b02005-05-09 04:08:39 +00001616 }
1617 }
Paul Mackerras232475d2005-11-15 10:34:03 +11001618 set headline {}
Paul Mackerras43c25072006-09-27 10:56:02 +10001619 # take the first non-blank line of the comment as the headline
1620 set headline [string trimleft $comment]
1621 set i [string first "\n" $headline]
Paul Mackerras232475d2005-11-15 10:34:03 +11001622 if {$i >= 0} {
Paul Mackerras43c25072006-09-27 10:56:02 +10001623 set headline [string range $headline 0 $i]
1624 }
1625 set headline [string trimright $headline]
1626 set i [string first "\r" $headline]
1627 if {$i >= 0} {
1628 set headline [string trimright [string range $headline 0 $i]]
Paul Mackerras232475d2005-11-15 10:34:03 +11001629 }
1630 if {!$listed} {
Paul Mackerrasf9e0b6f2008-03-04 21:14:17 +11001631 # git log indents the comment by 4 spaces;
Timo Hirvonen8974c6f2006-05-24 10:57:40 +03001632 # if we got this via git cat-file, add the indentation
Paul Mackerras232475d2005-11-15 10:34:03 +11001633 set newcomment {}
1634 foreach line [split $comment "\n"] {
1635 append newcomment " "
1636 append newcomment $line
Paul Mackerrasf6e28692005-11-20 23:08:22 +11001637 append newcomment "\n"
Paul Mackerras232475d2005-11-15 10:34:03 +11001638 }
1639 set comment $newcomment
Paul Mackerras1db95b02005-05-09 04:08:39 +00001640 }
1641 if {$comdate != {}} {
Paul Mackerrascfb45632005-05-31 12:14:42 +00001642 set cdate($id) $comdate
Paul Mackerras1db95b02005-05-09 04:08:39 +00001643 }
Paul Mackerrase5c2d852005-05-11 23:44:54 +00001644 set commitinfo($id) [list $headline $auname $audate \
1645 $comname $comdate $comment]
Paul Mackerras1db95b02005-05-09 04:08:39 +00001646}
1647
Paul Mackerrasf7a3e8d2006-03-18 10:04:48 +11001648proc getcommit {id} {
Paul Mackerras79b2c752006-04-02 20:47:40 +10001649 global commitdata commitinfo
Paul Mackerras8ed16482006-03-02 22:56:44 +11001650
Paul Mackerrasf7a3e8d2006-03-18 10:04:48 +11001651 if {[info exists commitdata($id)]} {
1652 parsecommit $id $commitdata($id) 1
Paul Mackerras8ed16482006-03-02 22:56:44 +11001653 } else {
1654 readcommit $id
1655 if {![info exists commitinfo($id)]} {
Christian Stimmingd990ced2007-11-07 18:42:55 +01001656 set commitinfo($id) [list [mc "No commit information available"]]
Paul Mackerras8ed16482006-03-02 22:56:44 +11001657 }
1658 }
1659 return 1
1660}
1661
Paul Mackerrasd375ef92008-10-21 10:18:12 +11001662# Expand an abbreviated commit ID to a list of full 40-char IDs that match
1663# and are present in the current view.
1664# This is fairly slow...
1665proc longid {prefix} {
1666 global varcid curview
1667
1668 set ids {}
1669 foreach match [array names varcid "$curview,$prefix*"] {
1670 lappend ids [lindex [split $match ","] 1]
1671 }
1672 return $ids
1673}
1674
Paul Mackerras887fe3c2005-05-21 07:35:37 +00001675proc readrefs {} {
Paul Mackerras62d3ea62006-09-11 10:36:53 +10001676 global tagids idtags headids idheads tagobjid
Paul Mackerras219ea3a2006-09-07 10:21:39 +10001677 global otherrefids idotherrefs mainhead mainheadid
Alexander Gavrilov39816d62008-08-23 12:27:44 +04001678 global selecthead selectheadid
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10001679
Sven Verdoolaegeb5c2f302005-11-29 22:15:51 +01001680 foreach v {tagids idtags headids idheads otherrefids idotherrefs} {
1681 catch {unset $v}
1682 }
Paul Mackerras62d3ea62006-09-11 10:36:53 +10001683 set refd [open [list | git show-ref -d] r]
1684 while {[gets $refd line] >= 0} {
1685 if {[string index $line 40] ne " "} continue
1686 set id [string range $line 0 39]
1687 set ref [string range $line 41 end]
1688 if {![string match "refs/*" $ref]} continue
1689 set name [string range $ref 5 end]
1690 if {[string match "remotes/*" $name]} {
1691 if {![string match "*/HEAD" $name]} {
1692 set headids($name) $id
1693 lappend idheads($id) $name
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10001694 }
Paul Mackerras62d3ea62006-09-11 10:36:53 +10001695 } elseif {[string match "heads/*" $name]} {
1696 set name [string range $name 6 end]
Junio C Hamano36a7cad2005-11-18 23:54:17 -08001697 set headids($name) $id
1698 lappend idheads($id) $name
Paul Mackerras62d3ea62006-09-11 10:36:53 +10001699 } elseif {[string match "tags/*" $name]} {
1700 # this lets refs/tags/foo^{} overwrite refs/tags/foo,
1701 # which is what we want since the former is the commit ID
1702 set name [string range $name 5 end]
1703 if {[string match "*^{}" $name]} {
1704 set name [string range $name 0 end-3]
1705 } else {
1706 set tagobjid($name) $id
1707 }
1708 set tagids($name) $id
1709 lappend idtags($id) $name
Junio C Hamano36a7cad2005-11-18 23:54:17 -08001710 } else {
1711 set otherrefids($name) $id
1712 lappend idotherrefs($id) $name
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10001713 }
1714 }
Alex Riesen062d6712007-07-29 22:28:40 +02001715 catch {close $refd}
Paul Mackerras8a485712006-07-06 10:21:23 +10001716 set mainhead {}
Paul Mackerras219ea3a2006-09-07 10:21:39 +10001717 set mainheadid {}
Paul Mackerras8a485712006-07-06 10:21:23 +10001718 catch {
Paul Mackerrasc11ff122008-05-26 10:11:33 +10001719 set mainheadid [exec git rev-parse HEAD]
Paul Mackerras8a485712006-07-06 10:21:23 +10001720 set thehead [exec git symbolic-ref HEAD]
1721 if {[string match "refs/heads/*" $thehead]} {
1722 set mainhead [string range $thehead 11 end]
1723 }
1724 }
Alexander Gavrilov39816d62008-08-23 12:27:44 +04001725 set selectheadid {}
1726 if {$selecthead ne {}} {
1727 catch {
1728 set selectheadid [exec git rev-parse --verify $selecthead]
1729 }
1730 }
Paul Mackerras887fe3c2005-05-21 07:35:37 +00001731}
1732
Paul Mackerras8f489362007-07-13 19:49:37 +10001733# skip over fake commits
1734proc first_real_row {} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001735 global nullid nullid2 numcommits
Paul Mackerras8f489362007-07-13 19:49:37 +10001736
1737 for {set row 0} {$row < $numcommits} {incr row} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001738 set id [commitonrow $row]
Paul Mackerras8f489362007-07-13 19:49:37 +10001739 if {$id ne $nullid && $id ne $nullid2} {
1740 break
1741 }
1742 }
1743 return $row
1744}
1745
Paul Mackerrase11f1232007-06-16 20:29:25 +10001746# update things for a head moved to a child of its previous location
1747proc movehead {id name} {
1748 global headids idheads
1749
1750 removehead $headids($name) $name
1751 set headids($name) $id
1752 lappend idheads($id) $name
1753}
1754
1755# update things when a head has been removed
1756proc removehead {id name} {
1757 global headids idheads
1758
1759 if {$idheads($id) eq $name} {
1760 unset idheads($id)
1761 } else {
1762 set i [lsearch -exact $idheads($id) $name]
1763 if {$i >= 0} {
1764 set idheads($id) [lreplace $idheads($id) $i $i]
1765 }
1766 }
1767 unset headids($name)
1768}
1769
Alexander Gavrilove7d64002008-11-11 23:55:42 +03001770proc make_transient {window origin} {
1771 global have_tk85
1772
1773 # In MacOS Tk 8.4 transient appears to work by setting
1774 # overrideredirect, which is utterly useless, since the
1775 # windows get no border, and are not even kept above
1776 # the parent.
1777 if {!$have_tk85 && [tk windowingsystem] eq {aqua}} return
1778
1779 wm transient $window $origin
1780
1781 # Windows fails to place transient windows normally, so
1782 # schedule a callback to center them on the parent.
1783 if {[tk windowingsystem] eq {win32}} {
1784 after idle [list tk::PlaceWindow $window widget $origin]
1785 }
1786}
1787
Paul Mackerrase54be9e2006-05-26 22:34:30 +10001788proc show_error {w top msg} {
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00001789 message $w.m -text $msg -justify center -aspect 400
1790 pack $w.m -side top -fill x -padx 20 -pady 20
Christian Stimmingd990ced2007-11-07 18:42:55 +01001791 button $w.ok -text [mc OK] -command "destroy $top"
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00001792 pack $w.ok -side bottom -fill x
Paul Mackerrase54be9e2006-05-26 22:34:30 +10001793 bind $top <Visibility> "grab $top; focus $top"
1794 bind $top <Key-Return> "destroy $top"
Alexander Gavrilov76f15942008-11-02 21:59:44 +03001795 bind $top <Key-space> "destroy $top"
1796 bind $top <Key-Escape> "destroy $top"
Paul Mackerrase54be9e2006-05-26 22:34:30 +10001797 tkwait window $top
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00001798}
1799
Alexander Gavrilov84a76f12008-11-02 21:59:45 +03001800proc error_popup {msg {owner .}} {
Paul Mackerras098dd8a2006-05-03 09:32:53 +10001801 set w .error
1802 toplevel $w
Alexander Gavrilove7d64002008-11-11 23:55:42 +03001803 make_transient $w $owner
Paul Mackerrase54be9e2006-05-26 22:34:30 +10001804 show_error $w $w $msg
Paul Mackerras098dd8a2006-05-03 09:32:53 +10001805}
1806
Alexander Gavrilov84a76f12008-11-02 21:59:45 +03001807proc confirm_popup {msg {owner .}} {
Paul Mackerras10299152006-08-02 09:52:01 +10001808 global confirm_ok
1809 set confirm_ok 0
1810 set w .confirm
1811 toplevel $w
Alexander Gavrilove7d64002008-11-11 23:55:42 +03001812 make_transient $w $owner
Paul Mackerras10299152006-08-02 09:52:01 +10001813 message $w.m -text $msg -justify center -aspect 400
1814 pack $w.m -side top -fill x -padx 20 -pady 20
Christian Stimmingd990ced2007-11-07 18:42:55 +01001815 button $w.ok -text [mc OK] -command "set confirm_ok 1; destroy $w"
Paul Mackerras10299152006-08-02 09:52:01 +10001816 pack $w.ok -side left -fill x
Christian Stimmingd990ced2007-11-07 18:42:55 +01001817 button $w.cancel -text [mc Cancel] -command "destroy $w"
Paul Mackerras10299152006-08-02 09:52:01 +10001818 pack $w.cancel -side right -fill x
1819 bind $w <Visibility> "grab $w; focus $w"
Alexander Gavrilov76f15942008-11-02 21:59:44 +03001820 bind $w <Key-Return> "set confirm_ok 1; destroy $w"
1821 bind $w <Key-space> "set confirm_ok 1; destroy $w"
1822 bind $w <Key-Escape> "destroy $w"
Paul Mackerras10299152006-08-02 09:52:01 +10001823 tkwait window $w
1824 return $confirm_ok
1825}
1826
Paul Mackerrasb039f0a2008-01-06 15:54:46 +11001827proc setoptions {} {
1828 option add *Panedwindow.showHandle 1 startupFile
1829 option add *Panedwindow.sashRelief raised startupFile
1830 option add *Button.font uifont startupFile
1831 option add *Checkbutton.font uifont startupFile
1832 option add *Radiobutton.font uifont startupFile
1833 option add *Menu.font uifont startupFile
1834 option add *Menubutton.font uifont startupFile
1835 option add *Label.font uifont startupFile
1836 option add *Message.font uifont startupFile
1837 option add *Entry.font uifont startupFile
1838}
1839
Paul Mackerras79056032008-10-18 16:24:46 +11001840# Make a menu and submenus.
1841# m is the window name for the menu, items is the list of menu items to add.
1842# Each item is a list {mc label type description options...}
1843# mc is ignored; it's so we can put mc there to alert xgettext
1844# label is the string that appears in the menu
1845# type is cascade, command or radiobutton (should add checkbutton)
1846# description depends on type; it's the sublist for cascade, the
1847# command to invoke for command, or {variable value} for radiobutton
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11001848proc makemenu {m items} {
1849 menu $m
Alexander Gavrilovcea07cf2008-11-09 13:00:45 +03001850 if {[tk windowingsystem] eq {aqua}} {
1851 set Meta1 Cmd
1852 } else {
1853 set Meta1 Ctrl
1854 }
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11001855 foreach i $items {
Paul Mackerras79056032008-10-18 16:24:46 +11001856 set name [mc [lindex $i 1]]
1857 set type [lindex $i 2]
1858 set thing [lindex $i 3]
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11001859 set params [list $type]
1860 if {$name ne {}} {
1861 set u [string first "&" [string map {&& x} $name]]
1862 lappend params -label [string map {&& & & {}} $name]
1863 if {$u >= 0} {
1864 lappend params -underline $u
1865 }
1866 }
1867 switch -- $type {
1868 "cascade" {
Paul Mackerras79056032008-10-18 16:24:46 +11001869 set submenu [string tolower [string map {& ""} [lindex $i 1]]]
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11001870 lappend params -menu $m.$submenu
1871 }
1872 "command" {
1873 lappend params -command $thing
1874 }
1875 "radiobutton" {
1876 lappend params -variable [lindex $thing 0] \
1877 -value [lindex $thing 1]
1878 }
1879 }
Alexander Gavrilovcea07cf2008-11-09 13:00:45 +03001880 set tail [lrange $i 4 end]
1881 regsub -all {\yMeta1\y} $tail $Meta1 tail
1882 eval $m add $params $tail
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11001883 if {$type eq "cascade"} {
1884 makemenu $m.$submenu $thing
1885 }
1886 }
1887}
1888
1889# translate string and remove ampersands
1890proc mca {str} {
1891 return [string map {&& & & {}} [mc $str]]
1892}
1893
Paul Mackerrasd94f8cd2006-04-06 10:18:23 +10001894proc makewindow {} {
Paul Mackerras31c0eaa2007-12-30 22:41:14 +11001895 global canv canv2 canv3 linespc charspc ctext cflist cscroll
Paul Mackerras9c311b32007-10-04 22:27:13 +10001896 global tabstop
Paul Mackerrasb74fd572005-07-16 07:46:13 -04001897 global findtype findtypemenu findloc findstring fstring geometry
Paul Mackerras887fe3c2005-05-21 07:35:37 +00001898 global entries sha1entry sha1string sha1but
Steffen Prohaska890fae72007-08-12 12:05:46 +02001899 global diffcontextstring diffcontext
Steffen Prohaskab9b86002008-01-17 23:42:55 +01001900 global ignorespace
Paul Mackerras94a2eed2005-08-07 15:27:57 +10001901 global maincursor textcursor curtextcursor
Paul Mackerras219ea3a2006-09-07 10:21:39 +10001902 global rowctxmenu fakerowmenu mergemax wrapcomment
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10001903 global highlight_files gdttype
Paul Mackerras3ea06f92006-05-24 10:16:03 +10001904 global searchstring sstring
Mark Levedahl60378c02007-05-20 12:12:48 -04001905 global bgcolor fgcolor bglist fglist diffcolors selectbgcolor
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10001906 global headctxmenu progresscanv progressitem progresscoords statusw
1907 global fprogitem fprogcoord lastprogupdate progupdatepending
Paul Mackerras6df74032008-05-11 22:13:02 +10001908 global rprogitem rprogcoord rownumsel numcommits
Paul Mackerras32f1b3e2007-09-28 21:27:39 +10001909 global have_tk85
Paul Mackerras9a40c502005-05-12 23:46:16 +00001910
Paul Mackerras79056032008-10-18 16:24:46 +11001911 # The "mc" arguments here are purely so that xgettext
1912 # sees the following string as needing to be translated
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11001913 makemenu .bar {
Paul Mackerras79056032008-10-18 16:24:46 +11001914 {mc "File" cascade {
1915 {mc "Update" command updatecommits -accelerator F5}
Alexander Gavrilovcea07cf2008-11-09 13:00:45 +03001916 {mc "Reload" command reloadcommits -accelerator Meta1-F5}
Paul Mackerras79056032008-10-18 16:24:46 +11001917 {mc "Reread references" command rereadrefs}
Alexander Gavrilovcea07cf2008-11-09 13:00:45 +03001918 {mc "List references" command showrefs -accelerator F2}
Alexander Gavrilov7fb0abb2008-11-13 23:12:42 +03001919 {xx "" separator}
1920 {mc "Start git gui" command {exec git gui &}}
1921 {xx "" separator}
Alexander Gavrilovcea07cf2008-11-09 13:00:45 +03001922 {mc "Quit" command doquit -accelerator Meta1-Q}
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11001923 }}
Paul Mackerras79056032008-10-18 16:24:46 +11001924 {mc "Edit" cascade {
1925 {mc "Preferences" command doprefs}
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11001926 }}
Paul Mackerras79056032008-10-18 16:24:46 +11001927 {mc "View" cascade {
Alexander Gavrilovcea07cf2008-11-09 13:00:45 +03001928 {mc "New view..." command {newview 0} -accelerator Shift-F4}
1929 {mc "Edit view..." command editview -state disabled -accelerator F4}
Paul Mackerras79056032008-10-18 16:24:46 +11001930 {mc "Delete view" command delview -state disabled}
1931 {xx "" separator}
1932 {mc "All files" radiobutton {selectedview 0} -command {showview 0}}
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11001933 }}
Paul Mackerras79056032008-10-18 16:24:46 +11001934 {mc "Help" cascade {
1935 {mc "About gitk" command about}
1936 {mc "Key bindings" command keys}
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11001937 }}
1938 }
Paul Mackerras9a40c502005-05-12 23:46:16 +00001939 . configure -menu .bar
1940
Junio C Hamanoe9937d22007-02-01 08:46:38 -05001941 # the gui has upper and lower half, parts of a paned window.
Paul Mackerras0327d272005-05-10 00:23:42 +00001942 panedwindow .ctop -orient vertical
Junio C Hamanoe9937d22007-02-01 08:46:38 -05001943
1944 # possibly use assumed geometry
Mark Levedahl9ca72f42007-02-12 19:19:34 -05001945 if {![info exists geometry(pwsash0)]} {
Junio C Hamanoe9937d22007-02-01 08:46:38 -05001946 set geometry(topheight) [expr {15 * $linespc}]
1947 set geometry(topwidth) [expr {80 * $charspc}]
1948 set geometry(botheight) [expr {15 * $linespc}]
1949 set geometry(botwidth) [expr {50 * $charspc}]
Mark Levedahl9ca72f42007-02-12 19:19:34 -05001950 set geometry(pwsash0) "[expr {40 * $charspc}] 2"
1951 set geometry(pwsash1) "[expr {60 * $charspc}] 2"
Paul Mackerras0fba86b2005-05-16 23:54:58 +00001952 }
Junio C Hamanoe9937d22007-02-01 08:46:38 -05001953
1954 # the upper half will have a paned window, a scroll bar to the right, and some stuff below
1955 frame .tf -height $geometry(topheight) -width $geometry(topwidth)
1956 frame .tf.histframe
1957 panedwindow .tf.histframe.pwclist -orient horizontal -sashpad 0 -handlesize 4
1958
1959 # create three canvases
1960 set cscroll .tf.histframe.csb
1961 set canv .tf.histframe.pwclist.canv
Mark Levedahl9ca72f42007-02-12 19:19:34 -05001962 canvas $canv \
Mark Levedahl60378c02007-05-20 12:12:48 -04001963 -selectbackground $selectbgcolor \
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10001964 -background $bgcolor -bd 0 \
Paul Mackerras9f1afe02006-02-19 22:44:47 +11001965 -yscrollincr $linespc -yscrollcommand "scrollcanv $cscroll"
Junio C Hamanoe9937d22007-02-01 08:46:38 -05001966 .tf.histframe.pwclist add $canv
1967 set canv2 .tf.histframe.pwclist.canv2
Mark Levedahl9ca72f42007-02-12 19:19:34 -05001968 canvas $canv2 \
Mark Levedahl60378c02007-05-20 12:12:48 -04001969 -selectbackground $selectbgcolor \
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10001970 -background $bgcolor -bd 0 -yscrollincr $linespc
Junio C Hamanoe9937d22007-02-01 08:46:38 -05001971 .tf.histframe.pwclist add $canv2
1972 set canv3 .tf.histframe.pwclist.canv3
Mark Levedahl9ca72f42007-02-12 19:19:34 -05001973 canvas $canv3 \
Mark Levedahl60378c02007-05-20 12:12:48 -04001974 -selectbackground $selectbgcolor \
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10001975 -background $bgcolor -bd 0 -yscrollincr $linespc
Junio C Hamanoe9937d22007-02-01 08:46:38 -05001976 .tf.histframe.pwclist add $canv3
Mark Levedahl9ca72f42007-02-12 19:19:34 -05001977 eval .tf.histframe.pwclist sash place 0 $geometry(pwsash0)
1978 eval .tf.histframe.pwclist sash place 1 $geometry(pwsash1)
Paul Mackerras98f350e2005-05-15 05:56:51 +00001979
Junio C Hamanoe9937d22007-02-01 08:46:38 -05001980 # a scroll bar to rule them
1981 scrollbar $cscroll -command {allcanvs yview} -highlightthickness 0
1982 pack $cscroll -side right -fill y
1983 bind .tf.histframe.pwclist <Configure> {resizeclistpanes %W %w}
1984 lappend bglist $canv $canv2 $canv3
1985 pack .tf.histframe.pwclist -fill both -expand 1 -side left
1986
1987 # we have two button bars at bottom of top frame. Bar 1
1988 frame .tf.bar
1989 frame .tf.lbar -height 15
1990
1991 set sha1entry .tf.bar.sha1
Paul Mackerras887fe3c2005-05-21 07:35:37 +00001992 set entries $sha1entry
Junio C Hamanoe9937d22007-02-01 08:46:38 -05001993 set sha1but .tf.bar.sha1label
Christian Stimmingd990ced2007-11-07 18:42:55 +01001994 button $sha1but -text [mc "SHA1 ID: "] -state disabled -relief flat \
Paul Mackerrasb039f0a2008-01-06 15:54:46 +11001995 -command gotocommit -width 8
Paul Mackerras887fe3c2005-05-21 07:35:37 +00001996 $sha1but conf -disabledforeground [$sha1but cget -foreground]
Junio C Hamanoe9937d22007-02-01 08:46:38 -05001997 pack .tf.bar.sha1label -side left
Paul Mackerras9c311b32007-10-04 22:27:13 +10001998 entry $sha1entry -width 40 -font textfont -textvariable sha1string
Paul Mackerras887fe3c2005-05-21 07:35:37 +00001999 trace add variable sha1string write sha1change
Paul Mackerras98f350e2005-05-15 05:56:51 +00002000 pack $sha1entry -side left -pady 2
Paul Mackerrasd6982062005-08-06 22:06:06 +10002001
2002 image create bitmap bm-left -data {
2003 #define left_width 16
2004 #define left_height 16
2005 static unsigned char left_bits[] = {
2006 0x00, 0x00, 0xc0, 0x01, 0xe0, 0x00, 0x70, 0x00, 0x38, 0x00, 0x1c, 0x00,
2007 0x0e, 0x00, 0xff, 0x7f, 0xff, 0x7f, 0xff, 0x7f, 0x0e, 0x00, 0x1c, 0x00,
2008 0x38, 0x00, 0x70, 0x00, 0xe0, 0x00, 0xc0, 0x01};
2009 }
2010 image create bitmap bm-right -data {
2011 #define right_width 16
2012 #define right_height 16
2013 static unsigned char right_bits[] = {
2014 0x00, 0x00, 0xc0, 0x01, 0x80, 0x03, 0x00, 0x07, 0x00, 0x0e, 0x00, 0x1c,
2015 0x00, 0x38, 0xff, 0x7f, 0xff, 0x7f, 0xff, 0x7f, 0x00, 0x38, 0x00, 0x1c,
2016 0x00, 0x0e, 0x00, 0x07, 0x80, 0x03, 0xc0, 0x01};
2017 }
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002018 button .tf.bar.leftbut -image bm-left -command goback \
Paul Mackerrasd6982062005-08-06 22:06:06 +10002019 -state disabled -width 26
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002020 pack .tf.bar.leftbut -side left -fill y
2021 button .tf.bar.rightbut -image bm-right -command goforw \
Paul Mackerrasd6982062005-08-06 22:06:06 +10002022 -state disabled -width 26
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002023 pack .tf.bar.rightbut -side left -fill y
Paul Mackerrasd6982062005-08-06 22:06:06 +10002024
Paul Mackerras6df74032008-05-11 22:13:02 +10002025 label .tf.bar.rowlabel -text [mc "Row"]
2026 set rownumsel {}
2027 label .tf.bar.rownum -width 7 -font textfont -textvariable rownumsel \
2028 -relief sunken -anchor e
2029 label .tf.bar.rowlabel2 -text "/"
2030 label .tf.bar.numcommits -width 7 -font textfont -textvariable numcommits \
2031 -relief sunken -anchor e
2032 pack .tf.bar.rowlabel .tf.bar.rownum .tf.bar.rowlabel2 .tf.bar.numcommits \
2033 -side left
2034 global selectedline
Paul Mackerras94b4a692008-05-20 20:51:06 +10002035 trace add variable selectedline write selectedline_change
Paul Mackerras6df74032008-05-11 22:13:02 +10002036
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10002037 # Status label and progress bar
2038 set statusw .tf.bar.status
Paul Mackerrasb039f0a2008-01-06 15:54:46 +11002039 label $statusw -width 15 -relief sunken
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10002040 pack $statusw -side left -padx 5
Paul Mackerras9c311b32007-10-04 22:27:13 +10002041 set h [expr {[font metrics uifont -linespace] + 2}]
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10002042 set progresscanv .tf.bar.progress
2043 canvas $progresscanv -relief sunken -height $h -borderwidth 2
2044 set progressitem [$progresscanv create rect -1 0 0 $h -fill green]
2045 set fprogitem [$progresscanv create rect -1 0 0 $h -fill yellow]
Paul Mackerrasa137a902007-10-23 21:12:49 +10002046 set rprogitem [$progresscanv create rect -1 0 0 $h -fill red]
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10002047 pack $progresscanv -side right -expand 1 -fill x
2048 set progresscoords {0 0}
2049 set fprogcoord 0
Paul Mackerrasa137a902007-10-23 21:12:49 +10002050 set rprogcoord 0
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10002051 bind $progresscanv <Configure> adjustprogress
2052 set lastprogupdate [clock clicks -milliseconds]
2053 set progupdatepending 0
Paul Mackerrasb5721c72005-05-10 12:08:22 +00002054
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002055 # build up the bottom bar of upper window
Paul Mackerrasb039f0a2008-01-06 15:54:46 +11002056 label .tf.lbar.flabel -text "[mc "Find"] "
2057 button .tf.lbar.fnext -text [mc "next"] -command {dofind 1 1}
2058 button .tf.lbar.fprev -text [mc "prev"] -command {dofind -1 1}
2059 label .tf.lbar.flab2 -text " [mc "commit"] "
Paul Mackerras687c8762007-09-22 12:49:33 +10002060 pack .tf.lbar.flabel .tf.lbar.fnext .tf.lbar.fprev .tf.lbar.flab2 \
2061 -side left -fill y
Christian Stimmingb007ee22007-11-07 18:44:35 +01002062 set gdttype [mc "containing:"]
Paul Mackerras687c8762007-09-22 12:49:33 +10002063 set gm [tk_optionMenu .tf.lbar.gdttype gdttype \
Christian Stimmingb007ee22007-11-07 18:44:35 +01002064 [mc "containing:"] \
2065 [mc "touching paths:"] \
2066 [mc "adding/removing string:"]]
Paul Mackerras687c8762007-09-22 12:49:33 +10002067 trace add variable gdttype write gdttype_change
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002068 pack .tf.lbar.gdttype -side left -fill y
Paul Mackerras687c8762007-09-22 12:49:33 +10002069
2070 set findstring {}
2071 set fstring .tf.lbar.findstring
2072 lappend entries $fstring
Paul Mackerras9c311b32007-10-04 22:27:13 +10002073 entry $fstring -width 30 -font textfont -textvariable findstring
Paul Mackerras687c8762007-09-22 12:49:33 +10002074 trace add variable findstring write find_change
Christian Stimmingb007ee22007-11-07 18:44:35 +01002075 set findtype [mc "Exact"]
Paul Mackerras687c8762007-09-22 12:49:33 +10002076 set findtypemenu [tk_optionMenu .tf.lbar.findtype \
Christian Stimmingb007ee22007-11-07 18:44:35 +01002077 findtype [mc "Exact"] [mc "IgnCase"] [mc "Regexp"]]
Paul Mackerras687c8762007-09-22 12:49:33 +10002078 trace add variable findtype write findcom_change
Christian Stimmingb007ee22007-11-07 18:44:35 +01002079 set findloc [mc "All fields"]
2080 tk_optionMenu .tf.lbar.findloc findloc [mc "All fields"] [mc "Headline"] \
2081 [mc "Comments"] [mc "Author"] [mc "Committer"]
Paul Mackerras687c8762007-09-22 12:49:33 +10002082 trace add variable findloc write find_change
Paul Mackerras687c8762007-09-22 12:49:33 +10002083 pack .tf.lbar.findloc -side right
2084 pack .tf.lbar.findtype -side right
2085 pack $fstring -side left -expand 1 -fill x
Paul Mackerras908c3582006-05-20 09:38:11 +10002086
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002087 # Finish putting the upper half of the viewer together
2088 pack .tf.lbar -in .tf -side bottom -fill x
2089 pack .tf.bar -in .tf -side bottom -fill x
2090 pack .tf.histframe -fill both -side top -expand 1
2091 .ctop add .tf
Mark Levedahl9ca72f42007-02-12 19:19:34 -05002092 .ctop paneconfigure .tf -height $geometry(topheight)
2093 .ctop paneconfigure .tf -width $geometry(topwidth)
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002094
2095 # now build up the bottom
2096 panedwindow .pwbottom -orient horizontal
2097
2098 # lower left, a text box over search bar, scroll bar to the right
2099 # if we know window height, then that will set the lower text height, otherwise
2100 # we set lower text height which will drive window height
2101 if {[info exists geometry(main)]} {
2102 frame .bleft -width $geometry(botwidth)
2103 } else {
2104 frame .bleft -width $geometry(botwidth) -height $geometry(botheight)
2105 }
2106 frame .bleft.top
Paul Mackerrasa8d610a2007-04-19 11:39:12 +10002107 frame .bleft.mid
Pekka Kaitaniemi8809d692008-03-08 14:27:23 +02002108 frame .bleft.bottom
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002109
Paul Mackerrasb039f0a2008-01-06 15:54:46 +11002110 button .bleft.top.search -text [mc "Search"] -command dosearch
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002111 pack .bleft.top.search -side left -padx 5
2112 set sstring .bleft.top.sstring
Paul Mackerras9c311b32007-10-04 22:27:13 +10002113 entry $sstring -width 20 -font textfont -textvariable searchstring
Paul Mackerras3ea06f92006-05-24 10:16:03 +10002114 lappend entries $sstring
2115 trace add variable searchstring write incrsearch
2116 pack $sstring -side left -expand 1 -fill x
Paul Mackerrasb039f0a2008-01-06 15:54:46 +11002117 radiobutton .bleft.mid.diff -text [mc "Diff"] \
Paul Mackerrasa8d610a2007-04-19 11:39:12 +10002118 -command changediffdisp -variable diffelide -value {0 0}
Paul Mackerrasb039f0a2008-01-06 15:54:46 +11002119 radiobutton .bleft.mid.old -text [mc "Old version"] \
Paul Mackerrasa8d610a2007-04-19 11:39:12 +10002120 -command changediffdisp -variable diffelide -value {0 1}
Paul Mackerrasb039f0a2008-01-06 15:54:46 +11002121 radiobutton .bleft.mid.new -text [mc "New version"] \
Paul Mackerrasa8d610a2007-04-19 11:39:12 +10002122 -command changediffdisp -variable diffelide -value {1 0}
Paul Mackerrasb039f0a2008-01-06 15:54:46 +11002123 label .bleft.mid.labeldiffcontext -text " [mc "Lines of context"]: "
Paul Mackerrasa8d610a2007-04-19 11:39:12 +10002124 pack .bleft.mid.diff .bleft.mid.old .bleft.mid.new -side left
Paul Mackerras9c311b32007-10-04 22:27:13 +10002125 spinbox .bleft.mid.diffcontext -width 5 -font textfont \
Steffen Prohaska890fae72007-08-12 12:05:46 +02002126 -from 1 -increment 1 -to 10000000 \
2127 -validate all -validatecommand "diffcontextvalidate %P" \
2128 -textvariable diffcontextstring
2129 .bleft.mid.diffcontext set $diffcontext
2130 trace add variable diffcontextstring write diffcontextchange
2131 lappend entries .bleft.mid.diffcontext
2132 pack .bleft.mid.labeldiffcontext .bleft.mid.diffcontext -side left
Steffen Prohaskab9b86002008-01-17 23:42:55 +01002133 checkbutton .bleft.mid.ignspace -text [mc "Ignore space change"] \
2134 -command changeignorespace -variable ignorespace
2135 pack .bleft.mid.ignspace -side left -padx 5
Pekka Kaitaniemi8809d692008-03-08 14:27:23 +02002136 set ctext .bleft.bottom.ctext
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10002137 text $ctext -background $bgcolor -foreground $fgcolor \
Paul Mackerras9c311b32007-10-04 22:27:13 +10002138 -state disabled -font textfont \
Pekka Kaitaniemi8809d692008-03-08 14:27:23 +02002139 -yscrollcommand scrolltext -wrap none \
2140 -xscrollcommand ".bleft.bottom.sbhorizontal set"
Paul Mackerras32f1b3e2007-09-28 21:27:39 +10002141 if {$have_tk85} {
2142 $ctext conf -tabstyle wordprocessor
2143 }
Pekka Kaitaniemi8809d692008-03-08 14:27:23 +02002144 scrollbar .bleft.bottom.sb -command "$ctext yview"
2145 scrollbar .bleft.bottom.sbhorizontal -command "$ctext xview" -orient h \
2146 -width 10
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002147 pack .bleft.top -side top -fill x
Paul Mackerrasa8d610a2007-04-19 11:39:12 +10002148 pack .bleft.mid -side top -fill x
Pekka Kaitaniemi8809d692008-03-08 14:27:23 +02002149 grid $ctext .bleft.bottom.sb -sticky nsew
2150 grid .bleft.bottom.sbhorizontal -sticky ew
2151 grid columnconfigure .bleft.bottom 0 -weight 1
2152 grid rowconfigure .bleft.bottom 0 -weight 1
2153 grid rowconfigure .bleft.bottom 1 -weight 0
2154 pack .bleft.bottom -side top -fill both -expand 1
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10002155 lappend bglist $ctext
2156 lappend fglist $ctext
Paul Mackerrasd2610d12005-05-11 00:45:38 +00002157
Sergey Vlasovf1b86292006-05-15 19:13:14 +04002158 $ctext tag conf comment -wrap $wrapcomment
Paul Mackerras9c311b32007-10-04 22:27:13 +10002159 $ctext tag conf filesep -font textfontbold -back "#aaaaaa"
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10002160 $ctext tag conf hunksep -fore [lindex $diffcolors 2]
2161 $ctext tag conf d0 -fore [lindex $diffcolors 0]
Paul Mackerras8b07dca2008-11-02 22:34:47 +11002162 $ctext tag conf dresult -fore [lindex $diffcolors 1]
Paul Mackerras712fcc02005-11-30 09:28:16 +11002163 $ctext tag conf m0 -fore red
2164 $ctext tag conf m1 -fore blue
2165 $ctext tag conf m2 -fore green
2166 $ctext tag conf m3 -fore purple
2167 $ctext tag conf m4 -fore brown
Paul Mackerrasb77b0272006-02-07 09:13:52 +11002168 $ctext tag conf m5 -fore "#009090"
2169 $ctext tag conf m6 -fore magenta
2170 $ctext tag conf m7 -fore "#808000"
2171 $ctext tag conf m8 -fore "#009000"
2172 $ctext tag conf m9 -fore "#ff0080"
2173 $ctext tag conf m10 -fore cyan
2174 $ctext tag conf m11 -fore "#b07070"
2175 $ctext tag conf m12 -fore "#70b0f0"
2176 $ctext tag conf m13 -fore "#70f0b0"
2177 $ctext tag conf m14 -fore "#f0b070"
2178 $ctext tag conf m15 -fore "#ff70b0"
Paul Mackerras712fcc02005-11-30 09:28:16 +11002179 $ctext tag conf mmax -fore darkgrey
Paul Mackerrasb77b0272006-02-07 09:13:52 +11002180 set mergemax 16
Paul Mackerras9c311b32007-10-04 22:27:13 +10002181 $ctext tag conf mresult -font textfontbold
2182 $ctext tag conf msep -font textfontbold
Paul Mackerras712fcc02005-11-30 09:28:16 +11002183 $ctext tag conf found -back yellow
Paul Mackerrase5c2d852005-05-11 23:44:54 +00002184
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002185 .pwbottom add .bleft
Mark Levedahl9ca72f42007-02-12 19:19:34 -05002186 .pwbottom paneconfigure .bleft -width $geometry(botwidth)
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002187
2188 # lower right
2189 frame .bright
2190 frame .bright.mode
Christian Stimmingd990ced2007-11-07 18:42:55 +01002191 radiobutton .bright.mode.patch -text [mc "Patch"] \
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10002192 -command reselectline -variable cmitmode -value "patch"
Christian Stimmingd990ced2007-11-07 18:42:55 +01002193 radiobutton .bright.mode.tree -text [mc "Tree"] \
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10002194 -command reselectline -variable cmitmode -value "tree"
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002195 grid .bright.mode.patch .bright.mode.tree -sticky ew
2196 pack .bright.mode -side top -fill x
2197 set cflist .bright.cfiles
Paul Mackerras9c311b32007-10-04 22:27:13 +10002198 set indent [font measure mainfont "nn"]
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002199 text $cflist \
Mark Levedahl60378c02007-05-20 12:12:48 -04002200 -selectbackground $selectbgcolor \
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10002201 -background $bgcolor -foreground $fgcolor \
Paul Mackerras9c311b32007-10-04 22:27:13 +10002202 -font mainfont \
Paul Mackerras7fcceed2006-04-27 19:21:49 +10002203 -tabs [list $indent [expr {2 * $indent}]] \
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002204 -yscrollcommand ".bright.sb set" \
Paul Mackerras7fcceed2006-04-27 19:21:49 +10002205 -cursor [. cget -cursor] \
2206 -spacing1 1 -spacing3 1
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10002207 lappend bglist $cflist
2208 lappend fglist $cflist
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002209 scrollbar .bright.sb -command "$cflist yview"
2210 pack .bright.sb -side right -fill y
Paul Mackerrasd2610d12005-05-11 00:45:38 +00002211 pack $cflist -side left -fill both -expand 1
Paul Mackerras89b11d32006-05-02 19:55:31 +10002212 $cflist tag configure highlight \
2213 -background [$cflist cget -selectbackground]
Paul Mackerras9c311b32007-10-04 22:27:13 +10002214 $cflist tag configure bold -font mainfontbold
Paul Mackerrasd2610d12005-05-11 00:45:38 +00002215
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002216 .pwbottom add .bright
2217 .ctop add .pwbottom
Paul Mackerras1db95b02005-05-09 04:08:39 +00002218
Paul Mackerrasb9bee112008-03-10 16:50:34 +11002219 # restore window width & height if known
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002220 if {[info exists geometry(main)]} {
Paul Mackerrasb9bee112008-03-10 16:50:34 +11002221 if {[scan $geometry(main) "%dx%d" w h] >= 2} {
2222 if {$w > [winfo screenwidth .]} {
2223 set w [winfo screenwidth .]
2224 }
2225 if {$h > [winfo screenheight .]} {
2226 set h [winfo screenheight .]
2227 }
2228 wm geometry . "${w}x$h"
2229 }
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002230 }
2231
Shawn O. Pearced23d98d2007-07-19 00:37:58 -04002232 if {[tk windowingsystem] eq {aqua}} {
2233 set M1B M1
2234 } else {
2235 set M1B Control
2236 }
2237
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002238 bind .pwbottom <Configure> {resizecdetpanes %W %w}
2239 pack .ctop -fill both -expand 1
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10002240 bindall <1> {selcanvline %W %x %y}
2241 #bindall <B1-Motion> {selcanvline %W %x %y}
Mark Levedahl314c3092007-08-07 21:40:35 -04002242 if {[tk windowingsystem] == "win32"} {
2243 bind . <MouseWheel> { windows_mousewheel_redirector %W %X %Y %D }
2244 bind $ctext <MouseWheel> { windows_mousewheel_redirector %W %X %Y %D ; break }
2245 } else {
2246 bindall <ButtonRelease-4> "allcanvs yview scroll -5 units"
2247 bindall <ButtonRelease-5> "allcanvs yview scroll 5 units"
Jonathan del Strother5dd57d52007-10-15 10:33:07 +01002248 if {[tk windowingsystem] eq "aqua"} {
2249 bindall <MouseWheel> {
2250 set delta [expr {- (%D)}]
2251 allcanvs yview scroll $delta units
2252 }
2253 }
Mark Levedahl314c3092007-08-07 21:40:35 -04002254 }
Paul Mackerrasbe0cd092006-03-31 09:55:11 +11002255 bindall <2> "canvscan mark %W %x %y"
2256 bindall <B2-Motion> "canvscan dragto %W %x %y"
Rutger Nijlunsing6e5f7202006-04-05 10:24:03 +10002257 bindkey <Home> selfirstline
2258 bindkey <End> sellastline
Paul Mackerras17386062005-05-18 22:51:00 +00002259 bind . <Key-Up> "selnextline -1"
2260 bind . <Key-Down> "selnextline 1"
Paul Mackerrascca5d942007-10-27 21:16:56 +10002261 bind . <Shift-Key-Up> "dofind -1 0"
2262 bind . <Shift-Key-Down> "dofind 1 0"
Rutger Nijlunsing6e5f7202006-04-05 10:24:03 +10002263 bindkey <Key-Right> "goforw"
2264 bindkey <Key-Left> "goback"
2265 bind . <Key-Prior> "selnextpage -1"
2266 bind . <Key-Next> "selnextpage 1"
Shawn O. Pearced23d98d2007-07-19 00:37:58 -04002267 bind . <$M1B-Home> "allcanvs yview moveto 0.0"
2268 bind . <$M1B-End> "allcanvs yview moveto 1.0"
2269 bind . <$M1B-Key-Up> "allcanvs yview scroll -1 units"
2270 bind . <$M1B-Key-Down> "allcanvs yview scroll 1 units"
2271 bind . <$M1B-Key-Prior> "allcanvs yview scroll -1 pages"
2272 bind . <$M1B-Key-Next> "allcanvs yview scroll 1 pages"
Paul Mackerrascfb45632005-05-31 12:14:42 +00002273 bindkey <Key-Delete> "$ctext yview scroll -1 pages"
2274 bindkey <Key-BackSpace> "$ctext yview scroll -1 pages"
2275 bindkey <Key-space> "$ctext yview scroll 1 pages"
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00002276 bindkey p "selnextline -1"
2277 bindkey n "selnextline 1"
Robert Suetterlin6e2dda32005-09-22 10:07:36 +10002278 bindkey z "goback"
2279 bindkey x "goforw"
2280 bindkey i "selnextline -1"
2281 bindkey k "selnextline 1"
2282 bindkey j "goback"
2283 bindkey l "goforw"
Paul Mackerrasf4c54b32008-05-10 13:15:36 +10002284 bindkey b prevfile
Paul Mackerrascfb45632005-05-31 12:14:42 +00002285 bindkey d "$ctext yview scroll 18 units"
2286 bindkey u "$ctext yview scroll -18 units"
Giuseppe Bilotta97bed032008-12-02 02:19:22 +01002287 bindkey / {focus $fstring}
Paul Mackerrascca5d942007-10-27 21:16:56 +10002288 bindkey <Key-Return> {dofind 1 1}
2289 bindkey ? {dofind -1 1}
Paul Mackerras39ad8572005-05-19 12:35:53 +00002290 bindkey f nextfile
Alexander Gavrilovcea07cf2008-11-09 13:00:45 +03002291 bind . <F5> updatecommits
2292 bind . <$M1B-F5> reloadcommits
2293 bind . <F2> showrefs
2294 bind . <Shift-F4> {newview 0}
2295 catch { bind . <Shift-Key-XF86_Switch_VT_4> {newview 0} }
2296 bind . <F4> edit_or_newview
Shawn O. Pearced23d98d2007-07-19 00:37:58 -04002297 bind . <$M1B-q> doquit
Paul Mackerrascca5d942007-10-27 21:16:56 +10002298 bind . <$M1B-f> {dofind 1 1}
2299 bind . <$M1B-g> {dofind 1 0}
Shawn O. Pearced23d98d2007-07-19 00:37:58 -04002300 bind . <$M1B-r> dosearchback
2301 bind . <$M1B-s> dosearch
2302 bind . <$M1B-equal> {incrfont 1}
Johannes Schindelin646f3a12008-01-11 12:39:33 +00002303 bind . <$M1B-plus> {incrfont 1}
Shawn O. Pearced23d98d2007-07-19 00:37:58 -04002304 bind . <$M1B-KP_Add> {incrfont 1}
2305 bind . <$M1B-minus> {incrfont -1}
2306 bind . <$M1B-KP_Subtract> {incrfont -1}
Mark Levedahlb6047c52007-02-08 22:22:24 -05002307 wm protocol . WM_DELETE_WINDOW doquit
Alexander Gavrilove2f90ee2008-07-12 16:09:28 +04002308 bind . <Destroy> {stop_backends}
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00002309 bind . <Button-1> "click %W"
Paul Mackerrascca5d942007-10-27 21:16:56 +10002310 bind $fstring <Key-Return> {dofind 1 1}
Paul Mackerras968ce452008-10-16 09:57:02 +11002311 bind $sha1entry <Key-Return> {gotocommit; break}
Paul Mackerrasee3dc722005-06-25 16:37:13 +10002312 bind $sha1entry <<PasteSelection>> clearsha1
Paul Mackerras7fcceed2006-04-27 19:21:49 +10002313 bind $cflist <1> {sel_flist %W %x %y; break}
2314 bind $cflist <B1-Motion> {sel_flist %W %x %y; break}
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10002315 bind $cflist <ButtonRelease-1> {treeclick %W %x %y}
Paul Mackerrasd277e892008-09-21 18:11:37 -05002316 global ctxbut
2317 bind $cflist $ctxbut {pop_flist_menu %W %X %Y %x %y}
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04002318 bind $ctext $ctxbut {pop_diff_menu %W %X %Y %x %y}
Paul Mackerrasea13cba2005-06-16 10:54:04 +00002319
2320 set maincursor [. cget -cursor]
2321 set textcursor [$ctext cget -cursor]
Paul Mackerras94a2eed2005-08-07 15:27:57 +10002322 set curtextcursor $textcursor
Paul Mackerras84ba7342005-06-17 00:12:26 +00002323
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10002324 set rowctxmenu .rowctxmenu
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11002325 makemenu $rowctxmenu {
Paul Mackerras79056032008-10-18 16:24:46 +11002326 {mc "Diff this -> selected" command {diffvssel 0}}
2327 {mc "Diff selected -> this" command {diffvssel 1}}
2328 {mc "Make patch" command mkpatch}
2329 {mc "Create tag" command mktag}
2330 {mc "Write commit to file" command writecommit}
2331 {mc "Create new branch" command mkbranch}
2332 {mc "Cherry-pick this commit" command cherrypick}
2333 {mc "Reset HEAD branch to here" command resethead}
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11002334 }
2335 $rowctxmenu configure -tearoff 0
Paul Mackerras10299152006-08-02 09:52:01 +10002336
Paul Mackerras219ea3a2006-09-07 10:21:39 +10002337 set fakerowmenu .fakerowmenu
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11002338 makemenu $fakerowmenu {
Paul Mackerras79056032008-10-18 16:24:46 +11002339 {mc "Diff this -> selected" command {diffvssel 0}}
2340 {mc "Diff selected -> this" command {diffvssel 1}}
2341 {mc "Make patch" command mkpatch}
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11002342 }
2343 $fakerowmenu configure -tearoff 0
Paul Mackerras219ea3a2006-09-07 10:21:39 +10002344
Paul Mackerras10299152006-08-02 09:52:01 +10002345 set headctxmenu .headctxmenu
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11002346 makemenu $headctxmenu {
Paul Mackerras79056032008-10-18 16:24:46 +11002347 {mc "Check out this branch" command cobranch}
2348 {mc "Remove this branch" command rmbranch}
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11002349 }
2350 $headctxmenu configure -tearoff 0
Paul Mackerras32447292007-07-27 22:30:15 +10002351
2352 global flist_menu
2353 set flist_menu .flistctxmenu
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11002354 makemenu $flist_menu {
Paul Mackerras79056032008-10-18 16:24:46 +11002355 {mc "Highlight this too" command {flist_hl 0}}
2356 {mc "Highlight this only" command {flist_hl 1}}
2357 {mc "External diff" command {external_diff}}
2358 {mc "Blame parent commit" command {external_blame 1}}
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11002359 }
2360 $flist_menu configure -tearoff 0
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04002361
2362 global diff_menu
2363 set diff_menu .diffctxmenu
2364 makemenu $diff_menu {
Paul Mackerras8a897742008-10-27 21:36:25 +11002365 {mc "Show origin of this line" command show_line_source}
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04002366 {mc "Run git gui blame on this line" command {external_blame_diff}}
2367 }
2368 $diff_menu configure -tearoff 0
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00002369}
2370
Mark Levedahl314c3092007-08-07 21:40:35 -04002371# Windows sends all mouse wheel events to the current focused window, not
2372# the one where the mouse hovers, so bind those events here and redirect
2373# to the correct window
2374proc windows_mousewheel_redirector {W X Y D} {
2375 global canv canv2 canv3
2376 set w [winfo containing -displayof $W $X $Y]
2377 if {$w ne ""} {
2378 set u [expr {$D < 0 ? 5 : -5}]
2379 if {$w == $canv || $w == $canv2 || $w == $canv3} {
2380 allcanvs yview scroll $u units
2381 } else {
2382 catch {
2383 $w yview scroll $u units
2384 }
2385 }
2386 }
2387}
2388
Paul Mackerras6df74032008-05-11 22:13:02 +10002389# Update row number label when selectedline changes
2390proc selectedline_change {n1 n2 op} {
2391 global selectedline rownumsel
2392
Paul Mackerras94b4a692008-05-20 20:51:06 +10002393 if {$selectedline eq {}} {
Paul Mackerras6df74032008-05-11 22:13:02 +10002394 set rownumsel {}
2395 } else {
2396 set rownumsel [expr {$selectedline + 1}]
2397 }
2398}
2399
Paul Mackerrasbe0cd092006-03-31 09:55:11 +11002400# mouse-2 makes all windows scan vertically, but only the one
2401# the cursor is in scans horizontally
2402proc canvscan {op w x y} {
2403 global canv canv2 canv3
2404 foreach c [list $canv $canv2 $canv3] {
2405 if {$c == $w} {
2406 $c scan $op $x $y
2407 } else {
2408 $c scan $op 0 $y
2409 }
2410 }
2411}
2412
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002413proc scrollcanv {cscroll f0 f1} {
2414 $cscroll set $f0 $f1
Paul Mackerras31c0eaa2007-12-30 22:41:14 +11002415 drawvisible
Paul Mackerras908c3582006-05-20 09:38:11 +10002416 flushhighlights
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002417}
2418
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00002419# when we make a key binding for the toplevel, make sure
2420# it doesn't get triggered when that key is pressed in the
2421# find string entry widget.
2422proc bindkey {ev script} {
Paul Mackerras887fe3c2005-05-21 07:35:37 +00002423 global entries
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00002424 bind . $ev $script
2425 set escript [bind Entry $ev]
2426 if {$escript == {}} {
2427 set escript [bind Entry <Key>]
2428 }
Paul Mackerras887fe3c2005-05-21 07:35:37 +00002429 foreach e $entries {
2430 bind $e $ev "$escript; break"
2431 }
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00002432}
2433
2434# set the focus back to the toplevel for any click outside
Paul Mackerras887fe3c2005-05-21 07:35:37 +00002435# the entry widgets
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00002436proc click {w} {
Mark Levedahlbd441de2007-08-07 21:40:34 -04002437 global ctext entries
2438 foreach e [concat $entries $ctext] {
Paul Mackerras887fe3c2005-05-21 07:35:37 +00002439 if {$w == $e} return
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00002440 }
Paul Mackerras887fe3c2005-05-21 07:35:37 +00002441 focus .
Paul Mackerras0fba86b2005-05-16 23:54:58 +00002442}
2443
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10002444# Adjust the progress bar for a change in requested extent or canvas size
2445proc adjustprogress {} {
2446 global progresscanv progressitem progresscoords
2447 global fprogitem fprogcoord lastprogupdate progupdatepending
Paul Mackerrasa137a902007-10-23 21:12:49 +10002448 global rprogitem rprogcoord
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10002449
2450 set w [expr {[winfo width $progresscanv] - 4}]
2451 set x0 [expr {$w * [lindex $progresscoords 0]}]
2452 set x1 [expr {$w * [lindex $progresscoords 1]}]
2453 set h [winfo height $progresscanv]
2454 $progresscanv coords $progressitem $x0 0 $x1 $h
2455 $progresscanv coords $fprogitem 0 0 [expr {$w * $fprogcoord}] $h
Paul Mackerrasa137a902007-10-23 21:12:49 +10002456 $progresscanv coords $rprogitem 0 0 [expr {$w * $rprogcoord}] $h
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10002457 set now [clock clicks -milliseconds]
2458 if {$now >= $lastprogupdate + 100} {
2459 set progupdatepending 0
2460 update
2461 } elseif {!$progupdatepending} {
2462 set progupdatepending 1
2463 after [expr {$lastprogupdate + 100 - $now}] doprogupdate
2464 }
2465}
2466
2467proc doprogupdate {} {
2468 global lastprogupdate progupdatepending
2469
2470 if {$progupdatepending} {
2471 set progupdatepending 0
2472 set lastprogupdate [clock clicks -milliseconds]
2473 update
2474 }
2475}
2476
Paul Mackerras0fba86b2005-05-16 23:54:58 +00002477proc savestuff {w} {
Paul Mackerras32f1b3e2007-09-28 21:27:39 +10002478 global canv canv2 canv3 mainfont textfont uifont tabstop
Paul Mackerras712fcc02005-11-30 09:28:16 +11002479 global stuffsaved findmergefiles maxgraphpct
Paul Mackerras219ea3a2006-09-07 10:21:39 +10002480 global maxwidth showneartags showlocalchanges
Yann Dirson2d480852008-02-21 21:23:31 +01002481 global viewname viewfiles viewargs viewargscmd viewperm nextviewnum
Paul Mackerras7a39a172007-10-23 10:15:11 +10002482 global cmitmode wrapcomment datetimeformat limitdiffs
Steffen Prohaska890fae72007-08-12 12:05:46 +02002483 global colors bgcolor fgcolor diffcolors diffcontext selectbgcolor
Paul Mackerrase3e901b2008-10-27 22:37:21 +11002484 global autoselect extdifftool perfile_attrs markbgcolor
Paul Mackerras4ef17532005-07-27 22:16:51 -05002485
Paul Mackerras0fba86b2005-05-16 23:54:58 +00002486 if {$stuffsaved} return
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00002487 if {![winfo viewable .]} return
Paul Mackerras0fba86b2005-05-16 23:54:58 +00002488 catch {
2489 set f [open "~/.gitk-new" w]
Paul Mackerrasf0654862005-07-18 14:29:03 -04002490 puts $f [list set mainfont $mainfont]
2491 puts $f [list set textfont $textfont]
Keith Packard4840be62006-04-04 00:19:45 -07002492 puts $f [list set uifont $uifont]
Mark Levedahl7e12f1a2007-05-20 11:45:50 -04002493 puts $f [list set tabstop $tabstop]
Paul Mackerrasf0654862005-07-18 14:29:03 -04002494 puts $f [list set findmergefiles $findmergefiles]
Paul Mackerras8d858d12005-08-05 09:52:16 +10002495 puts $f [list set maxgraphpct $maxgraphpct]
Paul Mackerras04c13d32005-08-19 10:22:24 +10002496 puts $f [list set maxwidth $maxwidth]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10002497 puts $f [list set cmitmode $cmitmode]
Sergey Vlasovf1b86292006-05-15 19:13:14 +04002498 puts $f [list set wrapcomment $wrapcomment]
Jeff King95293b52008-03-06 06:49:25 -05002499 puts $f [list set autoselect $autoselect]
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10002500 puts $f [list set showneartags $showneartags]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10002501 puts $f [list set showlocalchanges $showlocalchanges]
Arjen Laarhovene8b5f4b2007-08-14 22:02:04 +02002502 puts $f [list set datetimeformat $datetimeformat]
Paul Mackerras7a39a172007-10-23 10:15:11 +10002503 puts $f [list set limitdiffs $limitdiffs]
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10002504 puts $f [list set bgcolor $bgcolor]
2505 puts $f [list set fgcolor $fgcolor]
2506 puts $f [list set colors $colors]
2507 puts $f [list set diffcolors $diffcolors]
Paul Mackerrase3e901b2008-10-27 22:37:21 +11002508 puts $f [list set markbgcolor $markbgcolor]
Steffen Prohaska890fae72007-08-12 12:05:46 +02002509 puts $f [list set diffcontext $diffcontext]
Mark Levedahl60378c02007-05-20 12:12:48 -04002510 puts $f [list set selectbgcolor $selectbgcolor]
Thomas Arcila314f5de2008-03-24 12:55:36 +01002511 puts $f [list set extdifftool $extdifftool]
Paul Mackerras39ee47e2008-10-15 22:23:03 +11002512 puts $f [list set perfile_attrs $perfile_attrs]
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002513
Mark Levedahlb6047c52007-02-08 22:22:24 -05002514 puts $f "set geometry(main) [wm geometry .]"
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002515 puts $f "set geometry(topwidth) [winfo width .tf]"
2516 puts $f "set geometry(topheight) [winfo height .tf]"
Mark Levedahl9ca72f42007-02-12 19:19:34 -05002517 puts $f "set geometry(pwsash0) \"[.tf.histframe.pwclist sash coord 0]\""
2518 puts $f "set geometry(pwsash1) \"[.tf.histframe.pwclist sash coord 1]\""
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002519 puts $f "set geometry(botwidth) [winfo width .bleft]"
2520 puts $f "set geometry(botheight) [winfo height .bleft]"
2521
Paul Mackerrasa90a6d22006-04-25 17:12:46 +10002522 puts -nonewline $f "set permviews {"
2523 for {set v 0} {$v < $nextviewnum} {incr v} {
2524 if {$viewperm($v)} {
Yann Dirson2d480852008-02-21 21:23:31 +01002525 puts $f "{[list $viewname($v) $viewfiles($v) $viewargs($v) $viewargscmd($v)]}"
Paul Mackerrasa90a6d22006-04-25 17:12:46 +10002526 }
2527 }
2528 puts $f "}"
Paul Mackerras0fba86b2005-05-16 23:54:58 +00002529 close $f
2530 file rename -force "~/.gitk-new" "~/.gitk"
2531 }
2532 set stuffsaved 1
Paul Mackerras1db95b02005-05-09 04:08:39 +00002533}
2534
Paul Mackerras43bddeb2005-05-15 23:19:18 +00002535proc resizeclistpanes {win w} {
2536 global oldwidth
Paul Mackerras418c4c72006-02-07 09:10:18 +11002537 if {[info exists oldwidth($win)]} {
Paul Mackerras43bddeb2005-05-15 23:19:18 +00002538 set s0 [$win sash coord 0]
2539 set s1 [$win sash coord 1]
2540 if {$w < 60} {
2541 set sash0 [expr {int($w/2 - 2)}]
2542 set sash1 [expr {int($w*5/6 - 2)}]
2543 } else {
2544 set factor [expr {1.0 * $w / $oldwidth($win)}]
2545 set sash0 [expr {int($factor * [lindex $s0 0])}]
2546 set sash1 [expr {int($factor * [lindex $s1 0])}]
2547 if {$sash0 < 30} {
2548 set sash0 30
2549 }
2550 if {$sash1 < $sash0 + 20} {
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08002551 set sash1 [expr {$sash0 + 20}]
Paul Mackerras43bddeb2005-05-15 23:19:18 +00002552 }
2553 if {$sash1 > $w - 10} {
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08002554 set sash1 [expr {$w - 10}]
Paul Mackerras43bddeb2005-05-15 23:19:18 +00002555 if {$sash0 > $sash1 - 20} {
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08002556 set sash0 [expr {$sash1 - 20}]
Paul Mackerras43bddeb2005-05-15 23:19:18 +00002557 }
2558 }
2559 }
2560 $win sash place 0 $sash0 [lindex $s0 1]
2561 $win sash place 1 $sash1 [lindex $s1 1]
2562 }
2563 set oldwidth($win) $w
2564}
2565
2566proc resizecdetpanes {win w} {
2567 global oldwidth
Paul Mackerras418c4c72006-02-07 09:10:18 +11002568 if {[info exists oldwidth($win)]} {
Paul Mackerras43bddeb2005-05-15 23:19:18 +00002569 set s0 [$win sash coord 0]
2570 if {$w < 60} {
2571 set sash0 [expr {int($w*3/4 - 2)}]
2572 } else {
2573 set factor [expr {1.0 * $w / $oldwidth($win)}]
2574 set sash0 [expr {int($factor * [lindex $s0 0])}]
2575 if {$sash0 < 45} {
2576 set sash0 45
2577 }
2578 if {$sash0 > $w - 15} {
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08002579 set sash0 [expr {$w - 15}]
Paul Mackerras43bddeb2005-05-15 23:19:18 +00002580 }
2581 }
2582 $win sash place 0 $sash0 [lindex $s0 1]
2583 }
2584 set oldwidth($win) $w
2585}
2586
Paul Mackerrasb5721c72005-05-10 12:08:22 +00002587proc allcanvs args {
2588 global canv canv2 canv3
2589 eval $canv $args
2590 eval $canv2 $args
2591 eval $canv3 $args
2592}
2593
2594proc bindall {event action} {
2595 global canv canv2 canv3
2596 bind $canv $event $action
2597 bind $canv2 $event $action
2598 bind $canv3 $event $action
2599}
2600
Paul Mackerras9a40c502005-05-12 23:46:16 +00002601proc about {} {
Eygene Ryabinkind59c4b62007-03-27 14:36:12 +04002602 global uifont
Paul Mackerras9a40c502005-05-12 23:46:16 +00002603 set w .about
2604 if {[winfo exists $w]} {
2605 raise $w
2606 return
2607 }
2608 toplevel $w
Christian Stimmingd990ced2007-11-07 18:42:55 +01002609 wm title $w [mc "About gitk"]
Alexander Gavrilove7d64002008-11-11 23:55:42 +03002610 make_transient $w .
Christian Stimmingd990ced2007-11-07 18:42:55 +01002611 message $w.m -text [mc "
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002612Gitk - a commit viewer for git
Paul Mackerras9a40c502005-05-12 23:46:16 +00002613
Paul Mackerrasee66e082008-05-09 10:14:07 +10002614Copyright © 2005-2008 Paul Mackerras
Paul Mackerras9a40c502005-05-12 23:46:16 +00002615
Christian Stimmingd990ced2007-11-07 18:42:55 +01002616Use and redistribute under the terms of the GNU General Public License"] \
Eygene Ryabinkin3a950e92007-03-27 14:36:59 +04002617 -justify center -aspect 400 -border 2 -bg white -relief groove
2618 pack $w.m -side top -fill x -padx 2 -pady 2
Christian Stimmingd990ced2007-11-07 18:42:55 +01002619 button $w.ok -text [mc "Close"] -command "destroy $w" -default active
Paul Mackerras9a40c502005-05-12 23:46:16 +00002620 pack $w.ok -side bottom
Eygene Ryabinkin3a950e92007-03-27 14:36:59 +04002621 bind $w <Visibility> "focus $w.ok"
2622 bind $w <Key-Escape> "destroy $w"
2623 bind $w <Key-Return> "destroy $w"
Paul Mackerras9a40c502005-05-12 23:46:16 +00002624}
2625
Paul Mackerras4e95e1f2006-04-05 09:39:51 +10002626proc keys {} {
2627 set w .keys
2628 if {[winfo exists $w]} {
2629 raise $w
2630 return
2631 }
Shawn O. Pearced23d98d2007-07-19 00:37:58 -04002632 if {[tk windowingsystem] eq {aqua}} {
2633 set M1T Cmd
2634 } else {
2635 set M1T Ctrl
2636 }
Paul Mackerras4e95e1f2006-04-05 09:39:51 +10002637 toplevel $w
Christian Stimmingd990ced2007-11-07 18:42:55 +01002638 wm title $w [mc "Gitk key bindings"]
Alexander Gavrilove7d64002008-11-11 23:55:42 +03002639 make_transient $w .
Michele Ballabio3d2c9982008-01-15 23:31:49 +01002640 message $w.m -text "
2641[mc "Gitk key bindings:"]
Paul Mackerras4e95e1f2006-04-05 09:39:51 +10002642
Michele Ballabio3d2c9982008-01-15 23:31:49 +01002643[mc "<%s-Q> Quit" $M1T]
2644[mc "<Home> Move to first commit"]
2645[mc "<End> Move to last commit"]
2646[mc "<Up>, p, i Move up one commit"]
2647[mc "<Down>, n, k Move down one commit"]
2648[mc "<Left>, z, j Go back in history list"]
2649[mc "<Right>, x, l Go forward in history list"]
2650[mc "<PageUp> Move up one page in commit list"]
2651[mc "<PageDown> Move down one page in commit list"]
2652[mc "<%s-Home> Scroll to top of commit list" $M1T]
2653[mc "<%s-End> Scroll to bottom of commit list" $M1T]
2654[mc "<%s-Up> Scroll commit list up one line" $M1T]
2655[mc "<%s-Down> Scroll commit list down one line" $M1T]
2656[mc "<%s-PageUp> Scroll commit list up one page" $M1T]
2657[mc "<%s-PageDown> Scroll commit list down one page" $M1T]
2658[mc "<Shift-Up> Find backwards (upwards, later commits)"]
2659[mc "<Shift-Down> Find forwards (downwards, earlier commits)"]
2660[mc "<Delete>, b Scroll diff view up one page"]
2661[mc "<Backspace> Scroll diff view up one page"]
2662[mc "<Space> Scroll diff view down one page"]
2663[mc "u Scroll diff view up 18 lines"]
2664[mc "d Scroll diff view down 18 lines"]
2665[mc "<%s-F> Find" $M1T]
2666[mc "<%s-G> Move to next find hit" $M1T]
2667[mc "<Return> Move to next find hit"]
Giuseppe Bilotta97bed032008-12-02 02:19:22 +01002668[mc "/ Focus the search box"]
Michele Ballabio3d2c9982008-01-15 23:31:49 +01002669[mc "? Move to previous find hit"]
2670[mc "f Scroll diff view to next file"]
2671[mc "<%s-S> Search for next hit in diff view" $M1T]
2672[mc "<%s-R> Search for previous hit in diff view" $M1T]
2673[mc "<%s-KP+> Increase font size" $M1T]
2674[mc "<%s-plus> Increase font size" $M1T]
2675[mc "<%s-KP-> Decrease font size" $M1T]
2676[mc "<%s-minus> Decrease font size" $M1T]
2677[mc "<F5> Update"]
2678" \
Eygene Ryabinkin3a950e92007-03-27 14:36:59 +04002679 -justify left -bg white -border 2 -relief groove
2680 pack $w.m -side top -fill both -padx 2 -pady 2
Christian Stimmingd990ced2007-11-07 18:42:55 +01002681 button $w.ok -text [mc "Close"] -command "destroy $w" -default active
Alexander Gavrilov76f15942008-11-02 21:59:44 +03002682 bind $w <Key-Escape> [list destroy $w]
Paul Mackerras4e95e1f2006-04-05 09:39:51 +10002683 pack $w.ok -side bottom
Eygene Ryabinkin3a950e92007-03-27 14:36:59 +04002684 bind $w <Visibility> "focus $w.ok"
2685 bind $w <Key-Escape> "destroy $w"
2686 bind $w <Key-Return> "destroy $w"
Paul Mackerras4e95e1f2006-04-05 09:39:51 +10002687}
2688
Paul Mackerras7fcceed2006-04-27 19:21:49 +10002689# Procedures for manipulating the file list window at the
2690# bottom right of the overall window.
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10002691
2692proc treeview {w l openlevs} {
2693 global treecontents treediropen treeheight treeparent treeindex
2694
2695 set ix 0
2696 set treeindex() 0
2697 set lev 0
2698 set prefix {}
2699 set prefixend -1
2700 set prefendstack {}
2701 set htstack {}
2702 set ht 0
2703 set treecontents() {}
2704 $w conf -state normal
2705 foreach f $l {
2706 while {[string range $f 0 $prefixend] ne $prefix} {
2707 if {$lev <= $openlevs} {
2708 $w mark set e:$treeindex($prefix) "end -1c"
2709 $w mark gravity e:$treeindex($prefix) left
2710 }
2711 set treeheight($prefix) $ht
2712 incr ht [lindex $htstack end]
2713 set htstack [lreplace $htstack end end]
2714 set prefixend [lindex $prefendstack end]
2715 set prefendstack [lreplace $prefendstack end end]
2716 set prefix [string range $prefix 0 $prefixend]
2717 incr lev -1
2718 }
2719 set tail [string range $f [expr {$prefixend+1}] end]
2720 while {[set slash [string first "/" $tail]] >= 0} {
2721 lappend htstack $ht
2722 set ht 0
2723 lappend prefendstack $prefixend
2724 incr prefixend [expr {$slash + 1}]
2725 set d [string range $tail 0 $slash]
2726 lappend treecontents($prefix) $d
2727 set oldprefix $prefix
2728 append prefix $d
2729 set treecontents($prefix) {}
2730 set treeindex($prefix) [incr ix]
2731 set treeparent($prefix) $oldprefix
2732 set tail [string range $tail [expr {$slash+1}] end]
2733 if {$lev <= $openlevs} {
2734 set ht 1
2735 set treediropen($prefix) [expr {$lev < $openlevs}]
2736 set bm [expr {$lev == $openlevs? "tri-rt": "tri-dn"}]
2737 $w mark set d:$ix "end -1c"
2738 $w mark gravity d:$ix left
2739 set str "\n"
2740 for {set i 0} {$i < $lev} {incr i} {append str "\t"}
2741 $w insert end $str
2742 $w image create end -align center -image $bm -padx 1 \
2743 -name a:$ix
Paul Mackerras45a9d502006-05-20 22:56:27 +10002744 $w insert end $d [highlight_tag $prefix]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10002745 $w mark set s:$ix "end -1c"
2746 $w mark gravity s:$ix left
2747 }
2748 incr lev
2749 }
2750 if {$tail ne {}} {
2751 if {$lev <= $openlevs} {
2752 incr ht
2753 set str "\n"
2754 for {set i 0} {$i < $lev} {incr i} {append str "\t"}
2755 $w insert end $str
Paul Mackerras45a9d502006-05-20 22:56:27 +10002756 $w insert end $tail [highlight_tag $f]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10002757 }
2758 lappend treecontents($prefix) $tail
2759 }
2760 }
2761 while {$htstack ne {}} {
2762 set treeheight($prefix) $ht
2763 incr ht [lindex $htstack end]
2764 set htstack [lreplace $htstack end end]
Brian Downing096e96b2007-07-05 06:33:02 -05002765 set prefixend [lindex $prefendstack end]
2766 set prefendstack [lreplace $prefendstack end end]
2767 set prefix [string range $prefix 0 $prefixend]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10002768 }
2769 $w conf -state disabled
2770}
2771
2772proc linetoelt {l} {
2773 global treeheight treecontents
2774
2775 set y 2
2776 set prefix {}
2777 while {1} {
2778 foreach e $treecontents($prefix) {
2779 if {$y == $l} {
2780 return "$prefix$e"
2781 }
2782 set n 1
2783 if {[string index $e end] eq "/"} {
2784 set n $treeheight($prefix$e)
2785 if {$y + $n > $l} {
2786 append prefix $e
2787 incr y
2788 break
2789 }
2790 }
2791 incr y $n
2792 }
2793 }
2794}
2795
Paul Mackerras45a9d502006-05-20 22:56:27 +10002796proc highlight_tree {y prefix} {
2797 global treeheight treecontents cflist
2798
2799 foreach e $treecontents($prefix) {
2800 set path $prefix$e
2801 if {[highlight_tag $path] ne {}} {
2802 $cflist tag add bold $y.0 "$y.0 lineend"
2803 }
2804 incr y
2805 if {[string index $e end] eq "/" && $treeheight($path) > 1} {
2806 set y [highlight_tree $y $path]
2807 }
2808 }
2809 return $y
2810}
2811
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10002812proc treeclosedir {w dir} {
2813 global treediropen treeheight treeparent treeindex
2814
2815 set ix $treeindex($dir)
2816 $w conf -state normal
2817 $w delete s:$ix e:$ix
2818 set treediropen($dir) 0
2819 $w image configure a:$ix -image tri-rt
2820 $w conf -state disabled
2821 set n [expr {1 - $treeheight($dir)}]
2822 while {$dir ne {}} {
2823 incr treeheight($dir) $n
2824 set dir $treeparent($dir)
2825 }
2826}
2827
2828proc treeopendir {w dir} {
2829 global treediropen treeheight treeparent treecontents treeindex
2830
2831 set ix $treeindex($dir)
2832 $w conf -state normal
2833 $w image configure a:$ix -image tri-dn
2834 $w mark set e:$ix s:$ix
2835 $w mark gravity e:$ix right
2836 set lev 0
2837 set str "\n"
2838 set n [llength $treecontents($dir)]
2839 for {set x $dir} {$x ne {}} {set x $treeparent($x)} {
2840 incr lev
2841 append str "\t"
2842 incr treeheight($x) $n
2843 }
2844 foreach e $treecontents($dir) {
Paul Mackerras45a9d502006-05-20 22:56:27 +10002845 set de $dir$e
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10002846 if {[string index $e end] eq "/"} {
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10002847 set iy $treeindex($de)
2848 $w mark set d:$iy e:$ix
2849 $w mark gravity d:$iy left
2850 $w insert e:$ix $str
2851 set treediropen($de) 0
2852 $w image create e:$ix -align center -image tri-rt -padx 1 \
2853 -name a:$iy
Paul Mackerras45a9d502006-05-20 22:56:27 +10002854 $w insert e:$ix $e [highlight_tag $de]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10002855 $w mark set s:$iy e:$ix
2856 $w mark gravity s:$iy left
2857 set treeheight($de) 1
2858 } else {
2859 $w insert e:$ix $str
Paul Mackerras45a9d502006-05-20 22:56:27 +10002860 $w insert e:$ix $e [highlight_tag $de]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10002861 }
2862 }
Alexander Gavrilovb8a640e2008-09-08 11:28:16 +04002863 $w mark gravity e:$ix right
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10002864 $w conf -state disabled
2865 set treediropen($dir) 1
2866 set top [lindex [split [$w index @0,0] .] 0]
2867 set ht [$w cget -height]
2868 set l [lindex [split [$w index s:$ix] .] 0]
2869 if {$l < $top} {
2870 $w yview $l.0
2871 } elseif {$l + $n + 1 > $top + $ht} {
2872 set top [expr {$l + $n + 2 - $ht}]
2873 if {$l < $top} {
2874 set top $l
2875 }
2876 $w yview $top.0
2877 }
2878}
2879
2880proc treeclick {w x y} {
2881 global treediropen cmitmode ctext cflist cflist_top
2882
2883 if {$cmitmode ne "tree"} return
2884 if {![info exists cflist_top]} return
2885 set l [lindex [split [$w index "@$x,$y"] "."] 0]
2886 $cflist tag remove highlight $cflist_top.0 "$cflist_top.0 lineend"
2887 $cflist tag add highlight $l.0 "$l.0 lineend"
2888 set cflist_top $l
2889 if {$l == 1} {
2890 $ctext yview 1.0
2891 return
2892 }
2893 set e [linetoelt $l]
2894 if {[string index $e end] ne "/"} {
2895 showfile $e
2896 } elseif {$treediropen($e)} {
2897 treeclosedir $w $e
2898 } else {
2899 treeopendir $w $e
2900 }
2901}
2902
2903proc setfilelist {id} {
Paul Mackerras8a897742008-10-27 21:36:25 +11002904 global treefilelist cflist jump_to_here
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10002905
2906 treeview $cflist $treefilelist($id) 0
Paul Mackerras8a897742008-10-27 21:36:25 +11002907 if {$jump_to_here ne {}} {
2908 set f [lindex $jump_to_here 0]
2909 if {[lsearch -exact $treefilelist($id) $f] >= 0} {
2910 showfile $f
2911 }
2912 }
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10002913}
2914
2915image create bitmap tri-rt -background black -foreground blue -data {
2916 #define tri-rt_width 13
2917 #define tri-rt_height 13
2918 static unsigned char tri-rt_bits[] = {
2919 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x30, 0x00, 0x70, 0x00, 0xf0, 0x00,
2920 0xf0, 0x01, 0xf0, 0x00, 0x70, 0x00, 0x30, 0x00, 0x10, 0x00, 0x00, 0x00,
2921 0x00, 0x00};
2922} -maskdata {
2923 #define tri-rt-mask_width 13
2924 #define tri-rt-mask_height 13
2925 static unsigned char tri-rt-mask_bits[] = {
2926 0x08, 0x00, 0x18, 0x00, 0x38, 0x00, 0x78, 0x00, 0xf8, 0x00, 0xf8, 0x01,
2927 0xf8, 0x03, 0xf8, 0x01, 0xf8, 0x00, 0x78, 0x00, 0x38, 0x00, 0x18, 0x00,
2928 0x08, 0x00};
2929}
2930image create bitmap tri-dn -background black -foreground blue -data {
2931 #define tri-dn_width 13
2932 #define tri-dn_height 13
2933 static unsigned char tri-dn_bits[] = {
2934 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x07, 0xf8, 0x03,
2935 0xf0, 0x01, 0xe0, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2936 0x00, 0x00};
2937} -maskdata {
2938 #define tri-dn-mask_width 13
2939 #define tri-dn-mask_height 13
2940 static unsigned char tri-dn-mask_bits[] = {
2941 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x1f, 0xfe, 0x0f, 0xfc, 0x07,
2942 0xf8, 0x03, 0xf0, 0x01, 0xe0, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00,
2943 0x00, 0x00};
2944}
2945
Paul Mackerras887c9962007-08-20 19:36:20 +10002946image create bitmap reficon-T -background black -foreground yellow -data {
2947 #define tagicon_width 13
2948 #define tagicon_height 9
2949 static unsigned char tagicon_bits[] = {
2950 0x00, 0x00, 0x00, 0x00, 0xf0, 0x07, 0xf8, 0x07,
2951 0xfc, 0x07, 0xf8, 0x07, 0xf0, 0x07, 0x00, 0x00, 0x00, 0x00};
2952} -maskdata {
2953 #define tagicon-mask_width 13
2954 #define tagicon-mask_height 9
2955 static unsigned char tagicon-mask_bits[] = {
2956 0x00, 0x00, 0xf0, 0x0f, 0xf8, 0x0f, 0xfc, 0x0f,
2957 0xfe, 0x0f, 0xfc, 0x0f, 0xf8, 0x0f, 0xf0, 0x0f, 0x00, 0x00};
2958}
2959set rectdata {
2960 #define headicon_width 13
2961 #define headicon_height 9
2962 static unsigned char headicon_bits[] = {
2963 0x00, 0x00, 0x00, 0x00, 0xf8, 0x07, 0xf8, 0x07,
2964 0xf8, 0x07, 0xf8, 0x07, 0xf8, 0x07, 0x00, 0x00, 0x00, 0x00};
2965}
2966set rectmask {
2967 #define headicon-mask_width 13
2968 #define headicon-mask_height 9
2969 static unsigned char headicon-mask_bits[] = {
2970 0x00, 0x00, 0xfc, 0x0f, 0xfc, 0x0f, 0xfc, 0x0f,
2971 0xfc, 0x0f, 0xfc, 0x0f, 0xfc, 0x0f, 0xfc, 0x0f, 0x00, 0x00};
2972}
2973image create bitmap reficon-H -background black -foreground green \
2974 -data $rectdata -maskdata $rectmask
2975image create bitmap reficon-o -background black -foreground "#ddddff" \
2976 -data $rectdata -maskdata $rectmask
2977
Paul Mackerras7fcceed2006-04-27 19:21:49 +10002978proc init_flist {first} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11002979 global cflist cflist_top difffilestart
Paul Mackerras7fcceed2006-04-27 19:21:49 +10002980
2981 $cflist conf -state normal
2982 $cflist delete 0.0 end
2983 if {$first ne {}} {
2984 $cflist insert end $first
2985 set cflist_top 1
Paul Mackerras7fcceed2006-04-27 19:21:49 +10002986 $cflist tag add highlight 1.0 "1.0 lineend"
2987 } else {
2988 catch {unset cflist_top}
2989 }
2990 $cflist conf -state disabled
2991 set difffilestart {}
2992}
2993
Paul Mackerras63b79192006-05-20 21:31:52 +10002994proc highlight_tag {f} {
2995 global highlight_paths
2996
2997 foreach p $highlight_paths {
2998 if {[string match $p $f]} {
2999 return "bold"
3000 }
3001 }
3002 return {}
3003}
3004
3005proc highlight_filelist {} {
Paul Mackerras45a9d502006-05-20 22:56:27 +10003006 global cmitmode cflist
Paul Mackerras63b79192006-05-20 21:31:52 +10003007
Paul Mackerras45a9d502006-05-20 22:56:27 +10003008 $cflist conf -state normal
3009 if {$cmitmode ne "tree"} {
Paul Mackerras63b79192006-05-20 21:31:52 +10003010 set end [lindex [split [$cflist index end] .] 0]
3011 for {set l 2} {$l < $end} {incr l} {
3012 set line [$cflist get $l.0 "$l.0 lineend"]
3013 if {[highlight_tag $line] ne {}} {
3014 $cflist tag add bold $l.0 "$l.0 lineend"
3015 }
3016 }
Paul Mackerras45a9d502006-05-20 22:56:27 +10003017 } else {
3018 highlight_tree 2 {}
Paul Mackerras63b79192006-05-20 21:31:52 +10003019 }
Paul Mackerras45a9d502006-05-20 22:56:27 +10003020 $cflist conf -state disabled
Paul Mackerras63b79192006-05-20 21:31:52 +10003021}
3022
3023proc unhighlight_filelist {} {
Paul Mackerras45a9d502006-05-20 22:56:27 +10003024 global cflist
Paul Mackerras63b79192006-05-20 21:31:52 +10003025
Paul Mackerras45a9d502006-05-20 22:56:27 +10003026 $cflist conf -state normal
3027 $cflist tag remove bold 1.0 end
3028 $cflist conf -state disabled
Paul Mackerras63b79192006-05-20 21:31:52 +10003029}
3030
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10003031proc add_flist {fl} {
Paul Mackerras45a9d502006-05-20 22:56:27 +10003032 global cflist
Paul Mackerras7fcceed2006-04-27 19:21:49 +10003033
Paul Mackerras45a9d502006-05-20 22:56:27 +10003034 $cflist conf -state normal
3035 foreach f $fl {
3036 $cflist insert end "\n"
3037 $cflist insert end $f [highlight_tag $f]
Paul Mackerras7fcceed2006-04-27 19:21:49 +10003038 }
Paul Mackerras45a9d502006-05-20 22:56:27 +10003039 $cflist conf -state disabled
Paul Mackerras7fcceed2006-04-27 19:21:49 +10003040}
3041
3042proc sel_flist {w x y} {
Paul Mackerras45a9d502006-05-20 22:56:27 +10003043 global ctext difffilestart cflist cflist_top cmitmode
Paul Mackerras7fcceed2006-04-27 19:21:49 +10003044
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10003045 if {$cmitmode eq "tree"} return
Paul Mackerras7fcceed2006-04-27 19:21:49 +10003046 if {![info exists cflist_top]} return
3047 set l [lindex [split [$w index "@$x,$y"] "."] 0]
Paul Mackerras89b11d32006-05-02 19:55:31 +10003048 $cflist tag remove highlight $cflist_top.0 "$cflist_top.0 lineend"
3049 $cflist tag add highlight $l.0 "$l.0 lineend"
3050 set cflist_top $l
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10003051 if {$l == 1} {
3052 $ctext yview 1.0
3053 } else {
3054 catch {$ctext yview [lindex $difffilestart [expr {$l - 2}]]}
Paul Mackerras7fcceed2006-04-27 19:21:49 +10003055 }
Paul Mackerras7fcceed2006-04-27 19:21:49 +10003056}
3057
Paul Mackerras32447292007-07-27 22:30:15 +10003058proc pop_flist_menu {w X Y x y} {
3059 global ctext cflist cmitmode flist_menu flist_menu_file
3060 global treediffs diffids
3061
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10003062 stopfinding
Paul Mackerras32447292007-07-27 22:30:15 +10003063 set l [lindex [split [$w index "@$x,$y"] "."] 0]
3064 if {$l <= 1} return
3065 if {$cmitmode eq "tree"} {
3066 set e [linetoelt $l]
3067 if {[string index $e end] eq "/"} return
3068 } else {
3069 set e [lindex $treediffs($diffids) [expr {$l-2}]]
3070 }
3071 set flist_menu_file $e
Thomas Arcila314f5de2008-03-24 12:55:36 +01003072 set xdiffstate "normal"
3073 if {$cmitmode eq "tree"} {
3074 set xdiffstate "disabled"
3075 }
3076 # Disable "External diff" item in tree mode
3077 $flist_menu entryconf 2 -state $xdiffstate
Paul Mackerras32447292007-07-27 22:30:15 +10003078 tk_popup $flist_menu $X $Y
3079}
3080
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003081proc find_ctext_fileinfo {line} {
3082 global ctext_file_names ctext_file_lines
3083
3084 set ok [bsearch $ctext_file_lines $line]
3085 set tline [lindex $ctext_file_lines $ok]
3086
3087 if {$ok >= [llength $ctext_file_lines] || $line < $tline} {
3088 return {}
3089 } else {
3090 return [list [lindex $ctext_file_names $ok] $tline]
3091 }
3092}
3093
3094proc pop_diff_menu {w X Y x y} {
3095 global ctext diff_menu flist_menu_file
3096 global diff_menu_txtpos diff_menu_line
3097 global diff_menu_filebase
3098
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003099 set diff_menu_txtpos [split [$w index "@$x,$y"] "."]
3100 set diff_menu_line [lindex $diff_menu_txtpos 0]
Paul Mackerras190ec522008-10-27 21:13:37 +11003101 # don't pop up the menu on hunk-separator or file-separator lines
3102 if {[lsearch -glob [$ctext tag names $diff_menu_line.0] "*sep"] >= 0} {
3103 return
3104 }
3105 stopfinding
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003106 set f [find_ctext_fileinfo $diff_menu_line]
3107 if {$f eq {}} return
3108 set flist_menu_file [lindex $f 0]
3109 set diff_menu_filebase [lindex $f 1]
3110 tk_popup $diff_menu $X $Y
3111}
3112
Paul Mackerras32447292007-07-27 22:30:15 +10003113proc flist_hl {only} {
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10003114 global flist_menu_file findstring gdttype
Paul Mackerras32447292007-07-27 22:30:15 +10003115
3116 set x [shellquote $flist_menu_file]
Christian Stimmingb007ee22007-11-07 18:44:35 +01003117 if {$only || $findstring eq {} || $gdttype ne [mc "touching paths:"]} {
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10003118 set findstring $x
Paul Mackerras32447292007-07-27 22:30:15 +10003119 } else {
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10003120 append findstring " " $x
Paul Mackerras32447292007-07-27 22:30:15 +10003121 }
Christian Stimmingb007ee22007-11-07 18:44:35 +01003122 set gdttype [mc "touching paths:"]
Paul Mackerras32447292007-07-27 22:30:15 +10003123}
3124
Thomas Arcila314f5de2008-03-24 12:55:36 +01003125proc save_file_from_commit {filename output what} {
3126 global nullfile
3127
3128 if {[catch {exec git show $filename -- > $output} err]} {
3129 if {[string match "fatal: bad revision *" $err]} {
3130 return $nullfile
3131 }
Christian Stimming3945d2c2008-09-12 11:39:43 +02003132 error_popup "[mc "Error getting \"%s\" from %s:" $filename $what] $err"
Thomas Arcila314f5de2008-03-24 12:55:36 +01003133 return {}
3134 }
3135 return $output
3136}
3137
3138proc external_diff_get_one_file {diffid filename diffdir} {
3139 global nullid nullid2 nullfile
3140 global gitdir
3141
3142 if {$diffid == $nullid} {
3143 set difffile [file join [file dirname $gitdir] $filename]
3144 if {[file exists $difffile]} {
3145 return $difffile
3146 }
3147 return $nullfile
3148 }
3149 if {$diffid == $nullid2} {
3150 set difffile [file join $diffdir "\[index\] [file tail $filename]"]
3151 return [save_file_from_commit :$filename $difffile index]
3152 }
3153 set difffile [file join $diffdir "\[$diffid\] [file tail $filename]"]
3154 return [save_file_from_commit $diffid:$filename $difffile \
3155 "revision $diffid"]
3156}
3157
3158proc external_diff {} {
3159 global gitktmpdir nullid nullid2
3160 global flist_menu_file
3161 global diffids
3162 global diffnum
3163 global gitdir extdifftool
3164
3165 if {[llength $diffids] == 1} {
3166 # no reference commit given
3167 set diffidto [lindex $diffids 0]
3168 if {$diffidto eq $nullid} {
3169 # diffing working copy with index
3170 set diffidfrom $nullid2
3171 } elseif {$diffidto eq $nullid2} {
3172 # diffing index with HEAD
3173 set diffidfrom "HEAD"
3174 } else {
3175 # use first parent commit
3176 global parentlist selectedline
3177 set diffidfrom [lindex $parentlist $selectedline 0]
3178 }
3179 } else {
3180 set diffidfrom [lindex $diffids 0]
3181 set diffidto [lindex $diffids 1]
3182 }
3183
3184 # make sure that several diffs wont collide
3185 if {![info exists gitktmpdir]} {
3186 set gitktmpdir [file join [file dirname $gitdir] \
3187 [format ".gitk-tmp.%s" [pid]]]
3188 if {[catch {file mkdir $gitktmpdir} err]} {
Christian Stimming3945d2c2008-09-12 11:39:43 +02003189 error_popup "[mc "Error creating temporary directory %s:" $gitktmpdir] $err"
Thomas Arcila314f5de2008-03-24 12:55:36 +01003190 unset gitktmpdir
3191 return
3192 }
3193 set diffnum 0
3194 }
3195 incr diffnum
3196 set diffdir [file join $gitktmpdir $diffnum]
3197 if {[catch {file mkdir $diffdir} err]} {
Christian Stimming3945d2c2008-09-12 11:39:43 +02003198 error_popup "[mc "Error creating temporary directory %s:" $diffdir] $err"
Thomas Arcila314f5de2008-03-24 12:55:36 +01003199 return
3200 }
3201
3202 # gather files to diff
3203 set difffromfile [external_diff_get_one_file $diffidfrom $flist_menu_file $diffdir]
3204 set difftofile [external_diff_get_one_file $diffidto $flist_menu_file $diffdir]
3205
3206 if {$difffromfile ne {} && $difftofile ne {}} {
3207 set cmd [concat | [shellsplit $extdifftool] \
3208 [list $difffromfile $difftofile]]
3209 if {[catch {set fl [open $cmd r]} err]} {
3210 file delete -force $diffdir
Christian Stimming3945d2c2008-09-12 11:39:43 +02003211 error_popup "$extdifftool: [mc "command failed:"] $err"
Thomas Arcila314f5de2008-03-24 12:55:36 +01003212 } else {
3213 fconfigure $fl -blocking 0
3214 filerun $fl [list delete_at_eof $fl $diffdir]
3215 }
3216 }
3217}
3218
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003219proc find_hunk_blamespec {base line} {
3220 global ctext
3221
3222 # Find and parse the hunk header
3223 set s_lix [$ctext search -backwards -regexp ^@@ "$line.0 lineend" $base.0]
3224 if {$s_lix eq {}} return
3225
3226 set s_line [$ctext get $s_lix "$s_lix + 1 lines"]
3227 if {![regexp {^@@@*(( -\d+(,\d+)?)+) \+(\d+)(,\d+)? @@} $s_line \
3228 s_line old_specs osz osz1 new_line nsz]} {
3229 return
3230 }
3231
3232 # base lines for the parents
3233 set base_lines [list $new_line]
3234 foreach old_spec [lrange [split $old_specs " "] 1 end] {
3235 if {![regexp -- {-(\d+)(,\d+)?} $old_spec \
3236 old_spec old_line osz]} {
3237 return
3238 }
3239 lappend base_lines $old_line
3240 }
3241
3242 # Now scan the lines to determine offset within the hunk
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003243 set max_parent [expr {[llength $base_lines]-2}]
3244 set dline 0
3245 set s_lno [lindex [split $s_lix "."] 0]
3246
Paul Mackerras190ec522008-10-27 21:13:37 +11003247 # Determine if the line is removed
3248 set chunk [$ctext get $line.0 "$line.1 + $max_parent chars"]
3249 if {[string match {[-+ ]*} $chunk]} {
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003250 set removed_idx [string first "-" $chunk]
3251 # Choose a parent index
Paul Mackerras190ec522008-10-27 21:13:37 +11003252 if {$removed_idx >= 0} {
3253 set parent $removed_idx
3254 } else {
3255 set unchanged_idx [string first " " $chunk]
3256 if {$unchanged_idx >= 0} {
3257 set parent $unchanged_idx
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003258 } else {
Paul Mackerras190ec522008-10-27 21:13:37 +11003259 # blame the current commit
3260 set parent -1
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003261 }
3262 }
3263 # then count other lines that belong to it
Paul Mackerras190ec522008-10-27 21:13:37 +11003264 for {set i $line} {[incr i -1] > $s_lno} {} {
3265 set chunk [$ctext get $i.0 "$i.1 + $max_parent chars"]
3266 # Determine if the line is removed
3267 set removed_idx [string first "-" $chunk]
3268 if {$parent >= 0} {
3269 set code [string index $chunk $parent]
3270 if {$code eq "-" || ($removed_idx < 0 && $code ne "+")} {
3271 incr dline
3272 }
3273 } else {
3274 if {$removed_idx < 0} {
3275 incr dline
3276 }
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003277 }
3278 }
Paul Mackerras190ec522008-10-27 21:13:37 +11003279 incr parent
3280 } else {
3281 set parent 0
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003282 }
3283
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003284 incr dline [lindex $base_lines $parent]
3285 return [list $parent $dline]
3286}
3287
3288proc external_blame_diff {} {
Paul Mackerras8b07dca2008-11-02 22:34:47 +11003289 global currentid cmitmode
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003290 global diff_menu_txtpos diff_menu_line
3291 global diff_menu_filebase flist_menu_file
3292
3293 if {$cmitmode eq "tree"} {
3294 set parent_idx 0
Paul Mackerras190ec522008-10-27 21:13:37 +11003295 set line [expr {$diff_menu_line - $diff_menu_filebase}]
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003296 } else {
3297 set hinfo [find_hunk_blamespec $diff_menu_filebase $diff_menu_line]
3298 if {$hinfo ne {}} {
3299 set parent_idx [lindex $hinfo 0]
3300 set line [lindex $hinfo 1]
3301 } else {
3302 set parent_idx 0
3303 set line 0
3304 }
3305 }
3306
3307 external_blame $parent_idx $line
3308}
3309
Paul Mackerrasfc4977e2008-11-04 12:57:44 +11003310# Find the SHA1 ID of the blob for file $fname in the index
3311# at stage 0 or 2
3312proc index_sha1 {fname} {
3313 set f [open [list | git ls-files -s $fname] r]
3314 while {[gets $f line] >= 0} {
3315 set info [lindex [split $line "\t"] 0]
3316 set stage [lindex $info 2]
3317 if {$stage eq "0" || $stage eq "2"} {
3318 close $f
3319 return [lindex $info 1]
3320 }
3321 }
3322 close $f
3323 return {}
3324}
3325
Paul Mackerras9712b812008-12-06 21:44:05 +11003326# Turn an absolute path into one relative to the current directory
3327proc make_relative {f} {
3328 set elts [file split $f]
3329 set here [file split [pwd]]
3330 set ei 0
3331 set hi 0
3332 set res {}
3333 foreach d $here {
3334 if {$ei < $hi || $ei >= [llength $elts] || [lindex $elts $ei] ne $d} {
3335 lappend res ".."
3336 } else {
3337 incr ei
3338 }
3339 incr hi
3340 }
3341 set elts [concat $res [lrange $elts $ei end]]
3342 return [eval file join $elts]
3343}
3344
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003345proc external_blame {parent_idx {line {}}} {
Paul Mackerras9712b812008-12-06 21:44:05 +11003346 global flist_menu_file gitdir
Alexander Gavrilov77aa0ae2008-08-23 12:29:08 +04003347 global nullid nullid2
3348 global parentlist selectedline currentid
3349
3350 if {$parent_idx > 0} {
3351 set base_commit [lindex $parentlist $selectedline [expr {$parent_idx-1}]]
3352 } else {
3353 set base_commit $currentid
3354 }
3355
3356 if {$base_commit eq {} || $base_commit eq $nullid || $base_commit eq $nullid2} {
3357 error_popup [mc "No such commit"]
3358 return
3359 }
3360
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003361 set cmdline [list git gui blame]
3362 if {$line ne {} && $line > 1} {
3363 lappend cmdline "--line=$line"
3364 }
Paul Mackerras9712b812008-12-06 21:44:05 +11003365 set f [file join [file dirname $gitdir] $flist_menu_file]
3366 # Unfortunately it seems git gui blame doesn't like
3367 # being given an absolute path...
3368 set f [make_relative $f]
3369 lappend cmdline $base_commit $f
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003370 if {[catch {eval exec $cmdline &} err]} {
Christian Stimming3945d2c2008-09-12 11:39:43 +02003371 error_popup "[mc "git gui blame: command failed:"] $err"
Alexander Gavrilov77aa0ae2008-08-23 12:29:08 +04003372 }
3373}
3374
Paul Mackerras8a897742008-10-27 21:36:25 +11003375proc show_line_source {} {
3376 global cmitmode currentid parents curview blamestuff blameinst
3377 global diff_menu_line diff_menu_filebase flist_menu_file
Paul Mackerrasfc4977e2008-11-04 12:57:44 +11003378 global nullid nullid2 gitdir
Paul Mackerras8a897742008-10-27 21:36:25 +11003379
Paul Mackerrasfc4977e2008-11-04 12:57:44 +11003380 set from_index {}
Paul Mackerras8a897742008-10-27 21:36:25 +11003381 if {$cmitmode eq "tree"} {
3382 set id $currentid
3383 set line [expr {$diff_menu_line - $diff_menu_filebase}]
3384 } else {
3385 set h [find_hunk_blamespec $diff_menu_filebase $diff_menu_line]
3386 if {$h eq {}} return
3387 set pi [lindex $h 0]
3388 if {$pi == 0} {
3389 mark_ctext_line $diff_menu_line
3390 return
3391 }
Paul Mackerrasfc4977e2008-11-04 12:57:44 +11003392 incr pi -1
3393 if {$currentid eq $nullid} {
3394 if {$pi > 0} {
3395 # must be a merge in progress...
3396 if {[catch {
3397 # get the last line from .git/MERGE_HEAD
3398 set f [open [file join $gitdir MERGE_HEAD] r]
3399 set id [lindex [split [read $f] "\n"] end-1]
3400 close $f
3401 } err]} {
3402 error_popup [mc "Couldn't read merge head: %s" $err]
3403 return
3404 }
3405 } elseif {$parents($curview,$currentid) eq $nullid2} {
3406 # need to do the blame from the index
3407 if {[catch {
3408 set from_index [index_sha1 $flist_menu_file]
3409 } err]} {
3410 error_popup [mc "Error reading index: %s" $err]
3411 return
3412 }
Paul Mackerras9712b812008-12-06 21:44:05 +11003413 } else {
3414 set id $parents($curview,$currentid)
Paul Mackerrasfc4977e2008-11-04 12:57:44 +11003415 }
3416 } else {
3417 set id [lindex $parents($curview,$currentid) $pi]
3418 }
Paul Mackerras8a897742008-10-27 21:36:25 +11003419 set line [lindex $h 1]
3420 }
Paul Mackerrasfc4977e2008-11-04 12:57:44 +11003421 set blameargs {}
3422 if {$from_index ne {}} {
3423 lappend blameargs | git cat-file blob $from_index
3424 }
3425 lappend blameargs | git blame -p -L$line,+1
3426 if {$from_index ne {}} {
3427 lappend blameargs --contents -
3428 } else {
3429 lappend blameargs $id
3430 }
Paul Mackerras9712b812008-12-06 21:44:05 +11003431 lappend blameargs -- [file join [file dirname $gitdir] $flist_menu_file]
Paul Mackerras8a897742008-10-27 21:36:25 +11003432 if {[catch {
Paul Mackerrasfc4977e2008-11-04 12:57:44 +11003433 set f [open $blameargs r]
Paul Mackerras8a897742008-10-27 21:36:25 +11003434 } err]} {
3435 error_popup [mc "Couldn't start git blame: %s" $err]
3436 return
3437 }
Alexander Gavrilovf3413072008-12-01 20:30:09 +03003438 nowbusy blaming [mc "Searching"]
Paul Mackerras8a897742008-10-27 21:36:25 +11003439 fconfigure $f -blocking 0
3440 set i [reg_instance $f]
3441 set blamestuff($i) {}
3442 set blameinst $i
3443 filerun $f [list read_line_source $f $i]
3444}
3445
3446proc stopblaming {} {
3447 global blameinst
3448
3449 if {[info exists blameinst]} {
3450 stop_instance $blameinst
3451 unset blameinst
Alexander Gavrilovf3413072008-12-01 20:30:09 +03003452 notbusy blaming
Paul Mackerras8a897742008-10-27 21:36:25 +11003453 }
3454}
3455
3456proc read_line_source {fd inst} {
Paul Mackerrasfc4977e2008-11-04 12:57:44 +11003457 global blamestuff curview commfd blameinst nullid nullid2
Paul Mackerras8a897742008-10-27 21:36:25 +11003458
3459 while {[gets $fd line] >= 0} {
3460 lappend blamestuff($inst) $line
3461 }
3462 if {![eof $fd]} {
3463 return 1
3464 }
3465 unset commfd($inst)
3466 unset blameinst
Alexander Gavrilovf3413072008-12-01 20:30:09 +03003467 notbusy blaming
Paul Mackerras8a897742008-10-27 21:36:25 +11003468 fconfigure $fd -blocking 1
3469 if {[catch {close $fd} err]} {
3470 error_popup [mc "Error running git blame: %s" $err]
3471 return 0
3472 }
3473
3474 set fname {}
3475 set line [split [lindex $blamestuff($inst) 0] " "]
3476 set id [lindex $line 0]
3477 set lnum [lindex $line 1]
3478 if {[string length $id] == 40 && [string is xdigit $id] &&
3479 [string is digit -strict $lnum]} {
3480 # look for "filename" line
3481 foreach l $blamestuff($inst) {
3482 if {[string match "filename *" $l]} {
3483 set fname [string range $l 9 end]
3484 break
3485 }
3486 }
3487 }
3488 if {$fname ne {}} {
3489 # all looks good, select it
Paul Mackerrasfc4977e2008-11-04 12:57:44 +11003490 if {$id eq $nullid} {
3491 # blame uses all-zeroes to mean not committed,
3492 # which would mean a change in the index
3493 set id $nullid2
3494 }
Paul Mackerras8a897742008-10-27 21:36:25 +11003495 if {[commitinview $id $curview]} {
3496 selectline [rowofcommit $id] 1 [list $fname $lnum]
3497 } else {
3498 error_popup [mc "That line comes from commit %s, \
3499 which is not in this view" [shortids $id]]
3500 }
3501 } else {
3502 puts "oops couldn't parse git blame output"
3503 }
3504 return 0
3505}
3506
Thomas Arcila314f5de2008-03-24 12:55:36 +01003507# delete $dir when we see eof on $f (presumably because the child has exited)
3508proc delete_at_eof {f dir} {
3509 while {[gets $f line] >= 0} {}
3510 if {[eof $f]} {
3511 if {[catch {close $f} err]} {
Christian Stimming3945d2c2008-09-12 11:39:43 +02003512 error_popup "[mc "External diff viewer failed:"] $err"
Thomas Arcila314f5de2008-03-24 12:55:36 +01003513 }
3514 file delete -force $dir
3515 return 0
3516 }
3517 return 1
3518}
3519
Paul Mackerras098dd8a2006-05-03 09:32:53 +10003520# Functions for adding and removing shell-type quoting
3521
3522proc shellquote {str} {
3523 if {![string match "*\['\"\\ \t]*" $str]} {
3524 return $str
3525 }
3526 if {![string match "*\['\"\\]*" $str]} {
3527 return "\"$str\""
3528 }
3529 if {![string match "*'*" $str]} {
3530 return "'$str'"
3531 }
3532 return "\"[string map {\" \\\" \\ \\\\} $str]\""
3533}
3534
3535proc shellarglist {l} {
3536 set str {}
3537 foreach a $l {
3538 if {$str ne {}} {
3539 append str " "
3540 }
3541 append str [shellquote $a]
3542 }
3543 return $str
3544}
3545
3546proc shelldequote {str} {
3547 set ret {}
3548 set used -1
3549 while {1} {
3550 incr used
3551 if {![regexp -start $used -indices "\['\"\\\\ \t]" $str first]} {
3552 append ret [string range $str $used end]
3553 set used [string length $str]
3554 break
3555 }
3556 set first [lindex $first 0]
3557 set ch [string index $str $first]
3558 if {$first > $used} {
3559 append ret [string range $str $used [expr {$first - 1}]]
3560 set used $first
3561 }
3562 if {$ch eq " " || $ch eq "\t"} break
3563 incr used
3564 if {$ch eq "'"} {
3565 set first [string first "'" $str $used]
3566 if {$first < 0} {
3567 error "unmatched single-quote"
3568 }
3569 append ret [string range $str $used [expr {$first - 1}]]
3570 set used $first
3571 continue
3572 }
3573 if {$ch eq "\\"} {
3574 if {$used >= [string length $str]} {
3575 error "trailing backslash"
3576 }
3577 append ret [string index $str $used]
3578 continue
3579 }
3580 # here ch == "\""
3581 while {1} {
3582 if {![regexp -start $used -indices "\[\"\\\\]" $str first]} {
3583 error "unmatched double-quote"
3584 }
3585 set first [lindex $first 0]
3586 set ch [string index $str $first]
3587 if {$first > $used} {
3588 append ret [string range $str $used [expr {$first - 1}]]
3589 set used $first
3590 }
3591 if {$ch eq "\""} break
3592 incr used
3593 append ret [string index $str $used]
3594 incr used
3595 }
3596 }
3597 return [list $used $ret]
3598}
3599
3600proc shellsplit {str} {
3601 set l {}
3602 while {1} {
3603 set str [string trimleft $str]
3604 if {$str eq {}} break
3605 set dq [shelldequote $str]
3606 set n [lindex $dq 0]
3607 set word [lindex $dq 1]
3608 set str [string range $str $n end]
3609 lappend l $word
3610 }
3611 return $l
3612}
3613
Paul Mackerras7fcceed2006-04-27 19:21:49 +10003614# Code to implement multiple views
3615
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10003616proc newview {ishighlight} {
Alexander Gavrilov218a9002008-11-02 21:59:48 +03003617 global nextviewnum newviewname newishighlight
3618 global revtreeargs viewargscmd newviewopts curview
Paul Mackerras50b44ec2006-04-04 10:16:22 +10003619
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10003620 set newishighlight $ishighlight
Paul Mackerras50b44ec2006-04-04 10:16:22 +10003621 set top .gitkview
3622 if {[winfo exists $top]} {
3623 raise $top
3624 return
3625 }
Michele Ballabioa3a1f572008-03-03 21:12:47 +01003626 set newviewname($nextviewnum) "[mc "View"] $nextviewnum"
Alexander Gavrilov218a9002008-11-02 21:59:48 +03003627 set newviewopts($nextviewnum,perm) 0
3628 set newviewopts($nextviewnum,cmd) $viewargscmd($curview)
3629 decode_view_opts $nextviewnum $revtreeargs
Christian Stimmingd990ced2007-11-07 18:42:55 +01003630 vieweditor $top $nextviewnum [mc "Gitk view definition"]
Paul Mackerrasd16c0812006-04-25 21:21:10 +10003631}
3632
Alexander Gavrilov218a9002008-11-02 21:59:48 +03003633set known_view_options {
3634 {perm b . {} {mc "Remember this view"}}
3635 {args t50= + {} {mc "Commits to include (arguments to git log):"}}
3636 {all b * "--all" {mc "Use all refs"}}
3637 {dorder b . {"--date-order" "-d"} {mc "Strictly sort by date"}}
3638 {lright b . "--left-right" {mc "Mark branch sides"}}
3639 {since t15 + {"--since=*" "--after=*"} {mc "Since date:"}}
3640 {until t15 . {"--until=*" "--before=*"} {mc "Until date:"}}
3641 {limit t10 + "--max-count=*" {mc "Max count:"}}
3642 {skip t10 . "--skip=*" {mc "Skip:"}}
3643 {first b . "--first-parent" {mc "Limit to first parent"}}
3644 {cmd t50= + {} {mc "Command to generate more commits to include:"}}
3645 }
3646
3647proc encode_view_opts {n} {
3648 global known_view_options newviewopts
3649
3650 set rargs [list]
3651 foreach opt $known_view_options {
3652 set patterns [lindex $opt 3]
3653 if {$patterns eq {}} continue
3654 set pattern [lindex $patterns 0]
3655
3656 set val $newviewopts($n,[lindex $opt 0])
3657
3658 if {[lindex $opt 1] eq "b"} {
3659 if {$val} {
3660 lappend rargs $pattern
3661 }
3662 } else {
3663 set val [string trim $val]
3664 if {$val ne {}} {
3665 set pfix [string range $pattern 0 end-1]
3666 lappend rargs $pfix$val
3667 }
3668 }
3669 }
3670 return [concat $rargs [shellsplit $newviewopts($n,args)]]
3671}
3672
3673proc decode_view_opts {n view_args} {
3674 global known_view_options newviewopts
3675
3676 foreach opt $known_view_options {
3677 if {[lindex $opt 1] eq "b"} {
3678 set val 0
3679 } else {
3680 set val {}
3681 }
3682 set newviewopts($n,[lindex $opt 0]) $val
3683 }
3684 set oargs [list]
3685 foreach arg $view_args {
3686 if {[regexp -- {^-([0-9]+)$} $arg arg cnt]
3687 && ![info exists found(limit)]} {
3688 set newviewopts($n,limit) $cnt
3689 set found(limit) 1
3690 continue
3691 }
3692 catch { unset val }
3693 foreach opt $known_view_options {
3694 set id [lindex $opt 0]
3695 if {[info exists found($id)]} continue
3696 foreach pattern [lindex $opt 3] {
3697 if {![string match $pattern $arg]} continue
3698 if {[lindex $opt 1] ne "b"} {
3699 set size [string length $pattern]
3700 set val [string range $arg [expr {$size-1}] end]
3701 } else {
3702 set val 1
3703 }
3704 set newviewopts($n,$id) $val
3705 set found($id) 1
3706 break
3707 }
3708 if {[info exists val]} break
3709 }
3710 if {[info exists val]} continue
3711 lappend oargs $arg
3712 }
3713 set newviewopts($n,args) [shellarglist $oargs]
3714}
3715
Alexander Gavrilovcea07cf2008-11-09 13:00:45 +03003716proc edit_or_newview {} {
3717 global curview
3718
3719 if {$curview > 0} {
3720 editview
3721 } else {
3722 newview 0
3723 }
3724}
3725
Paul Mackerrasd16c0812006-04-25 21:21:10 +10003726proc editview {} {
3727 global curview
Alexander Gavrilov218a9002008-11-02 21:59:48 +03003728 global viewname viewperm newviewname newviewopts
3729 global viewargs viewargscmd
Paul Mackerrasd16c0812006-04-25 21:21:10 +10003730
3731 set top .gitkvedit-$curview
3732 if {[winfo exists $top]} {
3733 raise $top
3734 return
3735 }
Alexander Gavrilov218a9002008-11-02 21:59:48 +03003736 set newviewname($curview) $viewname($curview)
3737 set newviewopts($curview,perm) $viewperm($curview)
3738 set newviewopts($curview,cmd) $viewargscmd($curview)
3739 decode_view_opts $curview $viewargs($curview)
Paul Mackerrasd16c0812006-04-25 21:21:10 +10003740 vieweditor $top $curview "Gitk: edit view $viewname($curview)"
3741}
3742
3743proc vieweditor {top n title} {
Alexander Gavrilov218a9002008-11-02 21:59:48 +03003744 global newviewname newviewopts viewfiles bgcolor
3745 global known_view_options
Paul Mackerrasd16c0812006-04-25 21:21:10 +10003746
Paul Mackerras50b44ec2006-04-04 10:16:22 +10003747 toplevel $top
Paul Mackerrasd16c0812006-04-25 21:21:10 +10003748 wm title $top $title
Alexander Gavrilove7d64002008-11-11 23:55:42 +03003749 make_transient $top .
Alexander Gavrilov218a9002008-11-02 21:59:48 +03003750
3751 # View name
3752 frame $top.nfr
Paul Mackerrasb039f0a2008-01-06 15:54:46 +11003753 label $top.nl -text [mc "Name"]
3754 entry $top.name -width 20 -textvariable newviewname($n)
Alexander Gavrilov218a9002008-11-02 21:59:48 +03003755 pack $top.nfr -in $top -fill x -pady 5 -padx 3
3756 pack $top.nl -in $top.nfr -side left -padx {0 30}
3757 pack $top.name -in $top.nfr -side left
Yann Dirson2d480852008-02-21 21:23:31 +01003758
Alexander Gavrilov218a9002008-11-02 21:59:48 +03003759 # View options
3760 set cframe $top.nfr
3761 set cexpand 0
3762 set cnt 0
3763 foreach opt $known_view_options {
3764 set id [lindex $opt 0]
3765 set type [lindex $opt 1]
3766 set flags [lindex $opt 2]
3767 set title [eval [lindex $opt 4]]
3768 set lxpad 0
Yann Dirson2d480852008-02-21 21:23:31 +01003769
Alexander Gavrilov218a9002008-11-02 21:59:48 +03003770 if {$flags eq "+" || $flags eq "*"} {
3771 set cframe $top.fr$cnt
3772 incr cnt
3773 frame $cframe
3774 pack $cframe -in $top -fill x -pady 3 -padx 3
3775 set cexpand [expr {$flags eq "*"}]
3776 } else {
3777 set lxpad 5
3778 }
3779
3780 if {$type eq "b"} {
3781 checkbutton $cframe.c_$id -text $title -variable newviewopts($n,$id)
3782 pack $cframe.c_$id -in $cframe -side left \
3783 -padx [list $lxpad 0] -expand $cexpand -anchor w
3784 } elseif {[regexp {^t(\d+)$} $type type sz]} {
3785 message $cframe.l_$id -aspect 1500 -text $title
3786 entry $cframe.e_$id -width $sz -background $bgcolor \
3787 -textvariable newviewopts($n,$id)
3788 pack $cframe.l_$id -in $cframe -side left -padx [list $lxpad 0]
3789 pack $cframe.e_$id -in $cframe -side left -expand 1 -fill x
3790 } elseif {[regexp {^t(\d+)=$} $type type sz]} {
3791 message $cframe.l_$id -aspect 1500 -text $title
3792 entry $cframe.e_$id -width $sz -background $bgcolor \
3793 -textvariable newviewopts($n,$id)
3794 pack $cframe.l_$id -in $cframe -side top -pady [list 3 0] -anchor w
3795 pack $cframe.e_$id -in $cframe -side top -fill x
3796 }
3797 }
3798
3799 # Path list
3800 message $top.l -aspect 1500 \
Christian Stimmingd990ced2007-11-07 18:42:55 +01003801 -text [mc "Enter files and directories to include, one per line:"]
Alexander Gavrilov218a9002008-11-02 21:59:48 +03003802 pack $top.l -in $top -side top -pady [list 7 0] -anchor w -padx 3
3803 text $top.t -width 40 -height 5 -background $bgcolor -font uifont
Paul Mackerrasd16c0812006-04-25 21:21:10 +10003804 if {[info exists viewfiles($n)]} {
3805 foreach f $viewfiles($n) {
3806 $top.t insert end $f
3807 $top.t insert end "\n"
3808 }
3809 $top.t delete {end - 1c} end
3810 $top.t mark set insert 0.0
3811 }
Alexander Gavrilov218a9002008-11-02 21:59:48 +03003812 pack $top.t -in $top -side top -pady [list 0 5] -fill both -expand 1 -padx 3
Paul Mackerras50b44ec2006-04-04 10:16:22 +10003813 frame $top.buts
Paul Mackerrasb039f0a2008-01-06 15:54:46 +11003814 button $top.buts.ok -text [mc "OK"] -command [list newviewok $top $n]
Alexander Gavrilov218a9002008-11-02 21:59:48 +03003815 button $top.buts.apply -text [mc "Apply (F5)"] -command [list newviewok $top $n 1]
Paul Mackerrasb039f0a2008-01-06 15:54:46 +11003816 button $top.buts.can -text [mc "Cancel"] -command [list destroy $top]
Alexander Gavrilov218a9002008-11-02 21:59:48 +03003817 bind $top <Control-Return> [list newviewok $top $n]
3818 bind $top <F5> [list newviewok $top $n 1]
Alexander Gavrilov76f15942008-11-02 21:59:44 +03003819 bind $top <Escape> [list destroy $top]
Alexander Gavrilov218a9002008-11-02 21:59:48 +03003820 grid $top.buts.ok $top.buts.apply $top.buts.can
Paul Mackerras50b44ec2006-04-04 10:16:22 +10003821 grid columnconfigure $top.buts 0 -weight 1 -uniform a
3822 grid columnconfigure $top.buts 1 -weight 1 -uniform a
Alexander Gavrilov218a9002008-11-02 21:59:48 +03003823 grid columnconfigure $top.buts 2 -weight 1 -uniform a
3824 pack $top.buts -in $top -side top -fill x
Paul Mackerras50b44ec2006-04-04 10:16:22 +10003825 focus $top.t
3826}
3827
Paul Mackerras908c3582006-05-20 09:38:11 +10003828proc doviewmenu {m first cmd op argv} {
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10003829 set nmenu [$m index end]
3830 for {set i $first} {$i <= $nmenu} {incr i} {
3831 if {[$m entrycget $i -command] eq $cmd} {
Paul Mackerras908c3582006-05-20 09:38:11 +10003832 eval $m $op $i $argv
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10003833 break
Paul Mackerrasd16c0812006-04-25 21:21:10 +10003834 }
3835 }
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10003836}
3837
3838proc allviewmenus {n op args} {
Paul Mackerras687c8762007-09-22 12:49:33 +10003839 # global viewhlmenu
Paul Mackerras908c3582006-05-20 09:38:11 +10003840
Paul Mackerras3cd204e2006-11-23 21:06:16 +11003841 doviewmenu .bar.view 5 [list showview $n] $op $args
Paul Mackerras687c8762007-09-22 12:49:33 +10003842 # doviewmenu $viewhlmenu 1 [list addvhighlight $n] $op $args
Paul Mackerrasd16c0812006-04-25 21:21:10 +10003843}
Paul Mackerras50b44ec2006-04-04 10:16:22 +10003844
Alexander Gavrilov218a9002008-11-02 21:59:48 +03003845proc newviewok {top n {apply 0}} {
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10003846 global nextviewnum newviewperm newviewname newishighlight
Paul Mackerrasd16c0812006-04-25 21:21:10 +10003847 global viewname viewfiles viewperm selectedview curview
Alexander Gavrilov218a9002008-11-02 21:59:48 +03003848 global viewargs viewargscmd newviewopts viewhlmenu
Paul Mackerrasd16c0812006-04-25 21:21:10 +10003849
Paul Mackerras098dd8a2006-05-03 09:32:53 +10003850 if {[catch {
Alexander Gavrilov218a9002008-11-02 21:59:48 +03003851 set newargs [encode_view_opts $n]
Paul Mackerras098dd8a2006-05-03 09:32:53 +10003852 } err]} {
Alexander Gavrilov84a76f12008-11-02 21:59:45 +03003853 error_popup "[mc "Error in commit selection arguments:"] $err" $top
Paul Mackerras098dd8a2006-05-03 09:32:53 +10003854 return
3855 }
Paul Mackerras50b44ec2006-04-04 10:16:22 +10003856 set files {}
Paul Mackerrasd16c0812006-04-25 21:21:10 +10003857 foreach f [split [$top.t get 0.0 end] "\n"] {
Paul Mackerras50b44ec2006-04-04 10:16:22 +10003858 set ft [string trim $f]
3859 if {$ft ne {}} {
3860 lappend files $ft
3861 }
3862 }
Paul Mackerrasd16c0812006-04-25 21:21:10 +10003863 if {![info exists viewfiles($n)]} {
3864 # creating a new view
3865 incr nextviewnum
3866 set viewname($n) $newviewname($n)
Alexander Gavrilov218a9002008-11-02 21:59:48 +03003867 set viewperm($n) $newviewopts($n,perm)
Paul Mackerrasd16c0812006-04-25 21:21:10 +10003868 set viewfiles($n) $files
Paul Mackerras098dd8a2006-05-03 09:32:53 +10003869 set viewargs($n) $newargs
Alexander Gavrilov218a9002008-11-02 21:59:48 +03003870 set viewargscmd($n) $newviewopts($n,cmd)
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10003871 addviewmenu $n
3872 if {!$newishighlight} {
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10003873 run showview $n
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10003874 } else {
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10003875 run addvhighlight $n
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10003876 }
Paul Mackerrasd16c0812006-04-25 21:21:10 +10003877 } else {
3878 # editing an existing view
Alexander Gavrilov218a9002008-11-02 21:59:48 +03003879 set viewperm($n) $newviewopts($n,perm)
Paul Mackerrasd16c0812006-04-25 21:21:10 +10003880 if {$newviewname($n) ne $viewname($n)} {
3881 set viewname($n) $newviewname($n)
Paul Mackerras3cd204e2006-11-23 21:06:16 +11003882 doviewmenu .bar.view 5 [list showview $n] \
Paul Mackerras908c3582006-05-20 09:38:11 +10003883 entryconf [list -label $viewname($n)]
Paul Mackerras687c8762007-09-22 12:49:33 +10003884 # doviewmenu $viewhlmenu 1 [list addvhighlight $n] \
3885 # entryconf [list -label $viewname($n) -value $viewname($n)]
Paul Mackerrasd16c0812006-04-25 21:21:10 +10003886 }
Yann Dirson2d480852008-02-21 21:23:31 +01003887 if {$files ne $viewfiles($n) || $newargs ne $viewargs($n) || \
Alexander Gavrilov218a9002008-11-02 21:59:48 +03003888 $newviewopts($n,cmd) ne $viewargscmd($n)} {
Paul Mackerrasd16c0812006-04-25 21:21:10 +10003889 set viewfiles($n) $files
Paul Mackerras098dd8a2006-05-03 09:32:53 +10003890 set viewargs($n) $newargs
Alexander Gavrilov218a9002008-11-02 21:59:48 +03003891 set viewargscmd($n) $newviewopts($n,cmd)
Paul Mackerrasd16c0812006-04-25 21:21:10 +10003892 if {$curview == $n} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11003893 run reloadcommits
Paul Mackerrasd16c0812006-04-25 21:21:10 +10003894 }
3895 }
3896 }
Alexander Gavrilov218a9002008-11-02 21:59:48 +03003897 if {$apply} return
Paul Mackerrasd16c0812006-04-25 21:21:10 +10003898 catch {destroy $top}
Paul Mackerras50b44ec2006-04-04 10:16:22 +10003899}
3900
3901proc delview {} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11003902 global curview viewperm hlview selectedhlview
Paul Mackerras50b44ec2006-04-04 10:16:22 +10003903
3904 if {$curview == 0} return
Paul Mackerras908c3582006-05-20 09:38:11 +10003905 if {[info exists hlview] && $hlview == $curview} {
Christian Stimmingb007ee22007-11-07 18:44:35 +01003906 set selectedhlview [mc "None"]
Paul Mackerras908c3582006-05-20 09:38:11 +10003907 unset hlview
3908 }
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10003909 allviewmenus $curview delete
Paul Mackerrasa90a6d22006-04-25 17:12:46 +10003910 set viewperm($curview) 0
Paul Mackerras50b44ec2006-04-04 10:16:22 +10003911 showview 0
3912}
3913
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10003914proc addviewmenu {n} {
Paul Mackerras908c3582006-05-20 09:38:11 +10003915 global viewname viewhlmenu
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10003916
3917 .bar.view add radiobutton -label $viewname($n) \
3918 -command [list showview $n] -variable selectedview -value $n
Paul Mackerras687c8762007-09-22 12:49:33 +10003919 #$viewhlmenu add radiobutton -label $viewname($n) \
3920 # -command [list addvhighlight $n] -variable selectedhlview
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10003921}
3922
Paul Mackerras50b44ec2006-04-04 10:16:22 +10003923proc showview {n} {
Paul Mackerras3ed31a82008-04-26 16:00:00 +10003924 global curview cached_commitrow ordertok
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10003925 global displayorder parentlist rowidlist rowisopt rowfinal
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11003926 global colormap rowtextx nextcolor canvxmax
3927 global numcommits viewcomplete
Paul Mackerras50b44ec2006-04-04 10:16:22 +10003928 global selectedline currentid canv canvy0
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10003929 global treediffs
Paul Mackerras3e766082008-01-13 17:26:30 +11003930 global pending_select mainheadid
Paul Mackerras03800812007-08-29 21:45:21 +10003931 global commitidx
Paul Mackerras3e766082008-01-13 17:26:30 +11003932 global selectedview
Paul Mackerras97645682007-08-23 22:24:38 +10003933 global hlview selectedhlview commitinterest
Paul Mackerras50b44ec2006-04-04 10:16:22 +10003934
3935 if {$n == $curview} return
3936 set selid {}
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11003937 set ymax [lindex [$canv cget -scrollregion] 3]
3938 set span [$canv yview]
3939 set ytop [expr {[lindex $span 0] * $ymax}]
3940 set ybot [expr {[lindex $span 1] * $ymax}]
3941 set yscreen [expr {($ybot - $ytop) / 2}]
Paul Mackerras94b4a692008-05-20 20:51:06 +10003942 if {$selectedline ne {}} {
Paul Mackerras50b44ec2006-04-04 10:16:22 +10003943 set selid $currentid
3944 set y [yc $selectedline]
Paul Mackerras50b44ec2006-04-04 10:16:22 +10003945 if {$ytop < $y && $y < $ybot} {
3946 set yscreen [expr {$y - $ytop}]
Paul Mackerras50b44ec2006-04-04 10:16:22 +10003947 }
Paul Mackerrase507fd42007-06-16 21:51:08 +10003948 } elseif {[info exists pending_select]} {
3949 set selid $pending_select
3950 unset pending_select
Paul Mackerras50b44ec2006-04-04 10:16:22 +10003951 }
3952 unselectline
Paul Mackerrasfdedbcf2006-04-06 21:22:52 +10003953 normalline
Paul Mackerras50b44ec2006-04-04 10:16:22 +10003954 catch {unset treediffs}
3955 clear_display
Paul Mackerras908c3582006-05-20 09:38:11 +10003956 if {[info exists hlview] && $hlview == $n} {
3957 unset hlview
Christian Stimmingb007ee22007-11-07 18:44:35 +01003958 set selectedhlview [mc "None"]
Paul Mackerras908c3582006-05-20 09:38:11 +10003959 }
Paul Mackerras97645682007-08-23 22:24:38 +10003960 catch {unset commitinterest}
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11003961 catch {unset cached_commitrow}
Paul Mackerras9257d8f2007-12-11 10:45:38 +11003962 catch {unset ordertok}
Paul Mackerras50b44ec2006-04-04 10:16:22 +10003963
3964 set curview $n
Paul Mackerrasa90a6d22006-04-25 17:12:46 +10003965 set selectedview $n
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11003966 .bar.view entryconf [mca "Edit view..."] -state [expr {$n == 0? "disabled": "normal"}]
3967 .bar.view entryconf [mca "Delete view"] -state [expr {$n == 0? "disabled": "normal"}]
Paul Mackerras50b44ec2006-04-04 10:16:22 +10003968
Paul Mackerrasdf904492007-08-29 22:03:07 +10003969 run refill_reflist
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11003970 if {![info exists viewcomplete($n)]} {
Alexander Gavrilov567c34e2008-07-26 20:13:45 +04003971 getcommits $selid
Paul Mackerras50b44ec2006-04-04 10:16:22 +10003972 return
3973 }
3974
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11003975 set displayorder {}
3976 set parentlist {}
3977 set rowidlist {}
3978 set rowisopt {}
3979 set rowfinal {}
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10003980 set numcommits $commitidx($n)
Paul Mackerras22626ef2006-04-17 09:56:02 +10003981
Paul Mackerras50b44ec2006-04-04 10:16:22 +10003982 catch {unset colormap}
3983 catch {unset rowtextx}
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10003984 set nextcolor 0
3985 set canvxmax [$canv cget -width]
Paul Mackerras50b44ec2006-04-04 10:16:22 +10003986 set curview $n
3987 set row 0
Paul Mackerras50b44ec2006-04-04 10:16:22 +10003988 setcanvscroll
3989 set yf 0
Paul Mackerrase507fd42007-06-16 21:51:08 +10003990 set row {}
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11003991 if {$selid ne {} && [commitinview $selid $n]} {
3992 set row [rowofcommit $selid]
Paul Mackerras50b44ec2006-04-04 10:16:22 +10003993 # try to get the selected row in the same position on the screen
3994 set ymax [lindex [$canv cget -scrollregion] 3]
3995 set ytop [expr {[yc $row] - $yscreen}]
3996 if {$ytop < 0} {
3997 set ytop 0
3998 }
3999 set yf [expr {$ytop * 1.0 / $ymax}]
4000 }
4001 allcanvs yview moveto $yf
4002 drawvisible
Paul Mackerrase507fd42007-06-16 21:51:08 +10004003 if {$row ne {}} {
4004 selectline $row 0
Paul Mackerras3e766082008-01-13 17:26:30 +11004005 } elseif {!$viewcomplete($n)} {
Alexander Gavrilov567c34e2008-07-26 20:13:45 +04004006 reset_pending_select $selid
Paul Mackerrase507fd42007-06-16 21:51:08 +10004007 } else {
Alexander Gavrilov835e62a2008-07-26 20:15:54 +04004008 reset_pending_select {}
4009
4010 if {[commitinview $pending_select $curview]} {
4011 selectline [rowofcommit $pending_select] 1
4012 } else {
4013 set row [first_real_row]
4014 if {$row < $numcommits} {
4015 selectline $row 0
4016 }
Paul Mackerrase507fd42007-06-16 21:51:08 +10004017 }
4018 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004019 if {!$viewcomplete($n)} {
4020 if {$numcommits == 0} {
Christian Stimmingd990ced2007-11-07 18:42:55 +01004021 show_status [mc "Reading commits..."]
Paul Mackerrasd16c0812006-04-25 21:21:10 +10004022 }
Paul Mackerras098dd8a2006-05-03 09:32:53 +10004023 } elseif {$numcommits == 0} {
Christian Stimmingd990ced2007-11-07 18:42:55 +01004024 show_status [mc "No commits selected"]
Paul Mackerras2516dae2006-04-21 10:35:31 +10004025 }
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004026}
4027
Paul Mackerras908c3582006-05-20 09:38:11 +10004028# Stuff relating to the highlighting facility
4029
Paul Mackerras476ca632008-01-07 22:16:31 +11004030proc ishighlighted {id} {
Paul Mackerras164ff272006-05-29 19:50:02 +10004031 global vhighlights fhighlights nhighlights rhighlights
Paul Mackerras908c3582006-05-20 09:38:11 +10004032
Paul Mackerras476ca632008-01-07 22:16:31 +11004033 if {[info exists nhighlights($id)] && $nhighlights($id) > 0} {
4034 return $nhighlights($id)
Paul Mackerras908c3582006-05-20 09:38:11 +10004035 }
Paul Mackerras476ca632008-01-07 22:16:31 +11004036 if {[info exists vhighlights($id)] && $vhighlights($id) > 0} {
4037 return $vhighlights($id)
Paul Mackerras908c3582006-05-20 09:38:11 +10004038 }
Paul Mackerras476ca632008-01-07 22:16:31 +11004039 if {[info exists fhighlights($id)] && $fhighlights($id) > 0} {
4040 return $fhighlights($id)
Paul Mackerras908c3582006-05-20 09:38:11 +10004041 }
Paul Mackerras476ca632008-01-07 22:16:31 +11004042 if {[info exists rhighlights($id)] && $rhighlights($id) > 0} {
4043 return $rhighlights($id)
Paul Mackerras164ff272006-05-29 19:50:02 +10004044 }
Paul Mackerras908c3582006-05-20 09:38:11 +10004045 return 0
4046}
4047
Paul Mackerras28593d32008-11-13 23:01:46 +11004048proc bolden {id font} {
4049 global canv linehtag currentid boldids need_redisplay
Paul Mackerras908c3582006-05-20 09:38:11 +10004050
Paul Mackerrasd98d50e2008-11-13 22:39:00 +11004051 # need_redisplay = 1 means the display is stale and about to be redrawn
4052 if {$need_redisplay} return
Paul Mackerras28593d32008-11-13 23:01:46 +11004053 lappend boldids $id
4054 $canv itemconf $linehtag($id) -font $font
4055 if {[info exists currentid] && $id eq $currentid} {
Paul Mackerras908c3582006-05-20 09:38:11 +10004056 $canv delete secsel
Paul Mackerras28593d32008-11-13 23:01:46 +11004057 set t [eval $canv create rect [$canv bbox $linehtag($id)] \
Paul Mackerras908c3582006-05-20 09:38:11 +10004058 -outline {{}} -tags secsel \
4059 -fill [$canv cget -selectbackground]]
4060 $canv lower $t
4061 }
4062}
4063
Paul Mackerras28593d32008-11-13 23:01:46 +11004064proc bolden_name {id font} {
4065 global canv2 linentag currentid boldnameids need_redisplay
Paul Mackerras908c3582006-05-20 09:38:11 +10004066
Paul Mackerrasd98d50e2008-11-13 22:39:00 +11004067 if {$need_redisplay} return
Paul Mackerras28593d32008-11-13 23:01:46 +11004068 lappend boldnameids $id
4069 $canv2 itemconf $linentag($id) -font $font
4070 if {[info exists currentid] && $id eq $currentid} {
Paul Mackerras908c3582006-05-20 09:38:11 +10004071 $canv2 delete secsel
Paul Mackerras28593d32008-11-13 23:01:46 +11004072 set t [eval $canv2 create rect [$canv2 bbox $linentag($id)] \
Paul Mackerras908c3582006-05-20 09:38:11 +10004073 -outline {{}} -tags secsel \
4074 -fill [$canv2 cget -selectbackground]]
4075 $canv2 lower $t
4076 }
4077}
4078
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004079proc unbolden {} {
Paul Mackerras28593d32008-11-13 23:01:46 +11004080 global boldids
Paul Mackerras908c3582006-05-20 09:38:11 +10004081
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004082 set stillbold {}
Paul Mackerras28593d32008-11-13 23:01:46 +11004083 foreach id $boldids {
4084 if {![ishighlighted $id]} {
4085 bolden $id mainfont
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004086 } else {
Paul Mackerras28593d32008-11-13 23:01:46 +11004087 lappend stillbold $id
Paul Mackerras908c3582006-05-20 09:38:11 +10004088 }
4089 }
Paul Mackerras28593d32008-11-13 23:01:46 +11004090 set boldids $stillbold
Paul Mackerras908c3582006-05-20 09:38:11 +10004091}
4092
4093proc addvhighlight {n} {
Paul Mackerras476ca632008-01-07 22:16:31 +11004094 global hlview viewcomplete curview vhl_done commitidx
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004095
4096 if {[info exists hlview]} {
Paul Mackerras908c3582006-05-20 09:38:11 +10004097 delvhighlight
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004098 }
4099 set hlview $n
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004100 if {$n != $curview && ![info exists viewcomplete($n)]} {
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004101 start_rev_list $n
Paul Mackerras908c3582006-05-20 09:38:11 +10004102 }
4103 set vhl_done $commitidx($hlview)
4104 if {$vhl_done > 0} {
4105 drawvisible
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004106 }
4107}
4108
Paul Mackerras908c3582006-05-20 09:38:11 +10004109proc delvhighlight {} {
4110 global hlview vhighlights
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004111
4112 if {![info exists hlview]} return
4113 unset hlview
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004114 catch {unset vhighlights}
4115 unbolden
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004116}
4117
Paul Mackerras908c3582006-05-20 09:38:11 +10004118proc vhighlightmore {} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004119 global hlview vhl_done commitidx vhighlights curview
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004120
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004121 set max $commitidx($hlview)
Paul Mackerras908c3582006-05-20 09:38:11 +10004122 set vr [visiblerows]
4123 set r0 [lindex $vr 0]
4124 set r1 [lindex $vr 1]
4125 for {set i $vhl_done} {$i < $max} {incr i} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004126 set id [commitonrow $i $hlview]
4127 if {[commitinview $id $curview]} {
4128 set row [rowofcommit $id]
Paul Mackerras908c3582006-05-20 09:38:11 +10004129 if {$r0 <= $row && $row <= $r1} {
4130 if {![highlighted $row]} {
Paul Mackerras28593d32008-11-13 23:01:46 +11004131 bolden $id mainfontbold
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004132 }
Paul Mackerras476ca632008-01-07 22:16:31 +11004133 set vhighlights($id) 1
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004134 }
4135 }
4136 }
Paul Mackerras908c3582006-05-20 09:38:11 +10004137 set vhl_done $max
Paul Mackerrasac1276a2008-03-03 10:11:08 +11004138 return 0
Paul Mackerras908c3582006-05-20 09:38:11 +10004139}
4140
4141proc askvhighlight {row id} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004142 global hlview vhighlights iddrawn
Paul Mackerras908c3582006-05-20 09:38:11 +10004143
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004144 if {[commitinview $id $hlview]} {
Paul Mackerras476ca632008-01-07 22:16:31 +11004145 if {[info exists iddrawn($id)] && ![ishighlighted $id]} {
Paul Mackerras28593d32008-11-13 23:01:46 +11004146 bolden $id mainfontbold
Paul Mackerras908c3582006-05-20 09:38:11 +10004147 }
Paul Mackerras476ca632008-01-07 22:16:31 +11004148 set vhighlights($id) 1
Paul Mackerras908c3582006-05-20 09:38:11 +10004149 } else {
Paul Mackerras476ca632008-01-07 22:16:31 +11004150 set vhighlights($id) 0
Paul Mackerras908c3582006-05-20 09:38:11 +10004151 }
4152}
4153
Paul Mackerras687c8762007-09-22 12:49:33 +10004154proc hfiles_change {} {
Paul Mackerras908c3582006-05-20 09:38:11 +10004155 global highlight_files filehighlight fhighlights fh_serial
Paul Mackerras8b39e042008-12-02 09:02:46 +11004156 global highlight_paths
Paul Mackerras908c3582006-05-20 09:38:11 +10004157
4158 if {[info exists filehighlight]} {
4159 # delete previous highlights
4160 catch {close $filehighlight}
4161 unset filehighlight
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004162 catch {unset fhighlights}
4163 unbolden
Paul Mackerras63b79192006-05-20 21:31:52 +10004164 unhighlight_filelist
Paul Mackerras908c3582006-05-20 09:38:11 +10004165 }
Paul Mackerras63b79192006-05-20 21:31:52 +10004166 set highlight_paths {}
Paul Mackerras908c3582006-05-20 09:38:11 +10004167 after cancel do_file_hl $fh_serial
4168 incr fh_serial
4169 if {$highlight_files ne {}} {
4170 after 300 do_file_hl $fh_serial
4171 }
4172}
4173
Paul Mackerras687c8762007-09-22 12:49:33 +10004174proc gdttype_change {name ix op} {
4175 global gdttype highlight_files findstring findpattern
4176
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10004177 stopfinding
Paul Mackerras687c8762007-09-22 12:49:33 +10004178 if {$findstring ne {}} {
Christian Stimmingb007ee22007-11-07 18:44:35 +01004179 if {$gdttype eq [mc "containing:"]} {
Paul Mackerras687c8762007-09-22 12:49:33 +10004180 if {$highlight_files ne {}} {
4181 set highlight_files {}
4182 hfiles_change
4183 }
4184 findcom_change
4185 } else {
4186 if {$findpattern ne {}} {
4187 set findpattern {}
4188 findcom_change
4189 }
4190 set highlight_files $findstring
4191 hfiles_change
4192 }
4193 drawvisible
4194 }
4195 # enable/disable findtype/findloc menus too
4196}
4197
4198proc find_change {name ix op} {
4199 global gdttype findstring highlight_files
4200
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10004201 stopfinding
Christian Stimmingb007ee22007-11-07 18:44:35 +01004202 if {$gdttype eq [mc "containing:"]} {
Paul Mackerras687c8762007-09-22 12:49:33 +10004203 findcom_change
4204 } else {
4205 if {$highlight_files ne $findstring} {
4206 set highlight_files $findstring
4207 hfiles_change
4208 }
4209 }
4210 drawvisible
4211}
4212
Paul Mackerras64b5f142007-10-04 22:19:24 +10004213proc findcom_change args {
Paul Mackerras28593d32008-11-13 23:01:46 +11004214 global nhighlights boldnameids
Paul Mackerras687c8762007-09-22 12:49:33 +10004215 global findpattern findtype findstring gdttype
4216
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10004217 stopfinding
Paul Mackerras687c8762007-09-22 12:49:33 +10004218 # delete previous highlights, if any
Paul Mackerras28593d32008-11-13 23:01:46 +11004219 foreach id $boldnameids {
4220 bolden_name $id mainfont
Paul Mackerras687c8762007-09-22 12:49:33 +10004221 }
Paul Mackerras28593d32008-11-13 23:01:46 +11004222 set boldnameids {}
Paul Mackerras687c8762007-09-22 12:49:33 +10004223 catch {unset nhighlights}
4224 unbolden
4225 unmarkmatches
Christian Stimmingb007ee22007-11-07 18:44:35 +01004226 if {$gdttype ne [mc "containing:"] || $findstring eq {}} {
Paul Mackerras687c8762007-09-22 12:49:33 +10004227 set findpattern {}
Christian Stimmingb007ee22007-11-07 18:44:35 +01004228 } elseif {$findtype eq [mc "Regexp"]} {
Paul Mackerras687c8762007-09-22 12:49:33 +10004229 set findpattern $findstring
4230 } else {
4231 set e [string map {"*" "\\*" "?" "\\?" "\[" "\\\[" "\\" "\\\\"} \
4232 $findstring]
4233 set findpattern "*$e*"
4234 }
4235}
4236
Paul Mackerras63b79192006-05-20 21:31:52 +10004237proc makepatterns {l} {
4238 set ret {}
4239 foreach e $l {
4240 set ee [string map {"*" "\\*" "?" "\\?" "\[" "\\\[" "\\" "\\\\"} $e]
4241 if {[string index $ee end] eq "/"} {
4242 lappend ret "$ee*"
4243 } else {
4244 lappend ret $ee
4245 lappend ret "$ee/*"
4246 }
4247 }
4248 return $ret
4249}
4250
Paul Mackerras908c3582006-05-20 09:38:11 +10004251proc do_file_hl {serial} {
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004252 global highlight_files filehighlight highlight_paths gdttype fhl_list
Paul Mackerras908c3582006-05-20 09:38:11 +10004253
Christian Stimmingb007ee22007-11-07 18:44:35 +01004254 if {$gdttype eq [mc "touching paths:"]} {
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10004255 if {[catch {set paths [shellsplit $highlight_files]}]} return
4256 set highlight_paths [makepatterns $paths]
4257 highlight_filelist
4258 set gdtargs [concat -- $paths]
Christian Stimmingb007ee22007-11-07 18:44:35 +01004259 } elseif {$gdttype eq [mc "adding/removing string:"]} {
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10004260 set gdtargs [list "-S$highlight_files"]
Paul Mackerras687c8762007-09-22 12:49:33 +10004261 } else {
4262 # must be "containing:", i.e. we're searching commit info
4263 return
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10004264 }
Brandon Casey1ce09dd2007-03-19 18:00:37 -05004265 set cmd [concat | git diff-tree -r -s --stdin $gdtargs]
Paul Mackerras908c3582006-05-20 09:38:11 +10004266 set filehighlight [open $cmd r+]
4267 fconfigure $filehighlight -blocking 0
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004268 filerun $filehighlight readfhighlight
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004269 set fhl_list {}
Paul Mackerras908c3582006-05-20 09:38:11 +10004270 drawvisible
4271 flushhighlights
4272}
4273
4274proc flushhighlights {} {
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004275 global filehighlight fhl_list
Paul Mackerras908c3582006-05-20 09:38:11 +10004276
4277 if {[info exists filehighlight]} {
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004278 lappend fhl_list {}
Paul Mackerras908c3582006-05-20 09:38:11 +10004279 puts $filehighlight ""
4280 flush $filehighlight
4281 }
4282}
4283
4284proc askfilehighlight {row id} {
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004285 global filehighlight fhighlights fhl_list
Paul Mackerras908c3582006-05-20 09:38:11 +10004286
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004287 lappend fhl_list $id
Paul Mackerras476ca632008-01-07 22:16:31 +11004288 set fhighlights($id) -1
Paul Mackerras908c3582006-05-20 09:38:11 +10004289 puts $filehighlight $id
4290}
4291
4292proc readfhighlight {} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004293 global filehighlight fhighlights curview iddrawn
Paul Mackerras687c8762007-09-22 12:49:33 +10004294 global fhl_list find_dirn
Paul Mackerras908c3582006-05-20 09:38:11 +10004295
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004296 if {![info exists filehighlight]} {
4297 return 0
4298 }
4299 set nr 0
4300 while {[incr nr] <= 100 && [gets $filehighlight line] >= 0} {
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004301 set line [string trim $line]
4302 set i [lsearch -exact $fhl_list $line]
4303 if {$i < 0} continue
4304 for {set j 0} {$j < $i} {incr j} {
4305 set id [lindex $fhl_list $j]
Paul Mackerras476ca632008-01-07 22:16:31 +11004306 set fhighlights($id) 0
Paul Mackerras908c3582006-05-20 09:38:11 +10004307 }
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004308 set fhl_list [lrange $fhl_list [expr {$i+1}] end]
4309 if {$line eq {}} continue
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004310 if {![commitinview $line $curview]} continue
Paul Mackerras476ca632008-01-07 22:16:31 +11004311 if {[info exists iddrawn($line)] && ![ishighlighted $line]} {
Paul Mackerras28593d32008-11-13 23:01:46 +11004312 bolden $line mainfontbold
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004313 }
Paul Mackerras476ca632008-01-07 22:16:31 +11004314 set fhighlights($line) 1
Paul Mackerras908c3582006-05-20 09:38:11 +10004315 }
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004316 if {[eof $filehighlight]} {
4317 # strange...
Brandon Casey1ce09dd2007-03-19 18:00:37 -05004318 puts "oops, git diff-tree died"
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004319 catch {close $filehighlight}
4320 unset filehighlight
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004321 return 0
Paul Mackerras908c3582006-05-20 09:38:11 +10004322 }
Paul Mackerras687c8762007-09-22 12:49:33 +10004323 if {[info exists find_dirn]} {
Paul Mackerrascca5d942007-10-27 21:16:56 +10004324 run findmore
Paul Mackerras687c8762007-09-22 12:49:33 +10004325 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004326 return 1
Paul Mackerras908c3582006-05-20 09:38:11 +10004327}
4328
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004329proc doesmatch {f} {
Paul Mackerras687c8762007-09-22 12:49:33 +10004330 global findtype findpattern
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004331
Christian Stimmingb007ee22007-11-07 18:44:35 +01004332 if {$findtype eq [mc "Regexp"]} {
Paul Mackerras687c8762007-09-22 12:49:33 +10004333 return [regexp $findpattern $f]
Christian Stimmingb007ee22007-11-07 18:44:35 +01004334 } elseif {$findtype eq [mc "IgnCase"]} {
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004335 return [string match -nocase $findpattern $f]
4336 } else {
4337 return [string match $findpattern $f]
4338 }
4339}
4340
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10004341proc askfindhighlight {row id} {
Paul Mackerras9c311b32007-10-04 22:27:13 +10004342 global nhighlights commitinfo iddrawn
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004343 global findloc
4344 global markingmatches
Paul Mackerras908c3582006-05-20 09:38:11 +10004345
4346 if {![info exists commitinfo($id)]} {
4347 getcommit $id
4348 }
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10004349 set info $commitinfo($id)
Paul Mackerras908c3582006-05-20 09:38:11 +10004350 set isbold 0
Christian Stimmingb007ee22007-11-07 18:44:35 +01004351 set fldtypes [list [mc Headline] [mc Author] [mc Date] [mc Committer] [mc CDate] [mc Comments]]
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10004352 foreach f $info ty $fldtypes {
Christian Stimmingb007ee22007-11-07 18:44:35 +01004353 if {($findloc eq [mc "All fields"] || $findloc eq $ty) &&
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004354 [doesmatch $f]} {
Christian Stimmingb007ee22007-11-07 18:44:35 +01004355 if {$ty eq [mc "Author"]} {
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10004356 set isbold 2
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004357 break
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10004358 }
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004359 set isbold 1
Paul Mackerras908c3582006-05-20 09:38:11 +10004360 }
4361 }
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004362 if {$isbold && [info exists iddrawn($id)]} {
Paul Mackerras476ca632008-01-07 22:16:31 +11004363 if {![ishighlighted $id]} {
Paul Mackerras28593d32008-11-13 23:01:46 +11004364 bolden $id mainfontbold
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004365 if {$isbold > 1} {
Paul Mackerras28593d32008-11-13 23:01:46 +11004366 bolden_name $id mainfontbold
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004367 }
Paul Mackerras908c3582006-05-20 09:38:11 +10004368 }
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004369 if {$markingmatches} {
Paul Mackerras005a2f42007-07-26 22:36:39 +10004370 markrowmatches $row $id
Paul Mackerras908c3582006-05-20 09:38:11 +10004371 }
4372 }
Paul Mackerras476ca632008-01-07 22:16:31 +11004373 set nhighlights($id) $isbold
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004374}
4375
Paul Mackerras005a2f42007-07-26 22:36:39 +10004376proc markrowmatches {row id} {
4377 global canv canv2 linehtag linentag commitinfo findloc
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004378
Paul Mackerras005a2f42007-07-26 22:36:39 +10004379 set headline [lindex $commitinfo($id) 0]
4380 set author [lindex $commitinfo($id) 1]
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004381 $canv delete match$row
4382 $canv2 delete match$row
Christian Stimmingb007ee22007-11-07 18:44:35 +01004383 if {$findloc eq [mc "All fields"] || $findloc eq [mc "Headline"]} {
Paul Mackerras005a2f42007-07-26 22:36:39 +10004384 set m [findmatches $headline]
4385 if {$m ne {}} {
Paul Mackerras28593d32008-11-13 23:01:46 +11004386 markmatches $canv $row $headline $linehtag($id) $m \
4387 [$canv itemcget $linehtag($id) -font] $row
Paul Mackerras005a2f42007-07-26 22:36:39 +10004388 }
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004389 }
Christian Stimmingb007ee22007-11-07 18:44:35 +01004390 if {$findloc eq [mc "All fields"] || $findloc eq [mc "Author"]} {
Paul Mackerras005a2f42007-07-26 22:36:39 +10004391 set m [findmatches $author]
4392 if {$m ne {}} {
Paul Mackerras28593d32008-11-13 23:01:46 +11004393 markmatches $canv2 $row $author $linentag($id) $m \
4394 [$canv2 itemcget $linentag($id) -font] $row
Paul Mackerras005a2f42007-07-26 22:36:39 +10004395 }
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004396 }
4397}
4398
Paul Mackerras164ff272006-05-29 19:50:02 +10004399proc vrel_change {name ix op} {
4400 global highlight_related
4401
4402 rhighlight_none
Christian Stimmingb007ee22007-11-07 18:44:35 +01004403 if {$highlight_related ne [mc "None"]} {
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004404 run drawvisible
Paul Mackerras164ff272006-05-29 19:50:02 +10004405 }
4406}
4407
4408# prepare for testing whether commits are descendents or ancestors of a
4409proc rhighlight_sel {a} {
4410 global descendent desc_todo ancestor anc_todo
Paul Mackerras476ca632008-01-07 22:16:31 +11004411 global highlight_related
Paul Mackerras164ff272006-05-29 19:50:02 +10004412
4413 catch {unset descendent}
4414 set desc_todo [list $a]
4415 catch {unset ancestor}
4416 set anc_todo [list $a]
Christian Stimmingb007ee22007-11-07 18:44:35 +01004417 if {$highlight_related ne [mc "None"]} {
Paul Mackerras164ff272006-05-29 19:50:02 +10004418 rhighlight_none
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004419 run drawvisible
Paul Mackerras164ff272006-05-29 19:50:02 +10004420 }
4421}
4422
4423proc rhighlight_none {} {
4424 global rhighlights
4425
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004426 catch {unset rhighlights}
4427 unbolden
Paul Mackerras164ff272006-05-29 19:50:02 +10004428}
4429
4430proc is_descendent {a} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004431 global curview children descendent desc_todo
Paul Mackerras164ff272006-05-29 19:50:02 +10004432
4433 set v $curview
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004434 set la [rowofcommit $a]
Paul Mackerras164ff272006-05-29 19:50:02 +10004435 set todo $desc_todo
4436 set leftover {}
4437 set done 0
4438 for {set i 0} {$i < [llength $todo]} {incr i} {
4439 set do [lindex $todo $i]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004440 if {[rowofcommit $do] < $la} {
Paul Mackerras164ff272006-05-29 19:50:02 +10004441 lappend leftover $do
4442 continue
4443 }
4444 foreach nk $children($v,$do) {
4445 if {![info exists descendent($nk)]} {
4446 set descendent($nk) 1
4447 lappend todo $nk
4448 if {$nk eq $a} {
4449 set done 1
4450 }
4451 }
4452 }
4453 if {$done} {
4454 set desc_todo [concat $leftover [lrange $todo [expr {$i+1}] end]]
4455 return
4456 }
4457 }
4458 set descendent($a) 0
4459 set desc_todo $leftover
4460}
4461
4462proc is_ancestor {a} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004463 global curview parents ancestor anc_todo
Paul Mackerras164ff272006-05-29 19:50:02 +10004464
4465 set v $curview
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004466 set la [rowofcommit $a]
Paul Mackerras164ff272006-05-29 19:50:02 +10004467 set todo $anc_todo
4468 set leftover {}
4469 set done 0
4470 for {set i 0} {$i < [llength $todo]} {incr i} {
4471 set do [lindex $todo $i]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004472 if {![commitinview $do $v] || [rowofcommit $do] > $la} {
Paul Mackerras164ff272006-05-29 19:50:02 +10004473 lappend leftover $do
4474 continue
4475 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004476 foreach np $parents($v,$do) {
Paul Mackerras164ff272006-05-29 19:50:02 +10004477 if {![info exists ancestor($np)]} {
4478 set ancestor($np) 1
4479 lappend todo $np
4480 if {$np eq $a} {
4481 set done 1
4482 }
4483 }
4484 }
4485 if {$done} {
4486 set anc_todo [concat $leftover [lrange $todo [expr {$i+1}] end]]
4487 return
4488 }
4489 }
4490 set ancestor($a) 0
4491 set anc_todo $leftover
4492}
4493
4494proc askrelhighlight {row id} {
Paul Mackerras9c311b32007-10-04 22:27:13 +10004495 global descendent highlight_related iddrawn rhighlights
Paul Mackerras164ff272006-05-29 19:50:02 +10004496 global selectedline ancestor
4497
Paul Mackerras94b4a692008-05-20 20:51:06 +10004498 if {$selectedline eq {}} return
Paul Mackerras164ff272006-05-29 19:50:02 +10004499 set isbold 0
Christian Stimming55e34432008-01-09 22:23:18 +01004500 if {$highlight_related eq [mc "Descendant"] ||
4501 $highlight_related eq [mc "Not descendant"]} {
Paul Mackerras164ff272006-05-29 19:50:02 +10004502 if {![info exists descendent($id)]} {
4503 is_descendent $id
4504 }
Christian Stimming55e34432008-01-09 22:23:18 +01004505 if {$descendent($id) == ($highlight_related eq [mc "Descendant"])} {
Paul Mackerras164ff272006-05-29 19:50:02 +10004506 set isbold 1
4507 }
Christian Stimmingb007ee22007-11-07 18:44:35 +01004508 } elseif {$highlight_related eq [mc "Ancestor"] ||
4509 $highlight_related eq [mc "Not ancestor"]} {
Paul Mackerras164ff272006-05-29 19:50:02 +10004510 if {![info exists ancestor($id)]} {
4511 is_ancestor $id
4512 }
Christian Stimmingb007ee22007-11-07 18:44:35 +01004513 if {$ancestor($id) == ($highlight_related eq [mc "Ancestor"])} {
Paul Mackerras164ff272006-05-29 19:50:02 +10004514 set isbold 1
4515 }
4516 }
4517 if {[info exists iddrawn($id)]} {
Paul Mackerras476ca632008-01-07 22:16:31 +11004518 if {$isbold && ![ishighlighted $id]} {
Paul Mackerras28593d32008-11-13 23:01:46 +11004519 bolden $id mainfontbold
Paul Mackerras164ff272006-05-29 19:50:02 +10004520 }
4521 }
Paul Mackerras476ca632008-01-07 22:16:31 +11004522 set rhighlights($id) $isbold
Paul Mackerras164ff272006-05-29 19:50:02 +10004523}
4524
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004525# Graph layout functions
4526
Paul Mackerras9f1afe02006-02-19 22:44:47 +11004527proc shortids {ids} {
4528 set res {}
4529 foreach id $ids {
4530 if {[llength $id] > 1} {
4531 lappend res [shortids $id]
4532 } elseif {[regexp {^[0-9a-f]{40}$} $id]} {
4533 lappend res [string range $id 0 7]
4534 } else {
4535 lappend res $id
4536 }
4537 }
4538 return $res
4539}
4540
Paul Mackerras9f1afe02006-02-19 22:44:47 +11004541proc ntimes {n o} {
4542 set ret {}
Paul Mackerras03800812007-08-29 21:45:21 +10004543 set o [list $o]
4544 for {set mask 1} {$mask <= $n} {incr mask $mask} {
4545 if {($n & $mask) != 0} {
4546 set ret [concat $ret $o]
4547 }
4548 set o [concat $o $o]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11004549 }
4550 return $ret
4551}
4552
Paul Mackerras9257d8f2007-12-11 10:45:38 +11004553proc ordertoken {id} {
4554 global ordertok curview varcid varcstart varctok curview parents children
4555 global nullid nullid2
4556
4557 if {[info exists ordertok($id)]} {
4558 return $ordertok($id)
4559 }
4560 set origid $id
4561 set todo {}
4562 while {1} {
4563 if {[info exists varcid($curview,$id)]} {
4564 set a $varcid($curview,$id)
4565 set p [lindex $varcstart($curview) $a]
4566 } else {
4567 set p [lindex $children($curview,$id) 0]
4568 }
4569 if {[info exists ordertok($p)]} {
4570 set tok $ordertok($p)
4571 break
4572 }
Paul Mackerrasc8c9f3d2008-01-06 13:54:58 +11004573 set id [first_real_child $curview,$p]
4574 if {$id eq {}} {
Paul Mackerras9257d8f2007-12-11 10:45:38 +11004575 # it's a root
Paul Mackerras46308ea2008-01-15 22:16:32 +11004576 set tok [lindex $varctok($curview) $varcid($curview,$p)]
Paul Mackerras9257d8f2007-12-11 10:45:38 +11004577 break
4578 }
Paul Mackerras9257d8f2007-12-11 10:45:38 +11004579 if {[llength $parents($curview,$id)] == 1} {
4580 lappend todo [list $p {}]
4581 } else {
4582 set j [lsearch -exact $parents($curview,$id) $p]
4583 if {$j < 0} {
4584 puts "oops didn't find [shortids $p] in parents of [shortids $id]"
4585 }
4586 lappend todo [list $p [strrep $j]]
4587 }
4588 }
4589 for {set i [llength $todo]} {[incr i -1] >= 0} {} {
4590 set p [lindex $todo $i 0]
4591 append tok [lindex $todo $i 1]
4592 set ordertok($p) $tok
4593 }
4594 set ordertok($origid) $tok
4595 return $tok
4596}
4597
Paul Mackerras6e8c8702007-07-31 21:03:06 +10004598# Work out where id should go in idlist so that order-token
4599# values increase from left to right
4600proc idcol {idlist id {i 0}} {
Paul Mackerras9257d8f2007-12-11 10:45:38 +11004601 set t [ordertoken $id]
Paul Mackerrase5b37ac2007-12-12 18:13:51 +11004602 if {$i < 0} {
4603 set i 0
4604 }
Paul Mackerras9257d8f2007-12-11 10:45:38 +11004605 if {$i >= [llength $idlist] || $t < [ordertoken [lindex $idlist $i]]} {
Paul Mackerras6e8c8702007-07-31 21:03:06 +10004606 if {$i > [llength $idlist]} {
4607 set i [llength $idlist]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11004608 }
Paul Mackerras9257d8f2007-12-11 10:45:38 +11004609 while {[incr i -1] >= 0 && $t < [ordertoken [lindex $idlist $i]]} {}
Paul Mackerras6e8c8702007-07-31 21:03:06 +10004610 incr i
4611 } else {
Paul Mackerras9257d8f2007-12-11 10:45:38 +11004612 if {$t > [ordertoken [lindex $idlist $i]]} {
Paul Mackerras6e8c8702007-07-31 21:03:06 +10004613 while {[incr i] < [llength $idlist] &&
Paul Mackerras9257d8f2007-12-11 10:45:38 +11004614 $t >= [ordertoken [lindex $idlist $i]]} {}
Paul Mackerras9f1afe02006-02-19 22:44:47 +11004615 }
4616 }
Paul Mackerras6e8c8702007-07-31 21:03:06 +10004617 return $i
Paul Mackerras9f1afe02006-02-19 22:44:47 +11004618}
4619
4620proc initlayout {} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004621 global rowidlist rowisopt rowfinal displayorder parentlist
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004622 global numcommits canvxmax canv
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11004623 global nextcolor
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004624 global colormap rowtextx
Paul Mackerras9f1afe02006-02-19 22:44:47 +11004625
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11004626 set numcommits 0
4627 set displayorder {}
Paul Mackerras79b2c752006-04-02 20:47:40 +10004628 set parentlist {}
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11004629 set nextcolor 0
Paul Mackerras03800812007-08-29 21:45:21 +10004630 set rowidlist {}
4631 set rowisopt {}
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10004632 set rowfinal {}
Paul Mackerrasbe0cd092006-03-31 09:55:11 +11004633 set canvxmax [$canv cget -width]
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004634 catch {unset colormap}
4635 catch {unset rowtextx}
Paul Mackerrasac1276a2008-03-03 10:11:08 +11004636 setcanvscroll
Paul Mackerrasbe0cd092006-03-31 09:55:11 +11004637}
4638
4639proc setcanvscroll {} {
4640 global canv canv2 canv3 numcommits linespc canvxmax canvy0
Paul Mackerrasac1276a2008-03-03 10:11:08 +11004641 global lastscrollset lastscrollrows
Paul Mackerrasbe0cd092006-03-31 09:55:11 +11004642
4643 set ymax [expr {$canvy0 + ($numcommits - 0.5) * $linespc + 2}]
4644 $canv conf -scrollregion [list 0 0 $canvxmax $ymax]
4645 $canv2 conf -scrollregion [list 0 0 0 $ymax]
4646 $canv3 conf -scrollregion [list 0 0 0 $ymax]
Paul Mackerrasac1276a2008-03-03 10:11:08 +11004647 set lastscrollset [clock clicks -milliseconds]
4648 set lastscrollrows $numcommits
Paul Mackerras9f1afe02006-02-19 22:44:47 +11004649}
4650
4651proc visiblerows {} {
4652 global canv numcommits linespc
4653
4654 set ymax [lindex [$canv cget -scrollregion] 3]
4655 if {$ymax eq {} || $ymax == 0} return
4656 set f [$canv yview]
4657 set y0 [expr {int([lindex $f 0] * $ymax)}]
4658 set r0 [expr {int(($y0 - 3) / $linespc) - 1}]
4659 if {$r0 < 0} {
4660 set r0 0
4661 }
4662 set y1 [expr {int([lindex $f 1] * $ymax)}]
4663 set r1 [expr {int(($y1 - 3) / $linespc) + 1}]
4664 if {$r1 >= $numcommits} {
4665 set r1 [expr {$numcommits - 1}]
4666 }
4667 return [list $r0 $r1]
4668}
4669
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10004670proc layoutmore {} {
Paul Mackerras38dfe932007-12-06 20:50:31 +11004671 global commitidx viewcomplete curview
Paul Mackerras94b4a692008-05-20 20:51:06 +10004672 global numcommits pending_select curview
Paul Mackerrasd375ef92008-10-21 10:18:12 +11004673 global lastscrollset lastscrollrows
Paul Mackerras9f1afe02006-02-19 22:44:47 +11004674
Paul Mackerrasac1276a2008-03-03 10:11:08 +11004675 if {$lastscrollrows < 100 || $viewcomplete($curview) ||
4676 [clock clicks -milliseconds] - $lastscrollset > 500} {
Paul Mackerrasa2c22362006-10-31 15:00:53 +11004677 setcanvscroll
4678 }
Paul Mackerrasd94f8cd2006-04-06 10:18:23 +10004679 if {[info exists pending_select] &&
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004680 [commitinview $pending_select $curview]} {
Alexander Gavrilov567c34e2008-07-26 20:13:45 +04004681 update
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004682 selectline [rowofcommit $pending_select] 1
Paul Mackerrasd94f8cd2006-04-06 10:18:23 +10004683 }
Paul Mackerrasac1276a2008-03-03 10:11:08 +11004684 drawvisible
Paul Mackerras219ea3a2006-09-07 10:21:39 +10004685}
4686
Paul Mackerrascdc84292008-11-18 19:54:14 +11004687# With path limiting, we mightn't get the actual HEAD commit,
4688# so ask git rev-list what is the first ancestor of HEAD that
4689# touches a file in the path limit.
4690proc get_viewmainhead {view} {
4691 global viewmainheadid vfilelimit viewinstances mainheadid
Paul Mackerras219ea3a2006-09-07 10:21:39 +10004692
Paul Mackerrascdc84292008-11-18 19:54:14 +11004693 catch {
4694 set rfd [open [concat | git rev-list -1 $mainheadid \
4695 -- $vfilelimit($view)] r]
4696 set j [reg_instance $rfd]
4697 lappend viewinstances($view) $j
4698 fconfigure $rfd -blocking 0
4699 filerun $rfd [list getviewhead $rfd $j $view]
4700 set viewmainheadid($curview) {}
4701 }
4702}
4703
4704# git rev-list should give us just 1 line to use as viewmainheadid($view)
4705proc getviewhead {fd inst view} {
4706 global viewmainheadid commfd curview viewinstances showlocalchanges
4707
4708 set id {}
4709 if {[gets $fd line] < 0} {
4710 if {![eof $fd]} {
4711 return 1
4712 }
4713 } elseif {[string length $line] == 40 && [string is xdigit $line]} {
4714 set id $line
4715 }
4716 set viewmainheadid($view) $id
4717 close $fd
4718 unset commfd($inst)
4719 set i [lsearch -exact $viewinstances($view) $inst]
4720 if {$i >= 0} {
4721 set viewinstances($view) [lreplace $viewinstances($view) $i $i]
4722 }
4723 if {$showlocalchanges && $id ne {} && $view == $curview} {
4724 doshowlocalchanges
4725 }
4726 return 0
4727}
4728
4729proc doshowlocalchanges {} {
4730 global curview viewmainheadid
4731
4732 if {$viewmainheadid($curview) eq {}} return
4733 if {[commitinview $viewmainheadid($curview) $curview]} {
Paul Mackerras219ea3a2006-09-07 10:21:39 +10004734 dodiffindex
Paul Mackerras38dfe932007-12-06 20:50:31 +11004735 } else {
Paul Mackerrascdc84292008-11-18 19:54:14 +11004736 interestedin $viewmainheadid($curview) dodiffindex
Paul Mackerras219ea3a2006-09-07 10:21:39 +10004737 }
4738}
4739
4740proc dohidelocalchanges {} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004741 global nullid nullid2 lserial curview
Paul Mackerras219ea3a2006-09-07 10:21:39 +10004742
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004743 if {[commitinview $nullid $curview]} {
Paul Mackerrasb8a938c2008-02-13 22:12:31 +11004744 removefakerow $nullid
Paul Mackerras8f489362007-07-13 19:49:37 +10004745 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004746 if {[commitinview $nullid2 $curview]} {
Paul Mackerrasb8a938c2008-02-13 22:12:31 +11004747 removefakerow $nullid2
Paul Mackerras219ea3a2006-09-07 10:21:39 +10004748 }
4749 incr lserial
4750}
4751
Paul Mackerras8f489362007-07-13 19:49:37 +10004752# spawn off a process to do git diff-index --cached HEAD
Paul Mackerras219ea3a2006-09-07 10:21:39 +10004753proc dodiffindex {} {
Paul Mackerrascdc84292008-11-18 19:54:14 +11004754 global lserial showlocalchanges vfilelimit curview
David Aguilarcb8329a2008-03-10 03:54:56 -07004755 global isworktree
Paul Mackerras219ea3a2006-09-07 10:21:39 +10004756
David Aguilarcb8329a2008-03-10 03:54:56 -07004757 if {!$showlocalchanges || !$isworktree} return
Paul Mackerras219ea3a2006-09-07 10:21:39 +10004758 incr lserial
Paul Mackerrascdc84292008-11-18 19:54:14 +11004759 set cmd "|git diff-index --cached HEAD"
4760 if {$vfilelimit($curview) ne {}} {
4761 set cmd [concat $cmd -- $vfilelimit($curview)]
4762 }
4763 set fd [open $cmd r]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10004764 fconfigure $fd -blocking 0
Alexander Gavrilove439e092008-07-13 16:40:47 +04004765 set i [reg_instance $fd]
4766 filerun $fd [list readdiffindex $fd $lserial $i]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10004767}
4768
Alexander Gavrilove439e092008-07-13 16:40:47 +04004769proc readdiffindex {fd serial inst} {
Paul Mackerrascdc84292008-11-18 19:54:14 +11004770 global viewmainheadid nullid nullid2 curview commitinfo commitdata lserial
4771 global vfilelimit
Paul Mackerras219ea3a2006-09-07 10:21:39 +10004772
Paul Mackerras8f489362007-07-13 19:49:37 +10004773 set isdiff 1
Paul Mackerras219ea3a2006-09-07 10:21:39 +10004774 if {[gets $fd line] < 0} {
Paul Mackerras8f489362007-07-13 19:49:37 +10004775 if {![eof $fd]} {
4776 return 1
Paul Mackerras219ea3a2006-09-07 10:21:39 +10004777 }
Paul Mackerras8f489362007-07-13 19:49:37 +10004778 set isdiff 0
Paul Mackerras219ea3a2006-09-07 10:21:39 +10004779 }
4780 # we only need to see one line and we don't really care what it says...
Alexander Gavrilove439e092008-07-13 16:40:47 +04004781 stop_instance $inst
Paul Mackerras219ea3a2006-09-07 10:21:39 +10004782
Paul Mackerras24f7a662007-12-19 09:35:33 +11004783 if {$serial != $lserial} {
4784 return 0
Paul Mackerras8f489362007-07-13 19:49:37 +10004785 }
4786
Paul Mackerras24f7a662007-12-19 09:35:33 +11004787 # now see if there are any local changes not checked in to the index
Paul Mackerrascdc84292008-11-18 19:54:14 +11004788 set cmd "|git diff-files"
4789 if {$vfilelimit($curview) ne {}} {
4790 set cmd [concat $cmd -- $vfilelimit($curview)]
4791 }
4792 set fd [open $cmd r]
Paul Mackerras24f7a662007-12-19 09:35:33 +11004793 fconfigure $fd -blocking 0
Alexander Gavrilove439e092008-07-13 16:40:47 +04004794 set i [reg_instance $fd]
4795 filerun $fd [list readdifffiles $fd $serial $i]
Paul Mackerras24f7a662007-12-19 09:35:33 +11004796
4797 if {$isdiff && ![commitinview $nullid2 $curview]} {
Paul Mackerras8f489362007-07-13 19:49:37 +10004798 # add the line for the changes in the index to the graph
Christian Stimmingd990ced2007-11-07 18:42:55 +01004799 set hl [mc "Local changes checked in to index but not committed"]
Paul Mackerras8f489362007-07-13 19:49:37 +10004800 set commitinfo($nullid2) [list $hl {} {} {} {} " $hl\n"]
4801 set commitdata($nullid2) "\n $hl\n"
Paul Mackerrasfc2a2562007-12-26 23:03:43 +11004802 if {[commitinview $nullid $curview]} {
Paul Mackerrasb8a938c2008-02-13 22:12:31 +11004803 removefakerow $nullid
Paul Mackerrasfc2a2562007-12-26 23:03:43 +11004804 }
Paul Mackerrascdc84292008-11-18 19:54:14 +11004805 insertfakerow $nullid2 $viewmainheadid($curview)
Paul Mackerras24f7a662007-12-19 09:35:33 +11004806 } elseif {!$isdiff && [commitinview $nullid2 $curview]} {
Paul Mackerrascdc84292008-11-18 19:54:14 +11004807 if {[commitinview $nullid $curview]} {
4808 removefakerow $nullid
4809 }
Paul Mackerrasb8a938c2008-02-13 22:12:31 +11004810 removefakerow $nullid2
Paul Mackerras8f489362007-07-13 19:49:37 +10004811 }
4812 return 0
4813}
4814
Alexander Gavrilove439e092008-07-13 16:40:47 +04004815proc readdifffiles {fd serial inst} {
Paul Mackerrascdc84292008-11-18 19:54:14 +11004816 global viewmainheadid nullid nullid2 curview
Paul Mackerras8f489362007-07-13 19:49:37 +10004817 global commitinfo commitdata lserial
4818
4819 set isdiff 1
4820 if {[gets $fd line] < 0} {
4821 if {![eof $fd]} {
4822 return 1
4823 }
4824 set isdiff 0
4825 }
4826 # we only need to see one line and we don't really care what it says...
Alexander Gavrilove439e092008-07-13 16:40:47 +04004827 stop_instance $inst
Paul Mackerras8f489362007-07-13 19:49:37 +10004828
Paul Mackerras24f7a662007-12-19 09:35:33 +11004829 if {$serial != $lserial} {
4830 return 0
4831 }
4832
4833 if {$isdiff && ![commitinview $nullid $curview]} {
Paul Mackerras219ea3a2006-09-07 10:21:39 +10004834 # add the line for the local diff to the graph
Christian Stimmingd990ced2007-11-07 18:42:55 +01004835 set hl [mc "Local uncommitted changes, not checked in to index"]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10004836 set commitinfo($nullid) [list $hl {} {} {} {} " $hl\n"]
4837 set commitdata($nullid) "\n $hl\n"
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004838 if {[commitinview $nullid2 $curview]} {
4839 set p $nullid2
4840 } else {
Paul Mackerrascdc84292008-11-18 19:54:14 +11004841 set p $viewmainheadid($curview)
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004842 }
Paul Mackerrasb8a938c2008-02-13 22:12:31 +11004843 insertfakerow $nullid $p
Paul Mackerras24f7a662007-12-19 09:35:33 +11004844 } elseif {!$isdiff && [commitinview $nullid $curview]} {
Paul Mackerrasb8a938c2008-02-13 22:12:31 +11004845 removefakerow $nullid
Paul Mackerras219ea3a2006-09-07 10:21:39 +10004846 }
4847 return 0
Paul Mackerras9f1afe02006-02-19 22:44:47 +11004848}
4849
Paul Mackerras8f0bc7e2007-08-24 22:16:42 +10004850proc nextuse {id row} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004851 global curview children
Paul Mackerras8f0bc7e2007-08-24 22:16:42 +10004852
4853 if {[info exists children($curview,$id)]} {
4854 foreach kid $children($curview,$id) {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004855 if {![commitinview $kid $curview]} {
Paul Mackerras03800812007-08-29 21:45:21 +10004856 return -1
4857 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004858 if {[rowofcommit $kid] > $row} {
4859 return [rowofcommit $kid]
Paul Mackerras8f0bc7e2007-08-24 22:16:42 +10004860 }
4861 }
4862 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004863 if {[commitinview $id $curview]} {
4864 return [rowofcommit $id]
Paul Mackerras8f0bc7e2007-08-24 22:16:42 +10004865 }
4866 return -1
4867}
4868
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10004869proc prevuse {id row} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004870 global curview children
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10004871
4872 set ret -1
4873 if {[info exists children($curview,$id)]} {
4874 foreach kid $children($curview,$id) {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004875 if {![commitinview $kid $curview]} break
4876 if {[rowofcommit $kid] < $row} {
4877 set ret [rowofcommit $kid]
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10004878 }
4879 }
4880 }
4881 return $ret
4882}
4883
Paul Mackerras03800812007-08-29 21:45:21 +10004884proc make_idlist {row} {
4885 global displayorder parentlist uparrowlen downarrowlen mingaplen
Paul Mackerras9257d8f2007-12-11 10:45:38 +11004886 global commitidx curview children
Paul Mackerras03800812007-08-29 21:45:21 +10004887
4888 set r [expr {$row - $mingaplen - $downarrowlen - 1}]
4889 if {$r < 0} {
4890 set r 0
4891 }
4892 set ra [expr {$row - $downarrowlen}]
4893 if {$ra < 0} {
4894 set ra 0
4895 }
4896 set rb [expr {$row + $uparrowlen}]
4897 if {$rb > $commitidx($curview)} {
4898 set rb $commitidx($curview)
4899 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004900 make_disporder $r [expr {$rb + 1}]
Paul Mackerras03800812007-08-29 21:45:21 +10004901 set ids {}
4902 for {} {$r < $ra} {incr r} {
4903 set nextid [lindex $displayorder [expr {$r + 1}]]
4904 foreach p [lindex $parentlist $r] {
4905 if {$p eq $nextid} continue
4906 set rn [nextuse $p $r]
4907 if {$rn >= $row &&
4908 $rn <= $r + $downarrowlen + $mingaplen + $uparrowlen} {
Paul Mackerras9257d8f2007-12-11 10:45:38 +11004909 lappend ids [list [ordertoken $p] $p]
Paul Mackerras03800812007-08-29 21:45:21 +10004910 }
4911 }
4912 }
4913 for {} {$r < $row} {incr r} {
4914 set nextid [lindex $displayorder [expr {$r + 1}]]
4915 foreach p [lindex $parentlist $r] {
4916 if {$p eq $nextid} continue
4917 set rn [nextuse $p $r]
4918 if {$rn < 0 || $rn >= $row} {
Paul Mackerras9257d8f2007-12-11 10:45:38 +11004919 lappend ids [list [ordertoken $p] $p]
Paul Mackerras03800812007-08-29 21:45:21 +10004920 }
4921 }
4922 }
4923 set id [lindex $displayorder $row]
Paul Mackerras9257d8f2007-12-11 10:45:38 +11004924 lappend ids [list [ordertoken $id] $id]
Paul Mackerras03800812007-08-29 21:45:21 +10004925 while {$r < $rb} {
4926 foreach p [lindex $parentlist $r] {
4927 set firstkid [lindex $children($curview,$p) 0]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004928 if {[rowofcommit $firstkid] < $row} {
Paul Mackerras9257d8f2007-12-11 10:45:38 +11004929 lappend ids [list [ordertoken $p] $p]
Paul Mackerras03800812007-08-29 21:45:21 +10004930 }
4931 }
4932 incr r
4933 set id [lindex $displayorder $r]
4934 if {$id ne {}} {
4935 set firstkid [lindex $children($curview,$id) 0]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004936 if {$firstkid ne {} && [rowofcommit $firstkid] < $row} {
Paul Mackerras9257d8f2007-12-11 10:45:38 +11004937 lappend ids [list [ordertoken $id] $id]
Paul Mackerras03800812007-08-29 21:45:21 +10004938 }
4939 }
4940 }
4941 set idlist {}
4942 foreach idx [lsort -unique $ids] {
4943 lappend idlist [lindex $idx 1]
4944 }
4945 return $idlist
4946}
4947
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10004948proc rowsequal {a b} {
4949 while {[set i [lsearch -exact $a {}]] >= 0} {
4950 set a [lreplace $a $i $i]
4951 }
4952 while {[set i [lsearch -exact $b {}]] >= 0} {
4953 set b [lreplace $b $i $i]
4954 }
4955 return [expr {$a eq $b}]
4956}
4957
4958proc makeupline {id row rend col} {
4959 global rowidlist uparrowlen downarrowlen mingaplen
4960
4961 for {set r $rend} {1} {set r $rstart} {
4962 set rstart [prevuse $id $r]
4963 if {$rstart < 0} return
4964 if {$rstart < $row} break
4965 }
4966 if {$rstart + $uparrowlen + $mingaplen + $downarrowlen < $rend} {
4967 set rstart [expr {$rend - $uparrowlen - 1}]
4968 }
4969 for {set r $rstart} {[incr r] <= $row} {} {
4970 set idlist [lindex $rowidlist $r]
4971 if {$idlist ne {} && [lsearch -exact $idlist $id] < 0} {
4972 set col [idcol $idlist $id $col]
4973 lset rowidlist $r [linsert $idlist $col $id]
4974 changedrow $r
4975 }
4976 }
4977}
4978
Paul Mackerras03800812007-08-29 21:45:21 +10004979proc layoutrows {row endrow} {
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10004980 global rowidlist rowisopt rowfinal displayorder
Paul Mackerras9f1afe02006-02-19 22:44:47 +11004981 global uparrowlen downarrowlen maxwidth mingaplen
Paul Mackerras6a90bff2007-06-18 09:48:23 +10004982 global children parentlist
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004983 global commitidx viewcomplete curview
Paul Mackerras9f1afe02006-02-19 22:44:47 +11004984
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004985 make_disporder [expr {$row - 1}] [expr {$endrow + $uparrowlen}]
Paul Mackerras03800812007-08-29 21:45:21 +10004986 set idlist {}
4987 if {$row > 0} {
Paul Mackerrasf56782a2007-09-15 09:04:11 +10004988 set rm1 [expr {$row - 1}]
4989 foreach id [lindex $rowidlist $rm1] {
Paul Mackerras03800812007-08-29 21:45:21 +10004990 if {$id ne {}} {
4991 lappend idlist $id
Paul Mackerras9f1afe02006-02-19 22:44:47 +11004992 }
4993 }
Paul Mackerrasf56782a2007-09-15 09:04:11 +10004994 set final [lindex $rowfinal $rm1]
Paul Mackerras8f0bc7e2007-08-24 22:16:42 +10004995 }
Paul Mackerras03800812007-08-29 21:45:21 +10004996 for {} {$row < $endrow} {incr row} {
4997 set rm1 [expr {$row - 1}]
Paul Mackerrasf56782a2007-09-15 09:04:11 +10004998 if {$rm1 < 0 || $idlist eq {}} {
Paul Mackerras03800812007-08-29 21:45:21 +10004999 set idlist [make_idlist $row]
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10005000 set final 1
Paul Mackerras03800812007-08-29 21:45:21 +10005001 } else {
5002 set id [lindex $displayorder $rm1]
5003 set col [lsearch -exact $idlist $id]
5004 set idlist [lreplace $idlist $col $col]
5005 foreach p [lindex $parentlist $rm1] {
5006 if {[lsearch -exact $idlist $p] < 0} {
5007 set col [idcol $idlist $p $col]
5008 set idlist [linsert $idlist $col $p]
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10005009 # if not the first child, we have to insert a line going up
5010 if {$id ne [lindex $children($curview,$p) 0]} {
5011 makeupline $p $rm1 $row $col
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005012 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005013 }
5014 }
Paul Mackerras03800812007-08-29 21:45:21 +10005015 set id [lindex $displayorder $row]
5016 if {$row > $downarrowlen} {
5017 set termrow [expr {$row - $downarrowlen - 1}]
5018 foreach p [lindex $parentlist $termrow] {
5019 set i [lsearch -exact $idlist $p]
5020 if {$i < 0} continue
5021 set nr [nextuse $p $termrow]
5022 if {$nr < 0 || $nr >= $row + $mingaplen + $uparrowlen} {
5023 set idlist [lreplace $idlist $i $i]
5024 }
5025 }
5026 }
5027 set col [lsearch -exact $idlist $id]
5028 if {$col < 0} {
5029 set col [idcol $idlist $id]
5030 set idlist [linsert $idlist $col $id]
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10005031 if {$children($curview,$id) ne {}} {
5032 makeupline $id $rm1 $row $col
5033 }
Paul Mackerras03800812007-08-29 21:45:21 +10005034 }
5035 set r [expr {$row + $uparrowlen - 1}]
5036 if {$r < $commitidx($curview)} {
5037 set x $col
5038 foreach p [lindex $parentlist $r] {
5039 if {[lsearch -exact $idlist $p] >= 0} continue
5040 set fk [lindex $children($curview,$p) 0]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005041 if {[rowofcommit $fk] < $row} {
Paul Mackerras03800812007-08-29 21:45:21 +10005042 set x [idcol $idlist $p $x]
5043 set idlist [linsert $idlist $x $p]
5044 }
5045 }
5046 if {[incr r] < $commitidx($curview)} {
5047 set p [lindex $displayorder $r]
5048 if {[lsearch -exact $idlist $p] < 0} {
5049 set fk [lindex $children($curview,$p) 0]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005050 if {$fk ne {} && [rowofcommit $fk] < $row} {
Paul Mackerras03800812007-08-29 21:45:21 +10005051 set x [idcol $idlist $p $x]
5052 set idlist [linsert $idlist $x $p]
5053 }
5054 }
5055 }
Paul Mackerras7b459a12007-08-13 14:52:00 +10005056 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005057 }
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10005058 if {$final && !$viewcomplete($curview) &&
5059 $row + $uparrowlen + $mingaplen + $downarrowlen
5060 >= $commitidx($curview)} {
5061 set final 0
Paul Mackerras7b459a12007-08-13 14:52:00 +10005062 }
Paul Mackerras03800812007-08-29 21:45:21 +10005063 set l [llength $rowidlist]
5064 if {$row == $l} {
5065 lappend rowidlist $idlist
5066 lappend rowisopt 0
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10005067 lappend rowfinal $final
Paul Mackerras03800812007-08-29 21:45:21 +10005068 } elseif {$row < $l} {
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10005069 if {![rowsequal $idlist [lindex $rowidlist $row]]} {
Paul Mackerras03800812007-08-29 21:45:21 +10005070 lset rowidlist $row $idlist
5071 changedrow $row
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005072 }
Paul Mackerrasf56782a2007-09-15 09:04:11 +10005073 lset rowfinal $row $final
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005074 } else {
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10005075 set pad [ntimes [expr {$row - $l}] {}]
5076 set rowidlist [concat $rowidlist $pad]
Paul Mackerras03800812007-08-29 21:45:21 +10005077 lappend rowidlist $idlist
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10005078 set rowfinal [concat $rowfinal $pad]
5079 lappend rowfinal $final
Paul Mackerras03800812007-08-29 21:45:21 +10005080 set rowisopt [concat $rowisopt [ntimes [expr {$row - $l + 1}] 0]]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005081 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005082 }
5083 return $row
5084}
5085
Paul Mackerras03800812007-08-29 21:45:21 +10005086proc changedrow {row} {
5087 global displayorder iddrawn rowisopt need_redisplay
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005088
Paul Mackerras03800812007-08-29 21:45:21 +10005089 set l [llength $rowisopt]
5090 if {$row < $l} {
5091 lset rowisopt $row 0
5092 if {$row + 1 < $l} {
5093 lset rowisopt [expr {$row + 1}] 0
5094 if {$row + 2 < $l} {
5095 lset rowisopt [expr {$row + 2}] 0
5096 }
5097 }
Paul Mackerras79b2c752006-04-02 20:47:40 +10005098 }
Paul Mackerras03800812007-08-29 21:45:21 +10005099 set id [lindex $displayorder $row]
5100 if {[info exists iddrawn($id)]} {
5101 set need_redisplay 1
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005102 }
5103}
5104
5105proc insert_pad {row col npad} {
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005106 global rowidlist
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005107
5108 set pad [ntimes $npad {}]
Paul Mackerrase341c062007-08-12 12:42:57 +10005109 set idlist [lindex $rowidlist $row]
5110 set bef [lrange $idlist 0 [expr {$col - 1}]]
5111 set aft [lrange $idlist $col end]
5112 set i [lsearch -exact $aft {}]
5113 if {$i > 0} {
5114 set aft [lreplace $aft $i $i]
5115 }
5116 lset rowidlist $row [concat $bef $pad $aft]
Paul Mackerras03800812007-08-29 21:45:21 +10005117 changedrow $row
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005118}
5119
5120proc optimize_rows {row col endrow} {
Paul Mackerras03800812007-08-29 21:45:21 +10005121 global rowidlist rowisopt displayorder curview children
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005122
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005123 if {$row < 1} {
5124 set row 1
5125 }
Paul Mackerras03800812007-08-29 21:45:21 +10005126 for {} {$row < $endrow} {incr row; set col 0} {
5127 if {[lindex $rowisopt $row]} continue
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005128 set haspad 0
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005129 set y0 [expr {$row - 1}]
5130 set ym [expr {$row - 2}]
Paul Mackerras03800812007-08-29 21:45:21 +10005131 set idlist [lindex $rowidlist $row]
5132 set previdlist [lindex $rowidlist $y0]
5133 if {$idlist eq {} || $previdlist eq {}} continue
5134 if {$ym >= 0} {
5135 set pprevidlist [lindex $rowidlist $ym]
5136 if {$pprevidlist eq {}} continue
5137 } else {
5138 set pprevidlist {}
5139 }
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005140 set x0 -1
5141 set xm -1
5142 for {} {$col < [llength $idlist]} {incr col} {
5143 set id [lindex $idlist $col]
5144 if {[lindex $previdlist $col] eq $id} continue
5145 if {$id eq {}} {
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005146 set haspad 1
5147 continue
5148 }
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005149 set x0 [lsearch -exact $previdlist $id]
5150 if {$x0 < 0} continue
5151 set z [expr {$x0 - $col}]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005152 set isarrow 0
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005153 set z0 {}
5154 if {$ym >= 0} {
5155 set xm [lsearch -exact $pprevidlist $id]
5156 if {$xm >= 0} {
5157 set z0 [expr {$xm - $x0}]
5158 }
5159 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005160 if {$z0 eq {}} {
Paul Mackerras92ed6662007-08-22 22:35:28 +10005161 # if row y0 is the first child of $id then it's not an arrow
5162 if {[lindex $children($curview,$id) 0] ne
5163 [lindex $displayorder $y0]} {
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005164 set isarrow 1
5165 }
5166 }
Paul Mackerrase341c062007-08-12 12:42:57 +10005167 if {!$isarrow && $id ne [lindex $displayorder $row] &&
5168 [lsearch -exact [lindex $rowidlist [expr {$row+1}]] $id] < 0} {
5169 set isarrow 1
5170 }
Paul Mackerras3fc42792006-09-15 09:45:23 +10005171 # Looking at lines from this row to the previous row,
5172 # make them go straight up if they end in an arrow on
5173 # the previous row; otherwise make them go straight up
5174 # or at 45 degrees.
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005175 if {$z < -1 || ($z < 0 && $isarrow)} {
Paul Mackerras3fc42792006-09-15 09:45:23 +10005176 # Line currently goes left too much;
5177 # insert pads in the previous row, then optimize it
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005178 set npad [expr {-1 - $z + $isarrow}]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005179 insert_pad $y0 $x0 $npad
5180 if {$y0 > 0} {
5181 optimize_rows $y0 $x0 $row
5182 }
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005183 set previdlist [lindex $rowidlist $y0]
5184 set x0 [lsearch -exact $previdlist $id]
5185 set z [expr {$x0 - $col}]
5186 if {$z0 ne {}} {
5187 set pprevidlist [lindex $rowidlist $ym]
5188 set xm [lsearch -exact $pprevidlist $id]
5189 set z0 [expr {$xm - $x0}]
5190 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005191 } elseif {$z > 1 || ($z > 0 && $isarrow)} {
Paul Mackerras3fc42792006-09-15 09:45:23 +10005192 # Line currently goes right too much;
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005193 # insert pads in this line
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005194 set npad [expr {$z - 1 + $isarrow}]
Paul Mackerrase341c062007-08-12 12:42:57 +10005195 insert_pad $row $col $npad
5196 set idlist [lindex $rowidlist $row]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005197 incr col $npad
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005198 set z [expr {$x0 - $col}]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005199 set haspad 1
5200 }
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005201 if {$z0 eq {} && !$isarrow && $ym >= 0} {
Paul Mackerraseb447a12006-03-18 23:11:37 +11005202 # this line links to its first child on row $row-2
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005203 set id [lindex $displayorder $ym]
5204 set xc [lsearch -exact $pprevidlist $id]
Paul Mackerraseb447a12006-03-18 23:11:37 +11005205 if {$xc >= 0} {
5206 set z0 [expr {$xc - $x0}]
5207 }
5208 }
Paul Mackerras3fc42792006-09-15 09:45:23 +10005209 # avoid lines jigging left then immediately right
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005210 if {$z0 ne {} && $z < 0 && $z0 > 0} {
5211 insert_pad $y0 $x0 1
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005212 incr x0
5213 optimize_rows $y0 $x0 $row
5214 set previdlist [lindex $rowidlist $y0]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005215 }
5216 }
5217 if {!$haspad} {
Paul Mackerras3fc42792006-09-15 09:45:23 +10005218 # Find the first column that doesn't have a line going right
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005219 for {set col [llength $idlist]} {[incr col -1] >= 0} {} {
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005220 set id [lindex $idlist $col]
5221 if {$id eq {}} break
5222 set x0 [lsearch -exact $previdlist $id]
5223 if {$x0 < 0} {
Paul Mackerraseb447a12006-03-18 23:11:37 +11005224 # check if this is the link to the first child
Paul Mackerras92ed6662007-08-22 22:35:28 +10005225 set kid [lindex $displayorder $y0]
5226 if {[lindex $children($curview,$id) 0] eq $kid} {
Paul Mackerraseb447a12006-03-18 23:11:37 +11005227 # it is, work out offset to child
Paul Mackerras92ed6662007-08-22 22:35:28 +10005228 set x0 [lsearch -exact $previdlist $kid]
Paul Mackerraseb447a12006-03-18 23:11:37 +11005229 }
5230 }
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005231 if {$x0 <= $col} break
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005232 }
Paul Mackerras3fc42792006-09-15 09:45:23 +10005233 # Insert a pad at that column as long as it has a line and
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005234 # isn't the last column
5235 if {$x0 >= 0 && [incr col] < [llength $idlist]} {
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005236 set idlist [linsert $idlist $col {}]
Paul Mackerras03800812007-08-29 21:45:21 +10005237 lset rowidlist $row $idlist
5238 changedrow $row
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005239 }
5240 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005241 }
5242}
5243
5244proc xc {row col} {
5245 global canvx0 linespc
5246 return [expr {$canvx0 + $col * $linespc}]
5247}
5248
5249proc yc {row} {
5250 global canvy0 linespc
5251 return [expr {$canvy0 + $row * $linespc}]
5252}
5253
Paul Mackerrasc934a8a2006-03-02 23:00:44 +11005254proc linewidth {id} {
5255 global thickerline lthickness
5256
5257 set wid $lthickness
5258 if {[info exists thickerline] && $id eq $thickerline} {
5259 set wid [expr {2 * $lthickness}]
5260 }
5261 return $wid
5262}
5263
Paul Mackerras50b44ec2006-04-04 10:16:22 +10005264proc rowranges {id} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005265 global curview children uparrowlen downarrowlen
Paul Mackerras92ed6662007-08-22 22:35:28 +10005266 global rowidlist
Paul Mackerras50b44ec2006-04-04 10:16:22 +10005267
Paul Mackerras92ed6662007-08-22 22:35:28 +10005268 set kids $children($curview,$id)
5269 if {$kids eq {}} {
5270 return {}
Paul Mackerras50b44ec2006-04-04 10:16:22 +10005271 }
Paul Mackerras92ed6662007-08-22 22:35:28 +10005272 set ret {}
5273 lappend kids $id
5274 foreach child $kids {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005275 if {![commitinview $child $curview]} break
5276 set row [rowofcommit $child]
Paul Mackerras92ed6662007-08-22 22:35:28 +10005277 if {![info exists prev]} {
5278 lappend ret [expr {$row + 1}]
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005279 } else {
Paul Mackerras92ed6662007-08-22 22:35:28 +10005280 if {$row <= $prevrow} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005281 puts "oops children of [shortids $id] out of order [shortids $child] $row <= [shortids $prev] $prevrow"
Paul Mackerras92ed6662007-08-22 22:35:28 +10005282 }
5283 # see if the line extends the whole way from prevrow to row
5284 if {$row > $prevrow + $uparrowlen + $downarrowlen &&
5285 [lsearch -exact [lindex $rowidlist \
5286 [expr {int(($row + $prevrow) / 2)}]] $id] < 0} {
5287 # it doesn't, see where it ends
5288 set r [expr {$prevrow + $downarrowlen}]
5289 if {[lsearch -exact [lindex $rowidlist $r] $id] < 0} {
5290 while {[incr r -1] > $prevrow &&
5291 [lsearch -exact [lindex $rowidlist $r] $id] < 0} {}
5292 } else {
5293 while {[incr r] <= $row &&
5294 [lsearch -exact [lindex $rowidlist $r] $id] >= 0} {}
5295 incr r -1
5296 }
5297 lappend ret $r
5298 # see where it starts up again
5299 set r [expr {$row - $uparrowlen}]
5300 if {[lsearch -exact [lindex $rowidlist $r] $id] < 0} {
5301 while {[incr r] < $row &&
5302 [lsearch -exact [lindex $rowidlist $r] $id] < 0} {}
5303 } else {
5304 while {[incr r -1] >= $prevrow &&
5305 [lsearch -exact [lindex $rowidlist $r] $id] >= 0} {}
5306 incr r
5307 }
5308 lappend ret $r
5309 }
Paul Mackerraseb447a12006-03-18 23:11:37 +11005310 }
Paul Mackerras92ed6662007-08-22 22:35:28 +10005311 if {$child eq $id} {
5312 lappend ret $row
5313 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005314 set prev $child
Paul Mackerras92ed6662007-08-22 22:35:28 +10005315 set prevrow $row
Paul Mackerraseb447a12006-03-18 23:11:37 +11005316 }
Paul Mackerras92ed6662007-08-22 22:35:28 +10005317 return $ret
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005318}
5319
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005320proc drawlineseg {id row endrow arrowlow} {
5321 global rowidlist displayorder iddrawn linesegs
Paul Mackerrase341c062007-08-12 12:42:57 +10005322 global canv colormap linespc curview maxlinelen parentlist
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005323
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005324 set cols [list [lsearch -exact [lindex $rowidlist $row] $id]]
5325 set le [expr {$row + 1}]
5326 set arrowhigh 1
5327 while {1} {
5328 set c [lsearch -exact [lindex $rowidlist $le] $id]
5329 if {$c < 0} {
5330 incr le -1
5331 break
5332 }
5333 lappend cols $c
5334 set x [lindex $displayorder $le]
5335 if {$x eq $id} {
5336 set arrowhigh 0
5337 break
5338 }
5339 if {[info exists iddrawn($x)] || $le == $endrow} {
5340 set c [lsearch -exact [lindex $rowidlist [expr {$le+1}]] $id]
5341 if {$c >= 0} {
5342 lappend cols $c
5343 set arrowhigh 0
5344 }
5345 break
5346 }
5347 incr le
5348 }
5349 if {$le <= $row} {
5350 return $row
5351 }
5352
5353 set lines {}
5354 set i 0
5355 set joinhigh 0
5356 if {[info exists linesegs($id)]} {
5357 set lines $linesegs($id)
5358 foreach li $lines {
5359 set r0 [lindex $li 0]
5360 if {$r0 > $row} {
5361 if {$r0 == $le && [lindex $li 1] - $row <= $maxlinelen} {
5362 set joinhigh 1
5363 }
5364 break
5365 }
5366 incr i
5367 }
5368 }
5369 set joinlow 0
5370 if {$i > 0} {
5371 set li [lindex $lines [expr {$i-1}]]
5372 set r1 [lindex $li 1]
5373 if {$r1 == $row && $le - [lindex $li 0] <= $maxlinelen} {
5374 set joinlow 1
5375 }
5376 }
5377
5378 set x [lindex $cols [expr {$le - $row}]]
5379 set xp [lindex $cols [expr {$le - 1 - $row}]]
5380 set dir [expr {$xp - $x}]
5381 if {$joinhigh} {
5382 set ith [lindex $lines $i 2]
5383 set coords [$canv coords $ith]
5384 set ah [$canv itemcget $ith -arrow]
5385 set arrowhigh [expr {$ah eq "first" || $ah eq "both"}]
5386 set x2 [lindex $cols [expr {$le + 1 - $row}]]
5387 if {$x2 ne {} && $x - $x2 == $dir} {
5388 set coords [lrange $coords 0 end-2]
5389 }
5390 } else {
5391 set coords [list [xc $le $x] [yc $le]]
5392 }
5393 if {$joinlow} {
5394 set itl [lindex $lines [expr {$i-1}] 2]
5395 set al [$canv itemcget $itl -arrow]
5396 set arrowlow [expr {$al eq "last" || $al eq "both"}]
Paul Mackerrase341c062007-08-12 12:42:57 +10005397 } elseif {$arrowlow} {
5398 if {[lsearch -exact [lindex $rowidlist [expr {$row-1}]] $id] >= 0 ||
5399 [lsearch -exact [lindex $parentlist [expr {$row-1}]] $id] >= 0} {
5400 set arrowlow 0
5401 }
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005402 }
5403 set arrow [lindex {none first last both} [expr {$arrowhigh + 2*$arrowlow}]]
5404 for {set y $le} {[incr y -1] > $row} {} {
5405 set x $xp
5406 set xp [lindex $cols [expr {$y - 1 - $row}]]
5407 set ndir [expr {$xp - $x}]
5408 if {$dir != $ndir || $xp < 0} {
5409 lappend coords [xc $y $x] [yc $y]
5410 }
5411 set dir $ndir
5412 }
5413 if {!$joinlow} {
5414 if {$xp < 0} {
5415 # join parent line to first child
5416 set ch [lindex $displayorder $row]
5417 set xc [lsearch -exact [lindex $rowidlist $row] $ch]
5418 if {$xc < 0} {
5419 puts "oops: drawlineseg: child $ch not on row $row"
Paul Mackerrase341c062007-08-12 12:42:57 +10005420 } elseif {$xc != $x} {
5421 if {($arrowhigh && $le == $row + 1) || $dir == 0} {
5422 set d [expr {int(0.5 * $linespc)}]
5423 set x1 [xc $row $x]
5424 if {$xc < $x} {
5425 set x2 [expr {$x1 - $d}]
5426 } else {
5427 set x2 [expr {$x1 + $d}]
5428 }
5429 set y2 [yc $row]
5430 set y1 [expr {$y2 + $d}]
5431 lappend coords $x1 $y1 $x2 $y2
5432 } elseif {$xc < $x - 1} {
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005433 lappend coords [xc $row [expr {$x-1}]] [yc $row]
5434 } elseif {$xc > $x + 1} {
5435 lappend coords [xc $row [expr {$x+1}]] [yc $row]
5436 }
5437 set x $xc
5438 }
5439 lappend coords [xc $row $x] [yc $row]
5440 } else {
5441 set xn [xc $row $xp]
5442 set yn [yc $row]
Paul Mackerrase341c062007-08-12 12:42:57 +10005443 lappend coords $xn $yn
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005444 }
5445 if {!$joinhigh} {
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005446 assigncolor $id
5447 set t [$canv create line $coords -width [linewidth $id] \
5448 -fill $colormap($id) -tags lines.$id -arrow $arrow]
5449 $canv lower $t
5450 bindline $t $id
5451 set lines [linsert $lines $i [list $row $le $t]]
5452 } else {
5453 $canv coords $ith $coords
5454 if {$arrow ne $ah} {
5455 $canv itemconf $ith -arrow $arrow
5456 }
5457 lset lines $i 0 $row
5458 }
5459 } else {
5460 set xo [lsearch -exact [lindex $rowidlist [expr {$row - 1}]] $id]
5461 set ndir [expr {$xo - $xp}]
5462 set clow [$canv coords $itl]
5463 if {$dir == $ndir} {
5464 set clow [lrange $clow 2 end]
5465 }
5466 set coords [concat $coords $clow]
5467 if {!$joinhigh} {
5468 lset lines [expr {$i-1}] 1 $le
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005469 } else {
5470 # coalesce two pieces
5471 $canv delete $ith
5472 set b [lindex $lines [expr {$i-1}] 0]
5473 set e [lindex $lines $i 1]
5474 set lines [lreplace $lines [expr {$i-1}] $i [list $b $e $itl]]
5475 }
5476 $canv coords $itl $coords
5477 if {$arrow ne $al} {
5478 $canv itemconf $itl -arrow $arrow
5479 }
5480 }
5481
5482 set linesegs($id) $lines
5483 return $le
5484}
5485
5486proc drawparentlinks {id row} {
5487 global rowidlist canv colormap curview parentlist
Paul Mackerras513a54d2007-08-01 22:27:57 +10005488 global idpos linespc
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005489
5490 set rowids [lindex $rowidlist $row]
5491 set col [lsearch -exact $rowids $id]
5492 if {$col < 0} return
5493 set olds [lindex $parentlist $row]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005494 set row2 [expr {$row + 1}]
5495 set x [xc $row $col]
5496 set y [yc $row]
5497 set y2 [yc $row2]
Paul Mackerrase341c062007-08-12 12:42:57 +10005498 set d [expr {int(0.5 * $linespc)}]
Paul Mackerras513a54d2007-08-01 22:27:57 +10005499 set ymid [expr {$y + $d}]
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11005500 set ids [lindex $rowidlist $row2]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005501 # rmx = right-most X coord used
5502 set rmx 0
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005503 foreach p $olds {
Paul Mackerrasf3408442006-03-31 09:54:24 +11005504 set i [lsearch -exact $ids $p]
5505 if {$i < 0} {
5506 puts "oops, parent $p of $id not in list"
5507 continue
5508 }
5509 set x2 [xc $row2 $i]
5510 if {$x2 > $rmx} {
5511 set rmx $x2
5512 }
Paul Mackerras513a54d2007-08-01 22:27:57 +10005513 set j [lsearch -exact $rowids $p]
5514 if {$j < 0} {
Paul Mackerraseb447a12006-03-18 23:11:37 +11005515 # drawlineseg will do this one for us
5516 continue
5517 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005518 assigncolor $p
5519 # should handle duplicated parents here...
5520 set coords [list $x $y]
Paul Mackerras513a54d2007-08-01 22:27:57 +10005521 if {$i != $col} {
5522 # if attaching to a vertical segment, draw a smaller
5523 # slant for visual distinctness
5524 if {$i == $j} {
5525 if {$i < $col} {
5526 lappend coords [expr {$x2 + $d}] $y $x2 $ymid
5527 } else {
5528 lappend coords [expr {$x2 - $d}] $y $x2 $ymid
5529 }
5530 } elseif {$i < $col && $i < $j} {
5531 # segment slants towards us already
5532 lappend coords [xc $row $j] $y
5533 } else {
5534 if {$i < $col - 1} {
5535 lappend coords [expr {$x2 + $linespc}] $y
5536 } elseif {$i > $col + 1} {
5537 lappend coords [expr {$x2 - $linespc}] $y
5538 }
5539 lappend coords $x2 $y2
5540 }
5541 } else {
5542 lappend coords $x2 $y2
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005543 }
Paul Mackerrasc934a8a2006-03-02 23:00:44 +11005544 set t [$canv create line $coords -width [linewidth $p] \
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005545 -fill $colormap($p) -tags lines.$p]
5546 $canv lower $t
5547 bindline $t $p
5548 }
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005549 if {$rmx > [lindex $idpos($id) 1]} {
5550 lset idpos($id) 1 $rmx
5551 redrawtags $id
5552 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005553}
5554
Paul Mackerrasc934a8a2006-03-02 23:00:44 +11005555proc drawlines {id} {
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005556 global canv
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005557
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005558 $canv itemconf lines.$id -width [linewidth $id]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005559}
5560
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005561proc drawcmittext {id row col} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005562 global linespc canv canv2 canv3 fgcolor curview
5563 global cmitlisted commitinfo rowidlist parentlist
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005564 global rowtextx idpos idtags idheads idotherrefs
Paul Mackerras03800812007-08-29 21:45:21 +10005565 global linehtag linentag linedtag selectedline
Paul Mackerras28593d32008-11-13 23:01:46 +11005566 global canvxmax boldids boldnameids fgcolor
Paul Mackerrasd277e892008-09-21 18:11:37 -05005567 global mainheadid nullid nullid2 circleitem circlecolors ctxbut
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005568
Linus Torvalds1407ade2008-02-09 14:02:07 -08005569 # listed is 0 for boundary, 1 for normal, 2 for negative, 3 for left, 4 for right
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005570 set listed $cmitlisted($curview,$id)
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005571 if {$id eq $nullid} {
5572 set ofill red
Paul Mackerras8f489362007-07-13 19:49:37 +10005573 } elseif {$id eq $nullid2} {
Paul Mackerrasef3192b2007-07-22 22:05:30 +10005574 set ofill green
Paul Mackerrasc11ff122008-05-26 10:11:33 +10005575 } elseif {$id eq $mainheadid} {
5576 set ofill yellow
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005577 } else {
Paul Mackerrasc11ff122008-05-26 10:11:33 +10005578 set ofill [lindex $circlecolors $listed]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005579 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005580 set x [xc $row $col]
5581 set y [yc $row]
5582 set orad [expr {$linespc / 3}]
Linus Torvalds1407ade2008-02-09 14:02:07 -08005583 if {$listed <= 2} {
Paul Mackerrasc961b222007-07-09 22:45:47 +10005584 set t [$canv create oval [expr {$x - $orad}] [expr {$y - $orad}] \
5585 [expr {$x + $orad - 1}] [expr {$y + $orad - 1}] \
5586 -fill $ofill -outline $fgcolor -width 1 -tags circle]
Linus Torvalds1407ade2008-02-09 14:02:07 -08005587 } elseif {$listed == 3} {
Paul Mackerrasc961b222007-07-09 22:45:47 +10005588 # triangle pointing left for left-side commits
5589 set t [$canv create polygon \
5590 [expr {$x - $orad}] $y \
5591 [expr {$x + $orad - 1}] [expr {$y - $orad}] \
5592 [expr {$x + $orad - 1}] [expr {$y + $orad - 1}] \
5593 -fill $ofill -outline $fgcolor -width 1 -tags circle]
5594 } else {
5595 # triangle pointing right for right-side commits
5596 set t [$canv create polygon \
5597 [expr {$x + $orad - 1}] $y \
5598 [expr {$x - $orad}] [expr {$y - $orad}] \
5599 [expr {$x - $orad}] [expr {$y + $orad - 1}] \
5600 -fill $ofill -outline $fgcolor -width 1 -tags circle]
5601 }
Paul Mackerrasc11ff122008-05-26 10:11:33 +10005602 set circleitem($row) $t
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005603 $canv raise $t
5604 $canv bind $t <1> {selcanvline {} %x %y}
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005605 set rmx [llength [lindex $rowidlist $row]]
5606 set olds [lindex $parentlist $row]
5607 if {$olds ne {}} {
5608 set nextids [lindex $rowidlist [expr {$row + 1}]]
5609 foreach p $olds {
5610 set i [lsearch -exact $nextids $p]
5611 if {$i > $rmx} {
5612 set rmx $i
5613 }
5614 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005615 }
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005616 set xt [xc $row $rmx]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005617 set rowtextx($row) $xt
5618 set idpos($id) [list $x $xt $y]
5619 if {[info exists idtags($id)] || [info exists idheads($id)]
5620 || [info exists idotherrefs($id)]} {
5621 set xt [drawtags $id $x $xt $y]
5622 }
5623 set headline [lindex $commitinfo($id) 0]
5624 set name [lindex $commitinfo($id) 1]
5625 set date [lindex $commitinfo($id) 2]
5626 set date [formatdate $date]
Paul Mackerras9c311b32007-10-04 22:27:13 +10005627 set font mainfont
5628 set nfont mainfont
Paul Mackerras476ca632008-01-07 22:16:31 +11005629 set isbold [ishighlighted $id]
Paul Mackerras908c3582006-05-20 09:38:11 +10005630 if {$isbold > 0} {
Paul Mackerras28593d32008-11-13 23:01:46 +11005631 lappend boldids $id
Paul Mackerras9c311b32007-10-04 22:27:13 +10005632 set font mainfontbold
Paul Mackerras908c3582006-05-20 09:38:11 +10005633 if {$isbold > 1} {
Paul Mackerras28593d32008-11-13 23:01:46 +11005634 lappend boldnameids $id
Paul Mackerras9c311b32007-10-04 22:27:13 +10005635 set nfont mainfontbold
Paul Mackerras908c3582006-05-20 09:38:11 +10005636 }
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10005637 }
Paul Mackerras28593d32008-11-13 23:01:46 +11005638 set linehtag($id) [$canv create text $xt $y -anchor w -fill $fgcolor \
5639 -text $headline -font $font -tags text]
5640 $canv bind $linehtag($id) $ctxbut "rowmenu %X %Y $id"
5641 set linentag($id) [$canv2 create text 3 $y -anchor w -fill $fgcolor \
5642 -text $name -font $nfont -tags text]
5643 set linedtag($id) [$canv3 create text 3 $y -anchor w -fill $fgcolor \
5644 -text $date -font mainfont -tags text]
Paul Mackerras94b4a692008-05-20 20:51:06 +10005645 if {$selectedline == $row} {
Paul Mackerras28593d32008-11-13 23:01:46 +11005646 make_secsel $id
Paul Mackerras03800812007-08-29 21:45:21 +10005647 }
Paul Mackerras9c311b32007-10-04 22:27:13 +10005648 set xr [expr {$xt + [font measure $font $headline]}]
Paul Mackerrasbe0cd092006-03-31 09:55:11 +11005649 if {$xr > $canvxmax} {
5650 set canvxmax $xr
5651 setcanvscroll
5652 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005653}
5654
5655proc drawcmitrow {row} {
Paul Mackerras03800812007-08-29 21:45:21 +10005656 global displayorder rowidlist nrows_drawn
Paul Mackerras005a2f42007-07-26 22:36:39 +10005657 global iddrawn markingmatches
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005658 global commitinfo numcommits
Paul Mackerras687c8762007-09-22 12:49:33 +10005659 global filehighlight fhighlights findpattern nhighlights
Paul Mackerras908c3582006-05-20 09:38:11 +10005660 global hlview vhighlights
Paul Mackerras164ff272006-05-29 19:50:02 +10005661 global highlight_related rhighlights
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005662
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11005663 if {$row >= $numcommits} return
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005664
5665 set id [lindex $displayorder $row]
Paul Mackerras476ca632008-01-07 22:16:31 +11005666 if {[info exists hlview] && ![info exists vhighlights($id)]} {
Paul Mackerras908c3582006-05-20 09:38:11 +10005667 askvhighlight $row $id
5668 }
Paul Mackerras476ca632008-01-07 22:16:31 +11005669 if {[info exists filehighlight] && ![info exists fhighlights($id)]} {
Paul Mackerras908c3582006-05-20 09:38:11 +10005670 askfilehighlight $row $id
5671 }
Paul Mackerras476ca632008-01-07 22:16:31 +11005672 if {$findpattern ne {} && ![info exists nhighlights($id)]} {
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10005673 askfindhighlight $row $id
Paul Mackerras908c3582006-05-20 09:38:11 +10005674 }
Paul Mackerras476ca632008-01-07 22:16:31 +11005675 if {$highlight_related ne [mc "None"] && ![info exists rhighlights($id)]} {
Paul Mackerras164ff272006-05-29 19:50:02 +10005676 askrelhighlight $row $id
5677 }
Paul Mackerras005a2f42007-07-26 22:36:39 +10005678 if {![info exists iddrawn($id)]} {
5679 set col [lsearch -exact [lindex $rowidlist $row] $id]
5680 if {$col < 0} {
5681 puts "oops, row $row id $id not in list"
5682 return
5683 }
5684 if {![info exists commitinfo($id)]} {
5685 getcommit $id
5686 }
5687 assigncolor $id
5688 drawcmittext $id $row $col
5689 set iddrawn($id) 1
Paul Mackerras03800812007-08-29 21:45:21 +10005690 incr nrows_drawn
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005691 }
Paul Mackerras005a2f42007-07-26 22:36:39 +10005692 if {$markingmatches} {
5693 markrowmatches $row $id
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005694 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005695}
5696
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005697proc drawcommits {row {endrow {}}} {
Paul Mackerras03800812007-08-29 21:45:21 +10005698 global numcommits iddrawn displayorder curview need_redisplay
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10005699 global parentlist rowidlist rowfinal uparrowlen downarrowlen nrows_drawn
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005700
5701 if {$row < 0} {
5702 set row 0
5703 }
5704 if {$endrow eq {}} {
5705 set endrow $row
5706 }
5707 if {$endrow >= $numcommits} {
5708 set endrow [expr {$numcommits - 1}]
5709 }
5710
Paul Mackerras03800812007-08-29 21:45:21 +10005711 set rl1 [expr {$row - $downarrowlen - 3}]
5712 if {$rl1 < 0} {
5713 set rl1 0
5714 }
5715 set ro1 [expr {$row - 3}]
5716 if {$ro1 < 0} {
5717 set ro1 0
5718 }
5719 set r2 [expr {$endrow + $uparrowlen + 3}]
5720 if {$r2 > $numcommits} {
5721 set r2 $numcommits
5722 }
5723 for {set r $rl1} {$r < $r2} {incr r} {
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10005724 if {[lindex $rowidlist $r] ne {} && [lindex $rowfinal $r]} {
Paul Mackerras03800812007-08-29 21:45:21 +10005725 if {$rl1 < $r} {
5726 layoutrows $rl1 $r
5727 }
5728 set rl1 [expr {$r + 1}]
5729 }
5730 }
5731 if {$rl1 < $r} {
5732 layoutrows $rl1 $r
5733 }
5734 optimize_rows $ro1 0 $r2
5735 if {$need_redisplay || $nrows_drawn > 2000} {
5736 clear_display
Paul Mackerras03800812007-08-29 21:45:21 +10005737 }
5738
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005739 # make the lines join to already-drawn rows either side
5740 set r [expr {$row - 1}]
5741 if {$r < 0 || ![info exists iddrawn([lindex $displayorder $r])]} {
5742 set r $row
5743 }
5744 set er [expr {$endrow + 1}]
5745 if {$er >= $numcommits ||
5746 ![info exists iddrawn([lindex $displayorder $er])]} {
5747 set er $endrow
5748 }
5749 for {} {$r <= $er} {incr r} {
5750 set id [lindex $displayorder $r]
5751 set wasdrawn [info exists iddrawn($id)]
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10005752 drawcmitrow $r
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005753 if {$r == $er} break
5754 set nextid [lindex $displayorder [expr {$r + 1}]]
Paul Mackerrase5ef6f92007-10-21 12:58:42 +10005755 if {$wasdrawn && [info exists iddrawn($nextid)]} continue
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005756 drawparentlinks $id $r
5757
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005758 set rowids [lindex $rowidlist $r]
5759 foreach lid $rowids {
5760 if {$lid eq {}} continue
Paul Mackerrase5ef6f92007-10-21 12:58:42 +10005761 if {[info exists lineend($lid)] && $lineend($lid) > $r} continue
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005762 if {$lid eq $id} {
5763 # see if this is the first child of any of its parents
5764 foreach p [lindex $parentlist $r] {
5765 if {[lsearch -exact $rowids $p] < 0} {
5766 # make this line extend up to the child
Paul Mackerrase5ef6f92007-10-21 12:58:42 +10005767 set lineend($p) [drawlineseg $p $r $er 0]
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005768 }
5769 }
Paul Mackerrase5ef6f92007-10-21 12:58:42 +10005770 } else {
5771 set lineend($lid) [drawlineseg $lid $r $er 1]
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005772 }
5773 }
5774 }
5775}
5776
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005777proc undolayout {row} {
5778 global uparrowlen mingaplen downarrowlen
5779 global rowidlist rowisopt rowfinal need_redisplay
5780
5781 set r [expr {$row - ($uparrowlen + $mingaplen + $downarrowlen)}]
5782 if {$r < 0} {
5783 set r 0
5784 }
5785 if {[llength $rowidlist] > $r} {
5786 incr r -1
5787 set rowidlist [lrange $rowidlist 0 $r]
5788 set rowfinal [lrange $rowfinal 0 $r]
5789 set rowisopt [lrange $rowisopt 0 $r]
5790 set need_redisplay 1
5791 run drawvisible
5792 }
5793}
5794
Paul Mackerras31c0eaa2007-12-30 22:41:14 +11005795proc drawvisible {} {
5796 global canv linespc curview vrowmod selectedline targetrow targetid
Paul Mackerras42a671f2008-01-02 09:59:39 +11005797 global need_redisplay cscroll numcommits
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005798
Paul Mackerras31c0eaa2007-12-30 22:41:14 +11005799 set fs [$canv yview]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005800 set ymax [lindex [$canv cget -scrollregion] 3]
Paul Mackerras5a7f5772008-01-15 22:45:36 +11005801 if {$ymax eq {} || $ymax == 0 || $numcommits == 0} return
Paul Mackerras31c0eaa2007-12-30 22:41:14 +11005802 set f0 [lindex $fs 0]
5803 set f1 [lindex $fs 1]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005804 set y0 [expr {int($f0 * $ymax)}]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005805 set y1 [expr {int($f1 * $ymax)}]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005806
Paul Mackerras31c0eaa2007-12-30 22:41:14 +11005807 if {[info exists targetid]} {
Paul Mackerras42a671f2008-01-02 09:59:39 +11005808 if {[commitinview $targetid $curview]} {
5809 set r [rowofcommit $targetid]
5810 if {$r != $targetrow} {
5811 # Fix up the scrollregion and change the scrolling position
5812 # now that our target row has moved.
5813 set diff [expr {($r - $targetrow) * $linespc}]
5814 set targetrow $r
5815 setcanvscroll
5816 set ymax [lindex [$canv cget -scrollregion] 3]
5817 incr y0 $diff
5818 incr y1 $diff
5819 set f0 [expr {$y0 / $ymax}]
5820 set f1 [expr {$y1 / $ymax}]
5821 allcanvs yview moveto $f0
5822 $cscroll set $f0 $f1
5823 set need_redisplay 1
5824 }
5825 } else {
5826 unset targetid
Paul Mackerras31c0eaa2007-12-30 22:41:14 +11005827 }
5828 }
5829
5830 set row [expr {int(($y0 - 3) / $linespc) - 1}]
5831 set endrow [expr {int(($y1 - 3) / $linespc) + 1}]
5832 if {$endrow >= $vrowmod($curview)} {
5833 update_arcrows $curview
5834 }
Paul Mackerras94b4a692008-05-20 20:51:06 +10005835 if {$selectedline ne {} &&
Paul Mackerras31c0eaa2007-12-30 22:41:14 +11005836 $row <= $selectedline && $selectedline <= $endrow} {
5837 set targetrow $selectedline
Paul Mackerrasac1276a2008-03-03 10:11:08 +11005838 } elseif {[info exists targetid]} {
Paul Mackerras31c0eaa2007-12-30 22:41:14 +11005839 set targetrow [expr {int(($row + $endrow) / 2)}]
5840 }
Paul Mackerrasac1276a2008-03-03 10:11:08 +11005841 if {[info exists targetrow]} {
5842 if {$targetrow >= $numcommits} {
5843 set targetrow [expr {$numcommits - 1}]
5844 }
5845 set targetid [commitonrow $targetrow]
Paul Mackerras42a671f2008-01-02 09:59:39 +11005846 }
Paul Mackerras31c0eaa2007-12-30 22:41:14 +11005847 drawcommits $row $endrow
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005848}
5849
5850proc clear_display {} {
Paul Mackerras03800812007-08-29 21:45:21 +10005851 global iddrawn linesegs need_redisplay nrows_drawn
Paul Mackerras164ff272006-05-29 19:50:02 +10005852 global vhighlights fhighlights nhighlights rhighlights
Paul Mackerras28593d32008-11-13 23:01:46 +11005853 global linehtag linentag linedtag boldids boldnameids
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005854
5855 allcanvs delete all
5856 catch {unset iddrawn}
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005857 catch {unset linesegs}
Paul Mackerras94503a62008-05-19 09:48:45 +10005858 catch {unset linehtag}
5859 catch {unset linentag}
5860 catch {unset linedtag}
Paul Mackerras28593d32008-11-13 23:01:46 +11005861 set boldids {}
5862 set boldnameids {}
Paul Mackerras908c3582006-05-20 09:38:11 +10005863 catch {unset vhighlights}
5864 catch {unset fhighlights}
5865 catch {unset nhighlights}
Paul Mackerras164ff272006-05-29 19:50:02 +10005866 catch {unset rhighlights}
Paul Mackerras03800812007-08-29 21:45:21 +10005867 set need_redisplay 0
5868 set nrows_drawn 0
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005869}
5870
Paul Mackerras50b44ec2006-04-04 10:16:22 +10005871proc findcrossings {id} {
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005872 global rowidlist parentlist numcommits displayorder
Paul Mackerras50b44ec2006-04-04 10:16:22 +10005873
5874 set cross {}
5875 set ccross {}
5876 foreach {s e} [rowranges $id] {
5877 if {$e >= $numcommits} {
5878 set e [expr {$numcommits - 1}]
Paul Mackerras50b44ec2006-04-04 10:16:22 +10005879 }
Paul Mackerrasd94f8cd2006-04-06 10:18:23 +10005880 if {$e <= $s} continue
Paul Mackerras50b44ec2006-04-04 10:16:22 +10005881 for {set row $e} {[incr row -1] >= $s} {} {
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005882 set x [lsearch -exact [lindex $rowidlist $row] $id]
5883 if {$x < 0} break
Paul Mackerras50b44ec2006-04-04 10:16:22 +10005884 set olds [lindex $parentlist $row]
5885 set kid [lindex $displayorder $row]
5886 set kidx [lsearch -exact [lindex $rowidlist $row] $kid]
5887 if {$kidx < 0} continue
5888 set nextrow [lindex $rowidlist [expr {$row + 1}]]
5889 foreach p $olds {
5890 set px [lsearch -exact $nextrow $p]
5891 if {$px < 0} continue
5892 if {($kidx < $x && $x < $px) || ($px < $x && $x < $kidx)} {
5893 if {[lsearch -exact $ccross $p] >= 0} continue
5894 if {$x == $px + ($kidx < $px? -1: 1)} {
5895 lappend ccross $p
5896 } elseif {[lsearch -exact $cross $p] < 0} {
5897 lappend cross $p
5898 }
5899 }
5900 }
Paul Mackerras50b44ec2006-04-04 10:16:22 +10005901 }
5902 }
5903 return [concat $ccross {{}} $cross]
5904}
5905
Paul Mackerrase5c2d852005-05-11 23:44:54 +00005906proc assigncolor {id} {
Paul Mackerrasaa81d972006-02-28 11:27:12 +11005907 global colormap colors nextcolor
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005908 global parents children children curview
Paul Mackerras6c20ff32005-06-22 19:53:32 +10005909
Paul Mackerras418c4c72006-02-07 09:10:18 +11005910 if {[info exists colormap($id)]} return
Paul Mackerrase5c2d852005-05-11 23:44:54 +00005911 set ncolors [llength $colors]
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10005912 if {[info exists children($curview,$id)]} {
5913 set kids $children($curview,$id)
Paul Mackerras79b2c752006-04-02 20:47:40 +10005914 } else {
5915 set kids {}
5916 }
5917 if {[llength $kids] == 1} {
5918 set child [lindex $kids 0]
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +00005919 if {[info exists colormap($child)]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005920 && [llength $parents($curview,$child)] == 1} {
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +00005921 set colormap($id) $colormap($child)
5922 return
Paul Mackerrase5c2d852005-05-11 23:44:54 +00005923 }
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +00005924 }
5925 set badcolors {}
Paul Mackerras50b44ec2006-04-04 10:16:22 +10005926 set origbad {}
5927 foreach x [findcrossings $id] {
5928 if {$x eq {}} {
5929 # delimiter between corner crossings and other crossings
5930 if {[llength $badcolors] >= $ncolors - 1} break
5931 set origbad $badcolors
Paul Mackerrase5c2d852005-05-11 23:44:54 +00005932 }
Paul Mackerras50b44ec2006-04-04 10:16:22 +10005933 if {[info exists colormap($x)]
5934 && [lsearch -exact $badcolors $colormap($x)] < 0} {
5935 lappend badcolors $colormap($x)
Paul Mackerras6c20ff32005-06-22 19:53:32 +10005936 }
5937 }
Paul Mackerras50b44ec2006-04-04 10:16:22 +10005938 if {[llength $badcolors] >= $ncolors} {
5939 set badcolors $origbad
5940 }
Paul Mackerras6c20ff32005-06-22 19:53:32 +10005941 set origbad $badcolors
5942 if {[llength $badcolors] < $ncolors - 1} {
Paul Mackerras79b2c752006-04-02 20:47:40 +10005943 foreach child $kids {
Paul Mackerras6c20ff32005-06-22 19:53:32 +10005944 if {[info exists colormap($child)]
5945 && [lsearch -exact $badcolors $colormap($child)] < 0} {
5946 lappend badcolors $colormap($child)
5947 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005948 foreach p $parents($curview,$child) {
Paul Mackerras79b2c752006-04-02 20:47:40 +10005949 if {[info exists colormap($p)]
5950 && [lsearch -exact $badcolors $colormap($p)] < 0} {
5951 lappend badcolors $colormap($p)
Paul Mackerrase5c2d852005-05-11 23:44:54 +00005952 }
5953 }
5954 }
Paul Mackerras6c20ff32005-06-22 19:53:32 +10005955 if {[llength $badcolors] >= $ncolors} {
5956 set badcolors $origbad
5957 }
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +00005958 }
5959 for {set i 0} {$i <= $ncolors} {incr i} {
5960 set c [lindex $colors $nextcolor]
5961 if {[incr nextcolor] >= $ncolors} {
5962 set nextcolor 0
Paul Mackerrase5c2d852005-05-11 23:44:54 +00005963 }
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +00005964 if {[lsearch -exact $badcolors $c]} break
5965 }
5966 set colormap($id) $c
5967}
5968
Paul Mackerrasa823a912005-06-21 10:01:38 +10005969proc bindline {t id} {
5970 global canv
5971
Paul Mackerrasa823a912005-06-21 10:01:38 +10005972 $canv bind $t <Enter> "lineenter %x %y $id"
5973 $canv bind $t <Motion> "linemotion %x %y $id"
5974 $canv bind $t <Leave> "lineleave $id"
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10005975 $canv bind $t <Button-1> "lineclick %x %y $id 1"
Paul Mackerrasa823a912005-06-21 10:01:38 +10005976}
5977
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10005978proc drawtags {id x xt y1} {
Paul Mackerras8a485712006-07-06 10:21:23 +10005979 global idtags idheads idotherrefs mainhead
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10005980 global linespc lthickness
Paul Mackerrasd277e892008-09-21 18:11:37 -05005981 global canv rowtextx curview fgcolor bgcolor ctxbut
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10005982
5983 set marks {}
5984 set ntags 0
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10005985 set nheads 0
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10005986 if {[info exists idtags($id)]} {
5987 set marks $idtags($id)
5988 set ntags [llength $marks]
5989 }
5990 if {[info exists idheads($id)]} {
5991 set marks [concat $marks $idheads($id)]
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10005992 set nheads [llength $idheads($id)]
5993 }
5994 if {[info exists idotherrefs($id)]} {
5995 set marks [concat $marks $idotherrefs($id)]
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10005996 }
5997 if {$marks eq {}} {
5998 return $xt
5999 }
6000
6001 set delta [expr {int(0.5 * ($linespc - $lthickness))}]
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08006002 set yt [expr {$y1 - 0.5 * $linespc}]
6003 set yb [expr {$yt + $linespc - 1}]
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006004 set xvals {}
6005 set wvals {}
Paul Mackerras8a485712006-07-06 10:21:23 +10006006 set i -1
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006007 foreach tag $marks {
Paul Mackerras8a485712006-07-06 10:21:23 +10006008 incr i
6009 if {$i >= $ntags && $i < $ntags + $nheads && $tag eq $mainhead} {
Paul Mackerras9c311b32007-10-04 22:27:13 +10006010 set wid [font measure mainfontbold $tag]
Paul Mackerras8a485712006-07-06 10:21:23 +10006011 } else {
Paul Mackerras9c311b32007-10-04 22:27:13 +10006012 set wid [font measure mainfont $tag]
Paul Mackerras8a485712006-07-06 10:21:23 +10006013 }
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006014 lappend xvals $xt
6015 lappend wvals $wid
6016 set xt [expr {$xt + $delta + $wid + $lthickness + $linespc}]
6017 }
6018 set t [$canv create line $x $y1 [lindex $xvals end] $y1 \
6019 -width $lthickness -fill black -tags tag.$id]
6020 $canv lower $t
6021 foreach tag $marks x $xvals wid $wvals {
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08006022 set xl [expr {$x + $delta}]
6023 set xr [expr {$x + $delta + $wid + $lthickness}]
Paul Mackerras9c311b32007-10-04 22:27:13 +10006024 set font mainfont
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006025 if {[incr ntags -1] >= 0} {
6026 # draw a tag
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08006027 set t [$canv create polygon $x [expr {$yt + $delta}] $xl $yt \
6028 $xr $yt $xr $yb $xl $yb $x [expr {$yb - $delta}] \
Paul Mackerras106288c2005-08-19 23:11:39 +10006029 -width 1 -outline black -fill yellow -tags tag.$id]
6030 $canv bind $t <1> [list showtag $tag 1]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11006031 set rowtextx([rowofcommit $id]) [expr {$xr + $linespc}]
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006032 } else {
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10006033 # draw a head or other ref
6034 if {[incr nheads -1] >= 0} {
6035 set col green
Paul Mackerras8a485712006-07-06 10:21:23 +10006036 if {$tag eq $mainhead} {
Paul Mackerras9c311b32007-10-04 22:27:13 +10006037 set font mainfontbold
Paul Mackerras8a485712006-07-06 10:21:23 +10006038 }
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10006039 } else {
6040 set col "#ddddff"
6041 }
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08006042 set xl [expr {$xl - $delta/2}]
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006043 $canv create polygon $x $yt $xr $yt $xr $yb $x $yb \
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10006044 -width 1 -outline black -fill $col -tags tag.$id
Josef Weidendorfera970fcf2006-04-18 23:53:07 +02006045 if {[regexp {^(remotes/.*/|remotes/)} $tag match remoteprefix]} {
Paul Mackerras9c311b32007-10-04 22:27:13 +10006046 set rwid [font measure mainfont $remoteprefix]
Josef Weidendorfera970fcf2006-04-18 23:53:07 +02006047 set xi [expr {$x + 1}]
6048 set yti [expr {$yt + 1}]
6049 set xri [expr {$x + $rwid}]
6050 $canv create polygon $xi $yti $xri $yti $xri $yb $xi $yb \
6051 -width 0 -fill "#ffddaa" -tags tag.$id
6052 }
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006053 }
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10006054 set t [$canv create text $xl $y1 -anchor w -text $tag -fill $fgcolor \
Paul Mackerras8a485712006-07-06 10:21:23 +10006055 -font $font -tags [list tag.$id text]]
Paul Mackerras106288c2005-08-19 23:11:39 +10006056 if {$ntags >= 0} {
6057 $canv bind $t <1> [list showtag $tag 1]
Paul Mackerras10299152006-08-02 09:52:01 +10006058 } elseif {$nheads >= 0} {
Paul Mackerrasd277e892008-09-21 18:11:37 -05006059 $canv bind $t $ctxbut [list headmenu %X %Y $id $tag]
Paul Mackerras106288c2005-08-19 23:11:39 +10006060 }
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006061 }
6062 return $xt
6063}
6064
Paul Mackerras8d858d12005-08-05 09:52:16 +10006065proc xcoord {i level ln} {
6066 global canvx0 xspc1 xspc2
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +00006067
Paul Mackerras8d858d12005-08-05 09:52:16 +10006068 set x [expr {$canvx0 + $i * $xspc1($ln)}]
6069 if {$i > 0 && $i == $level} {
6070 set x [expr {$x + 0.5 * ($xspc2 - $xspc1($ln))}]
6071 } elseif {$i > $level} {
6072 set x [expr {$x + $xspc2 - $xspc1($ln)}]
6073 }
6074 return $x
6075}
6076
Paul Mackerras098dd8a2006-05-03 09:32:53 +10006077proc show_status {msg} {
Paul Mackerras9c311b32007-10-04 22:27:13 +10006078 global canv fgcolor
Paul Mackerras098dd8a2006-05-03 09:32:53 +10006079
6080 clear_display
Paul Mackerras9c311b32007-10-04 22:27:13 +10006081 $canv create text 3 3 -anchor nw -text $msg -font mainfont \
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10006082 -tags text -fill $fgcolor
Paul Mackerras098dd8a2006-05-03 09:32:53 +10006083}
6084
Paul Mackerras94a2eed2005-08-07 15:27:57 +10006085# Don't change the text pane cursor if it is currently the hand cursor,
6086# showing that we are over a sha1 ID link.
6087proc settextcursor {c} {
6088 global ctext curtextcursor
6089
6090 if {[$ctext cget -cursor] == $curtextcursor} {
6091 $ctext config -cursor $c
6092 }
6093 set curtextcursor $c
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +00006094}
6095
Paul Mackerrasa137a902007-10-23 21:12:49 +10006096proc nowbusy {what {name {}}} {
6097 global isbusy busyname statusw
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10006098
6099 if {[array names isbusy] eq {}} {
6100 . config -cursor watch
6101 settextcursor watch
6102 }
6103 set isbusy($what) 1
Paul Mackerrasa137a902007-10-23 21:12:49 +10006104 set busyname($what) $name
6105 if {$name ne {}} {
6106 $statusw conf -text $name
6107 }
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10006108}
6109
6110proc notbusy {what} {
Paul Mackerrasa137a902007-10-23 21:12:49 +10006111 global isbusy maincursor textcursor busyname statusw
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10006112
Paul Mackerrasa137a902007-10-23 21:12:49 +10006113 catch {
6114 unset isbusy($what)
6115 if {$busyname($what) ne {} &&
6116 [$statusw cget -text] eq $busyname($what)} {
6117 $statusw conf -text {}
6118 }
6119 }
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10006120 if {[array names isbusy] eq {}} {
6121 . config -cursor $maincursor
6122 settextcursor $textcursor
6123 }
6124}
6125
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00006126proc findmatches {f} {
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006127 global findtype findstring
Christian Stimmingb007ee22007-11-07 18:44:35 +01006128 if {$findtype == [mc "Regexp"]} {
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006129 set matches [regexp -indices -all -inline $findstring $f]
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00006130 } else {
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006131 set fs $findstring
Christian Stimmingb007ee22007-11-07 18:44:35 +01006132 if {$findtype == [mc "IgnCase"]} {
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006133 set f [string tolower $f]
6134 set fs [string tolower $fs]
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00006135 }
6136 set matches {}
6137 set i 0
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006138 set l [string length $fs]
6139 while {[set j [string first $fs $f $i]] >= 0} {
6140 lappend matches [list $j [expr {$j+$l-1}]]
6141 set i [expr {$j + $l}]
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00006142 }
6143 }
6144 return $matches
6145}
6146
Paul Mackerrascca5d942007-10-27 21:16:56 +10006147proc dofind {{dirn 1} {wrap 1}} {
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006148 global findstring findstartline findcurline selectedline numcommits
Paul Mackerrascca5d942007-10-27 21:16:56 +10006149 global gdttype filehighlight fh_serial find_dirn findallowwrap
Paul Mackerrasb74fd572005-07-16 07:46:13 -04006150
Paul Mackerrascca5d942007-10-27 21:16:56 +10006151 if {[info exists find_dirn]} {
6152 if {$find_dirn == $dirn} return
6153 stopfinding
6154 }
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00006155 focus .
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006156 if {$findstring eq {} || $numcommits == 0} return
Paul Mackerras94b4a692008-05-20 20:51:06 +10006157 if {$selectedline eq {}} {
Paul Mackerrascca5d942007-10-27 21:16:56 +10006158 set findstartline [lindex [visiblerows] [expr {$dirn < 0}]]
Paul Mackerras98f350e2005-05-15 05:56:51 +00006159 } else {
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006160 set findstartline $selectedline
Paul Mackerras98f350e2005-05-15 05:56:51 +00006161 }
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006162 set findcurline $findstartline
Christian Stimmingb007ee22007-11-07 18:44:35 +01006163 nowbusy finding [mc "Searching"]
6164 if {$gdttype ne [mc "containing:"] && ![info exists filehighlight]} {
Paul Mackerras687c8762007-09-22 12:49:33 +10006165 after cancel do_file_hl $fh_serial
6166 do_file_hl $fh_serial
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006167 }
Paul Mackerrascca5d942007-10-27 21:16:56 +10006168 set find_dirn $dirn
6169 set findallowwrap $wrap
6170 run findmore
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006171}
6172
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10006173proc stopfinding {} {
6174 global find_dirn findcurline fprogcoord
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006175
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10006176 if {[info exists find_dirn]} {
6177 unset find_dirn
6178 unset findcurline
6179 notbusy finding
6180 set fprogcoord 0
6181 adjustprogress
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006182 }
Paul Mackerras8a897742008-10-27 21:36:25 +11006183 stopblaming
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006184}
6185
6186proc findmore {} {
Paul Mackerras687c8762007-09-22 12:49:33 +10006187 global commitdata commitinfo numcommits findpattern findloc
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11006188 global findstartline findcurline findallowwrap
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10006189 global find_dirn gdttype fhighlights fprogcoord
Paul Mackerrascd2bcae2008-01-02 21:44:06 +11006190 global curview varcorder vrownum varccommits vrowmod
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006191
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10006192 if {![info exists find_dirn]} {
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006193 return 0
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00006194 }
Christian Stimmingb007ee22007-11-07 18:44:35 +01006195 set fldtypes [list [mc "Headline"] [mc "Author"] [mc "Date"] [mc "Committer"] [mc "CDate"] [mc "Comments"]]
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006196 set l $findcurline
Paul Mackerrascca5d942007-10-27 21:16:56 +10006197 set moretodo 0
6198 if {$find_dirn > 0} {
6199 incr l
6200 if {$l >= $numcommits} {
6201 set l 0
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006202 }
Paul Mackerrascca5d942007-10-27 21:16:56 +10006203 if {$l <= $findstartline} {
6204 set lim [expr {$findstartline + 1}]
6205 } else {
6206 set lim $numcommits
6207 set moretodo $findallowwrap
6208 }
Paul Mackerras98f350e2005-05-15 05:56:51 +00006209 } else {
Paul Mackerrascca5d942007-10-27 21:16:56 +10006210 if {$l == 0} {
6211 set l $numcommits
6212 }
6213 incr l -1
6214 if {$l >= $findstartline} {
6215 set lim [expr {$findstartline - 1}]
6216 } else {
6217 set lim -1
6218 set moretodo $findallowwrap
6219 }
Paul Mackerras98f350e2005-05-15 05:56:51 +00006220 }
Paul Mackerrascca5d942007-10-27 21:16:56 +10006221 set n [expr {($lim - $l) * $find_dirn}]
6222 if {$n > 500} {
6223 set n 500
6224 set moretodo 1
Paul Mackerras98f350e2005-05-15 05:56:51 +00006225 }
Paul Mackerrascd2bcae2008-01-02 21:44:06 +11006226 if {$l + ($find_dirn > 0? $n: 1) > $vrowmod($curview)} {
6227 update_arcrows $curview
6228 }
Paul Mackerras687c8762007-09-22 12:49:33 +10006229 set found 0
6230 set domore 1
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11006231 set ai [bsearch $vrownum($curview) $l]
6232 set a [lindex $varcorder($curview) $ai]
6233 set arow [lindex $vrownum($curview) $ai]
6234 set ids [lindex $varccommits($curview,$a)]
6235 set arowend [expr {$arow + [llength $ids]}]
Christian Stimmingb007ee22007-11-07 18:44:35 +01006236 if {$gdttype eq [mc "containing:"]} {
Paul Mackerrascca5d942007-10-27 21:16:56 +10006237 for {} {$n > 0} {incr n -1; incr l $find_dirn} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11006238 if {$l < $arow || $l >= $arowend} {
6239 incr ai $find_dirn
6240 set a [lindex $varcorder($curview) $ai]
6241 set arow [lindex $vrownum($curview) $ai]
6242 set ids [lindex $varccommits($curview,$a)]
6243 set arowend [expr {$arow + [llength $ids]}]
6244 }
6245 set id [lindex $ids [expr {$l - $arow}]]
Paul Mackerras687c8762007-09-22 12:49:33 +10006246 # shouldn't happen unless git log doesn't give all the commits...
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11006247 if {![info exists commitdata($id)] ||
6248 ![doesmatch $commitdata($id)]} {
6249 continue
6250 }
Paul Mackerras687c8762007-09-22 12:49:33 +10006251 if {![info exists commitinfo($id)]} {
6252 getcommit $id
6253 }
6254 set info $commitinfo($id)
6255 foreach f $info ty $fldtypes {
Christian Stimmingb007ee22007-11-07 18:44:35 +01006256 if {($findloc eq [mc "All fields"] || $findloc eq $ty) &&
Paul Mackerras687c8762007-09-22 12:49:33 +10006257 [doesmatch $f]} {
6258 set found 1
6259 break
6260 }
6261 }
6262 if {$found} break
Paul Mackerras98f350e2005-05-15 05:56:51 +00006263 }
Paul Mackerras687c8762007-09-22 12:49:33 +10006264 } else {
Paul Mackerrascca5d942007-10-27 21:16:56 +10006265 for {} {$n > 0} {incr n -1; incr l $find_dirn} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11006266 if {$l < $arow || $l >= $arowend} {
6267 incr ai $find_dirn
6268 set a [lindex $varcorder($curview) $ai]
6269 set arow [lindex $vrownum($curview) $ai]
6270 set ids [lindex $varccommits($curview,$a)]
6271 set arowend [expr {$arow + [llength $ids]}]
6272 }
6273 set id [lindex $ids [expr {$l - $arow}]]
Paul Mackerras476ca632008-01-07 22:16:31 +11006274 if {![info exists fhighlights($id)]} {
6275 # this sets fhighlights($id) to -1
Paul Mackerras687c8762007-09-22 12:49:33 +10006276 askfilehighlight $l $id
Paul Mackerrascd2bcae2008-01-02 21:44:06 +11006277 }
Paul Mackerras476ca632008-01-07 22:16:31 +11006278 if {$fhighlights($id) > 0} {
Paul Mackerrascd2bcae2008-01-02 21:44:06 +11006279 set found $domore
6280 break
6281 }
Paul Mackerras476ca632008-01-07 22:16:31 +11006282 if {$fhighlights($id) < 0} {
Paul Mackerras687c8762007-09-22 12:49:33 +10006283 if {$domore} {
6284 set domore 0
Paul Mackerrascca5d942007-10-27 21:16:56 +10006285 set findcurline [expr {$l - $find_dirn}]
Paul Mackerras687c8762007-09-22 12:49:33 +10006286 }
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006287 }
6288 }
6289 }
Paul Mackerrascca5d942007-10-27 21:16:56 +10006290 if {$found || ($domore && !$moretodo)} {
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006291 unset findcurline
Paul Mackerras687c8762007-09-22 12:49:33 +10006292 unset find_dirn
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006293 notbusy finding
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10006294 set fprogcoord 0
6295 adjustprogress
6296 if {$found} {
6297 findselectline $l
6298 } else {
6299 bell
6300 }
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006301 return 0
6302 }
Paul Mackerras687c8762007-09-22 12:49:33 +10006303 if {!$domore} {
6304 flushhighlights
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10006305 } else {
Paul Mackerrascca5d942007-10-27 21:16:56 +10006306 set findcurline [expr {$l - $find_dirn}]
Paul Mackerras687c8762007-09-22 12:49:33 +10006307 }
Paul Mackerrascca5d942007-10-27 21:16:56 +10006308 set n [expr {($findcurline - $findstartline) * $find_dirn - 1}]
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10006309 if {$n < 0} {
6310 incr n $numcommits
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006311 }
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10006312 set fprogcoord [expr {$n * 1.0 / $numcommits}]
6313 adjustprogress
6314 return $domore
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00006315}
6316
6317proc findselectline {l} {
Paul Mackerras687c8762007-09-22 12:49:33 +10006318 global findloc commentend ctext findcurline markingmatches gdttype
Paul Mackerras005a2f42007-07-26 22:36:39 +10006319
Paul Mackerras8b39e042008-12-02 09:02:46 +11006320 set markingmatches [expr {$gdttype eq [mc "containing:"]}]
Paul Mackerras005a2f42007-07-26 22:36:39 +10006321 set findcurline $l
Paul Mackerrasd6982062005-08-06 22:06:06 +10006322 selectline $l 1
Paul Mackerras8b39e042008-12-02 09:02:46 +11006323 if {$markingmatches &&
6324 ($findloc eq [mc "All fields"] || $findloc eq [mc "Comments"])} {
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00006325 # highlight the matches in the comments
6326 set f [$ctext get 1.0 $commentend]
6327 set matches [findmatches $f]
6328 foreach match $matches {
6329 set start [lindex $match 0]
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08006330 set end [expr {[lindex $match 1] + 1}]
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00006331 $ctext tag add found "1.0 + $start c" "1.0 + $end c"
6332 }
Paul Mackerras98f350e2005-05-15 05:56:51 +00006333 }
Paul Mackerras005a2f42007-07-26 22:36:39 +10006334 drawvisible
Paul Mackerras98f350e2005-05-15 05:56:51 +00006335}
6336
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006337# mark the bits of a headline or author that match a find string
Paul Mackerras005a2f42007-07-26 22:36:39 +10006338proc markmatches {canv l str tag matches font row} {
6339 global selectedline
6340
Paul Mackerras98f350e2005-05-15 05:56:51 +00006341 set bbox [$canv bbox $tag]
6342 set x0 [lindex $bbox 0]
6343 set y0 [lindex $bbox 1]
6344 set y1 [lindex $bbox 3]
6345 foreach match $matches {
6346 set start [lindex $match 0]
6347 set end [lindex $match 1]
6348 if {$start > $end} continue
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08006349 set xoff [font measure $font [string range $str 0 [expr {$start-1}]]]
6350 set xlen [font measure $font [string range $str 0 [expr {$end}]]]
6351 set t [$canv create rect [expr {$x0+$xoff}] $y0 \
6352 [expr {$x0+$xlen+2}] $y1 \
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006353 -outline {} -tags [list match$l matches] -fill yellow]
Paul Mackerras98f350e2005-05-15 05:56:51 +00006354 $canv lower $t
Paul Mackerras94b4a692008-05-20 20:51:06 +10006355 if {$row == $selectedline} {
Paul Mackerras005a2f42007-07-26 22:36:39 +10006356 $canv raise $t secsel
6357 }
Paul Mackerras98f350e2005-05-15 05:56:51 +00006358 }
6359}
6360
6361proc unmarkmatches {} {
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10006362 global markingmatches
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006363
Paul Mackerras98f350e2005-05-15 05:56:51 +00006364 allcanvs delete matches
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006365 set markingmatches 0
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10006366 stopfinding
Paul Mackerras98f350e2005-05-15 05:56:51 +00006367}
6368
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10006369proc selcanvline {w x y} {
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10006370 global canv canvy0 ctext linespc
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006371 global rowtextx
Paul Mackerras1db95b02005-05-09 04:08:39 +00006372 set ymax [lindex [$canv cget -scrollregion] 3]
Paul Mackerrascfb45632005-05-31 12:14:42 +00006373 if {$ymax == {}} return
Paul Mackerras1db95b02005-05-09 04:08:39 +00006374 set yfrac [lindex [$canv yview] 0]
6375 set y [expr {$y + $yfrac * $ymax}]
6376 set l [expr {int(($y - $canvy0) / $linespc + 0.5)}]
6377 if {$l < 0} {
6378 set l 0
6379 }
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10006380 if {$w eq $canv} {
Paul Mackerrasfc2a2562007-12-26 23:03:43 +11006381 set xmax [lindex [$canv cget -scrollregion] 2]
6382 set xleft [expr {[lindex [$canv xview] 0] * $xmax}]
6383 if {![info exists rowtextx($l)] || $xleft + $x < $rowtextx($l)} return
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10006384 }
Paul Mackerras98f350e2005-05-15 05:56:51 +00006385 unmarkmatches
Paul Mackerrasd6982062005-08-06 22:06:06 +10006386 selectline $l 1
Paul Mackerras5ad588d2005-05-10 01:02:55 +00006387}
6388
Linus Torvaldsb1ba39e2005-08-08 20:04:20 -07006389proc commit_descriptor {p} {
6390 global commitinfo
Paul Mackerrasb0934482006-05-15 09:56:08 +10006391 if {![info exists commitinfo($p)]} {
6392 getcommit $p
6393 }
Linus Torvaldsb1ba39e2005-08-08 20:04:20 -07006394 set l "..."
Paul Mackerrasb0934482006-05-15 09:56:08 +10006395 if {[llength $commitinfo($p)] > 1} {
Linus Torvaldsb1ba39e2005-08-08 20:04:20 -07006396 set l [lindex $commitinfo($p) 0]
6397 }
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10006398 return "$p ($l)\n"
Linus Torvaldsb1ba39e2005-08-08 20:04:20 -07006399}
6400
Paul Mackerras106288c2005-08-19 23:11:39 +10006401# append some text to the ctext widget, and make any SHA1 ID
6402# that we know about be a clickable link.
Sergey Vlasovf1b86292006-05-15 19:13:14 +04006403proc appendwithlinks {text tags} {
Paul Mackerrasd375ef92008-10-21 10:18:12 +11006404 global ctext linknum curview
Paul Mackerras106288c2005-08-19 23:11:39 +10006405
6406 set start [$ctext index "end - 1c"]
Sergey Vlasovf1b86292006-05-15 19:13:14 +04006407 $ctext insert end $text $tags
Paul Mackerrasd375ef92008-10-21 10:18:12 +11006408 set links [regexp -indices -all -inline {\m[0-9a-f]{6,40}\M} $text]
Paul Mackerras106288c2005-08-19 23:11:39 +10006409 foreach l $links {
6410 set s [lindex $l 0]
6411 set e [lindex $l 1]
6412 set linkid [string range $text $s $e]
Paul Mackerras106288c2005-08-19 23:11:39 +10006413 incr e
Paul Mackerrasc73adce2007-09-27 10:35:05 +10006414 $ctext tag delete link$linknum
Paul Mackerras106288c2005-08-19 23:11:39 +10006415 $ctext tag add link$linknum "$start + $s c" "$start + $e c"
Paul Mackerras97645682007-08-23 22:24:38 +10006416 setlink $linkid link$linknum
Paul Mackerras106288c2005-08-19 23:11:39 +10006417 incr linknum
6418 }
Paul Mackerras97645682007-08-23 22:24:38 +10006419}
6420
6421proc setlink {id lk} {
Paul Mackerrasd375ef92008-10-21 10:18:12 +11006422 global curview ctext pendinglinks
Paul Mackerras97645682007-08-23 22:24:38 +10006423
Paul Mackerrasd375ef92008-10-21 10:18:12 +11006424 set known 0
6425 if {[string length $id] < 40} {
6426 set matches [longid $id]
6427 if {[llength $matches] > 0} {
6428 if {[llength $matches] > 1} return
6429 set known 1
6430 set id [lindex $matches 0]
6431 }
6432 } else {
6433 set known [commitinview $id $curview]
6434 }
6435 if {$known} {
Paul Mackerras97645682007-08-23 22:24:38 +10006436 $ctext tag conf $lk -foreground blue -underline 1
Paul Mackerrasd375ef92008-10-21 10:18:12 +11006437 $ctext tag bind $lk <1> [list selbyid $id]
Paul Mackerras97645682007-08-23 22:24:38 +10006438 $ctext tag bind $lk <Enter> {linkcursor %W 1}
6439 $ctext tag bind $lk <Leave> {linkcursor %W -1}
6440 } else {
6441 lappend pendinglinks($id) $lk
Paul Mackerrasd375ef92008-10-21 10:18:12 +11006442 interestedin $id {makelink %P}
Paul Mackerras97645682007-08-23 22:24:38 +10006443 }
6444}
6445
6446proc makelink {id} {
6447 global pendinglinks
6448
6449 if {![info exists pendinglinks($id)]} return
6450 foreach lk $pendinglinks($id) {
6451 setlink $id $lk
6452 }
6453 unset pendinglinks($id)
6454}
6455
6456proc linkcursor {w inc} {
6457 global linkentercount curtextcursor
6458
6459 if {[incr linkentercount $inc] > 0} {
6460 $w configure -cursor hand2
6461 } else {
6462 $w configure -cursor $curtextcursor
6463 if {$linkentercount < 0} {
6464 set linkentercount 0
6465 }
6466 }
Paul Mackerras106288c2005-08-19 23:11:39 +10006467}
6468
Rutger Nijlunsing6e5f7202006-04-05 10:24:03 +10006469proc viewnextline {dir} {
6470 global canv linespc
6471
6472 $canv delete hover
6473 set ymax [lindex [$canv cget -scrollregion] 3]
6474 set wnow [$canv yview]
6475 set wtop [expr {[lindex $wnow 0] * $ymax}]
6476 set newtop [expr {$wtop + $dir * $linespc}]
6477 if {$newtop < 0} {
6478 set newtop 0
6479 } elseif {$newtop > $ymax} {
6480 set newtop $ymax
6481 }
6482 allcanvs yview moveto [expr {$newtop * 1.0 / $ymax}]
6483}
6484
Paul Mackerrasef030b82006-06-04 11:50:38 +10006485# add a list of tag or branch names at position pos
6486# returns the number of names inserted
Paul Mackerrase11f1232007-06-16 20:29:25 +10006487proc appendrefs {pos ids var} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11006488 global ctext linknum curview $var maxrefs
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10006489
Paul Mackerrasef030b82006-06-04 11:50:38 +10006490 if {[catch {$ctext index $pos}]} {
6491 return 0
6492 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10006493 $ctext conf -state normal
6494 $ctext delete $pos "$pos lineend"
6495 set tags {}
6496 foreach id $ids {
6497 foreach tag [set $var\($id\)] {
6498 lappend tags [list $tag $id]
6499 }
6500 }
Paul Mackerras0a4dd8b2007-06-16 21:21:57 +10006501 if {[llength $tags] > $maxrefs} {
6502 $ctext insert $pos "many ([llength $tags])"
6503 } else {
6504 set tags [lsort -index 0 -decreasing $tags]
6505 set sep {}
6506 foreach ti $tags {
6507 set id [lindex $ti 1]
6508 set lk link$linknum
6509 incr linknum
6510 $ctext tag delete $lk
6511 $ctext insert $pos $sep
6512 $ctext insert $pos [lindex $ti 0] $lk
Paul Mackerras97645682007-08-23 22:24:38 +10006513 setlink $id $lk
Paul Mackerras0a4dd8b2007-06-16 21:21:57 +10006514 set sep ", "
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10006515 }
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10006516 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10006517 $ctext conf -state disabled
Paul Mackerrasef030b82006-06-04 11:50:38 +10006518 return [llength $tags]
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10006519}
6520
6521# called when we have finished computing the nearby tags
Paul Mackerrase11f1232007-06-16 20:29:25 +10006522proc dispneartags {delay} {
6523 global selectedline currentid showneartags tagphase
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10006524
Paul Mackerras94b4a692008-05-20 20:51:06 +10006525 if {$selectedline eq {} || !$showneartags} return
Paul Mackerrase11f1232007-06-16 20:29:25 +10006526 after cancel dispnexttag
6527 if {$delay} {
6528 after 200 dispnexttag
6529 set tagphase -1
6530 } else {
6531 after idle dispnexttag
6532 set tagphase 0
6533 }
6534}
6535
6536proc dispnexttag {} {
6537 global selectedline currentid showneartags tagphase ctext
6538
Paul Mackerras94b4a692008-05-20 20:51:06 +10006539 if {$selectedline eq {} || !$showneartags} return
Paul Mackerrase11f1232007-06-16 20:29:25 +10006540 switch -- $tagphase {
6541 0 {
6542 set dtags [desctags $currentid]
6543 if {$dtags ne {}} {
6544 appendrefs precedes $dtags idtags
6545 }
6546 }
6547 1 {
6548 set atags [anctags $currentid]
6549 if {$atags ne {}} {
6550 appendrefs follows $atags idtags
6551 }
6552 }
6553 2 {
6554 set dheads [descheads $currentid]
6555 if {$dheads ne {}} {
6556 if {[appendrefs branch $dheads idheads] > 1
6557 && [$ctext get "branch -3c"] eq "h"} {
6558 # turn "Branch" into "Branches"
6559 $ctext conf -state normal
6560 $ctext insert "branch -2c" "es"
6561 $ctext conf -state disabled
6562 }
6563 }
Paul Mackerrasef030b82006-06-04 11:50:38 +10006564 }
6565 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10006566 if {[incr tagphase] <= 2} {
6567 after idle dispnexttag
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10006568 }
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10006569}
6570
Paul Mackerras28593d32008-11-13 23:01:46 +11006571proc make_secsel {id} {
Paul Mackerras03800812007-08-29 21:45:21 +10006572 global linehtag linentag linedtag canv canv2 canv3
6573
Paul Mackerras28593d32008-11-13 23:01:46 +11006574 if {![info exists linehtag($id)]} return
Paul Mackerras03800812007-08-29 21:45:21 +10006575 $canv delete secsel
Paul Mackerras28593d32008-11-13 23:01:46 +11006576 set t [eval $canv create rect [$canv bbox $linehtag($id)] -outline {{}} \
Paul Mackerras03800812007-08-29 21:45:21 +10006577 -tags secsel -fill [$canv cget -selectbackground]]
6578 $canv lower $t
6579 $canv2 delete secsel
Paul Mackerras28593d32008-11-13 23:01:46 +11006580 set t [eval $canv2 create rect [$canv2 bbox $linentag($id)] -outline {{}} \
Paul Mackerras03800812007-08-29 21:45:21 +10006581 -tags secsel -fill [$canv2 cget -selectbackground]]
6582 $canv2 lower $t
6583 $canv3 delete secsel
Paul Mackerras28593d32008-11-13 23:01:46 +11006584 set t [eval $canv3 create rect [$canv3 bbox $linedtag($id)] -outline {{}} \
Paul Mackerras03800812007-08-29 21:45:21 +10006585 -tags secsel -fill [$canv3 cget -selectbackground]]
6586 $canv3 lower $t
6587}
6588
Paul Mackerras8a897742008-10-27 21:36:25 +11006589proc selectline {l isnew {desired_loc {}}} {
Paul Mackerras03800812007-08-29 21:45:21 +10006590 global canv ctext commitinfo selectedline
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11006591 global canvy0 linespc parents children curview
Paul Mackerras7fcceed2006-04-27 19:21:49 +10006592 global currentid sha1entry
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006593 global commentend idtags linknum
Paul Mackerrasd94f8cd2006-04-06 10:18:23 +10006594 global mergemax numcommits pending_select
Paul Mackerrase11f1232007-06-16 20:29:25 +10006595 global cmitmode showneartags allcommits
Paul Mackerrasc30acc72008-03-07 22:51:55 +11006596 global targetrow targetid lastscrollrows
Paul Mackerras8a897742008-10-27 21:36:25 +11006597 global autoselect jump_to_here
Paul Mackerrasd6982062005-08-06 22:06:06 +10006598
Paul Mackerrasd94f8cd2006-04-06 10:18:23 +10006599 catch {unset pending_select}
Paul Mackerras84ba7342005-06-17 00:12:26 +00006600 $canv delete hover
Paul Mackerras9843c302005-08-30 10:57:11 +10006601 normalline
Paul Mackerras887c9962007-08-20 19:36:20 +10006602 unsel_reflist
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10006603 stopfinding
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11006604 if {$l < 0 || $l >= $numcommits} return
Paul Mackerrasac1276a2008-03-03 10:11:08 +11006605 set id [commitonrow $l]
6606 set targetid $id
6607 set targetrow $l
Paul Mackerrasc30acc72008-03-07 22:51:55 +11006608 set selectedline $l
6609 set currentid $id
6610 if {$lastscrollrows < $numcommits} {
6611 setcanvscroll
6612 }
Paul Mackerrasac1276a2008-03-03 10:11:08 +11006613
Paul Mackerras5ad588d2005-05-10 01:02:55 +00006614 set y [expr {$canvy0 + $l * $linespc}]
Paul Mackerras17386062005-05-18 22:51:00 +00006615 set ymax [lindex [$canv cget -scrollregion] 3]
Paul Mackerras58422152005-05-19 10:56:42 +00006616 set ytop [expr {$y - $linespc - 1}]
6617 set ybot [expr {$y + $linespc + 1}]
Paul Mackerras5ad588d2005-05-10 01:02:55 +00006618 set wnow [$canv yview]
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08006619 set wtop [expr {[lindex $wnow 0] * $ymax}]
6620 set wbot [expr {[lindex $wnow 1] * $ymax}]
Paul Mackerras58422152005-05-19 10:56:42 +00006621 set wh [expr {$wbot - $wtop}]
6622 set newtop $wtop
Paul Mackerras17386062005-05-18 22:51:00 +00006623 if {$ytop < $wtop} {
Paul Mackerras58422152005-05-19 10:56:42 +00006624 if {$ybot < $wtop} {
6625 set newtop [expr {$y - $wh / 2.0}]
6626 } else {
6627 set newtop $ytop
6628 if {$newtop > $wtop - $linespc} {
6629 set newtop [expr {$wtop - $linespc}]
6630 }
Paul Mackerras17386062005-05-18 22:51:00 +00006631 }
Paul Mackerras58422152005-05-19 10:56:42 +00006632 } elseif {$ybot > $wbot} {
6633 if {$ytop > $wbot} {
6634 set newtop [expr {$y - $wh / 2.0}]
6635 } else {
6636 set newtop [expr {$ybot - $wh}]
6637 if {$newtop < $wtop + $linespc} {
6638 set newtop [expr {$wtop + $linespc}]
6639 }
Paul Mackerras17386062005-05-18 22:51:00 +00006640 }
Paul Mackerras58422152005-05-19 10:56:42 +00006641 }
6642 if {$newtop != $wtop} {
6643 if {$newtop < 0} {
6644 set newtop 0
6645 }
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08006646 allcanvs yview moveto [expr {$newtop * 1.0 / $ymax}]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006647 drawvisible
Paul Mackerras5ad588d2005-05-10 01:02:55 +00006648 }
Paul Mackerrasd6982062005-08-06 22:06:06 +10006649
Paul Mackerras28593d32008-11-13 23:01:46 +11006650 make_secsel $id
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006651
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10006652 if {$isnew} {
Paul Mackerrasfc2a2562007-12-26 23:03:43 +11006653 addtohistory [list selbyid $id]
Paul Mackerrasd6982062005-08-06 22:06:06 +10006654 }
6655
Paul Mackerras98f350e2005-05-15 05:56:51 +00006656 $sha1entry delete 0 end
6657 $sha1entry insert 0 $id
Jeff King95293b52008-03-06 06:49:25 -05006658 if {$autoselect} {
6659 $sha1entry selection from 0
6660 $sha1entry selection to end
6661 }
Paul Mackerras164ff272006-05-29 19:50:02 +10006662 rhighlight_sel $id
Paul Mackerras98f350e2005-05-15 05:56:51 +00006663
Paul Mackerras5ad588d2005-05-10 01:02:55 +00006664 $ctext conf -state normal
Paul Mackerras3ea06f92006-05-24 10:16:03 +10006665 clear_ctext
Paul Mackerras106288c2005-08-19 23:11:39 +10006666 set linknum 0
Paul Mackerrasd76afb12008-03-07 21:19:18 +11006667 if {![info exists commitinfo($id)]} {
6668 getcommit $id
6669 }
Paul Mackerras1db95b02005-05-09 04:08:39 +00006670 set info $commitinfo($id)
Paul Mackerras232475d2005-11-15 10:34:03 +11006671 set date [formatdate [lindex $info 2]]
Christian Stimmingd990ced2007-11-07 18:42:55 +01006672 $ctext insert end "[mc "Author"]: [lindex $info 1] $date\n"
Paul Mackerras232475d2005-11-15 10:34:03 +11006673 set date [formatdate [lindex $info 4]]
Christian Stimmingd990ced2007-11-07 18:42:55 +01006674 $ctext insert end "[mc "Committer"]: [lindex $info 3] $date\n"
Paul Mackerras887fe3c2005-05-21 07:35:37 +00006675 if {[info exists idtags($id)]} {
Christian Stimmingd990ced2007-11-07 18:42:55 +01006676 $ctext insert end [mc "Tags:"]
Paul Mackerras887fe3c2005-05-21 07:35:37 +00006677 foreach tag $idtags($id) {
6678 $ctext insert end " $tag"
6679 }
6680 $ctext insert end "\n"
6681 }
Mark Levedahl40b87ff2007-02-01 08:44:46 -05006682
Sergey Vlasovf1b86292006-05-15 19:13:14 +04006683 set headers {}
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11006684 set olds $parents($curview,$id)
Paul Mackerras79b2c752006-04-02 20:47:40 +10006685 if {[llength $olds] > 1} {
Paul Mackerrasb77b0272006-02-07 09:13:52 +11006686 set np 0
Paul Mackerras79b2c752006-04-02 20:47:40 +10006687 foreach p $olds {
Paul Mackerrasb77b0272006-02-07 09:13:52 +11006688 if {$np >= $mergemax} {
6689 set tag mmax
6690 } else {
6691 set tag m$np
6692 }
Christian Stimmingd990ced2007-11-07 18:42:55 +01006693 $ctext insert end "[mc "Parent"]: " $tag
Sergey Vlasovf1b86292006-05-15 19:13:14 +04006694 appendwithlinks [commit_descriptor $p] {}
Paul Mackerrasb77b0272006-02-07 09:13:52 +11006695 incr np
6696 }
6697 } else {
Paul Mackerras79b2c752006-04-02 20:47:40 +10006698 foreach p $olds {
Christian Stimmingd990ced2007-11-07 18:42:55 +01006699 append headers "[mc "Parent"]: [commit_descriptor $p]"
Linus Torvalds8b192802005-08-07 13:58:56 -07006700 }
Linus Torvaldsb1ba39e2005-08-08 20:04:20 -07006701 }
Paul Mackerrasb77b0272006-02-07 09:13:52 +11006702
Paul Mackerras6a90bff2007-06-18 09:48:23 +10006703 foreach c $children($curview,$id) {
Christian Stimmingd990ced2007-11-07 18:42:55 +01006704 append headers "[mc "Child"]: [commit_descriptor $c]"
Linus Torvalds8b192802005-08-07 13:58:56 -07006705 }
Paul Mackerrasd6982062005-08-06 22:06:06 +10006706
6707 # make anything that looks like a SHA1 ID be a clickable link
Sergey Vlasovf1b86292006-05-15 19:13:14 +04006708 appendwithlinks $headers {}
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10006709 if {$showneartags} {
6710 if {![info exists allcommits]} {
6711 getallcommits
6712 }
Christian Stimmingd990ced2007-11-07 18:42:55 +01006713 $ctext insert end "[mc "Branch"]: "
Paul Mackerrasef030b82006-06-04 11:50:38 +10006714 $ctext mark set branch "end -1c"
6715 $ctext mark gravity branch left
Christian Stimmingd990ced2007-11-07 18:42:55 +01006716 $ctext insert end "\n[mc "Follows"]: "
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10006717 $ctext mark set follows "end -1c"
6718 $ctext mark gravity follows left
Christian Stimmingd990ced2007-11-07 18:42:55 +01006719 $ctext insert end "\n[mc "Precedes"]: "
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10006720 $ctext mark set precedes "end -1c"
6721 $ctext mark gravity precedes left
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10006722 $ctext insert end "\n"
Paul Mackerrase11f1232007-06-16 20:29:25 +10006723 dispneartags 1
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10006724 }
6725 $ctext insert end "\n"
Paul Mackerras43c25072006-09-27 10:56:02 +10006726 set comment [lindex $info 5]
6727 if {[string first "\r" $comment] >= 0} {
6728 set comment [string map {"\r" "\n "} $comment]
6729 }
6730 appendwithlinks $comment {comment}
Paul Mackerrasd6982062005-08-06 22:06:06 +10006731
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00006732 $ctext tag remove found 1.0 end
Paul Mackerras5ad588d2005-05-10 01:02:55 +00006733 $ctext conf -state disabled
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00006734 set commentend [$ctext index "end - 1c"]
Paul Mackerras5ad588d2005-05-10 01:02:55 +00006735
Paul Mackerras8a897742008-10-27 21:36:25 +11006736 set jump_to_here $desired_loc
Christian Stimmingb007ee22007-11-07 18:44:35 +01006737 init_flist [mc "Comments"]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10006738 if {$cmitmode eq "tree"} {
6739 gettree $id
6740 } elseif {[llength $olds] <= 1} {
Paul Mackerrasd3272442005-11-28 20:41:56 +11006741 startdiff $id
Paul Mackerras7b5ff7e2006-03-30 20:50:40 +11006742 } else {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11006743 mergediff $id
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10006744 }
6745}
6746
Rutger Nijlunsing6e5f7202006-04-05 10:24:03 +10006747proc selfirstline {} {
6748 unmarkmatches
6749 selectline 0 1
6750}
6751
6752proc sellastline {} {
6753 global numcommits
6754 unmarkmatches
6755 set l [expr {$numcommits - 1}]
6756 selectline $l 1
6757}
6758
Paul Mackerrase5c2d852005-05-11 23:44:54 +00006759proc selnextline {dir} {
6760 global selectedline
Mark Levedahlbd441de2007-08-07 21:40:34 -04006761 focus .
Paul Mackerras94b4a692008-05-20 20:51:06 +10006762 if {$selectedline eq {}} return
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08006763 set l [expr {$selectedline + $dir}]
Paul Mackerras98f350e2005-05-15 05:56:51 +00006764 unmarkmatches
Paul Mackerrasd6982062005-08-06 22:06:06 +10006765 selectline $l 1
6766}
6767
Rutger Nijlunsing6e5f7202006-04-05 10:24:03 +10006768proc selnextpage {dir} {
6769 global canv linespc selectedline numcommits
6770
6771 set lpp [expr {([winfo height $canv] - 2) / $linespc}]
6772 if {$lpp < 1} {
6773 set lpp 1
6774 }
6775 allcanvs yview scroll [expr {$dir * $lpp}] units
Paul Mackerrase72ee5e2006-05-20 09:58:49 +10006776 drawvisible
Paul Mackerras94b4a692008-05-20 20:51:06 +10006777 if {$selectedline eq {}} return
Rutger Nijlunsing6e5f7202006-04-05 10:24:03 +10006778 set l [expr {$selectedline + $dir * $lpp}]
6779 if {$l < 0} {
6780 set l 0
6781 } elseif {$l >= $numcommits} {
6782 set l [expr $numcommits - 1]
6783 }
6784 unmarkmatches
Mark Levedahl40b87ff2007-02-01 08:44:46 -05006785 selectline $l 1
Rutger Nijlunsing6e5f7202006-04-05 10:24:03 +10006786}
6787
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10006788proc unselectline {} {
Paul Mackerras50b44ec2006-04-04 10:16:22 +10006789 global selectedline currentid
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10006790
Paul Mackerras94b4a692008-05-20 20:51:06 +10006791 set selectedline {}
Paul Mackerras50b44ec2006-04-04 10:16:22 +10006792 catch {unset currentid}
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10006793 allcanvs delete secsel
Paul Mackerras164ff272006-05-29 19:50:02 +10006794 rhighlight_none
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10006795}
6796
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10006797proc reselectline {} {
6798 global selectedline
6799
Paul Mackerras94b4a692008-05-20 20:51:06 +10006800 if {$selectedline ne {}} {
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10006801 selectline $selectedline 0
6802 }
6803}
6804
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10006805proc addtohistory {cmd} {
Paul Mackerras2516dae2006-04-21 10:35:31 +10006806 global history historyindex curview
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10006807
Paul Mackerras2516dae2006-04-21 10:35:31 +10006808 set elt [list $curview $cmd]
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10006809 if {$historyindex > 0
Paul Mackerras2516dae2006-04-21 10:35:31 +10006810 && [lindex $history [expr {$historyindex - 1}]] == $elt} {
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10006811 return
6812 }
6813
6814 if {$historyindex < [llength $history]} {
Paul Mackerras2516dae2006-04-21 10:35:31 +10006815 set history [lreplace $history $historyindex end $elt]
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10006816 } else {
Paul Mackerras2516dae2006-04-21 10:35:31 +10006817 lappend history $elt
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10006818 }
6819 incr historyindex
6820 if {$historyindex > 1} {
Junio C Hamanoe9937d22007-02-01 08:46:38 -05006821 .tf.bar.leftbut conf -state normal
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10006822 } else {
Junio C Hamanoe9937d22007-02-01 08:46:38 -05006823 .tf.bar.leftbut conf -state disabled
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10006824 }
Junio C Hamanoe9937d22007-02-01 08:46:38 -05006825 .tf.bar.rightbut conf -state disabled
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10006826}
6827
Paul Mackerras2516dae2006-04-21 10:35:31 +10006828proc godo {elt} {
6829 global curview
6830
6831 set view [lindex $elt 0]
6832 set cmd [lindex $elt 1]
6833 if {$curview != $view} {
6834 showview $view
6835 }
6836 eval $cmd
6837}
6838
Paul Mackerrasd6982062005-08-06 22:06:06 +10006839proc goback {} {
6840 global history historyindex
Mark Levedahlbd441de2007-08-07 21:40:34 -04006841 focus .
Paul Mackerrasd6982062005-08-06 22:06:06 +10006842
6843 if {$historyindex > 1} {
6844 incr historyindex -1
Paul Mackerras2516dae2006-04-21 10:35:31 +10006845 godo [lindex $history [expr {$historyindex - 1}]]
Junio C Hamanoe9937d22007-02-01 08:46:38 -05006846 .tf.bar.rightbut conf -state normal
Paul Mackerrasd6982062005-08-06 22:06:06 +10006847 }
6848 if {$historyindex <= 1} {
Junio C Hamanoe9937d22007-02-01 08:46:38 -05006849 .tf.bar.leftbut conf -state disabled
Paul Mackerrasd6982062005-08-06 22:06:06 +10006850 }
6851}
6852
6853proc goforw {} {
6854 global history historyindex
Mark Levedahlbd441de2007-08-07 21:40:34 -04006855 focus .
Paul Mackerrasd6982062005-08-06 22:06:06 +10006856
6857 if {$historyindex < [llength $history]} {
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10006858 set cmd [lindex $history $historyindex]
Paul Mackerrasd6982062005-08-06 22:06:06 +10006859 incr historyindex
Paul Mackerras2516dae2006-04-21 10:35:31 +10006860 godo $cmd
Junio C Hamanoe9937d22007-02-01 08:46:38 -05006861 .tf.bar.leftbut conf -state normal
Paul Mackerrasd6982062005-08-06 22:06:06 +10006862 }
6863 if {$historyindex >= [llength $history]} {
Junio C Hamanoe9937d22007-02-01 08:46:38 -05006864 .tf.bar.rightbut conf -state disabled
Paul Mackerrasd6982062005-08-06 22:06:06 +10006865 }
Paul Mackerras5ad588d2005-05-10 01:02:55 +00006866}
6867
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10006868proc gettree {id} {
Paul Mackerras8f489362007-07-13 19:49:37 +10006869 global treefilelist treeidlist diffids diffmergeid treepending
6870 global nullid nullid2
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10006871
6872 set diffids $id
6873 catch {unset diffmergeid}
6874 if {![info exists treefilelist($id)]} {
6875 if {![info exists treepending]} {
Paul Mackerras8f489362007-07-13 19:49:37 +10006876 if {$id eq $nullid} {
6877 set cmd [list | git ls-files]
6878 } elseif {$id eq $nullid2} {
6879 set cmd [list | git ls-files --stage -t]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10006880 } else {
Paul Mackerras8f489362007-07-13 19:49:37 +10006881 set cmd [list | git ls-tree -r $id]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10006882 }
6883 if {[catch {set gtf [open $cmd r]}]} {
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10006884 return
6885 }
6886 set treepending $id
6887 set treefilelist($id) {}
6888 set treeidlist($id) {}
Alexander Gavrilov09c70292008-10-13 12:12:31 +04006889 fconfigure $gtf -blocking 0 -encoding binary
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10006890 filerun $gtf [list gettreeline $gtf $id]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10006891 }
6892 } else {
6893 setfilelist $id
6894 }
6895}
6896
6897proc gettreeline {gtf id} {
Paul Mackerras8f489362007-07-13 19:49:37 +10006898 global treefilelist treeidlist treepending cmitmode diffids nullid nullid2
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10006899
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10006900 set nl 0
6901 while {[incr nl] <= 1000 && [gets $gtf line] >= 0} {
Paul Mackerras8f489362007-07-13 19:49:37 +10006902 if {$diffids eq $nullid} {
6903 set fname $line
6904 } else {
Paul Mackerras9396cd32007-06-23 20:28:15 +10006905 set i [string first "\t" $line]
6906 if {$i < 0} continue
Paul Mackerras9396cd32007-06-23 20:28:15 +10006907 set fname [string range $line [expr {$i+1}] end]
Paul Mackerrasf31fa2c2008-04-28 09:40:50 +10006908 set line [string range $line 0 [expr {$i-1}]]
6909 if {$diffids ne $nullid2 && [lindex $line 1] ne "blob"} continue
6910 set sha1 [lindex $line 2]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10006911 lappend treeidlist($id) $sha1
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10006912 }
Alexander Gavrilov09c70292008-10-13 12:12:31 +04006913 if {[string index $fname 0] eq "\""} {
6914 set fname [lindex $fname 0]
6915 }
6916 set fname [encoding convertfrom $fname]
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10006917 lappend treefilelist($id) $fname
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10006918 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10006919 if {![eof $gtf]} {
6920 return [expr {$nl >= 1000? 2: 1}]
6921 }
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10006922 close $gtf
6923 unset treepending
6924 if {$cmitmode ne "tree"} {
6925 if {![info exists diffmergeid]} {
6926 gettreediffs $diffids
6927 }
6928 } elseif {$id ne $diffids} {
6929 gettree $diffids
6930 } else {
6931 setfilelist $id
6932 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10006933 return 0
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10006934}
6935
6936proc showfile {f} {
Paul Mackerras8f489362007-07-13 19:49:37 +10006937 global treefilelist treeidlist diffids nullid nullid2
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04006938 global ctext_file_names ctext_file_lines
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10006939 global ctext commentend
6940
6941 set i [lsearch -exact $treefilelist($diffids) $f]
6942 if {$i < 0} {
6943 puts "oops, $f not in list for id $diffids"
6944 return
6945 }
Paul Mackerras8f489362007-07-13 19:49:37 +10006946 if {$diffids eq $nullid} {
6947 if {[catch {set bf [open $f r]} err]} {
6948 puts "oops, can't read $f: $err"
Paul Mackerras219ea3a2006-09-07 10:21:39 +10006949 return
6950 }
6951 } else {
Paul Mackerras8f489362007-07-13 19:49:37 +10006952 set blob [lindex $treeidlist($diffids) $i]
6953 if {[catch {set bf [open [concat | git cat-file blob $blob] r]} err]} {
6954 puts "oops, error reading blob $blob: $err"
Paul Mackerras219ea3a2006-09-07 10:21:39 +10006955 return
6956 }
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10006957 }
Alexander Gavrilov09c70292008-10-13 12:12:31 +04006958 fconfigure $bf -blocking 0 -encoding [get_path_encoding $f]
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10006959 filerun $bf [list getblobline $bf $diffids]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10006960 $ctext config -state normal
Paul Mackerras3ea06f92006-05-24 10:16:03 +10006961 clear_ctext $commentend
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04006962 lappend ctext_file_names $f
6963 lappend ctext_file_lines [lindex [split $commentend "."] 0]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10006964 $ctext insert end "\n"
6965 $ctext insert end "$f\n" filesep
6966 $ctext config -state disabled
6967 $ctext yview $commentend
Paul Mackerras32f1b3e2007-09-28 21:27:39 +10006968 settabs 0
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10006969}
6970
6971proc getblobline {bf id} {
6972 global diffids cmitmode ctext
6973
6974 if {$id ne $diffids || $cmitmode ne "tree"} {
6975 catch {close $bf}
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10006976 return 0
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10006977 }
6978 $ctext config -state normal
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10006979 set nl 0
6980 while {[incr nl] <= 1000 && [gets $bf line] >= 0} {
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10006981 $ctext insert end "$line\n"
6982 }
6983 if {[eof $bf]} {
Paul Mackerras8a897742008-10-27 21:36:25 +11006984 global jump_to_here ctext_file_names commentend
6985
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10006986 # delete last newline
6987 $ctext delete "end - 2c" "end - 1c"
6988 close $bf
Paul Mackerras8a897742008-10-27 21:36:25 +11006989 if {$jump_to_here ne {} &&
6990 [lindex $jump_to_here 0] eq [lindex $ctext_file_names 0]} {
6991 set lnum [expr {[lindex $jump_to_here 1] +
6992 [lindex [split $commentend .] 0]}]
6993 mark_ctext_line $lnum
6994 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10006995 return 0
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10006996 }
6997 $ctext config -state disabled
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10006998 return [expr {$nl >= 1000? 2: 1}]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10006999}
7000
Paul Mackerras8a897742008-10-27 21:36:25 +11007001proc mark_ctext_line {lnum} {
Paul Mackerrase3e901b2008-10-27 22:37:21 +11007002 global ctext markbgcolor
Paul Mackerras8a897742008-10-27 21:36:25 +11007003
7004 $ctext tag delete omark
7005 $ctext tag add omark $lnum.0 "$lnum.0 + 1 line"
Paul Mackerrase3e901b2008-10-27 22:37:21 +11007006 $ctext tag conf omark -background $markbgcolor
Paul Mackerras8a897742008-10-27 21:36:25 +11007007 $ctext see $lnum.0
7008}
7009
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11007010proc mergediff {id} {
Paul Mackerras8b07dca2008-11-02 22:34:47 +11007011 global diffmergeid
Alexander Gavrilov2df64422008-10-08 11:05:37 +04007012 global diffids treediffs
Paul Mackerras8b07dca2008-11-02 22:34:47 +11007013 global parents curview
Paul Mackerrase2ed4322005-07-17 03:39:44 -04007014
Paul Mackerras3c461ff2005-07-20 09:13:46 -04007015 set diffmergeid $id
Paul Mackerras7a1d9d12006-03-22 10:21:45 +11007016 set diffids $id
Alexander Gavrilov2df64422008-10-08 11:05:37 +04007017 set treediffs($id) {}
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11007018 set np [llength $parents($curview,$id)]
Paul Mackerras32f1b3e2007-09-28 21:27:39 +10007019 settabs $np
Paul Mackerras8b07dca2008-11-02 22:34:47 +11007020 getblobdiffs $id
Paul Mackerrasc8a4acb2005-07-29 09:23:03 -05007021}
7022
Paul Mackerras3c461ff2005-07-20 09:13:46 -04007023proc startdiff {ids} {
Paul Mackerras8f489362007-07-13 19:49:37 +10007024 global treediffs diffids treepending diffmergeid nullid nullid2
Paul Mackerras3c461ff2005-07-20 09:13:46 -04007025
Paul Mackerras32f1b3e2007-09-28 21:27:39 +10007026 settabs 1
Paul Mackerras3c461ff2005-07-20 09:13:46 -04007027 set diffids $ids
7028 catch {unset diffmergeid}
Paul Mackerras8f489362007-07-13 19:49:37 +10007029 if {![info exists treediffs($ids)] ||
7030 [lsearch -exact $ids $nullid] >= 0 ||
7031 [lsearch -exact $ids $nullid2] >= 0} {
Paul Mackerras3c461ff2005-07-20 09:13:46 -04007032 if {![info exists treepending]} {
7033 gettreediffs $ids
7034 }
7035 } else {
7036 addtocflist $ids
7037 }
7038}
7039
Paul Mackerras7a39a172007-10-23 10:15:11 +10007040proc path_filter {filter name} {
7041 foreach p $filter {
7042 set l [string length $p]
Paul Mackerras74a40c72007-10-24 10:16:56 +10007043 if {[string index $p end] eq "/"} {
7044 if {[string compare -length $l $p $name] == 0} {
7045 return 1
7046 }
7047 } else {
7048 if {[string compare -length $l $p $name] == 0 &&
7049 ([string length $name] == $l ||
7050 [string index $name $l] eq "/")} {
7051 return 1
7052 }
Paul Mackerras7a39a172007-10-23 10:15:11 +10007053 }
7054 }
7055 return 0
7056}
7057
Paul Mackerras3c461ff2005-07-20 09:13:46 -04007058proc addtocflist {ids} {
Paul Mackerras74a40c72007-10-24 10:16:56 +10007059 global treediffs
Paul Mackerras7a39a172007-10-23 10:15:11 +10007060
Paul Mackerras74a40c72007-10-24 10:16:56 +10007061 add_flist $treediffs($ids)
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10007062 getblobdiffs $ids
Paul Mackerrasd2610d12005-05-11 00:45:38 +00007063}
7064
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007065proc diffcmd {ids flags} {
Paul Mackerras8f489362007-07-13 19:49:37 +10007066 global nullid nullid2
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007067
7068 set i [lsearch -exact $ids $nullid]
Paul Mackerras8f489362007-07-13 19:49:37 +10007069 set j [lsearch -exact $ids $nullid2]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007070 if {$i >= 0} {
Paul Mackerras8f489362007-07-13 19:49:37 +10007071 if {[llength $ids] > 1 && $j < 0} {
7072 # comparing working directory with some specific revision
7073 set cmd [concat | git diff-index $flags]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007074 if {$i == 0} {
7075 lappend cmd -R [lindex $ids 1]
7076 } else {
7077 lappend cmd [lindex $ids 0]
7078 }
7079 } else {
Paul Mackerras8f489362007-07-13 19:49:37 +10007080 # comparing working directory with index
7081 set cmd [concat | git diff-files $flags]
7082 if {$j == 1} {
7083 lappend cmd -R
7084 }
7085 }
7086 } elseif {$j >= 0} {
7087 set cmd [concat | git diff-index --cached $flags]
7088 if {[llength $ids] > 1} {
7089 # comparing index with specific revision
7090 if {$i == 0} {
7091 lappend cmd -R [lindex $ids 1]
7092 } else {
7093 lappend cmd [lindex $ids 0]
7094 }
7095 } else {
7096 # comparing index with HEAD
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007097 lappend cmd HEAD
7098 }
7099 } else {
Paul Mackerras8f489362007-07-13 19:49:37 +10007100 set cmd [concat | git diff-tree -r $flags $ids]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007101 }
7102 return $cmd
7103}
7104
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10007105proc gettreediffs {ids} {
Paul Mackerras79b2c752006-04-02 20:47:40 +10007106 global treediff treepending
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007107
Alexander Gavrilov72721312008-07-26 18:48:41 +04007108 if {[catch {set gdtf [open [diffcmd $ids {--no-commit-id}] r]}]} return
7109
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10007110 set treepending $ids
Paul Mackerras3c461ff2005-07-20 09:13:46 -04007111 set treediff {}
Alexander Gavrilov09c70292008-10-13 12:12:31 +04007112 fconfigure $gdtf -blocking 0 -encoding binary
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007113 filerun $gdtf [list gettreediffline $gdtf $ids]
Paul Mackerrasd2610d12005-05-11 00:45:38 +00007114}
7115
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10007116proc gettreediffline {gdtf ids} {
Paul Mackerras3c461ff2005-07-20 09:13:46 -04007117 global treediff treediffs treepending diffids diffmergeid
Paul Mackerras39ee47e2008-10-15 22:23:03 +11007118 global cmitmode vfilelimit curview limitdiffs perfile_attrs
Paul Mackerras3c461ff2005-07-20 09:13:46 -04007119
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007120 set nr 0
Alexander Gavrilov4db09302008-10-13 12:12:33 +04007121 set sublist {}
Paul Mackerras39ee47e2008-10-15 22:23:03 +11007122 set max 1000
7123 if {$perfile_attrs} {
7124 # cache_gitattr is slow, and even slower on win32 where we
7125 # have to invoke it for only about 30 paths at a time
7126 set max 500
7127 if {[tk windowingsystem] == "win32"} {
7128 set max 120
7129 }
7130 }
7131 while {[incr nr] <= $max && [gets $gdtf line] >= 0} {
Paul Mackerras9396cd32007-06-23 20:28:15 +10007132 set i [string first "\t" $line]
7133 if {$i >= 0} {
7134 set file [string range $line [expr {$i+1}] end]
7135 if {[string index $file 0] eq "\""} {
7136 set file [lindex $file 0]
7137 }
Alexander Gavrilov09c70292008-10-13 12:12:31 +04007138 set file [encoding convertfrom $file]
Paul Mackerras48a81b72008-11-04 21:09:00 +11007139 if {$file ne [lindex $treediff end]} {
7140 lappend treediff $file
7141 lappend sublist $file
7142 }
Paul Mackerras9396cd32007-06-23 20:28:15 +10007143 }
Paul Mackerrasd2610d12005-05-11 00:45:38 +00007144 }
Paul Mackerras39ee47e2008-10-15 22:23:03 +11007145 if {$perfile_attrs} {
7146 cache_gitattr encoding $sublist
7147 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007148 if {![eof $gdtf]} {
Paul Mackerras39ee47e2008-10-15 22:23:03 +11007149 return [expr {$nr >= $max? 2: 1}]
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007150 }
7151 close $gdtf
Paul Mackerras3ed31a82008-04-26 16:00:00 +10007152 if {$limitdiffs && $vfilelimit($curview) ne {}} {
Paul Mackerras74a40c72007-10-24 10:16:56 +10007153 set flist {}
7154 foreach f $treediff {
Paul Mackerras3ed31a82008-04-26 16:00:00 +10007155 if {[path_filter $vfilelimit($curview) $f]} {
Paul Mackerras74a40c72007-10-24 10:16:56 +10007156 lappend flist $f
7157 }
7158 }
7159 set treediffs($ids) $flist
7160 } else {
7161 set treediffs($ids) $treediff
7162 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007163 unset treepending
Paul Mackerrase1160132008-11-18 21:40:32 +11007164 if {$cmitmode eq "tree" && [llength $diffids] == 1} {
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007165 gettree $diffids
7166 } elseif {$ids != $diffids} {
7167 if {![info exists diffmergeid]} {
7168 gettreediffs $diffids
7169 }
7170 } else {
7171 addtocflist $ids
7172 }
7173 return 0
Paul Mackerrasd2610d12005-05-11 00:45:38 +00007174}
7175
Steffen Prohaska890fae72007-08-12 12:05:46 +02007176# empty string or positive integer
7177proc diffcontextvalidate {v} {
7178 return [regexp {^(|[1-9][0-9]*)$} $v]
7179}
7180
7181proc diffcontextchange {n1 n2 op} {
7182 global diffcontextstring diffcontext
7183
7184 if {[string is integer -strict $diffcontextstring]} {
7185 if {$diffcontextstring > 0} {
7186 set diffcontext $diffcontextstring
7187 reselectline
7188 }
7189 }
7190}
7191
Steffen Prohaskab9b86002008-01-17 23:42:55 +01007192proc changeignorespace {} {
7193 reselectline
7194}
7195
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10007196proc getblobdiffs {ids} {
Paul Mackerras8d73b242007-10-06 20:22:00 +10007197 global blobdifffd diffids env
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007198 global diffinhdr treediffs
Steffen Prohaska890fae72007-08-12 12:05:46 +02007199 global diffcontext
Steffen Prohaskab9b86002008-01-17 23:42:55 +01007200 global ignorespace
Paul Mackerras3ed31a82008-04-26 16:00:00 +10007201 global limitdiffs vfilelimit curview
Paul Mackerras8b07dca2008-11-02 22:34:47 +11007202 global diffencoding targetline diffnparents
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10007203
Paul Mackerras8b07dca2008-11-02 22:34:47 +11007204 set cmd [diffcmd $ids "-p -C --cc --no-commit-id -U$diffcontext"]
Steffen Prohaskab9b86002008-01-17 23:42:55 +01007205 if {$ignorespace} {
7206 append cmd " -w"
7207 }
Paul Mackerras3ed31a82008-04-26 16:00:00 +10007208 if {$limitdiffs && $vfilelimit($curview) ne {}} {
7209 set cmd [concat $cmd -- $vfilelimit($curview)]
Paul Mackerras7a39a172007-10-23 10:15:11 +10007210 }
7211 if {[catch {set bdf [open $cmd r]} err]} {
Paul Mackerras8b07dca2008-11-02 22:34:47 +11007212 error_popup [mc "Error getting diffs: %s" $err]
Paul Mackerrase5c2d852005-05-11 23:44:54 +00007213 return
7214 }
Paul Mackerras8a897742008-10-27 21:36:25 +11007215 set targetline {}
Paul Mackerras8b07dca2008-11-02 22:34:47 +11007216 set diffnparents 0
Paul Mackerras4f2c2642005-07-17 11:11:44 -04007217 set diffinhdr 0
Alexander Gavrilov09c70292008-10-13 12:12:31 +04007218 set diffencoding [get_path_encoding {}]
Pat Thoyts681c3292009-03-16 10:24:40 +00007219 fconfigure $bdf -blocking 0 -encoding binary -eofchar {}
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10007220 set blobdifffd($ids) $bdf
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007221 filerun $bdf [list getblobdiffline $bdf $diffids]
Paul Mackerrase5c2d852005-05-11 23:44:54 +00007222}
7223
Paul Mackerras89b11d32006-05-02 19:55:31 +10007224proc setinlist {var i val} {
7225 global $var
7226
7227 while {[llength [set $var]] < $i} {
7228 lappend $var {}
7229 }
7230 if {[llength [set $var]] == $i} {
7231 lappend $var $val
7232 } else {
7233 lset $var $i $val
7234 }
7235}
7236
Paul Mackerras9396cd32007-06-23 20:28:15 +10007237proc makediffhdr {fname ids} {
Paul Mackerras8b07dca2008-11-02 22:34:47 +11007238 global ctext curdiffstart treediffs diffencoding
Paul Mackerras8a897742008-10-27 21:36:25 +11007239 global ctext_file_names jump_to_here targetline diffline
Paul Mackerras9396cd32007-06-23 20:28:15 +10007240
Paul Mackerras8b07dca2008-11-02 22:34:47 +11007241 set fname [encoding convertfrom $fname]
7242 set diffencoding [get_path_encoding $fname]
Paul Mackerras9396cd32007-06-23 20:28:15 +10007243 set i [lsearch -exact $treediffs($ids) $fname]
7244 if {$i >= 0} {
7245 setinlist difffilestart $i $curdiffstart
7246 }
Paul Mackerras48a81b72008-11-04 21:09:00 +11007247 lset ctext_file_names end $fname
Paul Mackerras9396cd32007-06-23 20:28:15 +10007248 set l [expr {(78 - [string length $fname]) / 2}]
7249 set pad [string range "----------------------------------------" 1 $l]
7250 $ctext insert $curdiffstart "$pad $fname $pad" filesep
Paul Mackerras8a897742008-10-27 21:36:25 +11007251 set targetline {}
7252 if {$jump_to_here ne {} && [lindex $jump_to_here 0] eq $fname} {
7253 set targetline [lindex $jump_to_here 1]
7254 }
7255 set diffline 0
Paul Mackerras9396cd32007-06-23 20:28:15 +10007256}
7257
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10007258proc getblobdiffline {bdf ids} {
Paul Mackerras9396cd32007-06-23 20:28:15 +10007259 global diffids blobdifffd ctext curdiffstart
Paul Mackerras7eab2932005-07-20 12:25:54 -04007260 global diffnexthead diffnextnote difffilestart
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04007261 global ctext_file_names ctext_file_lines
Paul Mackerras8b07dca2008-11-02 22:34:47 +11007262 global diffinhdr treediffs mergemax diffnparents
Paul Mackerras8a897742008-10-27 21:36:25 +11007263 global diffencoding jump_to_here targetline diffline
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10007264
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007265 set nr 0
Paul Mackerrase5c2d852005-05-11 23:44:54 +00007266 $ctext conf -state normal
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007267 while {[incr nr] <= 1000 && [gets $bdf line] >= 0} {
7268 if {$ids != $diffids || $bdf != $blobdifffd($ids)} {
7269 close $bdf
7270 return 0
Paul Mackerras89b11d32006-05-02 19:55:31 +10007271 }
Paul Mackerras8b07dca2008-11-02 22:34:47 +11007272 if {![string compare -length 5 "diff " $line]} {
7273 if {![regexp {^diff (--cc|--git) } $line m type]} {
7274 set line [encoding convertfrom $line]
7275 $ctext insert end "$line\n" hunksep
7276 continue
7277 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007278 # start of a new file
Paul Mackerras8b07dca2008-11-02 22:34:47 +11007279 set diffinhdr 1
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007280 $ctext insert end "\n"
Paul Mackerras9396cd32007-06-23 20:28:15 +10007281 set curdiffstart [$ctext index "end - 1c"]
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04007282 lappend ctext_file_names ""
7283 lappend ctext_file_lines [lindex [split $curdiffstart "."] 0]
Paul Mackerras9396cd32007-06-23 20:28:15 +10007284 $ctext insert end "\n" filesep
Paul Mackerras8b07dca2008-11-02 22:34:47 +11007285
7286 if {$type eq "--cc"} {
7287 # start of a new file in a merge diff
7288 set fname [string range $line 10 end]
7289 if {[lsearch -exact $treediffs($ids) $fname] < 0} {
7290 lappend treediffs($ids) $fname
7291 add_flist [list $fname]
7292 }
7293
Paul Mackerras9396cd32007-06-23 20:28:15 +10007294 } else {
Paul Mackerras8b07dca2008-11-02 22:34:47 +11007295 set line [string range $line 11 end]
7296 # If the name hasn't changed the length will be odd,
7297 # the middle char will be a space, and the two bits either
7298 # side will be a/name and b/name, or "a/name" and "b/name".
7299 # If the name has changed we'll get "rename from" and
7300 # "rename to" or "copy from" and "copy to" lines following
7301 # this, and we'll use them to get the filenames.
7302 # This complexity is necessary because spaces in the
7303 # filename(s) don't get escaped.
7304 set l [string length $line]
7305 set i [expr {$l / 2}]
7306 if {!(($l & 1) && [string index $line $i] eq " " &&
7307 [string range $line 2 [expr {$i - 1}]] eq \
7308 [string range $line [expr {$i + 3}] end])} {
7309 continue
7310 }
7311 # unescape if quoted and chop off the a/ from the front
7312 if {[string index $line 0] eq "\""} {
7313 set fname [string range [lindex $line 0] 2 end]
7314 } else {
7315 set fname [string range $line 2 [expr {$i - 1}]]
7316 }
Paul Mackerrase5c2d852005-05-11 23:44:54 +00007317 }
Paul Mackerras9396cd32007-06-23 20:28:15 +10007318 makediffhdr $fname $ids
7319
Paul Mackerras48a81b72008-11-04 21:09:00 +11007320 } elseif {![string compare -length 16 "* Unmerged path " $line]} {
7321 set fname [encoding convertfrom [string range $line 16 end]]
7322 $ctext insert end "\n"
7323 set curdiffstart [$ctext index "end - 1c"]
7324 lappend ctext_file_names $fname
7325 lappend ctext_file_lines [lindex [split $curdiffstart "."] 0]
7326 $ctext insert end "$line\n" filesep
7327 set i [lsearch -exact $treediffs($ids) $fname]
7328 if {$i >= 0} {
7329 setinlist difffilestart $i $curdiffstart
7330 }
7331
Paul Mackerras8b07dca2008-11-02 22:34:47 +11007332 } elseif {![string compare -length 2 "@@" $line]} {
7333 regexp {^@@+} $line ats
Alexander Gavrilov09c70292008-10-13 12:12:31 +04007334 set line [encoding convertfrom $diffencoding $line]
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007335 $ctext insert end "$line\n" hunksep
Paul Mackerras8b07dca2008-11-02 22:34:47 +11007336 if {[regexp { \+(\d+),\d+ @@} $line m nl]} {
7337 set diffline $nl
7338 }
7339 set diffnparents [expr {[string length $ats] - 1}]
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007340 set diffinhdr 0
Paul Mackerras9396cd32007-06-23 20:28:15 +10007341
7342 } elseif {$diffinhdr} {
Johannes Sixt5e85ec42007-10-02 16:16:54 +02007343 if {![string compare -length 12 "rename from " $line]} {
Johannes Sixtd1cb2982007-08-16 14:32:29 +02007344 set fname [string range $line [expr 6 + [string first " from " $line] ] end]
Paul Mackerras9396cd32007-06-23 20:28:15 +10007345 if {[string index $fname 0] eq "\""} {
7346 set fname [lindex $fname 0]
7347 }
Alexander Gavrilov09c70292008-10-13 12:12:31 +04007348 set fname [encoding convertfrom $fname]
Paul Mackerras9396cd32007-06-23 20:28:15 +10007349 set i [lsearch -exact $treediffs($ids) $fname]
7350 if {$i >= 0} {
7351 setinlist difffilestart $i $curdiffstart
7352 }
Johannes Sixtd1cb2982007-08-16 14:32:29 +02007353 } elseif {![string compare -length 10 $line "rename to "] ||
7354 ![string compare -length 8 $line "copy to "]} {
7355 set fname [string range $line [expr 4 + [string first " to " $line] ] end]
Paul Mackerras9396cd32007-06-23 20:28:15 +10007356 if {[string index $fname 0] eq "\""} {
7357 set fname [lindex $fname 0]
7358 }
7359 makediffhdr $fname $ids
7360 } elseif {[string compare -length 3 $line "---"] == 0} {
7361 # do nothing
7362 continue
7363 } elseif {[string compare -length 3 $line "+++"] == 0} {
7364 set diffinhdr 0
7365 continue
7366 }
7367 $ctext insert end "$line\n" filesep
7368
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007369 } else {
Pat Thoyts681c3292009-03-16 10:24:40 +00007370 set line [string map {\x1A ^Z} \
7371 [encoding convertfrom $diffencoding $line]]
Paul Mackerras8b07dca2008-11-02 22:34:47 +11007372 # parse the prefix - one ' ', '-' or '+' for each parent
7373 set prefix [string range $line 0 [expr {$diffnparents - 1}]]
7374 set tag [expr {$diffnparents > 1? "m": "d"}]
7375 if {[string trim $prefix " -+"] eq {}} {
7376 # prefix only has " ", "-" and "+" in it: normal diff line
7377 set num [string first "-" $prefix]
7378 if {$num >= 0} {
7379 # removed line, first parent with line is $num
7380 if {$num >= $mergemax} {
7381 set num "max"
7382 }
7383 $ctext insert end "$line\n" $tag$num
7384 } else {
7385 set tags {}
7386 if {[string first "+" $prefix] >= 0} {
7387 # added line
7388 lappend tags ${tag}result
7389 if {$diffnparents > 1} {
7390 set num [string first " " $prefix]
7391 if {$num >= 0} {
7392 if {$num >= $mergemax} {
7393 set num "max"
7394 }
7395 lappend tags m$num
7396 }
7397 }
7398 }
7399 if {$targetline ne {}} {
7400 if {$diffline == $targetline} {
7401 set seehere [$ctext index "end - 1 chars"]
7402 set targetline {}
7403 } else {
7404 incr diffline
7405 }
7406 }
7407 $ctext insert end "$line\n" $tags
7408 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007409 } else {
Paul Mackerras9396cd32007-06-23 20:28:15 +10007410 # "\ No newline at end of file",
7411 # or something else we don't recognize
7412 $ctext insert end "$line\n" hunksep
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007413 }
Paul Mackerrase5c2d852005-05-11 23:44:54 +00007414 }
7415 }
Paul Mackerras8b07dca2008-11-02 22:34:47 +11007416 if {[info exists seehere]} {
7417 mark_ctext_line [lindex [split $seehere .] 0]
7418 }
Paul Mackerrase5c2d852005-05-11 23:44:54 +00007419 $ctext conf -state disabled
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007420 if {[eof $bdf]} {
7421 close $bdf
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007422 return 0
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10007423 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007424 return [expr {$nr >= 1000? 2: 1}]
Paul Mackerrase5c2d852005-05-11 23:44:54 +00007425}
7426
Paul Mackerrasa8d610a2007-04-19 11:39:12 +10007427proc changediffdisp {} {
7428 global ctext diffelide
7429
7430 $ctext tag conf d0 -elide [lindex $diffelide 0]
Paul Mackerras8b07dca2008-11-02 22:34:47 +11007431 $ctext tag conf dresult -elide [lindex $diffelide 1]
Paul Mackerrasa8d610a2007-04-19 11:39:12 +10007432}
7433
Paul Mackerrasf4c54b32008-05-10 13:15:36 +10007434proc highlightfile {loc cline} {
7435 global ctext cflist cflist_top
7436
7437 $ctext yview $loc
7438 $cflist tag remove highlight $cflist_top.0 "$cflist_top.0 lineend"
7439 $cflist tag add highlight $cline.0 "$cline.0 lineend"
7440 $cflist see $cline.0
7441 set cflist_top $cline
7442}
7443
OGAWA Hirofumi67c22872006-09-27 12:32:19 +09007444proc prevfile {} {
Paul Mackerrasf4c54b32008-05-10 13:15:36 +10007445 global difffilestart ctext cmitmode
7446
7447 if {$cmitmode eq "tree"} return
7448 set prev 0.0
7449 set prevline 1
OGAWA Hirofumi67c22872006-09-27 12:32:19 +09007450 set here [$ctext index @0,0]
7451 foreach loc $difffilestart {
7452 if {[$ctext compare $loc >= $here]} {
Paul Mackerrasf4c54b32008-05-10 13:15:36 +10007453 highlightfile $prev $prevline
OGAWA Hirofumi67c22872006-09-27 12:32:19 +09007454 return
7455 }
7456 set prev $loc
Paul Mackerrasf4c54b32008-05-10 13:15:36 +10007457 incr prevline
OGAWA Hirofumi67c22872006-09-27 12:32:19 +09007458 }
Paul Mackerrasf4c54b32008-05-10 13:15:36 +10007459 highlightfile $prev $prevline
OGAWA Hirofumi67c22872006-09-27 12:32:19 +09007460}
7461
Paul Mackerras39ad8572005-05-19 12:35:53 +00007462proc nextfile {} {
Paul Mackerrasf4c54b32008-05-10 13:15:36 +10007463 global difffilestart ctext cmitmode
7464
7465 if {$cmitmode eq "tree"} return
Paul Mackerras39ad8572005-05-19 12:35:53 +00007466 set here [$ctext index @0,0]
Paul Mackerrasf4c54b32008-05-10 13:15:36 +10007467 set line 1
Paul Mackerras7fcceed2006-04-27 19:21:49 +10007468 foreach loc $difffilestart {
Paul Mackerrasf4c54b32008-05-10 13:15:36 +10007469 incr line
Paul Mackerras7fcceed2006-04-27 19:21:49 +10007470 if {[$ctext compare $loc > $here]} {
Paul Mackerrasf4c54b32008-05-10 13:15:36 +10007471 highlightfile $loc $line
OGAWA Hirofumi67c22872006-09-27 12:32:19 +09007472 return
Paul Mackerras39ad8572005-05-19 12:35:53 +00007473 }
7474 }
Paul Mackerras1db95b02005-05-09 04:08:39 +00007475}
7476
Paul Mackerras3ea06f92006-05-24 10:16:03 +10007477proc clear_ctext {{first 1.0}} {
7478 global ctext smarktop smarkbot
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04007479 global ctext_file_names ctext_file_lines
Paul Mackerras97645682007-08-23 22:24:38 +10007480 global pendinglinks
Paul Mackerras3ea06f92006-05-24 10:16:03 +10007481
Paul Mackerras1902c272006-05-25 21:25:13 +10007482 set l [lindex [split $first .] 0]
7483 if {![info exists smarktop] || [$ctext compare $first < $smarktop.0]} {
7484 set smarktop $l
Paul Mackerras3ea06f92006-05-24 10:16:03 +10007485 }
Paul Mackerras1902c272006-05-25 21:25:13 +10007486 if {![info exists smarkbot] || [$ctext compare $first < $smarkbot.0]} {
7487 set smarkbot $l
Paul Mackerras3ea06f92006-05-24 10:16:03 +10007488 }
7489 $ctext delete $first end
Paul Mackerras97645682007-08-23 22:24:38 +10007490 if {$first eq "1.0"} {
7491 catch {unset pendinglinks}
7492 }
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04007493 set ctext_file_names {}
7494 set ctext_file_lines {}
Paul Mackerras3ea06f92006-05-24 10:16:03 +10007495}
7496
Paul Mackerras32f1b3e2007-09-28 21:27:39 +10007497proc settabs {{firstab {}}} {
Paul Mackerras9c311b32007-10-04 22:27:13 +10007498 global firsttabstop tabstop ctext have_tk85
Paul Mackerras32f1b3e2007-09-28 21:27:39 +10007499
7500 if {$firstab ne {} && $have_tk85} {
7501 set firsttabstop $firstab
7502 }
Paul Mackerras9c311b32007-10-04 22:27:13 +10007503 set w [font measure textfont "0"]
Paul Mackerras32f1b3e2007-09-28 21:27:39 +10007504 if {$firsttabstop != 0} {
Paul Mackerras64b5f142007-10-04 22:19:24 +10007505 $ctext conf -tabs [list [expr {($firsttabstop + $tabstop) * $w}] \
7506 [expr {($firsttabstop + 2 * $tabstop) * $w}]]
Paul Mackerras32f1b3e2007-09-28 21:27:39 +10007507 } elseif {$have_tk85 || $tabstop != 8} {
7508 $ctext conf -tabs [expr {$tabstop * $w}]
7509 } else {
7510 $ctext conf -tabs {}
7511 }
Paul Mackerras3ea06f92006-05-24 10:16:03 +10007512}
7513
7514proc incrsearch {name ix op} {
Paul Mackerras1902c272006-05-25 21:25:13 +10007515 global ctext searchstring searchdirn
Paul Mackerras3ea06f92006-05-24 10:16:03 +10007516
7517 $ctext tag remove found 1.0 end
Paul Mackerras1902c272006-05-25 21:25:13 +10007518 if {[catch {$ctext index anchor}]} {
7519 # no anchor set, use start of selection, or of visible area
7520 set sel [$ctext tag ranges sel]
7521 if {$sel ne {}} {
7522 $ctext mark set anchor [lindex $sel 0]
7523 } elseif {$searchdirn eq "-forwards"} {
7524 $ctext mark set anchor @0,0
7525 } else {
7526 $ctext mark set anchor @0,[winfo height $ctext]
7527 }
7528 }
Paul Mackerras3ea06f92006-05-24 10:16:03 +10007529 if {$searchstring ne {}} {
Paul Mackerras1902c272006-05-25 21:25:13 +10007530 set here [$ctext search $searchdirn -- $searchstring anchor]
7531 if {$here ne {}} {
7532 $ctext see $here
7533 }
Paul Mackerras3ea06f92006-05-24 10:16:03 +10007534 searchmarkvisible 1
7535 }
7536}
7537
7538proc dosearch {} {
Paul Mackerras1902c272006-05-25 21:25:13 +10007539 global sstring ctext searchstring searchdirn
Paul Mackerras3ea06f92006-05-24 10:16:03 +10007540
7541 focus $sstring
7542 $sstring icursor end
Paul Mackerras1902c272006-05-25 21:25:13 +10007543 set searchdirn -forwards
7544 if {$searchstring ne {}} {
7545 set sel [$ctext tag ranges sel]
7546 if {$sel ne {}} {
7547 set start "[lindex $sel 0] + 1c"
7548 } elseif {[catch {set start [$ctext index anchor]}]} {
7549 set start "@0,0"
7550 }
7551 set match [$ctext search -count mlen -- $searchstring $start]
7552 $ctext tag remove sel 1.0 end
7553 if {$match eq {}} {
7554 bell
7555 return
7556 }
7557 $ctext see $match
7558 set mend "$match + $mlen c"
7559 $ctext tag add sel $match $mend
7560 $ctext mark unset anchor
Paul Mackerras3ea06f92006-05-24 10:16:03 +10007561 }
Paul Mackerras1902c272006-05-25 21:25:13 +10007562}
7563
7564proc dosearchback {} {
7565 global sstring ctext searchstring searchdirn
7566
7567 focus $sstring
7568 $sstring icursor end
7569 set searchdirn -backwards
7570 if {$searchstring ne {}} {
7571 set sel [$ctext tag ranges sel]
7572 if {$sel ne {}} {
7573 set start [lindex $sel 0]
7574 } elseif {[catch {set start [$ctext index anchor]}]} {
7575 set start @0,[winfo height $ctext]
7576 }
7577 set match [$ctext search -backwards -count ml -- $searchstring $start]
7578 $ctext tag remove sel 1.0 end
7579 if {$match eq {}} {
7580 bell
7581 return
7582 }
7583 $ctext see $match
7584 set mend "$match + $ml c"
7585 $ctext tag add sel $match $mend
7586 $ctext mark unset anchor
7587 }
Paul Mackerras3ea06f92006-05-24 10:16:03 +10007588}
7589
7590proc searchmark {first last} {
7591 global ctext searchstring
7592
7593 set mend $first.0
7594 while {1} {
7595 set match [$ctext search -count mlen -- $searchstring $mend $last.end]
7596 if {$match eq {}} break
7597 set mend "$match + $mlen c"
7598 $ctext tag add found $match $mend
7599 }
7600}
7601
7602proc searchmarkvisible {doall} {
7603 global ctext smarktop smarkbot
7604
7605 set topline [lindex [split [$ctext index @0,0] .] 0]
7606 set botline [lindex [split [$ctext index @0,[winfo height $ctext]] .] 0]
7607 if {$doall || $botline < $smarktop || $topline > $smarkbot} {
7608 # no overlap with previous
7609 searchmark $topline $botline
7610 set smarktop $topline
7611 set smarkbot $botline
7612 } else {
7613 if {$topline < $smarktop} {
7614 searchmark $topline [expr {$smarktop-1}]
7615 set smarktop $topline
7616 }
7617 if {$botline > $smarkbot} {
7618 searchmark [expr {$smarkbot+1}] $botline
7619 set smarkbot $botline
7620 }
7621 }
7622}
7623
7624proc scrolltext {f0 f1} {
Paul Mackerras1902c272006-05-25 21:25:13 +10007625 global searchstring
Paul Mackerras3ea06f92006-05-24 10:16:03 +10007626
Pekka Kaitaniemi8809d692008-03-08 14:27:23 +02007627 .bleft.bottom.sb set $f0 $f1
Paul Mackerras3ea06f92006-05-24 10:16:03 +10007628 if {$searchstring ne {}} {
7629 searchmarkvisible 0
7630 }
7631}
7632
Paul Mackerras1d10f362005-05-15 12:55:47 +00007633proc setcoords {} {
Paul Mackerras9c311b32007-10-04 22:27:13 +10007634 global linespc charspc canvx0 canvy0
Paul Mackerrasf6075eb2005-08-18 09:30:10 +10007635 global xspc1 xspc2 lthickness
Paul Mackerras8d858d12005-08-05 09:52:16 +10007636
Paul Mackerras9c311b32007-10-04 22:27:13 +10007637 set linespc [font metrics mainfont -linespace]
7638 set charspc [font measure mainfont "m"]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11007639 set canvy0 [expr {int(3 + 0.5 * $linespc)}]
7640 set canvx0 [expr {int(3 + 0.5 * $linespc)}]
Paul Mackerrasf6075eb2005-08-18 09:30:10 +10007641 set lthickness [expr {int($linespc / 9) + 1}]
Paul Mackerras8d858d12005-08-05 09:52:16 +10007642 set xspc1(0) $linespc
7643 set xspc2 $linespc
Paul Mackerras9a40c502005-05-12 23:46:16 +00007644}
Paul Mackerras1db95b02005-05-09 04:08:39 +00007645
Paul Mackerras1d10f362005-05-15 12:55:47 +00007646proc redisplay {} {
Paul Mackerrasbe0cd092006-03-31 09:55:11 +11007647 global canv
Paul Mackerras9f1afe02006-02-19 22:44:47 +11007648 global selectedline
7649
7650 set ymax [lindex [$canv cget -scrollregion] 3]
7651 if {$ymax eq {} || $ymax == 0} return
7652 set span [$canv yview]
7653 clear_display
Paul Mackerrasbe0cd092006-03-31 09:55:11 +11007654 setcanvscroll
Paul Mackerras9f1afe02006-02-19 22:44:47 +11007655 allcanvs yview moveto [lindex $span 0]
7656 drawvisible
Paul Mackerras94b4a692008-05-20 20:51:06 +10007657 if {$selectedline ne {}} {
Paul Mackerras9f1afe02006-02-19 22:44:47 +11007658 selectline $selectedline 0
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10007659 allcanvs yview moveto [lindex $span 0]
Paul Mackerras1db95b02005-05-09 04:08:39 +00007660 }
7661}
Paul Mackerras1d10f362005-05-15 12:55:47 +00007662
Paul Mackerras0ed1dd32007-10-06 18:27:37 +10007663proc parsefont {f n} {
7664 global fontattr
7665
7666 set fontattr($f,family) [lindex $n 0]
7667 set s [lindex $n 1]
7668 if {$s eq {} || $s == 0} {
7669 set s 10
7670 } elseif {$s < 0} {
7671 set s [expr {int(-$s / [winfo fpixels . 1p] + 0.5)}]
Paul Mackerras9c311b32007-10-04 22:27:13 +10007672 }
Paul Mackerras0ed1dd32007-10-06 18:27:37 +10007673 set fontattr($f,size) $s
7674 set fontattr($f,weight) normal
7675 set fontattr($f,slant) roman
7676 foreach style [lrange $n 2 end] {
7677 switch -- $style {
7678 "normal" -
7679 "bold" {set fontattr($f,weight) $style}
7680 "roman" -
7681 "italic" {set fontattr($f,slant) $style}
7682 }
Paul Mackerras9c311b32007-10-04 22:27:13 +10007683 }
Paul Mackerras0ed1dd32007-10-06 18:27:37 +10007684}
7685
7686proc fontflags {f {isbold 0}} {
7687 global fontattr
7688
7689 return [list -family $fontattr($f,family) -size $fontattr($f,size) \
7690 -weight [expr {$isbold? "bold": $fontattr($f,weight)}] \
7691 -slant $fontattr($f,slant)]
7692}
7693
7694proc fontname {f} {
7695 global fontattr
7696
7697 set n [list $fontattr($f,family) $fontattr($f,size)]
7698 if {$fontattr($f,weight) eq "bold"} {
7699 lappend n "bold"
Paul Mackerras9c311b32007-10-04 22:27:13 +10007700 }
Paul Mackerras0ed1dd32007-10-06 18:27:37 +10007701 if {$fontattr($f,slant) eq "italic"} {
7702 lappend n "italic"
Paul Mackerras9c311b32007-10-04 22:27:13 +10007703 }
Paul Mackerras0ed1dd32007-10-06 18:27:37 +10007704 return $n
Paul Mackerras9c311b32007-10-04 22:27:13 +10007705}
7706
Paul Mackerras1d10f362005-05-15 12:55:47 +00007707proc incrfont {inc} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11007708 global mainfont textfont ctext canv cflist showrefstop
Paul Mackerras0ed1dd32007-10-06 18:27:37 +10007709 global stopped entries fontattr
7710
Paul Mackerras1d10f362005-05-15 12:55:47 +00007711 unmarkmatches
Paul Mackerras0ed1dd32007-10-06 18:27:37 +10007712 set s $fontattr(mainfont,size)
Paul Mackerras9c311b32007-10-04 22:27:13 +10007713 incr s $inc
7714 if {$s < 1} {
7715 set s 1
7716 }
Paul Mackerras0ed1dd32007-10-06 18:27:37 +10007717 set fontattr(mainfont,size) $s
Paul Mackerras9c311b32007-10-04 22:27:13 +10007718 font config mainfont -size $s
7719 font config mainfontbold -size $s
Paul Mackerras0ed1dd32007-10-06 18:27:37 +10007720 set mainfont [fontname mainfont]
7721 set s $fontattr(textfont,size)
Paul Mackerras9c311b32007-10-04 22:27:13 +10007722 incr s $inc
7723 if {$s < 1} {
7724 set s 1
7725 }
Paul Mackerras0ed1dd32007-10-06 18:27:37 +10007726 set fontattr(textfont,size) $s
Paul Mackerras9c311b32007-10-04 22:27:13 +10007727 font config textfont -size $s
7728 font config textfontbold -size $s
Paul Mackerras0ed1dd32007-10-06 18:27:37 +10007729 set textfont [fontname textfont]
Paul Mackerras1d10f362005-05-15 12:55:47 +00007730 setcoords
Paul Mackerras32f1b3e2007-09-28 21:27:39 +10007731 settabs
Paul Mackerras1d10f362005-05-15 12:55:47 +00007732 redisplay
Paul Mackerras1db95b02005-05-09 04:08:39 +00007733}
Paul Mackerras1d10f362005-05-15 12:55:47 +00007734
Paul Mackerrasee3dc722005-06-25 16:37:13 +10007735proc clearsha1 {} {
7736 global sha1entry sha1string
7737 if {[string length $sha1string] == 40} {
7738 $sha1entry delete 0 end
7739 }
7740}
7741
Paul Mackerras887fe3c2005-05-21 07:35:37 +00007742proc sha1change {n1 n2 op} {
7743 global sha1string currentid sha1but
7744 if {$sha1string == {}
7745 || ([info exists currentid] && $sha1string == $currentid)} {
7746 set state disabled
7747 } else {
7748 set state normal
7749 }
7750 if {[$sha1but cget -state] == $state} return
7751 if {$state == "normal"} {
Christian Stimmingd990ced2007-11-07 18:42:55 +01007752 $sha1but conf -state normal -relief raised -text "[mc "Goto:"] "
Paul Mackerras887fe3c2005-05-21 07:35:37 +00007753 } else {
Christian Stimmingd990ced2007-11-07 18:42:55 +01007754 $sha1but conf -state disabled -relief flat -text "[mc "SHA1 ID:"] "
Paul Mackerras887fe3c2005-05-21 07:35:37 +00007755 }
7756}
7757
7758proc gotocommit {} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11007759 global sha1string tagids headids curview varcid
Paul Mackerrasf3b8b3c2005-07-18 12:16:35 -04007760
Paul Mackerras887fe3c2005-05-21 07:35:37 +00007761 if {$sha1string == {}
7762 || ([info exists currentid] && $sha1string == $currentid)} return
7763 if {[info exists tagids($sha1string)]} {
7764 set id $tagids($sha1string)
Stephen Rothwelle1007122006-03-30 16:13:12 +11007765 } elseif {[info exists headids($sha1string)]} {
7766 set id $headids($sha1string)
Paul Mackerras887fe3c2005-05-21 07:35:37 +00007767 } else {
7768 set id [string tolower $sha1string]
Paul Mackerrasf3b8b3c2005-07-18 12:16:35 -04007769 if {[regexp {^[0-9a-f]{4,39}$} $id]} {
Paul Mackerrasd375ef92008-10-21 10:18:12 +11007770 set matches [longid $id]
Paul Mackerrasf3b8b3c2005-07-18 12:16:35 -04007771 if {$matches ne {}} {
7772 if {[llength $matches] > 1} {
Christian Stimmingd990ced2007-11-07 18:42:55 +01007773 error_popup [mc "Short SHA1 id %s is ambiguous" $id]
Paul Mackerrasf3b8b3c2005-07-18 12:16:35 -04007774 return
7775 }
Paul Mackerrasd375ef92008-10-21 10:18:12 +11007776 set id [lindex $matches 0]
Paul Mackerrasf3b8b3c2005-07-18 12:16:35 -04007777 }
7778 }
Paul Mackerras887fe3c2005-05-21 07:35:37 +00007779 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11007780 if {[commitinview $id $curview]} {
7781 selectline [rowofcommit $id] 1
Paul Mackerras887fe3c2005-05-21 07:35:37 +00007782 return
7783 }
Paul Mackerrasf3b8b3c2005-07-18 12:16:35 -04007784 if {[regexp {^[0-9a-fA-F]{4,}$} $sha1string]} {
Christian Stimmingd990ced2007-11-07 18:42:55 +01007785 set msg [mc "SHA1 id %s is not known" $sha1string]
Paul Mackerras887fe3c2005-05-21 07:35:37 +00007786 } else {
Christian Stimmingd990ced2007-11-07 18:42:55 +01007787 set msg [mc "Tag/Head %s is not known" $sha1string]
Paul Mackerras887fe3c2005-05-21 07:35:37 +00007788 }
Christian Stimmingd990ced2007-11-07 18:42:55 +01007789 error_popup $msg
Paul Mackerras887fe3c2005-05-21 07:35:37 +00007790}
7791
Paul Mackerras84ba7342005-06-17 00:12:26 +00007792proc lineenter {x y id} {
7793 global hoverx hovery hoverid hovertimer
7794 global commitinfo canv
7795
Paul Mackerras8ed16482006-03-02 22:56:44 +11007796 if {![info exists commitinfo($id)] && ![getcommit $id]} return
Paul Mackerras84ba7342005-06-17 00:12:26 +00007797 set hoverx $x
7798 set hovery $y
7799 set hoverid $id
7800 if {[info exists hovertimer]} {
7801 after cancel $hovertimer
7802 }
7803 set hovertimer [after 500 linehover]
7804 $canv delete hover
7805}
7806
7807proc linemotion {x y id} {
7808 global hoverx hovery hoverid hovertimer
7809
7810 if {[info exists hoverid] && $id == $hoverid} {
7811 set hoverx $x
7812 set hovery $y
7813 if {[info exists hovertimer]} {
7814 after cancel $hovertimer
7815 }
7816 set hovertimer [after 500 linehover]
7817 }
7818}
7819
7820proc lineleave {id} {
7821 global hoverid hovertimer canv
7822
7823 if {[info exists hoverid] && $id == $hoverid} {
7824 $canv delete hover
7825 if {[info exists hovertimer]} {
7826 after cancel $hovertimer
7827 unset hovertimer
7828 }
7829 unset hoverid
7830 }
7831}
7832
7833proc linehover {} {
7834 global hoverx hovery hoverid hovertimer
7835 global canv linespc lthickness
Paul Mackerras9c311b32007-10-04 22:27:13 +10007836 global commitinfo
Paul Mackerras84ba7342005-06-17 00:12:26 +00007837
7838 set text [lindex $commitinfo($hoverid) 0]
7839 set ymax [lindex [$canv cget -scrollregion] 3]
7840 if {$ymax == {}} return
7841 set yfrac [lindex [$canv yview] 0]
7842 set x [expr {$hoverx + 2 * $linespc}]
7843 set y [expr {$hovery + $yfrac * $ymax - $linespc / 2}]
7844 set x0 [expr {$x - 2 * $lthickness}]
7845 set y0 [expr {$y - 2 * $lthickness}]
Paul Mackerras9c311b32007-10-04 22:27:13 +10007846 set x1 [expr {$x + [font measure mainfont $text] + 2 * $lthickness}]
Paul Mackerras84ba7342005-06-17 00:12:26 +00007847 set y1 [expr {$y + $linespc + 2 * $lthickness}]
7848 set t [$canv create rectangle $x0 $y0 $x1 $y1 \
7849 -fill \#ffff80 -outline black -width 1 -tags hover]
7850 $canv raise $t
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10007851 set t [$canv create text $x $y -anchor nw -text $text -tags hover \
Paul Mackerras9c311b32007-10-04 22:27:13 +10007852 -font mainfont]
Paul Mackerras84ba7342005-06-17 00:12:26 +00007853 $canv raise $t
7854}
7855
Paul Mackerras9843c302005-08-30 10:57:11 +10007856proc clickisonarrow {id y} {
Paul Mackerras50b44ec2006-04-04 10:16:22 +10007857 global lthickness
Paul Mackerras9843c302005-08-30 10:57:11 +10007858
Paul Mackerras50b44ec2006-04-04 10:16:22 +10007859 set ranges [rowranges $id]
Paul Mackerras9843c302005-08-30 10:57:11 +10007860 set thresh [expr {2 * $lthickness + 6}]
Paul Mackerras50b44ec2006-04-04 10:16:22 +10007861 set n [expr {[llength $ranges] - 1}]
Paul Mackerrasf6342482006-02-28 10:02:03 +11007862 for {set i 1} {$i < $n} {incr i} {
Paul Mackerras50b44ec2006-04-04 10:16:22 +10007863 set row [lindex $ranges $i]
Paul Mackerrasf6342482006-02-28 10:02:03 +11007864 if {abs([yc $row] - $y) < $thresh} {
7865 return $i
Paul Mackerras9843c302005-08-30 10:57:11 +10007866 }
7867 }
7868 return {}
7869}
7870
Paul Mackerrasf6342482006-02-28 10:02:03 +11007871proc arrowjump {id n y} {
Paul Mackerras50b44ec2006-04-04 10:16:22 +10007872 global canv
Paul Mackerras9843c302005-08-30 10:57:11 +10007873
Paul Mackerrasf6342482006-02-28 10:02:03 +11007874 # 1 <-> 2, 3 <-> 4, etc...
7875 set n [expr {(($n - 1) ^ 1) + 1}]
Paul Mackerras50b44ec2006-04-04 10:16:22 +10007876 set row [lindex [rowranges $id] $n]
Paul Mackerrasf6342482006-02-28 10:02:03 +11007877 set yt [yc $row]
Paul Mackerras9843c302005-08-30 10:57:11 +10007878 set ymax [lindex [$canv cget -scrollregion] 3]
7879 if {$ymax eq {} || $ymax <= 0} return
7880 set view [$canv yview]
7881 set yspan [expr {[lindex $view 1] - [lindex $view 0]}]
7882 set yfrac [expr {$yt / $ymax - $yspan / 2}]
7883 if {$yfrac < 0} {
7884 set yfrac 0
7885 }
Paul Mackerrasf6342482006-02-28 10:02:03 +11007886 allcanvs yview moveto $yfrac
Paul Mackerras9843c302005-08-30 10:57:11 +10007887}
7888
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10007889proc lineclick {x y id isnew} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11007890 global ctext commitinfo children canv thickerline curview
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10007891
Paul Mackerras8ed16482006-03-02 22:56:44 +11007892 if {![info exists commitinfo($id)] && ![getcommit $id]} return
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10007893 unmarkmatches
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10007894 unselectline
Paul Mackerras9843c302005-08-30 10:57:11 +10007895 normalline
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10007896 $canv delete hover
Paul Mackerras9843c302005-08-30 10:57:11 +10007897 # draw this line thicker than normal
Paul Mackerras9843c302005-08-30 10:57:11 +10007898 set thickerline $id
Paul Mackerrasc934a8a2006-03-02 23:00:44 +11007899 drawlines $id
Paul Mackerras9843c302005-08-30 10:57:11 +10007900 if {$isnew} {
7901 set ymax [lindex [$canv cget -scrollregion] 3]
7902 if {$ymax eq {}} return
7903 set yfrac [lindex [$canv yview] 0]
7904 set y [expr {$y + $yfrac * $ymax}]
7905 }
7906 set dirn [clickisonarrow $id $y]
7907 if {$dirn ne {}} {
7908 arrowjump $id $dirn $y
7909 return
7910 }
7911
7912 if {$isnew} {
7913 addtohistory [list lineclick $x $y $id 0]
7914 }
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10007915 # fill the details pane with info about this line
7916 $ctext conf -state normal
Paul Mackerras3ea06f92006-05-24 10:16:03 +10007917 clear_ctext
Paul Mackerras32f1b3e2007-09-28 21:27:39 +10007918 settabs 0
Christian Stimmingd990ced2007-11-07 18:42:55 +01007919 $ctext insert end "[mc "Parent"]:\t"
Paul Mackerras97645682007-08-23 22:24:38 +10007920 $ctext insert end $id link0
7921 setlink $id link0
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10007922 set info $commitinfo($id)
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10007923 $ctext insert end "\n\t[lindex $info 0]\n"
Christian Stimmingd990ced2007-11-07 18:42:55 +01007924 $ctext insert end "\t[mc "Author"]:\t[lindex $info 1]\n"
Paul Mackerras232475d2005-11-15 10:34:03 +11007925 set date [formatdate [lindex $info 2]]
Christian Stimmingd990ced2007-11-07 18:42:55 +01007926 $ctext insert end "\t[mc "Date"]:\t$date\n"
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10007927 set kids $children($curview,$id)
Paul Mackerras79b2c752006-04-02 20:47:40 +10007928 if {$kids ne {}} {
Christian Stimmingd990ced2007-11-07 18:42:55 +01007929 $ctext insert end "\n[mc "Children"]:"
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10007930 set i 0
Paul Mackerras79b2c752006-04-02 20:47:40 +10007931 foreach child $kids {
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10007932 incr i
Paul Mackerras8ed16482006-03-02 22:56:44 +11007933 if {![info exists commitinfo($child)] && ![getcommit $child]} continue
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10007934 set info $commitinfo($child)
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10007935 $ctext insert end "\n\t"
Paul Mackerras97645682007-08-23 22:24:38 +10007936 $ctext insert end $child link$i
7937 setlink $child link$i
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10007938 $ctext insert end "\n\t[lindex $info 0]"
Christian Stimmingd990ced2007-11-07 18:42:55 +01007939 $ctext insert end "\n\t[mc "Author"]:\t[lindex $info 1]"
Paul Mackerras232475d2005-11-15 10:34:03 +11007940 set date [formatdate [lindex $info 2]]
Christian Stimmingd990ced2007-11-07 18:42:55 +01007941 $ctext insert end "\n\t[mc "Date"]:\t$date\n"
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10007942 }
7943 }
7944 $ctext conf -state disabled
Paul Mackerras7fcceed2006-04-27 19:21:49 +10007945 init_flist {}
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10007946}
7947
Paul Mackerras9843c302005-08-30 10:57:11 +10007948proc normalline {} {
7949 global thickerline
7950 if {[info exists thickerline]} {
Paul Mackerrasc934a8a2006-03-02 23:00:44 +11007951 set id $thickerline
Paul Mackerras9843c302005-08-30 10:57:11 +10007952 unset thickerline
Paul Mackerrasc934a8a2006-03-02 23:00:44 +11007953 drawlines $id
Paul Mackerras9843c302005-08-30 10:57:11 +10007954 }
7955}
7956
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10007957proc selbyid {id} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11007958 global curview
7959 if {[commitinview $id $curview]} {
7960 selectline [rowofcommit $id] 1
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10007961 }
7962}
7963
7964proc mstime {} {
7965 global startmstime
7966 if {![info exists startmstime]} {
7967 set startmstime [clock clicks -milliseconds]
7968 }
7969 return [format "%.3f" [expr {([clock click -milliseconds] - $startmstime) / 1000.0}]]
7970}
7971
7972proc rowmenu {x y id} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11007973 global rowctxmenu selectedline rowmenuid curview
Paul Mackerras8f489362007-07-13 19:49:37 +10007974 global nullid nullid2 fakerowmenu mainhead
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10007975
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10007976 stopfinding
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007977 set rowmenuid $id
Paul Mackerras94b4a692008-05-20 20:51:06 +10007978 if {$selectedline eq {} || [rowofcommit $id] eq $selectedline} {
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10007979 set state disabled
7980 } else {
7981 set state normal
7982 }
Paul Mackerras8f489362007-07-13 19:49:37 +10007983 if {$id ne $nullid && $id ne $nullid2} {
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007984 set menu $rowctxmenu
Michele Ballabio5e3502d2008-05-02 17:46:20 +02007985 if {$mainhead ne {}} {
Johannes Sixtda12e592008-12-03 13:43:20 +01007986 $menu entryconfigure 7 -label [mc "Reset %s branch to here" $mainhead] -state normal
Michele Ballabio5e3502d2008-05-02 17:46:20 +02007987 } else {
7988 $menu entryconfigure 7 -label [mc "Detached head: can't reset" $mainhead] -state disabled
7989 }
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007990 } else {
7991 set menu $fakerowmenu
7992 }
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11007993 $menu entryconfigure [mca "Diff this -> selected"] -state $state
7994 $menu entryconfigure [mca "Diff selected -> this"] -state $state
7995 $menu entryconfigure [mca "Make patch"] -state $state
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007996 tk_popup $menu $x $y
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10007997}
7998
7999proc diffvssel {dirn} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11008000 global rowmenuid selectedline
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008001
Paul Mackerras94b4a692008-05-20 20:51:06 +10008002 if {$selectedline eq {}} return
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008003 if {$dirn} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11008004 set oldid [commitonrow $selectedline]
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008005 set newid $rowmenuid
8006 } else {
8007 set oldid $rowmenuid
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11008008 set newid [commitonrow $selectedline]
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008009 }
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10008010 addtohistory [list doseldiff $oldid $newid]
8011 doseldiff $oldid $newid
8012}
8013
8014proc doseldiff {oldid newid} {
Paul Mackerras7fcceed2006-04-27 19:21:49 +10008015 global ctext
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10008016 global commitinfo
8017
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008018 $ctext conf -state normal
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008019 clear_ctext
Christian Stimmingd990ced2007-11-07 18:42:55 +01008020 init_flist [mc "Top"]
8021 $ctext insert end "[mc "From"] "
Paul Mackerras97645682007-08-23 22:24:38 +10008022 $ctext insert end $oldid link0
8023 setlink $oldid link0
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10008024 $ctext insert end "\n "
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008025 $ctext insert end [lindex $commitinfo($oldid) 0]
Christian Stimmingd990ced2007-11-07 18:42:55 +01008026 $ctext insert end "\n\n[mc "To"] "
Paul Mackerras97645682007-08-23 22:24:38 +10008027 $ctext insert end $newid link1
8028 setlink $newid link1
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10008029 $ctext insert end "\n "
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008030 $ctext insert end [lindex $commitinfo($newid) 0]
8031 $ctext insert end "\n"
8032 $ctext conf -state disabled
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008033 $ctext tag remove found 1.0 end
Paul Mackerrasd3272442005-11-28 20:41:56 +11008034 startdiff [list $oldid $newid]
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008035}
8036
Paul Mackerras74daedb2005-06-27 19:27:32 +10008037proc mkpatch {} {
8038 global rowmenuid currentid commitinfo patchtop patchnum
8039
8040 if {![info exists currentid]} return
8041 set oldid $currentid
8042 set oldhead [lindex $commitinfo($oldid) 0]
8043 set newid $rowmenuid
8044 set newhead [lindex $commitinfo($newid) 0]
8045 set top .patch
8046 set patchtop $top
8047 catch {destroy $top}
8048 toplevel $top
Alexander Gavrilove7d64002008-11-11 23:55:42 +03008049 make_transient $top .
Christian Stimmingd990ced2007-11-07 18:42:55 +01008050 label $top.title -text [mc "Generate patch"]
Paul Mackerras4a2139f2005-06-29 09:47:48 +10008051 grid $top.title - -pady 10
Christian Stimmingd990ced2007-11-07 18:42:55 +01008052 label $top.from -text [mc "From:"]
Paul Mackerras4a2139f2005-06-29 09:47:48 +10008053 entry $top.fromsha1 -width 40 -relief flat
Paul Mackerras74daedb2005-06-27 19:27:32 +10008054 $top.fromsha1 insert 0 $oldid
8055 $top.fromsha1 conf -state readonly
8056 grid $top.from $top.fromsha1 -sticky w
Paul Mackerras4a2139f2005-06-29 09:47:48 +10008057 entry $top.fromhead -width 60 -relief flat
Paul Mackerras74daedb2005-06-27 19:27:32 +10008058 $top.fromhead insert 0 $oldhead
8059 $top.fromhead conf -state readonly
8060 grid x $top.fromhead -sticky w
Christian Stimmingd990ced2007-11-07 18:42:55 +01008061 label $top.to -text [mc "To:"]
Paul Mackerras4a2139f2005-06-29 09:47:48 +10008062 entry $top.tosha1 -width 40 -relief flat
Paul Mackerras74daedb2005-06-27 19:27:32 +10008063 $top.tosha1 insert 0 $newid
8064 $top.tosha1 conf -state readonly
8065 grid $top.to $top.tosha1 -sticky w
Paul Mackerras4a2139f2005-06-29 09:47:48 +10008066 entry $top.tohead -width 60 -relief flat
Paul Mackerras74daedb2005-06-27 19:27:32 +10008067 $top.tohead insert 0 $newhead
8068 $top.tohead conf -state readonly
8069 grid x $top.tohead -sticky w
Christian Stimmingd990ced2007-11-07 18:42:55 +01008070 button $top.rev -text [mc "Reverse"] -command mkpatchrev -padx 5
Paul Mackerras74daedb2005-06-27 19:27:32 +10008071 grid $top.rev x -pady 10
Christian Stimmingd990ced2007-11-07 18:42:55 +01008072 label $top.flab -text [mc "Output file:"]
Paul Mackerras74daedb2005-06-27 19:27:32 +10008073 entry $top.fname -width 60
8074 $top.fname insert 0 [file normalize "patch$patchnum.patch"]
8075 incr patchnum
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10008076 grid $top.flab $top.fname -sticky w
Paul Mackerras74daedb2005-06-27 19:27:32 +10008077 frame $top.buts
Christian Stimmingd990ced2007-11-07 18:42:55 +01008078 button $top.buts.gen -text [mc "Generate"] -command mkpatchgo
8079 button $top.buts.can -text [mc "Cancel"] -command mkpatchcan
Alexander Gavrilov76f15942008-11-02 21:59:44 +03008080 bind $top <Key-Return> mkpatchgo
8081 bind $top <Key-Escape> mkpatchcan
Paul Mackerras74daedb2005-06-27 19:27:32 +10008082 grid $top.buts.gen $top.buts.can
8083 grid columnconfigure $top.buts 0 -weight 1 -uniform a
8084 grid columnconfigure $top.buts 1 -weight 1 -uniform a
8085 grid $top.buts - -pady 10 -sticky ew
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10008086 focus $top.fname
Paul Mackerras74daedb2005-06-27 19:27:32 +10008087}
8088
8089proc mkpatchrev {} {
8090 global patchtop
8091
8092 set oldid [$patchtop.fromsha1 get]
8093 set oldhead [$patchtop.fromhead get]
8094 set newid [$patchtop.tosha1 get]
8095 set newhead [$patchtop.tohead get]
8096 foreach e [list fromsha1 fromhead tosha1 tohead] \
8097 v [list $newid $newhead $oldid $oldhead] {
8098 $patchtop.$e conf -state normal
8099 $patchtop.$e delete 0 end
8100 $patchtop.$e insert 0 $v
8101 $patchtop.$e conf -state readonly
8102 }
8103}
8104
8105proc mkpatchgo {} {
Paul Mackerras8f489362007-07-13 19:49:37 +10008106 global patchtop nullid nullid2
Paul Mackerras74daedb2005-06-27 19:27:32 +10008107
8108 set oldid [$patchtop.fromsha1 get]
8109 set newid [$patchtop.tosha1 get]
8110 set fname [$patchtop.fname get]
Paul Mackerras8f489362007-07-13 19:49:37 +10008111 set cmd [diffcmd [list $oldid $newid] -p]
Paul Mackerrasd372e212007-09-15 12:08:38 +10008112 # trim off the initial "|"
8113 set cmd [lrange $cmd 1 end]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10008114 lappend cmd >$fname &
8115 if {[catch {eval exec $cmd} err]} {
Alexander Gavrilov84a76f12008-11-02 21:59:45 +03008116 error_popup "[mc "Error creating patch:"] $err" $patchtop
Paul Mackerras74daedb2005-06-27 19:27:32 +10008117 }
8118 catch {destroy $patchtop}
8119 unset patchtop
8120}
8121
8122proc mkpatchcan {} {
8123 global patchtop
8124
8125 catch {destroy $patchtop}
8126 unset patchtop
8127}
8128
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10008129proc mktag {} {
8130 global rowmenuid mktagtop commitinfo
8131
8132 set top .maketag
8133 set mktagtop $top
8134 catch {destroy $top}
8135 toplevel $top
Alexander Gavrilove7d64002008-11-11 23:55:42 +03008136 make_transient $top .
Christian Stimmingd990ced2007-11-07 18:42:55 +01008137 label $top.title -text [mc "Create tag"]
Paul Mackerras4a2139f2005-06-29 09:47:48 +10008138 grid $top.title - -pady 10
Christian Stimmingd990ced2007-11-07 18:42:55 +01008139 label $top.id -text [mc "ID:"]
Paul Mackerras4a2139f2005-06-29 09:47:48 +10008140 entry $top.sha1 -width 40 -relief flat
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10008141 $top.sha1 insert 0 $rowmenuid
8142 $top.sha1 conf -state readonly
8143 grid $top.id $top.sha1 -sticky w
Paul Mackerras4a2139f2005-06-29 09:47:48 +10008144 entry $top.head -width 60 -relief flat
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10008145 $top.head insert 0 [lindex $commitinfo($rowmenuid) 0]
8146 $top.head conf -state readonly
8147 grid x $top.head -sticky w
Christian Stimmingd990ced2007-11-07 18:42:55 +01008148 label $top.tlab -text [mc "Tag name:"]
Paul Mackerras4a2139f2005-06-29 09:47:48 +10008149 entry $top.tag -width 60
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10008150 grid $top.tlab $top.tag -sticky w
8151 frame $top.buts
Christian Stimmingd990ced2007-11-07 18:42:55 +01008152 button $top.buts.gen -text [mc "Create"] -command mktaggo
8153 button $top.buts.can -text [mc "Cancel"] -command mktagcan
Alexander Gavrilov76f15942008-11-02 21:59:44 +03008154 bind $top <Key-Return> mktaggo
8155 bind $top <Key-Escape> mktagcan
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10008156 grid $top.buts.gen $top.buts.can
8157 grid columnconfigure $top.buts 0 -weight 1 -uniform a
8158 grid columnconfigure $top.buts 1 -weight 1 -uniform a
8159 grid $top.buts - -pady 10 -sticky ew
8160 focus $top.tag
8161}
8162
8163proc domktag {} {
8164 global mktagtop env tagids idtags
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10008165
8166 set id [$mktagtop.sha1 get]
8167 set tag [$mktagtop.tag get]
8168 if {$tag == {}} {
Alexander Gavrilov84a76f12008-11-02 21:59:45 +03008169 error_popup [mc "No tag name specified"] $mktagtop
8170 return 0
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10008171 }
8172 if {[info exists tagids($tag)]} {
Alexander Gavrilov84a76f12008-11-02 21:59:45 +03008173 error_popup [mc "Tag \"%s\" already exists" $tag] $mktagtop
8174 return 0
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10008175 }
8176 if {[catch {
Gerrit Pape48750d62008-02-11 10:57:40 +00008177 exec git tag $tag $id
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10008178 } err]} {
Alexander Gavrilov84a76f12008-11-02 21:59:45 +03008179 error_popup "[mc "Error creating tag:"] $err" $mktagtop
8180 return 0
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10008181 }
8182
8183 set tagids($tag) $id
8184 lappend idtags($id) $tag
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10008185 redrawtags $id
Paul Mackerrasceadfe92006-08-08 20:55:36 +10008186 addedtag $id
Paul Mackerras887c9962007-08-20 19:36:20 +10008187 dispneartags 0
8188 run refill_reflist
Alexander Gavrilov84a76f12008-11-02 21:59:45 +03008189 return 1
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10008190}
8191
8192proc redrawtags {id} {
Paul Mackerrasc11ff122008-05-26 10:11:33 +10008193 global canv linehtag idpos currentid curview cmitlisted
8194 global canvxmax iddrawn circleitem mainheadid circlecolors
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10008195
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11008196 if {![commitinview $id $curview]} return
Paul Mackerras322a8cc2006-10-15 18:03:46 +10008197 if {![info exists iddrawn($id)]} return
Paul Mackerrasfc2a2562007-12-26 23:03:43 +11008198 set row [rowofcommit $id]
Paul Mackerrasc11ff122008-05-26 10:11:33 +10008199 if {$id eq $mainheadid} {
8200 set ofill yellow
8201 } else {
8202 set ofill [lindex $circlecolors $cmitlisted($curview,$id)]
8203 }
8204 $canv itemconf $circleitem($row) -fill $ofill
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10008205 $canv delete tag.$id
8206 set xt [eval drawtags $id $idpos($id)]
Paul Mackerras28593d32008-11-13 23:01:46 +11008207 $canv coords $linehtag($id) $xt [lindex $idpos($id) 2]
8208 set text [$canv itemcget $linehtag($id) -text]
8209 set font [$canv itemcget $linehtag($id) -font]
Paul Mackerrasfc2a2562007-12-26 23:03:43 +11008210 set xr [expr {$xt + [font measure $font $text]}]
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10008211 if {$xr > $canvxmax} {
8212 set canvxmax $xr
8213 setcanvscroll
8214 }
Paul Mackerrasfc2a2562007-12-26 23:03:43 +11008215 if {[info exists currentid] && $currentid == $id} {
Paul Mackerras28593d32008-11-13 23:01:46 +11008216 make_secsel $id
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10008217 }
8218}
8219
8220proc mktagcan {} {
8221 global mktagtop
8222
8223 catch {destroy $mktagtop}
8224 unset mktagtop
8225}
8226
8227proc mktaggo {} {
Alexander Gavrilov84a76f12008-11-02 21:59:45 +03008228 if {![domktag]} return
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10008229 mktagcan
8230}
8231
Paul Mackerras4a2139f2005-06-29 09:47:48 +10008232proc writecommit {} {
8233 global rowmenuid wrcomtop commitinfo wrcomcmd
8234
8235 set top .writecommit
8236 set wrcomtop $top
8237 catch {destroy $top}
8238 toplevel $top
Alexander Gavrilove7d64002008-11-11 23:55:42 +03008239 make_transient $top .
Christian Stimmingd990ced2007-11-07 18:42:55 +01008240 label $top.title -text [mc "Write commit to file"]
Paul Mackerras4a2139f2005-06-29 09:47:48 +10008241 grid $top.title - -pady 10
Christian Stimmingd990ced2007-11-07 18:42:55 +01008242 label $top.id -text [mc "ID:"]
Paul Mackerras4a2139f2005-06-29 09:47:48 +10008243 entry $top.sha1 -width 40 -relief flat
8244 $top.sha1 insert 0 $rowmenuid
8245 $top.sha1 conf -state readonly
8246 grid $top.id $top.sha1 -sticky w
8247 entry $top.head -width 60 -relief flat
8248 $top.head insert 0 [lindex $commitinfo($rowmenuid) 0]
8249 $top.head conf -state readonly
8250 grid x $top.head -sticky w
Christian Stimmingd990ced2007-11-07 18:42:55 +01008251 label $top.clab -text [mc "Command:"]
Paul Mackerras4a2139f2005-06-29 09:47:48 +10008252 entry $top.cmd -width 60 -textvariable wrcomcmd
8253 grid $top.clab $top.cmd -sticky w -pady 10
Christian Stimmingd990ced2007-11-07 18:42:55 +01008254 label $top.flab -text [mc "Output file:"]
Paul Mackerras4a2139f2005-06-29 09:47:48 +10008255 entry $top.fname -width 60
8256 $top.fname insert 0 [file normalize "commit-[string range $rowmenuid 0 6]"]
8257 grid $top.flab $top.fname -sticky w
8258 frame $top.buts
Christian Stimmingd990ced2007-11-07 18:42:55 +01008259 button $top.buts.gen -text [mc "Write"] -command wrcomgo
8260 button $top.buts.can -text [mc "Cancel"] -command wrcomcan
Alexander Gavrilov76f15942008-11-02 21:59:44 +03008261 bind $top <Key-Return> wrcomgo
8262 bind $top <Key-Escape> wrcomcan
Paul Mackerras4a2139f2005-06-29 09:47:48 +10008263 grid $top.buts.gen $top.buts.can
8264 grid columnconfigure $top.buts 0 -weight 1 -uniform a
8265 grid columnconfigure $top.buts 1 -weight 1 -uniform a
8266 grid $top.buts - -pady 10 -sticky ew
8267 focus $top.fname
8268}
8269
8270proc wrcomgo {} {
8271 global wrcomtop
8272
8273 set id [$wrcomtop.sha1 get]
8274 set cmd "echo $id | [$wrcomtop.cmd get]"
8275 set fname [$wrcomtop.fname get]
8276 if {[catch {exec sh -c $cmd >$fname &} err]} {
Alexander Gavrilov84a76f12008-11-02 21:59:45 +03008277 error_popup "[mc "Error writing commit:"] $err" $wrcomtop
Paul Mackerras4a2139f2005-06-29 09:47:48 +10008278 }
8279 catch {destroy $wrcomtop}
8280 unset wrcomtop
8281}
8282
8283proc wrcomcan {} {
8284 global wrcomtop
8285
8286 catch {destroy $wrcomtop}
8287 unset wrcomtop
8288}
8289
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10008290proc mkbranch {} {
8291 global rowmenuid mkbrtop
8292
8293 set top .makebranch
8294 catch {destroy $top}
8295 toplevel $top
Alexander Gavrilove7d64002008-11-11 23:55:42 +03008296 make_transient $top .
Christian Stimmingd990ced2007-11-07 18:42:55 +01008297 label $top.title -text [mc "Create new branch"]
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10008298 grid $top.title - -pady 10
Christian Stimmingd990ced2007-11-07 18:42:55 +01008299 label $top.id -text [mc "ID:"]
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10008300 entry $top.sha1 -width 40 -relief flat
8301 $top.sha1 insert 0 $rowmenuid
8302 $top.sha1 conf -state readonly
8303 grid $top.id $top.sha1 -sticky w
Christian Stimmingd990ced2007-11-07 18:42:55 +01008304 label $top.nlab -text [mc "Name:"]
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10008305 entry $top.name -width 40
8306 grid $top.nlab $top.name -sticky w
8307 frame $top.buts
Christian Stimmingd990ced2007-11-07 18:42:55 +01008308 button $top.buts.go -text [mc "Create"] -command [list mkbrgo $top]
8309 button $top.buts.can -text [mc "Cancel"] -command "catch {destroy $top}"
Alexander Gavrilov76f15942008-11-02 21:59:44 +03008310 bind $top <Key-Return> [list mkbrgo $top]
8311 bind $top <Key-Escape> "catch {destroy $top}"
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10008312 grid $top.buts.go $top.buts.can
8313 grid columnconfigure $top.buts 0 -weight 1 -uniform a
8314 grid columnconfigure $top.buts 1 -weight 1 -uniform a
8315 grid $top.buts - -pady 10 -sticky ew
8316 focus $top.name
8317}
8318
8319proc mkbrgo {top} {
8320 global headids idheads
8321
8322 set name [$top.name get]
8323 set id [$top.sha1 get]
Alexander Gavrilovbee866f2008-10-08 11:05:35 +04008324 set cmdargs {}
8325 set old_id {}
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10008326 if {$name eq {}} {
Alexander Gavrilov84a76f12008-11-02 21:59:45 +03008327 error_popup [mc "Please specify a name for the new branch"] $top
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10008328 return
8329 }
Alexander Gavrilovbee866f2008-10-08 11:05:35 +04008330 if {[info exists headids($name)]} {
8331 if {![confirm_popup [mc \
Alexander Gavrilov84a76f12008-11-02 21:59:45 +03008332 "Branch '%s' already exists. Overwrite?" $name] $top]} {
Alexander Gavrilovbee866f2008-10-08 11:05:35 +04008333 return
8334 }
8335 set old_id $headids($name)
8336 lappend cmdargs -f
8337 }
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10008338 catch {destroy $top}
Alexander Gavrilovbee866f2008-10-08 11:05:35 +04008339 lappend cmdargs $name $id
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10008340 nowbusy newbranch
8341 update
8342 if {[catch {
Alexander Gavrilovbee866f2008-10-08 11:05:35 +04008343 eval exec git branch $cmdargs
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10008344 } err]} {
8345 notbusy newbranch
8346 error_popup $err
8347 } else {
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10008348 notbusy newbranch
Alexander Gavrilovbee866f2008-10-08 11:05:35 +04008349 if {$old_id ne {}} {
8350 movehead $id $name
8351 movedhead $id $name
8352 redrawtags $old_id
8353 redrawtags $id
8354 } else {
8355 set headids($name) $id
8356 lappend idheads($id) $name
8357 addedhead $id $name
8358 redrawtags $id
8359 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10008360 dispneartags 0
Paul Mackerras887c9962007-08-20 19:36:20 +10008361 run refill_reflist
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10008362 }
8363}
8364
Alexander Gavrilov15e35052008-11-02 21:59:47 +03008365proc exec_citool {tool_args {baseid {}}} {
8366 global commitinfo env
8367
8368 set save_env [array get env GIT_AUTHOR_*]
8369
8370 if {$baseid ne {}} {
8371 if {![info exists commitinfo($baseid)]} {
8372 getcommit $baseid
8373 }
8374 set author [lindex $commitinfo($baseid) 1]
8375 set date [lindex $commitinfo($baseid) 2]
8376 if {[regexp {^\s*(\S.*\S|\S)\s*<(.*)>\s*$} \
8377 $author author name email]
8378 && $date ne {}} {
8379 set env(GIT_AUTHOR_NAME) $name
8380 set env(GIT_AUTHOR_EMAIL) $email
8381 set env(GIT_AUTHOR_DATE) $date
8382 }
8383 }
8384
8385 eval exec git citool $tool_args &
8386
8387 array unset env GIT_AUTHOR_*
8388 array set env $save_env
8389}
8390
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10008391proc cherrypick {} {
Paul Mackerras468bcae2008-03-03 10:19:35 +11008392 global rowmenuid curview
Paul Mackerrasb8a938c2008-02-13 22:12:31 +11008393 global mainhead mainheadid
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10008394
Paul Mackerrase11f1232007-06-16 20:29:25 +10008395 set oldhead [exec git rev-parse HEAD]
8396 set dheads [descheads $rowmenuid]
8397 if {$dheads ne {} && [lsearch -exact $dheads $oldhead] >= 0} {
Christian Stimmingd990ced2007-11-07 18:42:55 +01008398 set ok [confirm_popup [mc "Commit %s is already\
8399 included in branch %s -- really re-apply it?" \
8400 [string range $rowmenuid 0 7] $mainhead]]
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10008401 if {!$ok} return
8402 }
Christian Stimmingd990ced2007-11-07 18:42:55 +01008403 nowbusy cherrypick [mc "Cherry-picking"]
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10008404 update
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10008405 # Unfortunately git-cherry-pick writes stuff to stderr even when
8406 # no error occurs, and exec takes that as an indication of error...
8407 if {[catch {exec sh -c "git cherry-pick -r $rowmenuid 2>&1"} err]} {
8408 notbusy cherrypick
Alexander Gavrilov15e35052008-11-02 21:59:47 +03008409 if {[regexp -line \
Paul Mackerras887a7912008-11-08 21:37:09 +11008410 {Entry '(.*)' (would be overwritten by merge|not uptodate)} \
8411 $err msg fname]} {
8412 error_popup [mc "Cherry-pick failed because of local changes\
8413 to file '%s'.\nPlease commit, reset or stash\
8414 your changes and try again." $fname]
8415 } elseif {[regexp -line \
8416 {^(CONFLICT \(.*\):|Automatic cherry-pick failed)} \
8417 $err]} {
8418 if {[confirm_popup [mc "Cherry-pick failed because of merge\
8419 conflict.\nDo you wish to run git citool to\
8420 resolve it?"]]} {
8421 # Force citool to read MERGE_MSG
8422 file delete [file join [gitdir] "GITGUI_MSG"]
8423 exec_citool {} $rowmenuid
8424 }
Alexander Gavrilov15e35052008-11-02 21:59:47 +03008425 } else {
8426 error_popup $err
8427 }
Paul Mackerras887a7912008-11-08 21:37:09 +11008428 run updatecommits
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10008429 return
8430 }
8431 set newhead [exec git rev-parse HEAD]
8432 if {$newhead eq $oldhead} {
8433 notbusy cherrypick
Christian Stimmingd990ced2007-11-07 18:42:55 +01008434 error_popup [mc "No changes committed"]
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10008435 return
8436 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10008437 addnewchild $newhead $oldhead
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11008438 if {[commitinview $oldhead $curview]} {
Paul Mackerrascdc84292008-11-18 19:54:14 +11008439 # XXX this isn't right if we have a path limit...
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11008440 insertrow $newhead $oldhead $curview
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10008441 if {$mainhead ne {}} {
Paul Mackerrase11f1232007-06-16 20:29:25 +10008442 movehead $newhead $mainhead
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10008443 movedhead $newhead $mainhead
8444 }
Paul Mackerrasc11ff122008-05-26 10:11:33 +10008445 set mainheadid $newhead
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10008446 redrawtags $oldhead
8447 redrawtags $newhead
Paul Mackerras46308ea2008-01-15 22:16:32 +11008448 selbyid $newhead
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10008449 }
8450 notbusy cherrypick
8451}
8452
Paul Mackerras6fb735a2006-10-19 10:09:06 +10008453proc resethead {} {
Paul Mackerrasb8a938c2008-02-13 22:12:31 +11008454 global mainhead rowmenuid confirm_ok resettype
Paul Mackerras6fb735a2006-10-19 10:09:06 +10008455
8456 set confirm_ok 0
8457 set w ".confirmreset"
8458 toplevel $w
Alexander Gavrilove7d64002008-11-11 23:55:42 +03008459 make_transient $w .
Christian Stimmingd990ced2007-11-07 18:42:55 +01008460 wm title $w [mc "Confirm reset"]
Paul Mackerras6fb735a2006-10-19 10:09:06 +10008461 message $w.m -text \
Christian Stimmingd990ced2007-11-07 18:42:55 +01008462 [mc "Reset branch %s to %s?" $mainhead [string range $rowmenuid 0 7]] \
Paul Mackerras6fb735a2006-10-19 10:09:06 +10008463 -justify center -aspect 1000
8464 pack $w.m -side top -fill x -padx 20 -pady 20
8465 frame $w.f -relief sunken -border 2
Christian Stimmingd990ced2007-11-07 18:42:55 +01008466 message $w.f.rt -text [mc "Reset type:"] -aspect 1000
Paul Mackerras6fb735a2006-10-19 10:09:06 +10008467 grid $w.f.rt -sticky w
8468 set resettype mixed
8469 radiobutton $w.f.soft -value soft -variable resettype -justify left \
Christian Stimmingd990ced2007-11-07 18:42:55 +01008470 -text [mc "Soft: Leave working tree and index untouched"]
Paul Mackerras6fb735a2006-10-19 10:09:06 +10008471 grid $w.f.soft -sticky w
8472 radiobutton $w.f.mixed -value mixed -variable resettype -justify left \
Christian Stimmingd990ced2007-11-07 18:42:55 +01008473 -text [mc "Mixed: Leave working tree untouched, reset index"]
Paul Mackerras6fb735a2006-10-19 10:09:06 +10008474 grid $w.f.mixed -sticky w
8475 radiobutton $w.f.hard -value hard -variable resettype -justify left \
Christian Stimmingd990ced2007-11-07 18:42:55 +01008476 -text [mc "Hard: Reset working tree and index\n(discard ALL local changes)"]
Paul Mackerras6fb735a2006-10-19 10:09:06 +10008477 grid $w.f.hard -sticky w
8478 pack $w.f -side top -fill x
Christian Stimmingd990ced2007-11-07 18:42:55 +01008479 button $w.ok -text [mc OK] -command "set confirm_ok 1; destroy $w"
Paul Mackerras6fb735a2006-10-19 10:09:06 +10008480 pack $w.ok -side left -fill x -padx 20 -pady 20
Christian Stimmingd990ced2007-11-07 18:42:55 +01008481 button $w.cancel -text [mc Cancel] -command "destroy $w"
Alexander Gavrilov76f15942008-11-02 21:59:44 +03008482 bind $w <Key-Escape> [list destroy $w]
Paul Mackerras6fb735a2006-10-19 10:09:06 +10008483 pack $w.cancel -side right -fill x -padx 20 -pady 20
8484 bind $w <Visibility> "grab $w; focus $w"
8485 tkwait window $w
8486 if {!$confirm_ok} return
Paul Mackerras706d6c32007-06-26 11:09:49 +10008487 if {[catch {set fd [open \
Paul Mackerras08ba8202008-05-12 10:18:38 +10008488 [list | git reset --$resettype $rowmenuid 2>@1] r]} err]} {
Paul Mackerras6fb735a2006-10-19 10:09:06 +10008489 error_popup $err
8490 } else {
Paul Mackerras706d6c32007-06-26 11:09:49 +10008491 dohidelocalchanges
Paul Mackerrasa137a902007-10-23 21:12:49 +10008492 filerun $fd [list readresetstat $fd]
Christian Stimmingd990ced2007-11-07 18:42:55 +01008493 nowbusy reset [mc "Resetting"]
Paul Mackerras46308ea2008-01-15 22:16:32 +11008494 selbyid $rowmenuid
Paul Mackerras706d6c32007-06-26 11:09:49 +10008495 }
8496}
8497
Paul Mackerrasa137a902007-10-23 21:12:49 +10008498proc readresetstat {fd} {
8499 global mainhead mainheadid showlocalchanges rprogcoord
Paul Mackerras706d6c32007-06-26 11:09:49 +10008500
8501 if {[gets $fd line] >= 0} {
8502 if {[regexp {([0-9]+)% \(([0-9]+)/([0-9]+)\)} $line match p m n]} {
Paul Mackerrasa137a902007-10-23 21:12:49 +10008503 set rprogcoord [expr {1.0 * $m / $n}]
8504 adjustprogress
Paul Mackerras706d6c32007-06-26 11:09:49 +10008505 }
8506 return 1
8507 }
Paul Mackerrasa137a902007-10-23 21:12:49 +10008508 set rprogcoord 0
8509 adjustprogress
Paul Mackerras706d6c32007-06-26 11:09:49 +10008510 notbusy reset
8511 if {[catch {close $fd} err]} {
8512 error_popup $err
8513 }
8514 set oldhead $mainheadid
8515 set newhead [exec git rev-parse HEAD]
8516 if {$newhead ne $oldhead} {
8517 movehead $newhead $mainhead
8518 movedhead $newhead $mainhead
8519 set mainheadid $newhead
Paul Mackerras6fb735a2006-10-19 10:09:06 +10008520 redrawtags $oldhead
Paul Mackerras706d6c32007-06-26 11:09:49 +10008521 redrawtags $newhead
Paul Mackerras6fb735a2006-10-19 10:09:06 +10008522 }
8523 if {$showlocalchanges} {
8524 doshowlocalchanges
8525 }
Paul Mackerras706d6c32007-06-26 11:09:49 +10008526 return 0
Paul Mackerras6fb735a2006-10-19 10:09:06 +10008527}
8528
Paul Mackerras10299152006-08-02 09:52:01 +10008529# context menu for a head
8530proc headmenu {x y id head} {
Paul Mackerras00609462007-06-17 17:08:35 +10008531 global headmenuid headmenuhead headctxmenu mainhead
Paul Mackerras10299152006-08-02 09:52:01 +10008532
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10008533 stopfinding
Paul Mackerras10299152006-08-02 09:52:01 +10008534 set headmenuid $id
8535 set headmenuhead $head
Paul Mackerras00609462007-06-17 17:08:35 +10008536 set state normal
8537 if {$head eq $mainhead} {
8538 set state disabled
8539 }
8540 $headctxmenu entryconfigure 0 -state $state
8541 $headctxmenu entryconfigure 1 -state $state
Paul Mackerras10299152006-08-02 09:52:01 +10008542 tk_popup $headctxmenu $x $y
8543}
8544
8545proc cobranch {} {
Paul Mackerrasc11ff122008-05-26 10:11:33 +10008546 global headmenuid headmenuhead headids
Paul Mackerrascdc84292008-11-18 19:54:14 +11008547 global showlocalchanges
Paul Mackerras10299152006-08-02 09:52:01 +10008548
8549 # check the tree is clean first??
Christian Stimmingd990ced2007-11-07 18:42:55 +01008550 nowbusy checkout [mc "Checking out"]
Paul Mackerras10299152006-08-02 09:52:01 +10008551 update
Paul Mackerras219ea3a2006-09-07 10:21:39 +10008552 dohidelocalchanges
Paul Mackerras10299152006-08-02 09:52:01 +10008553 if {[catch {
Paul Mackerras08ba8202008-05-12 10:18:38 +10008554 set fd [open [list | git checkout $headmenuhead 2>@1] r]
Paul Mackerras10299152006-08-02 09:52:01 +10008555 } err]} {
8556 notbusy checkout
8557 error_popup $err
Paul Mackerras08ba8202008-05-12 10:18:38 +10008558 if {$showlocalchanges} {
8559 dodiffindex
Paul Mackerras10299152006-08-02 09:52:01 +10008560 }
Paul Mackerras08ba8202008-05-12 10:18:38 +10008561 } else {
8562 filerun $fd [list readcheckoutstat $fd $headmenuhead $headmenuid]
Paul Mackerras6fb735a2006-10-19 10:09:06 +10008563 }
Paul Mackerras08ba8202008-05-12 10:18:38 +10008564}
8565
8566proc readcheckoutstat {fd newhead newheadid} {
8567 global mainhead mainheadid headids showlocalchanges progresscoords
Paul Mackerrascdc84292008-11-18 19:54:14 +11008568 global viewmainheadid curview
Paul Mackerras08ba8202008-05-12 10:18:38 +10008569
8570 if {[gets $fd line] >= 0} {
8571 if {[regexp {([0-9]+)% \(([0-9]+)/([0-9]+)\)} $line match p m n]} {
8572 set progresscoords [list 0 [expr {1.0 * $m / $n}]]
8573 adjustprogress
8574 }
8575 return 1
8576 }
8577 set progresscoords {0 0}
8578 adjustprogress
8579 notbusy checkout
8580 if {[catch {close $fd} err]} {
8581 error_popup $err
8582 }
Paul Mackerrasc11ff122008-05-26 10:11:33 +10008583 set oldmainid $mainheadid
Paul Mackerras08ba8202008-05-12 10:18:38 +10008584 set mainhead $newhead
8585 set mainheadid $newheadid
Paul Mackerrascdc84292008-11-18 19:54:14 +11008586 set viewmainheadid($curview) $newheadid
Paul Mackerrasc11ff122008-05-26 10:11:33 +10008587 redrawtags $oldmainid
Paul Mackerras08ba8202008-05-12 10:18:38 +10008588 redrawtags $newheadid
8589 selbyid $newheadid
Paul Mackerras6fb735a2006-10-19 10:09:06 +10008590 if {$showlocalchanges} {
8591 dodiffindex
Paul Mackerras10299152006-08-02 09:52:01 +10008592 }
8593}
8594
8595proc rmbranch {} {
Paul Mackerrase11f1232007-06-16 20:29:25 +10008596 global headmenuid headmenuhead mainhead
Paul Mackerrasb1054ac2007-08-15 10:09:47 +10008597 global idheads
Paul Mackerras10299152006-08-02 09:52:01 +10008598
8599 set head $headmenuhead
8600 set id $headmenuid
Paul Mackerras00609462007-06-17 17:08:35 +10008601 # this check shouldn't be needed any more...
Paul Mackerras10299152006-08-02 09:52:01 +10008602 if {$head eq $mainhead} {
Christian Stimmingd990ced2007-11-07 18:42:55 +01008603 error_popup [mc "Cannot delete the currently checked-out branch"]
Paul Mackerras10299152006-08-02 09:52:01 +10008604 return
8605 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10008606 set dheads [descheads $id]
Paul Mackerrasd7b16112007-08-17 17:57:31 +10008607 if {[llength $dheads] == 1 && $idheads($dheads) eq $head} {
Paul Mackerras10299152006-08-02 09:52:01 +10008608 # the stuff on this branch isn't on any other branch
Christian Stimmingd990ced2007-11-07 18:42:55 +01008609 if {![confirm_popup [mc "The commits on branch %s aren't on any other\
8610 branch.\nReally delete branch %s?" $head $head]]} return
Paul Mackerras10299152006-08-02 09:52:01 +10008611 }
8612 nowbusy rmbranch
8613 update
8614 if {[catch {exec git branch -D $head} err]} {
8615 notbusy rmbranch
8616 error_popup $err
8617 return
8618 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10008619 removehead $id $head
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10008620 removedhead $id $head
Paul Mackerras10299152006-08-02 09:52:01 +10008621 redrawtags $id
8622 notbusy rmbranch
Paul Mackerrase11f1232007-06-16 20:29:25 +10008623 dispneartags 0
Paul Mackerras887c9962007-08-20 19:36:20 +10008624 run refill_reflist
8625}
8626
8627# Display a list of tags and heads
8628proc showrefs {} {
Paul Mackerras9c311b32007-10-04 22:27:13 +10008629 global showrefstop bgcolor fgcolor selectbgcolor
8630 global bglist fglist reflistfilter reflist maincursor
Paul Mackerras887c9962007-08-20 19:36:20 +10008631
8632 set top .showrefs
8633 set showrefstop $top
8634 if {[winfo exists $top]} {
8635 raise $top
8636 refill_reflist
8637 return
8638 }
8639 toplevel $top
Christian Stimmingd990ced2007-11-07 18:42:55 +01008640 wm title $top [mc "Tags and heads: %s" [file tail [pwd]]]
Alexander Gavrilove7d64002008-11-11 23:55:42 +03008641 make_transient $top .
Paul Mackerras887c9962007-08-20 19:36:20 +10008642 text $top.list -background $bgcolor -foreground $fgcolor \
Paul Mackerras9c311b32007-10-04 22:27:13 +10008643 -selectbackground $selectbgcolor -font mainfont \
Paul Mackerras887c9962007-08-20 19:36:20 +10008644 -xscrollcommand "$top.xsb set" -yscrollcommand "$top.ysb set" \
8645 -width 30 -height 20 -cursor $maincursor \
8646 -spacing1 1 -spacing3 1 -state disabled
8647 $top.list tag configure highlight -background $selectbgcolor
8648 lappend bglist $top.list
8649 lappend fglist $top.list
8650 scrollbar $top.ysb -command "$top.list yview" -orient vertical
8651 scrollbar $top.xsb -command "$top.list xview" -orient horizontal
8652 grid $top.list $top.ysb -sticky nsew
8653 grid $top.xsb x -sticky ew
8654 frame $top.f
Paul Mackerrasb039f0a2008-01-06 15:54:46 +11008655 label $top.f.l -text "[mc "Filter"]: "
8656 entry $top.f.e -width 20 -textvariable reflistfilter
Paul Mackerras887c9962007-08-20 19:36:20 +10008657 set reflistfilter "*"
8658 trace add variable reflistfilter write reflistfilter_change
8659 pack $top.f.e -side right -fill x -expand 1
8660 pack $top.f.l -side left
8661 grid $top.f - -sticky ew -pady 2
Paul Mackerrasb039f0a2008-01-06 15:54:46 +11008662 button $top.close -command [list destroy $top] -text [mc "Close"]
Alexander Gavrilov76f15942008-11-02 21:59:44 +03008663 bind $top <Key-Escape> [list destroy $top]
Paul Mackerras887c9962007-08-20 19:36:20 +10008664 grid $top.close -
8665 grid columnconfigure $top 0 -weight 1
8666 grid rowconfigure $top 0 -weight 1
8667 bind $top.list <1> {break}
8668 bind $top.list <B1-Motion> {break}
8669 bind $top.list <ButtonRelease-1> {sel_reflist %W %x %y; break}
8670 set reflist {}
8671 refill_reflist
8672}
8673
8674proc sel_reflist {w x y} {
8675 global showrefstop reflist headids tagids otherrefids
8676
8677 if {![winfo exists $showrefstop]} return
8678 set l [lindex [split [$w index "@$x,$y"] "."] 0]
8679 set ref [lindex $reflist [expr {$l-1}]]
8680 set n [lindex $ref 0]
8681 switch -- [lindex $ref 1] {
8682 "H" {selbyid $headids($n)}
8683 "T" {selbyid $tagids($n)}
8684 "o" {selbyid $otherrefids($n)}
8685 }
8686 $showrefstop.list tag add highlight $l.0 "$l.0 lineend"
8687}
8688
8689proc unsel_reflist {} {
8690 global showrefstop
8691
8692 if {![info exists showrefstop] || ![winfo exists $showrefstop]} return
8693 $showrefstop.list tag remove highlight 0.0 end
8694}
8695
8696proc reflistfilter_change {n1 n2 op} {
8697 global reflistfilter
8698
8699 after cancel refill_reflist
8700 after 200 refill_reflist
8701}
8702
8703proc refill_reflist {} {
8704 global reflist reflistfilter showrefstop headids tagids otherrefids
Paul Mackerrasd375ef92008-10-21 10:18:12 +11008705 global curview
Paul Mackerras887c9962007-08-20 19:36:20 +10008706
8707 if {![info exists showrefstop] || ![winfo exists $showrefstop]} return
8708 set refs {}
8709 foreach n [array names headids] {
8710 if {[string match $reflistfilter $n]} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11008711 if {[commitinview $headids($n) $curview]} {
Paul Mackerras887c9962007-08-20 19:36:20 +10008712 lappend refs [list $n H]
8713 } else {
Paul Mackerrasd375ef92008-10-21 10:18:12 +11008714 interestedin $headids($n) {run refill_reflist}
Paul Mackerras887c9962007-08-20 19:36:20 +10008715 }
8716 }
8717 }
8718 foreach n [array names tagids] {
8719 if {[string match $reflistfilter $n]} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11008720 if {[commitinview $tagids($n) $curview]} {
Paul Mackerras887c9962007-08-20 19:36:20 +10008721 lappend refs [list $n T]
8722 } else {
Paul Mackerrasd375ef92008-10-21 10:18:12 +11008723 interestedin $tagids($n) {run refill_reflist}
Paul Mackerras887c9962007-08-20 19:36:20 +10008724 }
8725 }
8726 }
8727 foreach n [array names otherrefids] {
8728 if {[string match $reflistfilter $n]} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11008729 if {[commitinview $otherrefids($n) $curview]} {
Paul Mackerras887c9962007-08-20 19:36:20 +10008730 lappend refs [list $n o]
8731 } else {
Paul Mackerrasd375ef92008-10-21 10:18:12 +11008732 interestedin $otherrefids($n) {run refill_reflist}
Paul Mackerras887c9962007-08-20 19:36:20 +10008733 }
8734 }
8735 }
8736 set refs [lsort -index 0 $refs]
8737 if {$refs eq $reflist} return
8738
8739 # Update the contents of $showrefstop.list according to the
8740 # differences between $reflist (old) and $refs (new)
8741 $showrefstop.list conf -state normal
8742 $showrefstop.list insert end "\n"
8743 set i 0
8744 set j 0
8745 while {$i < [llength $reflist] || $j < [llength $refs]} {
8746 if {$i < [llength $reflist]} {
8747 if {$j < [llength $refs]} {
8748 set cmp [string compare [lindex $reflist $i 0] \
8749 [lindex $refs $j 0]]
8750 if {$cmp == 0} {
8751 set cmp [string compare [lindex $reflist $i 1] \
8752 [lindex $refs $j 1]]
8753 }
8754 } else {
8755 set cmp -1
8756 }
8757 } else {
8758 set cmp 1
8759 }
8760 switch -- $cmp {
8761 -1 {
8762 $showrefstop.list delete "[expr {$j+1}].0" "[expr {$j+2}].0"
8763 incr i
8764 }
8765 0 {
8766 incr i
8767 incr j
8768 }
8769 1 {
8770 set l [expr {$j + 1}]
8771 $showrefstop.list image create $l.0 -align baseline \
8772 -image reficon-[lindex $refs $j 1] -padx 2
8773 $showrefstop.list insert $l.1 "[lindex $refs $j 0]\n"
8774 incr j
8775 }
8776 }
8777 }
8778 set reflist $refs
8779 # delete last newline
8780 $showrefstop.list delete end-2c end-1c
8781 $showrefstop.list conf -state disabled
Paul Mackerras10299152006-08-02 09:52:01 +10008782}
8783
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10008784# Stuff for finding nearby tags
8785proc getallcommits {} {
Paul Mackerras5cd15b62007-08-30 21:54:17 +10008786 global allcommits nextarc seeds allccache allcwait cachedarcs allcupdate
8787 global idheads idtags idotherrefs allparents tagobjid
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10008788
Paul Mackerrasa69b2d12007-08-13 15:02:02 +10008789 if {![info exists allcommits]} {
Paul Mackerrasa69b2d12007-08-13 15:02:02 +10008790 set nextarc 0
8791 set allcommits 0
8792 set seeds {}
Paul Mackerras5cd15b62007-08-30 21:54:17 +10008793 set allcwait 0
8794 set cachedarcs 0
8795 set allccache [file join [gitdir] "gitk.cache"]
8796 if {![catch {
8797 set f [open $allccache r]
8798 set allcwait 1
8799 getcache $f
8800 }]} return
Paul Mackerrasa69b2d12007-08-13 15:02:02 +10008801 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10008802
Paul Mackerras5cd15b62007-08-30 21:54:17 +10008803 if {$allcwait} {
8804 return
Paul Mackerrase11f1232007-06-16 20:29:25 +10008805 }
Paul Mackerras5cd15b62007-08-30 21:54:17 +10008806 set cmd [list | git rev-list --parents]
8807 set allcupdate [expr {$seeds ne {}}]
8808 if {!$allcupdate} {
8809 set ids "--all"
8810 } else {
8811 set refs [concat [array names idheads] [array names idtags] \
8812 [array names idotherrefs]]
8813 set ids {}
8814 set tagobjs {}
8815 foreach name [array names tagobjid] {
8816 lappend tagobjs $tagobjid($name)
8817 }
8818 foreach id [lsort -unique $refs] {
8819 if {![info exists allparents($id)] &&
8820 [lsearch -exact $tagobjs $id] < 0} {
8821 lappend ids $id
8822 }
8823 }
8824 if {$ids ne {}} {
8825 foreach id $seeds {
8826 lappend ids "^$id"
8827 }
8828 }
8829 }
8830 if {$ids ne {}} {
8831 set fd [open [concat $cmd $ids] r]
8832 fconfigure $fd -blocking 0
8833 incr allcommits
8834 nowbusy allcommits
8835 filerun $fd [list getallclines $fd]
8836 } else {
8837 dispneartags 0
8838 }
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10008839}
8840
Paul Mackerrase11f1232007-06-16 20:29:25 +10008841# Since most commits have 1 parent and 1 child, we group strings of
8842# such commits into "arcs" joining branch/merge points (BMPs), which
8843# are commits that either don't have 1 parent or don't have 1 child.
8844#
8845# arcnos(id) - incoming arcs for BMP, arc we're on for other nodes
8846# arcout(id) - outgoing arcs for BMP
8847# arcids(a) - list of IDs on arc including end but not start
8848# arcstart(a) - BMP ID at start of arc
8849# arcend(a) - BMP ID at end of arc
8850# growing(a) - arc a is still growing
8851# arctags(a) - IDs out of arcids (excluding end) that have tags
8852# archeads(a) - IDs out of arcids (excluding end) that have heads
8853# The start of an arc is at the descendent end, so "incoming" means
8854# coming from descendents, and "outgoing" means going towards ancestors.
Paul Mackerrascec7bec2006-08-02 09:38:10 +10008855
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10008856proc getallclines {fd} {
Paul Mackerras5cd15b62007-08-30 21:54:17 +10008857 global allparents allchildren idtags idheads nextarc
Paul Mackerrase11f1232007-06-16 20:29:25 +10008858 global arcnos arcids arctags arcout arcend arcstart archeads growing
Paul Mackerras5cd15b62007-08-30 21:54:17 +10008859 global seeds allcommits cachedarcs allcupdate
8860
Paul Mackerrase11f1232007-06-16 20:29:25 +10008861 set nid 0
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10008862 while {[incr nid] <= 1000 && [gets $fd line] >= 0} {
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10008863 set id [lindex $line 0]
Paul Mackerrase11f1232007-06-16 20:29:25 +10008864 if {[info exists allparents($id)]} {
8865 # seen it already
8866 continue
8867 }
Paul Mackerras5cd15b62007-08-30 21:54:17 +10008868 set cachedarcs 0
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10008869 set olds [lrange $line 1 end]
8870 set allparents($id) $olds
8871 if {![info exists allchildren($id)]} {
8872 set allchildren($id) {}
Paul Mackerrase11f1232007-06-16 20:29:25 +10008873 set arcnos($id) {}
8874 lappend seeds $id
8875 } else {
8876 set a $arcnos($id)
8877 if {[llength $olds] == 1 && [llength $a] == 1} {
8878 lappend arcids($a) $id
8879 if {[info exists idtags($id)]} {
8880 lappend arctags($a) $id
8881 }
8882 if {[info exists idheads($id)]} {
8883 lappend archeads($a) $id
8884 }
8885 if {[info exists allparents($olds)]} {
8886 # seen parent already
8887 if {![info exists arcout($olds)]} {
8888 splitarc $olds
8889 }
8890 lappend arcids($a) $olds
8891 set arcend($a) $olds
8892 unset growing($a)
8893 }
8894 lappend allchildren($olds) $id
8895 lappend arcnos($olds) $a
8896 continue
8897 }
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10008898 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10008899 foreach a $arcnos($id) {
8900 lappend arcids($a) $id
8901 set arcend($a) $id
8902 unset growing($a)
8903 }
8904
8905 set ao {}
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10008906 foreach p $olds {
8907 lappend allchildren($p) $id
Paul Mackerrase11f1232007-06-16 20:29:25 +10008908 set a [incr nextarc]
8909 set arcstart($a) $id
8910 set archeads($a) {}
8911 set arctags($a) {}
8912 set archeads($a) {}
8913 set arcids($a) {}
8914 lappend ao $a
8915 set growing($a) 1
8916 if {[info exists allparents($p)]} {
8917 # seen it already, may need to make a new branch
8918 if {![info exists arcout($p)]} {
8919 splitarc $p
8920 }
8921 lappend arcids($a) $p
8922 set arcend($a) $p
8923 unset growing($a)
8924 }
8925 lappend arcnos($p) $a
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10008926 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10008927 set arcout($id) $ao
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10008928 }
Paul Mackerrasf3326b62007-06-18 22:39:21 +10008929 if {$nid > 0} {
8930 global cached_dheads cached_dtags cached_atags
8931 catch {unset cached_dheads}
8932 catch {unset cached_dtags}
8933 catch {unset cached_atags}
8934 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10008935 if {![eof $fd]} {
8936 return [expr {$nid >= 1000? 2: 1}]
8937 }
Paul Mackerras5cd15b62007-08-30 21:54:17 +10008938 set cacheok 1
8939 if {[catch {
8940 fconfigure $fd -blocking 1
8941 close $fd
8942 } err]} {
8943 # got an error reading the list of commits
8944 # if we were updating, try rereading the whole thing again
8945 if {$allcupdate} {
8946 incr allcommits -1
8947 dropcache $err
8948 return
8949 }
Christian Stimmingd990ced2007-11-07 18:42:55 +01008950 error_popup "[mc "Error reading commit topology information;\
Paul Mackerras5cd15b62007-08-30 21:54:17 +10008951 branch and preceding/following tag information\
Christian Stimmingd990ced2007-11-07 18:42:55 +01008952 will be incomplete."]\n($err)"
Paul Mackerras5cd15b62007-08-30 21:54:17 +10008953 set cacheok 0
8954 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10008955 if {[incr allcommits -1] == 0} {
8956 notbusy allcommits
Paul Mackerras5cd15b62007-08-30 21:54:17 +10008957 if {$cacheok} {
8958 run savecache
8959 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10008960 }
8961 dispneartags 0
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10008962 return 0
Paul Mackerrase11f1232007-06-16 20:29:25 +10008963}
8964
8965proc recalcarc {a} {
8966 global arctags archeads arcids idtags idheads
8967
8968 set at {}
8969 set ah {}
8970 foreach id [lrange $arcids($a) 0 end-1] {
8971 if {[info exists idtags($id)]} {
8972 lappend at $id
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10008973 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10008974 if {[info exists idheads($id)]} {
8975 lappend ah $id
8976 }
8977 }
8978 set arctags($a) $at
8979 set archeads($a) $ah
8980}
8981
8982proc splitarc {p} {
Paul Mackerras5cd15b62007-08-30 21:54:17 +10008983 global arcnos arcids nextarc arctags archeads idtags idheads
Paul Mackerrase11f1232007-06-16 20:29:25 +10008984 global arcstart arcend arcout allparents growing
8985
8986 set a $arcnos($p)
8987 if {[llength $a] != 1} {
8988 puts "oops splitarc called but [llength $a] arcs already"
8989 return
8990 }
8991 set a [lindex $a 0]
8992 set i [lsearch -exact $arcids($a) $p]
8993 if {$i < 0} {
8994 puts "oops splitarc $p not in arc $a"
8995 return
8996 }
8997 set na [incr nextarc]
8998 if {[info exists arcend($a)]} {
8999 set arcend($na) $arcend($a)
9000 } else {
9001 set l [lindex $allparents([lindex $arcids($a) end]) 0]
9002 set j [lsearch -exact $arcnos($l) $a]
9003 set arcnos($l) [lreplace $arcnos($l) $j $j $na]
9004 }
9005 set tail [lrange $arcids($a) [expr {$i+1}] end]
9006 set arcids($a) [lrange $arcids($a) 0 $i]
9007 set arcend($a) $p
9008 set arcstart($na) $p
9009 set arcout($p) $na
9010 set arcids($na) $tail
9011 if {[info exists growing($a)]} {
9012 set growing($na) 1
9013 unset growing($a)
9014 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10009015
9016 foreach id $tail {
9017 if {[llength $arcnos($id)] == 1} {
9018 set arcnos($id) $na
9019 } else {
9020 set j [lsearch -exact $arcnos($id) $a]
9021 set arcnos($id) [lreplace $arcnos($id) $j $j $na]
9022 }
9023 }
9024
9025 # reconstruct tags and heads lists
9026 if {$arctags($a) ne {} || $archeads($a) ne {}} {
9027 recalcarc $a
9028 recalcarc $na
9029 } else {
9030 set arctags($na) {}
9031 set archeads($na) {}
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10009032 }
9033}
9034
Paul Mackerrase11f1232007-06-16 20:29:25 +10009035# Update things for a new commit added that is a child of one
9036# existing commit. Used when cherry-picking.
9037proc addnewchild {id p} {
Paul Mackerras5cd15b62007-08-30 21:54:17 +10009038 global allparents allchildren idtags nextarc
Paul Mackerrase11f1232007-06-16 20:29:25 +10009039 global arcnos arcids arctags arcout arcend arcstart archeads growing
Paul Mackerras719c2b92007-08-29 22:41:34 +10009040 global seeds allcommits
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10009041
Paul Mackerras3ebba3c2007-10-20 22:10:52 +10009042 if {![info exists allcommits] || ![info exists arcnos($p)]} return
Paul Mackerrase11f1232007-06-16 20:29:25 +10009043 set allparents($id) [list $p]
9044 set allchildren($id) {}
9045 set arcnos($id) {}
9046 lappend seeds $id
Paul Mackerrase11f1232007-06-16 20:29:25 +10009047 lappend allchildren($p) $id
9048 set a [incr nextarc]
9049 set arcstart($a) $id
9050 set archeads($a) {}
9051 set arctags($a) {}
9052 set arcids($a) [list $p]
9053 set arcend($a) $p
9054 if {![info exists arcout($p)]} {
9055 splitarc $p
9056 }
9057 lappend arcnos($p) $a
9058 set arcout($id) [list $a]
9059}
9060
Paul Mackerras5cd15b62007-08-30 21:54:17 +10009061# This implements a cache for the topology information.
9062# The cache saves, for each arc, the start and end of the arc,
9063# the ids on the arc, and the outgoing arcs from the end.
9064proc readcache {f} {
9065 global arcnos arcids arcout arcstart arcend arctags archeads nextarc
9066 global idtags idheads allparents cachedarcs possible_seeds seeds growing
9067 global allcwait
9068
9069 set a $nextarc
9070 set lim $cachedarcs
9071 if {$lim - $a > 500} {
9072 set lim [expr {$a + 500}]
9073 }
9074 if {[catch {
9075 if {$a == $lim} {
9076 # finish reading the cache and setting up arctags, etc.
9077 set line [gets $f]
9078 if {$line ne "1"} {error "bad final version"}
9079 close $f
9080 foreach id [array names idtags] {
9081 if {[info exists arcnos($id)] && [llength $arcnos($id)] == 1 &&
9082 [llength $allparents($id)] == 1} {
9083 set a [lindex $arcnos($id) 0]
9084 if {$arctags($a) eq {}} {
9085 recalcarc $a
9086 }
9087 }
9088 }
9089 foreach id [array names idheads] {
9090 if {[info exists arcnos($id)] && [llength $arcnos($id)] == 1 &&
9091 [llength $allparents($id)] == 1} {
9092 set a [lindex $arcnos($id) 0]
9093 if {$archeads($a) eq {}} {
9094 recalcarc $a
9095 }
9096 }
9097 }
9098 foreach id [lsort -unique $possible_seeds] {
9099 if {$arcnos($id) eq {}} {
9100 lappend seeds $id
9101 }
9102 }
9103 set allcwait 0
9104 } else {
9105 while {[incr a] <= $lim} {
9106 set line [gets $f]
9107 if {[llength $line] != 3} {error "bad line"}
9108 set s [lindex $line 0]
9109 set arcstart($a) $s
9110 lappend arcout($s) $a
9111 if {![info exists arcnos($s)]} {
9112 lappend possible_seeds $s
9113 set arcnos($s) {}
9114 }
9115 set e [lindex $line 1]
9116 if {$e eq {}} {
9117 set growing($a) 1
9118 } else {
9119 set arcend($a) $e
9120 if {![info exists arcout($e)]} {
9121 set arcout($e) {}
9122 }
9123 }
9124 set arcids($a) [lindex $line 2]
9125 foreach id $arcids($a) {
9126 lappend allparents($s) $id
9127 set s $id
9128 lappend arcnos($id) $a
9129 }
9130 if {![info exists allparents($s)]} {
9131 set allparents($s) {}
9132 }
9133 set arctags($a) {}
9134 set archeads($a) {}
9135 }
9136 set nextarc [expr {$a - 1}]
9137 }
9138 } err]} {
9139 dropcache $err
9140 return 0
9141 }
9142 if {!$allcwait} {
9143 getallcommits
9144 }
9145 return $allcwait
9146}
9147
9148proc getcache {f} {
9149 global nextarc cachedarcs possible_seeds
9150
9151 if {[catch {
9152 set line [gets $f]
9153 if {[llength $line] != 2 || [lindex $line 0] ne "1"} {error "bad version"}
9154 # make sure it's an integer
9155 set cachedarcs [expr {int([lindex $line 1])}]
9156 if {$cachedarcs < 0} {error "bad number of arcs"}
9157 set nextarc 0
9158 set possible_seeds {}
9159 run readcache $f
9160 } err]} {
9161 dropcache $err
9162 }
9163 return 0
9164}
9165
9166proc dropcache {err} {
9167 global allcwait nextarc cachedarcs seeds
9168
9169 #puts "dropping cache ($err)"
9170 foreach v {arcnos arcout arcids arcstart arcend growing \
9171 arctags archeads allparents allchildren} {
9172 global $v
9173 catch {unset $v}
9174 }
9175 set allcwait 0
9176 set nextarc 0
9177 set cachedarcs 0
9178 set seeds {}
9179 getallcommits
9180}
9181
9182proc writecache {f} {
9183 global cachearc cachedarcs allccache
9184 global arcstart arcend arcnos arcids arcout
9185
9186 set a $cachearc
9187 set lim $cachedarcs
9188 if {$lim - $a > 1000} {
9189 set lim [expr {$a + 1000}]
9190 }
9191 if {[catch {
9192 while {[incr a] <= $lim} {
9193 if {[info exists arcend($a)]} {
9194 puts $f [list $arcstart($a) $arcend($a) $arcids($a)]
9195 } else {
9196 puts $f [list $arcstart($a) {} $arcids($a)]
9197 }
9198 }
9199 } err]} {
9200 catch {close $f}
9201 catch {file delete $allccache}
9202 #puts "writing cache failed ($err)"
9203 return 0
9204 }
9205 set cachearc [expr {$a - 1}]
9206 if {$a > $cachedarcs} {
9207 puts $f "1"
9208 close $f
9209 return 0
9210 }
9211 return 1
9212}
9213
9214proc savecache {} {
9215 global nextarc cachedarcs cachearc allccache
9216
9217 if {$nextarc == $cachedarcs} return
9218 set cachearc 0
9219 set cachedarcs $nextarc
9220 catch {
9221 set f [open $allccache w]
9222 puts $f [list 1 $cachedarcs]
9223 run writecache $f
9224 }
9225}
9226
Paul Mackerrase11f1232007-06-16 20:29:25 +10009227# Returns 1 if a is an ancestor of b, -1 if b is an ancestor of a,
9228# or 0 if neither is true.
9229proc anc_or_desc {a b} {
9230 global arcout arcstart arcend arcnos cached_isanc
9231
9232 if {$arcnos($a) eq $arcnos($b)} {
9233 # Both are on the same arc(s); either both are the same BMP,
9234 # or if one is not a BMP, the other is also not a BMP or is
9235 # the BMP at end of the arc (and it only has 1 incoming arc).
Paul Mackerras69c0b5d2007-07-04 21:57:04 +10009236 # Or both can be BMPs with no incoming arcs.
9237 if {$a eq $b || $arcnos($a) eq {}} {
Paul Mackerrase11f1232007-06-16 20:29:25 +10009238 return 0
9239 }
9240 # assert {[llength $arcnos($a)] == 1}
9241 set arc [lindex $arcnos($a) 0]
9242 set i [lsearch -exact $arcids($arc) $a]
9243 set j [lsearch -exact $arcids($arc) $b]
9244 if {$i < 0 || $i > $j} {
9245 return 1
9246 } else {
9247 return -1
9248 }
9249 }
9250
9251 if {![info exists arcout($a)]} {
9252 set arc [lindex $arcnos($a) 0]
9253 if {[info exists arcend($arc)]} {
9254 set aend $arcend($arc)
9255 } else {
9256 set aend {}
9257 }
9258 set a $arcstart($arc)
9259 } else {
9260 set aend $a
9261 }
9262 if {![info exists arcout($b)]} {
9263 set arc [lindex $arcnos($b) 0]
9264 if {[info exists arcend($arc)]} {
9265 set bend $arcend($arc)
9266 } else {
9267 set bend {}
9268 }
9269 set b $arcstart($arc)
9270 } else {
9271 set bend $b
9272 }
9273 if {$a eq $bend} {
9274 return 1
9275 }
9276 if {$b eq $aend} {
9277 return -1
9278 }
9279 if {[info exists cached_isanc($a,$bend)]} {
9280 if {$cached_isanc($a,$bend)} {
9281 return 1
9282 }
9283 }
9284 if {[info exists cached_isanc($b,$aend)]} {
9285 if {$cached_isanc($b,$aend)} {
9286 return -1
9287 }
9288 if {[info exists cached_isanc($a,$bend)]} {
9289 return 0
9290 }
9291 }
9292
9293 set todo [list $a $b]
9294 set anc($a) a
9295 set anc($b) b
9296 for {set i 0} {$i < [llength $todo]} {incr i} {
9297 set x [lindex $todo $i]
9298 if {$anc($x) eq {}} {
9299 continue
9300 }
9301 foreach arc $arcnos($x) {
9302 set xd $arcstart($arc)
9303 if {$xd eq $bend} {
9304 set cached_isanc($a,$bend) 1
9305 set cached_isanc($b,$aend) 0
9306 return 1
9307 } elseif {$xd eq $aend} {
9308 set cached_isanc($b,$aend) 1
9309 set cached_isanc($a,$bend) 0
9310 return -1
9311 }
9312 if {![info exists anc($xd)]} {
9313 set anc($xd) $anc($x)
9314 lappend todo $xd
9315 } elseif {$anc($xd) ne $anc($x)} {
9316 set anc($xd) {}
9317 }
9318 }
9319 }
9320 set cached_isanc($a,$bend) 0
9321 set cached_isanc($b,$aend) 0
9322 return 0
9323}
9324
9325# This identifies whether $desc has an ancestor that is
9326# a growing tip of the graph and which is not an ancestor of $anc
9327# and returns 0 if so and 1 if not.
9328# If we subsequently discover a tag on such a growing tip, and that
9329# turns out to be a descendent of $anc (which it could, since we
9330# don't necessarily see children before parents), then $desc
9331# isn't a good choice to display as a descendent tag of
9332# $anc (since it is the descendent of another tag which is
9333# a descendent of $anc). Similarly, $anc isn't a good choice to
9334# display as a ancestor tag of $desc.
9335#
9336proc is_certain {desc anc} {
9337 global arcnos arcout arcstart arcend growing problems
9338
9339 set certain {}
9340 if {[llength $arcnos($anc)] == 1} {
9341 # tags on the same arc are certain
9342 if {$arcnos($desc) eq $arcnos($anc)} {
9343 return 1
9344 }
9345 if {![info exists arcout($anc)]} {
9346 # if $anc is partway along an arc, use the start of the arc instead
9347 set a [lindex $arcnos($anc) 0]
9348 set anc $arcstart($a)
9349 }
9350 }
9351 if {[llength $arcnos($desc)] > 1 || [info exists arcout($desc)]} {
9352 set x $desc
9353 } else {
9354 set a [lindex $arcnos($desc) 0]
9355 set x $arcend($a)
9356 }
9357 if {$x == $anc} {
9358 return 1
9359 }
9360 set anclist [list $x]
9361 set dl($x) 1
9362 set nnh 1
9363 set ngrowanc 0
9364 for {set i 0} {$i < [llength $anclist] && ($nnh > 0 || $ngrowanc > 0)} {incr i} {
9365 set x [lindex $anclist $i]
9366 if {$dl($x)} {
9367 incr nnh -1
9368 }
9369 set done($x) 1
9370 foreach a $arcout($x) {
9371 if {[info exists growing($a)]} {
9372 if {![info exists growanc($x)] && $dl($x)} {
9373 set growanc($x) 1
9374 incr ngrowanc
9375 }
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10009376 } else {
Paul Mackerrase11f1232007-06-16 20:29:25 +10009377 set y $arcend($a)
9378 if {[info exists dl($y)]} {
9379 if {$dl($y)} {
9380 if {!$dl($x)} {
9381 set dl($y) 0
9382 if {![info exists done($y)]} {
9383 incr nnh -1
9384 }
9385 if {[info exists growanc($x)]} {
9386 incr ngrowanc -1
9387 }
9388 set xl [list $y]
9389 for {set k 0} {$k < [llength $xl]} {incr k} {
9390 set z [lindex $xl $k]
9391 foreach c $arcout($z) {
9392 if {[info exists arcend($c)]} {
9393 set v $arcend($c)
9394 if {[info exists dl($v)] && $dl($v)} {
9395 set dl($v) 0
9396 if {![info exists done($v)]} {
9397 incr nnh -1
9398 }
9399 if {[info exists growanc($v)]} {
9400 incr ngrowanc -1
9401 }
9402 lappend xl $v
9403 }
9404 }
9405 }
9406 }
9407 }
9408 }
9409 } elseif {$y eq $anc || !$dl($x)} {
9410 set dl($y) 0
9411 lappend anclist $y
9412 } else {
9413 set dl($y) 1
9414 lappend anclist $y
9415 incr nnh
9416 }
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10009417 }
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10009418 }
9419 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10009420 foreach x [array names growanc] {
9421 if {$dl($x)} {
9422 return 0
9423 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10009424 return 0
Paul Mackerrase11f1232007-06-16 20:29:25 +10009425 }
9426 return 1
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10009427}
9428
Paul Mackerrase11f1232007-06-16 20:29:25 +10009429proc validate_arctags {a} {
9430 global arctags idtags
9431
9432 set i -1
9433 set na $arctags($a)
9434 foreach id $arctags($a) {
9435 incr i
9436 if {![info exists idtags($id)]} {
9437 set na [lreplace $na $i $i]
9438 incr i -1
9439 }
9440 }
9441 set arctags($a) $na
9442}
9443
9444proc validate_archeads {a} {
9445 global archeads idheads
9446
9447 set i -1
9448 set na $archeads($a)
9449 foreach id $archeads($a) {
9450 incr i
9451 if {![info exists idheads($id)]} {
9452 set na [lreplace $na $i $i]
9453 incr i -1
9454 }
9455 }
9456 set archeads($a) $na
9457}
9458
9459# Return the list of IDs that have tags that are descendents of id,
9460# ignoring IDs that are descendents of IDs already reported.
9461proc desctags {id} {
9462 global arcnos arcstart arcids arctags idtags allparents
9463 global growing cached_dtags
9464
9465 if {![info exists allparents($id)]} {
9466 return {}
9467 }
9468 set t1 [clock clicks -milliseconds]
9469 set argid $id
9470 if {[llength $arcnos($id)] == 1 && [llength $allparents($id)] == 1} {
9471 # part-way along an arc; check that arc first
9472 set a [lindex $arcnos($id) 0]
9473 if {$arctags($a) ne {}} {
9474 validate_arctags $a
9475 set i [lsearch -exact $arcids($a) $id]
9476 set tid {}
9477 foreach t $arctags($a) {
9478 set j [lsearch -exact $arcids($a) $t]
9479 if {$j >= $i} break
9480 set tid $t
9481 }
9482 if {$tid ne {}} {
9483 return $tid
9484 }
9485 }
9486 set id $arcstart($a)
9487 if {[info exists idtags($id)]} {
9488 return $id
9489 }
9490 }
9491 if {[info exists cached_dtags($id)]} {
9492 return $cached_dtags($id)
9493 }
9494
9495 set origid $id
9496 set todo [list $id]
9497 set queued($id) 1
9498 set nc 1
9499 for {set i 0} {$i < [llength $todo] && $nc > 0} {incr i} {
9500 set id [lindex $todo $i]
9501 set done($id) 1
9502 set ta [info exists hastaggedancestor($id)]
9503 if {!$ta} {
9504 incr nc -1
9505 }
9506 # ignore tags on starting node
9507 if {!$ta && $i > 0} {
9508 if {[info exists idtags($id)]} {
9509 set tagloc($id) $id
9510 set ta 1
9511 } elseif {[info exists cached_dtags($id)]} {
9512 set tagloc($id) $cached_dtags($id)
9513 set ta 1
9514 }
9515 }
9516 foreach a $arcnos($id) {
9517 set d $arcstart($a)
9518 if {!$ta && $arctags($a) ne {}} {
9519 validate_arctags $a
9520 if {$arctags($a) ne {}} {
9521 lappend tagloc($id) [lindex $arctags($a) end]
9522 }
9523 }
9524 if {$ta || $arctags($a) ne {}} {
9525 set tomark [list $d]
9526 for {set j 0} {$j < [llength $tomark]} {incr j} {
9527 set dd [lindex $tomark $j]
9528 if {![info exists hastaggedancestor($dd)]} {
9529 if {[info exists done($dd)]} {
9530 foreach b $arcnos($dd) {
9531 lappend tomark $arcstart($b)
9532 }
9533 if {[info exists tagloc($dd)]} {
9534 unset tagloc($dd)
9535 }
9536 } elseif {[info exists queued($dd)]} {
9537 incr nc -1
9538 }
9539 set hastaggedancestor($dd) 1
9540 }
9541 }
9542 }
9543 if {![info exists queued($d)]} {
9544 lappend todo $d
9545 set queued($d) 1
9546 if {![info exists hastaggedancestor($d)]} {
9547 incr nc
9548 }
9549 }
9550 }
9551 }
9552 set tags {}
9553 foreach id [array names tagloc] {
9554 if {![info exists hastaggedancestor($id)]} {
9555 foreach t $tagloc($id) {
9556 if {[lsearch -exact $tags $t] < 0} {
9557 lappend tags $t
9558 }
9559 }
9560 }
9561 }
9562 set t2 [clock clicks -milliseconds]
9563 set loopix $i
9564
9565 # remove tags that are descendents of other tags
9566 for {set i 0} {$i < [llength $tags]} {incr i} {
9567 set a [lindex $tags $i]
9568 for {set j 0} {$j < $i} {incr j} {
9569 set b [lindex $tags $j]
9570 set r [anc_or_desc $a $b]
9571 if {$r == 1} {
9572 set tags [lreplace $tags $j $j]
9573 incr j -1
9574 incr i -1
9575 } elseif {$r == -1} {
9576 set tags [lreplace $tags $i $i]
9577 incr i -1
9578 break
9579 }
9580 }
9581 }
9582
9583 if {[array names growing] ne {}} {
9584 # graph isn't finished, need to check if any tag could get
9585 # eclipsed by another tag coming later. Simply ignore any
9586 # tags that could later get eclipsed.
9587 set ctags {}
9588 foreach t $tags {
9589 if {[is_certain $t $origid]} {
9590 lappend ctags $t
9591 }
9592 }
9593 if {$tags eq $ctags} {
9594 set cached_dtags($origid) $tags
9595 } else {
9596 set tags $ctags
9597 }
9598 } else {
9599 set cached_dtags($origid) $tags
9600 }
9601 set t3 [clock clicks -milliseconds]
9602 if {0 && $t3 - $t1 >= 100} {
9603 puts "iterating descendents ($loopix/[llength $todo] nodes) took\
9604 [expr {$t2-$t1}]+[expr {$t3-$t2}]ms, $nc candidates left"
9605 }
9606 return $tags
9607}
9608
9609proc anctags {id} {
9610 global arcnos arcids arcout arcend arctags idtags allparents
9611 global growing cached_atags
9612
9613 if {![info exists allparents($id)]} {
9614 return {}
9615 }
9616 set t1 [clock clicks -milliseconds]
9617 set argid $id
9618 if {[llength $arcnos($id)] == 1 && [llength $allparents($id)] == 1} {
9619 # part-way along an arc; check that arc first
9620 set a [lindex $arcnos($id) 0]
9621 if {$arctags($a) ne {}} {
9622 validate_arctags $a
9623 set i [lsearch -exact $arcids($a) $id]
9624 foreach t $arctags($a) {
9625 set j [lsearch -exact $arcids($a) $t]
9626 if {$j > $i} {
9627 return $t
9628 }
9629 }
9630 }
9631 if {![info exists arcend($a)]} {
9632 return {}
9633 }
9634 set id $arcend($a)
9635 if {[info exists idtags($id)]} {
9636 return $id
9637 }
9638 }
9639 if {[info exists cached_atags($id)]} {
9640 return $cached_atags($id)
9641 }
9642
9643 set origid $id
9644 set todo [list $id]
9645 set queued($id) 1
9646 set taglist {}
9647 set nc 1
9648 for {set i 0} {$i < [llength $todo] && $nc > 0} {incr i} {
9649 set id [lindex $todo $i]
9650 set done($id) 1
9651 set td [info exists hastaggeddescendent($id)]
9652 if {!$td} {
9653 incr nc -1
9654 }
9655 # ignore tags on starting node
9656 if {!$td && $i > 0} {
9657 if {[info exists idtags($id)]} {
9658 set tagloc($id) $id
9659 set td 1
9660 } elseif {[info exists cached_atags($id)]} {
9661 set tagloc($id) $cached_atags($id)
9662 set td 1
9663 }
9664 }
9665 foreach a $arcout($id) {
9666 if {!$td && $arctags($a) ne {}} {
9667 validate_arctags $a
9668 if {$arctags($a) ne {}} {
9669 lappend tagloc($id) [lindex $arctags($a) 0]
9670 }
9671 }
9672 if {![info exists arcend($a)]} continue
9673 set d $arcend($a)
9674 if {$td || $arctags($a) ne {}} {
9675 set tomark [list $d]
9676 for {set j 0} {$j < [llength $tomark]} {incr j} {
9677 set dd [lindex $tomark $j]
9678 if {![info exists hastaggeddescendent($dd)]} {
9679 if {[info exists done($dd)]} {
9680 foreach b $arcout($dd) {
9681 if {[info exists arcend($b)]} {
9682 lappend tomark $arcend($b)
9683 }
9684 }
9685 if {[info exists tagloc($dd)]} {
9686 unset tagloc($dd)
9687 }
9688 } elseif {[info exists queued($dd)]} {
9689 incr nc -1
9690 }
9691 set hastaggeddescendent($dd) 1
9692 }
9693 }
9694 }
9695 if {![info exists queued($d)]} {
9696 lappend todo $d
9697 set queued($d) 1
9698 if {![info exists hastaggeddescendent($d)]} {
9699 incr nc
9700 }
9701 }
9702 }
9703 }
9704 set t2 [clock clicks -milliseconds]
9705 set loopix $i
9706 set tags {}
9707 foreach id [array names tagloc] {
9708 if {![info exists hastaggeddescendent($id)]} {
9709 foreach t $tagloc($id) {
9710 if {[lsearch -exact $tags $t] < 0} {
9711 lappend tags $t
9712 }
9713 }
9714 }
9715 }
9716
9717 # remove tags that are ancestors of other tags
9718 for {set i 0} {$i < [llength $tags]} {incr i} {
9719 set a [lindex $tags $i]
9720 for {set j 0} {$j < $i} {incr j} {
9721 set b [lindex $tags $j]
9722 set r [anc_or_desc $a $b]
9723 if {$r == -1} {
9724 set tags [lreplace $tags $j $j]
9725 incr j -1
9726 incr i -1
9727 } elseif {$r == 1} {
9728 set tags [lreplace $tags $i $i]
9729 incr i -1
9730 break
9731 }
9732 }
9733 }
9734
9735 if {[array names growing] ne {}} {
9736 # graph isn't finished, need to check if any tag could get
9737 # eclipsed by another tag coming later. Simply ignore any
9738 # tags that could later get eclipsed.
9739 set ctags {}
9740 foreach t $tags {
9741 if {[is_certain $origid $t]} {
9742 lappend ctags $t
9743 }
9744 }
9745 if {$tags eq $ctags} {
9746 set cached_atags($origid) $tags
9747 } else {
9748 set tags $ctags
9749 }
9750 } else {
9751 set cached_atags($origid) $tags
9752 }
9753 set t3 [clock clicks -milliseconds]
9754 if {0 && $t3 - $t1 >= 100} {
9755 puts "iterating ancestors ($loopix/[llength $todo] nodes) took\
9756 [expr {$t2-$t1}]+[expr {$t3-$t2}]ms, $nc candidates left"
9757 }
9758 return $tags
9759}
9760
9761# Return the list of IDs that have heads that are descendents of id,
9762# including id itself if it has a head.
9763proc descheads {id} {
9764 global arcnos arcstart arcids archeads idheads cached_dheads
9765 global allparents
9766
9767 if {![info exists allparents($id)]} {
9768 return {}
9769 }
Paul Mackerrasf3326b62007-06-18 22:39:21 +10009770 set aret {}
Paul Mackerrase11f1232007-06-16 20:29:25 +10009771 if {[llength $arcnos($id)] == 1 && [llength $allparents($id)] == 1} {
9772 # part-way along an arc; check it first
9773 set a [lindex $arcnos($id) 0]
9774 if {$archeads($a) ne {}} {
9775 validate_archeads $a
9776 set i [lsearch -exact $arcids($a) $id]
9777 foreach t $archeads($a) {
9778 set j [lsearch -exact $arcids($a) $t]
9779 if {$j > $i} break
Paul Mackerrasf3326b62007-06-18 22:39:21 +10009780 lappend aret $t
Paul Mackerrase11f1232007-06-16 20:29:25 +10009781 }
9782 }
9783 set id $arcstart($a)
9784 }
9785 set origid $id
9786 set todo [list $id]
9787 set seen($id) 1
Paul Mackerrasf3326b62007-06-18 22:39:21 +10009788 set ret {}
Paul Mackerrase11f1232007-06-16 20:29:25 +10009789 for {set i 0} {$i < [llength $todo]} {incr i} {
9790 set id [lindex $todo $i]
9791 if {[info exists cached_dheads($id)]} {
9792 set ret [concat $ret $cached_dheads($id)]
9793 } else {
9794 if {[info exists idheads($id)]} {
9795 lappend ret $id
9796 }
9797 foreach a $arcnos($id) {
9798 if {$archeads($a) ne {}} {
Paul Mackerras706d6c32007-06-26 11:09:49 +10009799 validate_archeads $a
9800 if {$archeads($a) ne {}} {
9801 set ret [concat $ret $archeads($a)]
9802 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10009803 }
9804 set d $arcstart($a)
9805 if {![info exists seen($d)]} {
9806 lappend todo $d
9807 set seen($d) 1
9808 }
9809 }
9810 }
9811 }
9812 set ret [lsort -unique $ret]
9813 set cached_dheads($origid) $ret
Paul Mackerrasf3326b62007-06-18 22:39:21 +10009814 return [concat $ret $aret]
Paul Mackerrase11f1232007-06-16 20:29:25 +10009815}
9816
Paul Mackerrasceadfe92006-08-08 20:55:36 +10009817proc addedtag {id} {
Paul Mackerrase11f1232007-06-16 20:29:25 +10009818 global arcnos arcout cached_dtags cached_atags
Paul Mackerrasceadfe92006-08-08 20:55:36 +10009819
Paul Mackerrase11f1232007-06-16 20:29:25 +10009820 if {![info exists arcnos($id)]} return
9821 if {![info exists arcout($id)]} {
9822 recalcarc [lindex $arcnos($id) 0]
Paul Mackerrasceadfe92006-08-08 20:55:36 +10009823 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10009824 catch {unset cached_dtags}
9825 catch {unset cached_atags}
Paul Mackerrasceadfe92006-08-08 20:55:36 +10009826}
9827
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10009828proc addedhead {hid head} {
Paul Mackerrase11f1232007-06-16 20:29:25 +10009829 global arcnos arcout cached_dheads
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10009830
Paul Mackerrase11f1232007-06-16 20:29:25 +10009831 if {![info exists arcnos($hid)]} return
9832 if {![info exists arcout($hid)]} {
9833 recalcarc [lindex $arcnos($hid) 0]
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10009834 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10009835 catch {unset cached_dheads}
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10009836}
9837
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10009838proc removedhead {hid head} {
Paul Mackerrase11f1232007-06-16 20:29:25 +10009839 global cached_dheads
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10009840
Paul Mackerrase11f1232007-06-16 20:29:25 +10009841 catch {unset cached_dheads}
Paul Mackerras10299152006-08-02 09:52:01 +10009842}
9843
Paul Mackerrase11f1232007-06-16 20:29:25 +10009844proc movedhead {hid head} {
9845 global arcnos arcout cached_dheads
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10009846
Paul Mackerrase11f1232007-06-16 20:29:25 +10009847 if {![info exists arcnos($hid)]} return
9848 if {![info exists arcout($hid)]} {
9849 recalcarc [lindex $arcnos($hid) 0]
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10009850 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10009851 catch {unset cached_dheads}
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10009852}
9853
Paul Mackerrascec7bec2006-08-02 09:38:10 +10009854proc changedrefs {} {
Paul Mackerrase11f1232007-06-16 20:29:25 +10009855 global cached_dheads cached_dtags cached_atags
9856 global arctags archeads arcnos arcout idheads idtags
Paul Mackerrascec7bec2006-08-02 09:38:10 +10009857
Paul Mackerrase11f1232007-06-16 20:29:25 +10009858 foreach id [concat [array names idheads] [array names idtags]] {
9859 if {[info exists arcnos($id)] && ![info exists arcout($id)]} {
9860 set a [lindex $arcnos($id) 0]
9861 if {![info exists donearc($a)]} {
9862 recalcarc $a
9863 set donearc($a) 1
9864 }
Paul Mackerrascec7bec2006-08-02 09:38:10 +10009865 }
9866 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10009867 catch {unset cached_dtags}
9868 catch {unset cached_atags}
9869 catch {unset cached_dheads}
Paul Mackerrascec7bec2006-08-02 09:38:10 +10009870}
9871
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10009872proc rereadrefs {} {
Paul Mackerrasfc2a2562007-12-26 23:03:43 +11009873 global idtags idheads idotherrefs mainheadid
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10009874
9875 set refids [concat [array names idtags] \
9876 [array names idheads] [array names idotherrefs]]
9877 foreach id $refids {
9878 if {![info exists ref($id)]} {
9879 set ref($id) [listrefs $id]
9880 }
9881 }
Paul Mackerrasfc2a2562007-12-26 23:03:43 +11009882 set oldmainhead $mainheadid
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10009883 readrefs
Paul Mackerrascec7bec2006-08-02 09:38:10 +10009884 changedrefs
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10009885 set refids [lsort -unique [concat $refids [array names idtags] \
9886 [array names idheads] [array names idotherrefs]]]
9887 foreach id $refids {
9888 set v [listrefs $id]
Paul Mackerrasc11ff122008-05-26 10:11:33 +10009889 if {![info exists ref($id)] || $ref($id) != $v} {
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10009890 redrawtags $id
9891 }
9892 }
Paul Mackerrasc11ff122008-05-26 10:11:33 +10009893 if {$oldmainhead ne $mainheadid} {
9894 redrawtags $oldmainhead
9895 redrawtags $mainheadid
9896 }
Paul Mackerras887c9962007-08-20 19:36:20 +10009897 run refill_reflist
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10009898}
9899
Junio C Hamano2e1ded42006-06-11 09:50:47 -07009900proc listrefs {id} {
9901 global idtags idheads idotherrefs
9902
9903 set x {}
9904 if {[info exists idtags($id)]} {
9905 set x $idtags($id)
9906 }
9907 set y {}
9908 if {[info exists idheads($id)]} {
9909 set y $idheads($id)
9910 }
9911 set z {}
9912 if {[info exists idotherrefs($id)]} {
9913 set z $idotherrefs($id)
9914 }
9915 return [list $x $y $z]
9916}
9917
Paul Mackerras106288c2005-08-19 23:11:39 +10009918proc showtag {tag isnew} {
Paul Mackerras62d3ea62006-09-11 10:36:53 +10009919 global ctext tagcontents tagids linknum tagobjid
Paul Mackerras106288c2005-08-19 23:11:39 +10009920
9921 if {$isnew} {
9922 addtohistory [list showtag $tag 0]
9923 }
9924 $ctext conf -state normal
Paul Mackerras3ea06f92006-05-24 10:16:03 +10009925 clear_ctext
Paul Mackerras32f1b3e2007-09-28 21:27:39 +10009926 settabs 0
Paul Mackerras106288c2005-08-19 23:11:39 +10009927 set linknum 0
Paul Mackerras62d3ea62006-09-11 10:36:53 +10009928 if {![info exists tagcontents($tag)]} {
9929 catch {
9930 set tagcontents($tag) [exec git cat-file tag $tagobjid($tag)]
9931 }
9932 }
Paul Mackerras106288c2005-08-19 23:11:39 +10009933 if {[info exists tagcontents($tag)]} {
9934 set text $tagcontents($tag)
9935 } else {
Christian Stimmingd990ced2007-11-07 18:42:55 +01009936 set text "[mc "Tag"]: $tag\n[mc "Id"]: $tagids($tag)"
Paul Mackerras106288c2005-08-19 23:11:39 +10009937 }
Sergey Vlasovf1b86292006-05-15 19:13:14 +04009938 appendwithlinks $text {}
Paul Mackerras106288c2005-08-19 23:11:39 +10009939 $ctext conf -state disabled
Paul Mackerras7fcceed2006-04-27 19:21:49 +10009940 init_flist {}
Paul Mackerras106288c2005-08-19 23:11:39 +10009941}
9942
Paul Mackerras1d10f362005-05-15 12:55:47 +00009943proc doquit {} {
9944 global stopped
Thomas Arcila314f5de2008-03-24 12:55:36 +01009945 global gitktmpdir
9946
Paul Mackerras1d10f362005-05-15 12:55:47 +00009947 set stopped 100
Mark Levedahlb6047c52007-02-08 22:22:24 -05009948 savestuff .
Paul Mackerras1d10f362005-05-15 12:55:47 +00009949 destroy .
Thomas Arcila314f5de2008-03-24 12:55:36 +01009950
9951 if {[info exists gitktmpdir]} {
9952 catch {file delete -force $gitktmpdir}
9953 }
Paul Mackerras1d10f362005-05-15 12:55:47 +00009954}
9955
Paul Mackerras9a7558f2007-10-06 20:16:06 +10009956proc mkfontdisp {font top which} {
9957 global fontattr fontpref $font
9958
9959 set fontpref($font) [set $font]
9960 button $top.${font}but -text $which -font optionfont \
9961 -command [list choosefont $font $which]
9962 label $top.$font -relief flat -font $font \
9963 -text $fontattr($font,family) -justify left
9964 grid x $top.${font}but $top.$font -sticky w
9965}
9966
9967proc choosefont {font which} {
9968 global fontparam fontlist fonttop fontattr
Alexander Gavrilov84a76f12008-11-02 21:59:45 +03009969 global prefstop
Paul Mackerras9a7558f2007-10-06 20:16:06 +10009970
9971 set fontparam(which) $which
9972 set fontparam(font) $font
9973 set fontparam(family) [font actual $font -family]
9974 set fontparam(size) $fontattr($font,size)
9975 set fontparam(weight) $fontattr($font,weight)
9976 set fontparam(slant) $fontattr($font,slant)
9977 set top .gitkfont
9978 set fonttop $top
9979 if {![winfo exists $top]} {
9980 font create sample
9981 eval font config sample [font actual $font]
9982 toplevel $top
Alexander Gavrilove7d64002008-11-11 23:55:42 +03009983 make_transient $top $prefstop
Christian Stimmingd990ced2007-11-07 18:42:55 +01009984 wm title $top [mc "Gitk font chooser"]
Paul Mackerrasb039f0a2008-01-06 15:54:46 +11009985 label $top.l -textvariable fontparam(which)
Paul Mackerras9a7558f2007-10-06 20:16:06 +10009986 pack $top.l -side top
9987 set fontlist [lsort [font families]]
9988 frame $top.f
9989 listbox $top.f.fam -listvariable fontlist \
9990 -yscrollcommand [list $top.f.sb set]
9991 bind $top.f.fam <<ListboxSelect>> selfontfam
9992 scrollbar $top.f.sb -command [list $top.f.fam yview]
9993 pack $top.f.sb -side right -fill y
9994 pack $top.f.fam -side left -fill both -expand 1
9995 pack $top.f -side top -fill both -expand 1
9996 frame $top.g
9997 spinbox $top.g.size -from 4 -to 40 -width 4 \
9998 -textvariable fontparam(size) \
9999 -validatecommand {string is integer -strict %s}
10000 checkbutton $top.g.bold -padx 5 \
Christian Stimmingd990ced2007-11-07 18:42:55 +010010001 -font {{Times New Roman} 12 bold} -text [mc "B"] -indicatoron 0 \
Paul Mackerras9a7558f2007-10-06 20:16:06 +100010002 -variable fontparam(weight) -onvalue bold -offvalue normal
10003 checkbutton $top.g.ital -padx 5 \
Christian Stimmingd990ced2007-11-07 18:42:55 +010010004 -font {{Times New Roman} 12 italic} -text [mc "I"] -indicatoron 0 \
Paul Mackerras9a7558f2007-10-06 20:16:06 +100010005 -variable fontparam(slant) -onvalue italic -offvalue roman
10006 pack $top.g.size $top.g.bold $top.g.ital -side left
10007 pack $top.g -side top
10008 canvas $top.c -width 150 -height 50 -border 2 -relief sunk \
10009 -background white
10010 $top.c create text 100 25 -anchor center -text $which -font sample \
10011 -fill black -tags text
10012 bind $top.c <Configure> [list centertext $top.c]
10013 pack $top.c -side top -fill x
10014 frame $top.buts
Paul Mackerrasb039f0a2008-01-06 15:54:46 +110010015 button $top.buts.ok -text [mc "OK"] -command fontok -default active
10016 button $top.buts.can -text [mc "Cancel"] -command fontcan -default normal
Alexander Gavrilov76f15942008-11-02 21:59:44 +030010017 bind $top <Key-Return> fontok
10018 bind $top <Key-Escape> fontcan
Paul Mackerras9a7558f2007-10-06 20:16:06 +100010019 grid $top.buts.ok $top.buts.can
10020 grid columnconfigure $top.buts 0 -weight 1 -uniform a
10021 grid columnconfigure $top.buts 1 -weight 1 -uniform a
10022 pack $top.buts -side bottom -fill x
10023 trace add variable fontparam write chg_fontparam
10024 } else {
10025 raise $top
10026 $top.c itemconf text -text $which
10027 }
10028 set i [lsearch -exact $fontlist $fontparam(family)]
10029 if {$i >= 0} {
10030 $top.f.fam selection set $i
10031 $top.f.fam see $i
10032 }
10033}
10034
10035proc centertext {w} {
10036 $w coords text [expr {[winfo width $w] / 2}] [expr {[winfo height $w] / 2}]
10037}
10038
10039proc fontok {} {
10040 global fontparam fontpref prefstop
10041
10042 set f $fontparam(font)
10043 set fontpref($f) [list $fontparam(family) $fontparam(size)]
10044 if {$fontparam(weight) eq "bold"} {
10045 lappend fontpref($f) "bold"
10046 }
10047 if {$fontparam(slant) eq "italic"} {
10048 lappend fontpref($f) "italic"
10049 }
10050 set w $prefstop.$f
10051 $w conf -text $fontparam(family) -font $fontpref($f)
10052
10053 fontcan
10054}
10055
10056proc fontcan {} {
10057 global fonttop fontparam
10058
10059 if {[info exists fonttop]} {
10060 catch {destroy $fonttop}
10061 catch {font delete sample}
10062 unset fonttop
10063 unset fontparam
10064 }
10065}
10066
10067proc selfontfam {} {
10068 global fonttop fontparam
10069
10070 set i [$fonttop.f.fam curselection]
10071 if {$i ne {}} {
10072 set fontparam(family) [$fonttop.f.fam get $i]
10073 }
10074}
10075
10076proc chg_fontparam {v sub op} {
10077 global fontparam
10078
10079 font config sample -$sub $fontparam($sub)
10080}
10081
Paul Mackerras712fcc02005-11-30 09:28:16 +110010082proc doprefs {} {
Paul Mackerras8d73b242007-10-06 20:22:00 +100010083 global maxwidth maxgraphpct
Paul Mackerras219ea3a2006-09-07 10:21:39 +100010084 global oldprefs prefstop showneartags showlocalchanges
Paul Mackerrase3e901b2008-10-27 22:37:21 +110010085 global bgcolor fgcolor ctext diffcolors selectbgcolor markbgcolor
Paul Mackerras39ee47e2008-10-15 22:23:03 +110010086 global tabstop limitdiffs autoselect extdifftool perfile_attrs
Paul Mackerras232475d2005-11-15 10:34:03 +110010087
Paul Mackerras712fcc02005-11-30 09:28:16 +110010088 set top .gitkprefs
10089 set prefstop $top
10090 if {[winfo exists $top]} {
10091 raise $top
10092 return
Paul Mackerras757f17b2005-11-21 09:56:07 +110010093 }
Paul Mackerras3de07112007-10-23 22:40:50 +100010094 foreach v {maxwidth maxgraphpct showneartags showlocalchanges \
Paul Mackerras39ee47e2008-10-15 22:23:03 +110010095 limitdiffs tabstop perfile_attrs} {
Paul Mackerras712fcc02005-11-30 09:28:16 +110010096 set oldprefs($v) [set $v]
Paul Mackerras232475d2005-11-15 10:34:03 +110010097 }
Paul Mackerras712fcc02005-11-30 09:28:16 +110010098 toplevel $top
Christian Stimmingd990ced2007-11-07 18:42:55 +010010099 wm title $top [mc "Gitk preferences"]
Alexander Gavrilove7d64002008-11-11 23:55:42 +030010100 make_transient $top .
Christian Stimmingd990ced2007-11-07 18:42:55 +010010101 label $top.ldisp -text [mc "Commit list display options"]
Paul Mackerras712fcc02005-11-30 09:28:16 +110010102 grid $top.ldisp - -sticky w -pady 10
10103 label $top.spacer -text " "
Christian Stimmingd990ced2007-11-07 18:42:55 +010010104 label $top.maxwidthl -text [mc "Maximum graph width (lines)"] \
Paul Mackerras712fcc02005-11-30 09:28:16 +110010105 -font optionfont
10106 spinbox $top.maxwidth -from 0 -to 100 -width 4 -textvariable maxwidth
10107 grid $top.spacer $top.maxwidthl $top.maxwidth -sticky w
Christian Stimmingd990ced2007-11-07 18:42:55 +010010108 label $top.maxpctl -text [mc "Maximum graph width (% of pane)"] \
Paul Mackerras712fcc02005-11-30 09:28:16 +110010109 -font optionfont
10110 spinbox $top.maxpct -from 1 -to 100 -width 4 -textvariable maxgraphpct
10111 grid x $top.maxpctl $top.maxpct -sticky w
Johannes Sixtadcbec12008-12-02 21:42:16 +010010112 checkbutton $top.showlocal -text [mc "Show local changes"] \
10113 -font optionfont -variable showlocalchanges
Paul Mackerras219ea3a2006-09-07 10:21:39 +100010114 grid x $top.showlocal -sticky w
Johannes Sixtadcbec12008-12-02 21:42:16 +010010115 checkbutton $top.autoselect -text [mc "Auto-select SHA1"] \
10116 -font optionfont -variable autoselect
Jeff King95293b52008-03-06 06:49:25 -050010117 grid x $top.autoselect -sticky w
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +100010118
Christian Stimmingd990ced2007-11-07 18:42:55 +010010119 label $top.ddisp -text [mc "Diff display options"]
Paul Mackerras712fcc02005-11-30 09:28:16 +110010120 grid $top.ddisp - -sticky w -pady 10
Christian Stimmingd990ced2007-11-07 18:42:55 +010010121 label $top.tabstopl -text [mc "Tab spacing"] -font optionfont
Paul Mackerras94503912007-10-23 10:33:38 +100010122 spinbox $top.tabstop -from 1 -to 20 -width 4 -textvariable tabstop
10123 grid x $top.tabstopl $top.tabstop -sticky w
Johannes Sixtadcbec12008-12-02 21:42:16 +010010124 checkbutton $top.ntag -text [mc "Display nearby tags"] \
10125 -font optionfont -variable showneartags
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +100010126 grid x $top.ntag -sticky w
Johannes Sixtadcbec12008-12-02 21:42:16 +010010127 checkbutton $top.ldiff -text [mc "Limit diffs to listed paths"] \
10128 -font optionfont -variable limitdiffs
Paul Mackerras7a39a172007-10-23 10:15:11 +100010129 grid x $top.ldiff -sticky w
Johannes Sixtadcbec12008-12-02 21:42:16 +010010130 checkbutton $top.lattr -text [mc "Support per-file encodings"] \
10131 -font optionfont -variable perfile_attrs
Paul Mackerras39ee47e2008-10-15 22:23:03 +110010132 grid x $top.lattr -sticky w
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +100010133
Thomas Arcila314f5de2008-03-24 12:55:36 +010010134 entry $top.extdifft -textvariable extdifftool
10135 frame $top.extdifff
10136 label $top.extdifff.l -text [mc "External diff tool" ] -font optionfont \
10137 -padx 10
10138 button $top.extdifff.b -text [mc "Choose..."] -font optionfont \
10139 -command choose_extdiff
10140 pack $top.extdifff.l $top.extdifff.b -side left
10141 grid x $top.extdifff $top.extdifft -sticky w
10142
Christian Stimmingd990ced2007-11-07 18:42:55 +010010143 label $top.cdisp -text [mc "Colors: press to choose"]
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +100010144 grid $top.cdisp - -sticky w -pady 10
10145 label $top.bg -padx 40 -relief sunk -background $bgcolor
Christian Stimmingd990ced2007-11-07 18:42:55 +010010146 button $top.bgbut -text [mc "Background"] -font optionfont \
Christian Stimming968b0162008-12-06 20:48:30 +010010147 -command [list choosecolor bgcolor {} $top.bg [mc "background"] setbg]
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +100010148 grid x $top.bgbut $top.bg -sticky w
10149 label $top.fg -padx 40 -relief sunk -background $fgcolor
Christian Stimmingd990ced2007-11-07 18:42:55 +010010150 button $top.fgbut -text [mc "Foreground"] -font optionfont \
Christian Stimming968b0162008-12-06 20:48:30 +010010151 -command [list choosecolor fgcolor {} $top.fg [mc "foreground"] setfg]
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +100010152 grid x $top.fgbut $top.fg -sticky w
10153 label $top.diffold -padx 40 -relief sunk -background [lindex $diffcolors 0]
Christian Stimmingd990ced2007-11-07 18:42:55 +010010154 button $top.diffoldbut -text [mc "Diff: old lines"] -font optionfont \
Christian Stimming968b0162008-12-06 20:48:30 +010010155 -command [list choosecolor diffcolors 0 $top.diffold [mc "diff old lines"] \
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +100010156 [list $ctext tag conf d0 -foreground]]
10157 grid x $top.diffoldbut $top.diffold -sticky w
10158 label $top.diffnew -padx 40 -relief sunk -background [lindex $diffcolors 1]
Christian Stimmingd990ced2007-11-07 18:42:55 +010010159 button $top.diffnewbut -text [mc "Diff: new lines"] -font optionfont \
Christian Stimming968b0162008-12-06 20:48:30 +010010160 -command [list choosecolor diffcolors 1 $top.diffnew [mc "diff new lines"] \
Paul Mackerras8b07dca2008-11-02 22:34:47 +110010161 [list $ctext tag conf dresult -foreground]]
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +100010162 grid x $top.diffnewbut $top.diffnew -sticky w
10163 label $top.hunksep -padx 40 -relief sunk -background [lindex $diffcolors 2]
Christian Stimmingd990ced2007-11-07 18:42:55 +010010164 button $top.hunksepbut -text [mc "Diff: hunk header"] -font optionfont \
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +100010165 -command [list choosecolor diffcolors 2 $top.hunksep \
Christian Stimming968b0162008-12-06 20:48:30 +010010166 [mc "diff hunk header"] \
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +100010167 [list $ctext tag conf hunksep -foreground]]
10168 grid x $top.hunksepbut $top.hunksep -sticky w
Paul Mackerrase3e901b2008-10-27 22:37:21 +110010169 label $top.markbgsep -padx 40 -relief sunk -background $markbgcolor
10170 button $top.markbgbut -text [mc "Marked line bg"] -font optionfont \
10171 -command [list choosecolor markbgcolor {} $top.markbgsep \
10172 [mc "marked line background"] \
10173 [list $ctext tag conf omark -background]]
10174 grid x $top.markbgbut $top.markbgsep -sticky w
Mark Levedahl60378c02007-05-20 12:12:48 -040010175 label $top.selbgsep -padx 40 -relief sunk -background $selectbgcolor
Christian Stimmingd990ced2007-11-07 18:42:55 +010010176 button $top.selbgbut -text [mc "Select bg"] -font optionfont \
Christian Stimming968b0162008-12-06 20:48:30 +010010177 -command [list choosecolor selectbgcolor {} $top.selbgsep [mc "background"] setselbg]
Mark Levedahl60378c02007-05-20 12:12:48 -040010178 grid x $top.selbgbut $top.selbgsep -sticky w
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +100010179
Christian Stimmingd990ced2007-11-07 18:42:55 +010010180 label $top.cfont -text [mc "Fonts: press to choose"]
Paul Mackerras9a7558f2007-10-06 20:16:06 +100010181 grid $top.cfont - -sticky w -pady 10
Christian Stimmingd990ced2007-11-07 18:42:55 +010010182 mkfontdisp mainfont $top [mc "Main font"]
10183 mkfontdisp textfont $top [mc "Diff display font"]
10184 mkfontdisp uifont $top [mc "User interface font"]
Paul Mackerras9a7558f2007-10-06 20:16:06 +100010185
Paul Mackerras712fcc02005-11-30 09:28:16 +110010186 frame $top.buts
Christian Stimmingd990ced2007-11-07 18:42:55 +010010187 button $top.buts.ok -text [mc "OK"] -command prefsok -default active
Christian Stimmingd990ced2007-11-07 18:42:55 +010010188 button $top.buts.can -text [mc "Cancel"] -command prefscan -default normal
Alexander Gavrilov76f15942008-11-02 21:59:44 +030010189 bind $top <Key-Return> prefsok
10190 bind $top <Key-Escape> prefscan
Paul Mackerras712fcc02005-11-30 09:28:16 +110010191 grid $top.buts.ok $top.buts.can
10192 grid columnconfigure $top.buts 0 -weight 1 -uniform a
10193 grid columnconfigure $top.buts 1 -weight 1 -uniform a
10194 grid $top.buts - - -pady 10 -sticky ew
Eygene Ryabinkin3a950e92007-03-27 14:36:59 +040010195 bind $top <Visibility> "focus $top.buts.ok"
Paul Mackerras712fcc02005-11-30 09:28:16 +110010196}
10197
Thomas Arcila314f5de2008-03-24 12:55:36 +010010198proc choose_extdiff {} {
10199 global extdifftool
10200
10201 set prog [tk_getOpenFile -title "External diff tool" -multiple false]
10202 if {$prog ne {}} {
10203 set extdifftool $prog
10204 }
10205}
10206
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +100010207proc choosecolor {v vi w x cmd} {
10208 global $v
10209
10210 set c [tk_chooseColor -initialcolor [lindex [set $v] $vi] \
Christian Stimmingd990ced2007-11-07 18:42:55 +010010211 -title [mc "Gitk: choose color for %s" $x]]
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +100010212 if {$c eq {}} return
10213 $w conf -background $c
10214 lset $v $vi $c
10215 eval $cmd $c
10216}
10217
Mark Levedahl60378c02007-05-20 12:12:48 -040010218proc setselbg {c} {
10219 global bglist cflist
10220 foreach w $bglist {
10221 $w configure -selectbackground $c
10222 }
10223 $cflist tag configure highlight \
10224 -background [$cflist cget -selectbackground]
10225 allcanvs itemconf secsel -fill $c
10226}
10227
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +100010228proc setbg {c} {
10229 global bglist
10230
10231 foreach w $bglist {
10232 $w conf -background $c
10233 }
10234}
10235
10236proc setfg {c} {
10237 global fglist canv
10238
10239 foreach w $fglist {
10240 $w conf -foreground $c
10241 }
10242 allcanvs itemconf text -fill $c
10243 $canv itemconf circle -outline $c
10244}
10245
Paul Mackerras712fcc02005-11-30 09:28:16 +110010246proc prefscan {} {
Paul Mackerras94503912007-10-23 10:33:38 +100010247 global oldprefs prefstop
Paul Mackerras712fcc02005-11-30 09:28:16 +110010248
Paul Mackerras3de07112007-10-23 22:40:50 +100010249 foreach v {maxwidth maxgraphpct showneartags showlocalchanges \
Paul Mackerras39ee47e2008-10-15 22:23:03 +110010250 limitdiffs tabstop perfile_attrs} {
Paul Mackerras94503912007-10-23 10:33:38 +100010251 global $v
Paul Mackerras712fcc02005-11-30 09:28:16 +110010252 set $v $oldprefs($v)
10253 }
10254 catch {destroy $prefstop}
10255 unset prefstop
Paul Mackerras9a7558f2007-10-06 20:16:06 +100010256 fontcan
Paul Mackerras712fcc02005-11-30 09:28:16 +110010257}
10258
10259proc prefsok {} {
10260 global maxwidth maxgraphpct
Paul Mackerras219ea3a2006-09-07 10:21:39 +100010261 global oldprefs prefstop showneartags showlocalchanges
Paul Mackerras9a7558f2007-10-06 20:16:06 +100010262 global fontpref mainfont textfont uifont
Paul Mackerras39ee47e2008-10-15 22:23:03 +110010263 global limitdiffs treediffs perfile_attrs
Paul Mackerras712fcc02005-11-30 09:28:16 +110010264
10265 catch {destroy $prefstop}
10266 unset prefstop
Paul Mackerras9a7558f2007-10-06 20:16:06 +100010267 fontcan
10268 set fontchanged 0
10269 if {$mainfont ne $fontpref(mainfont)} {
10270 set mainfont $fontpref(mainfont)
10271 parsefont mainfont $mainfont
10272 eval font configure mainfont [fontflags mainfont]
10273 eval font configure mainfontbold [fontflags mainfont 1]
10274 setcoords
10275 set fontchanged 1
10276 }
10277 if {$textfont ne $fontpref(textfont)} {
10278 set textfont $fontpref(textfont)
10279 parsefont textfont $textfont
10280 eval font configure textfont [fontflags textfont]
10281 eval font configure textfontbold [fontflags textfont 1]
10282 }
10283 if {$uifont ne $fontpref(uifont)} {
10284 set uifont $fontpref(uifont)
10285 parsefont uifont $uifont
10286 eval font configure uifont [fontflags uifont]
10287 }
Paul Mackerras32f1b3e2007-09-28 21:27:39 +100010288 settabs
Paul Mackerras219ea3a2006-09-07 10:21:39 +100010289 if {$showlocalchanges != $oldprefs(showlocalchanges)} {
10290 if {$showlocalchanges} {
10291 doshowlocalchanges
10292 } else {
10293 dohidelocalchanges
10294 }
10295 }
Paul Mackerras39ee47e2008-10-15 22:23:03 +110010296 if {$limitdiffs != $oldprefs(limitdiffs) ||
10297 ($perfile_attrs && !$oldprefs(perfile_attrs))} {
10298 # treediffs elements are limited by path;
10299 # won't have encodings cached if perfile_attrs was just turned on
Paul Mackerras74a40c72007-10-24 10:16:56 +100010300 catch {unset treediffs}
10301 }
Paul Mackerras9a7558f2007-10-06 20:16:06 +100010302 if {$fontchanged || $maxwidth != $oldprefs(maxwidth)
Paul Mackerras712fcc02005-11-30 09:28:16 +110010303 || $maxgraphpct != $oldprefs(maxgraphpct)} {
10304 redisplay
Paul Mackerras7a39a172007-10-23 10:15:11 +100010305 } elseif {$showneartags != $oldprefs(showneartags) ||
10306 $limitdiffs != $oldprefs(limitdiffs)} {
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +100010307 reselectline
Paul Mackerras712fcc02005-11-30 09:28:16 +110010308 }
10309}
10310
10311proc formatdate {d} {
Arjen Laarhovene8b5f4b2007-08-14 22:02:04 +020010312 global datetimeformat
Paul Mackerras219ea3a2006-09-07 10:21:39 +100010313 if {$d ne {}} {
Arjen Laarhovene8b5f4b2007-08-14 22:02:04 +020010314 set d [clock format $d -format $datetimeformat]
Paul Mackerras219ea3a2006-09-07 10:21:39 +100010315 }
10316 return $d
Paul Mackerras232475d2005-11-15 10:34:03 +110010317}
10318
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +110010319# This list of encoding names and aliases is distilled from
10320# http://www.iana.org/assignments/character-sets.
10321# Not all of them are supported by Tcl.
10322set encoding_aliases {
10323 { ANSI_X3.4-1968 iso-ir-6 ANSI_X3.4-1986 ISO_646.irv:1991 ASCII
10324 ISO646-US US-ASCII us IBM367 cp367 csASCII }
10325 { ISO-10646-UTF-1 csISO10646UTF1 }
10326 { ISO_646.basic:1983 ref csISO646basic1983 }
10327 { INVARIANT csINVARIANT }
10328 { ISO_646.irv:1983 iso-ir-2 irv csISO2IntlRefVersion }
10329 { BS_4730 iso-ir-4 ISO646-GB gb uk csISO4UnitedKingdom }
10330 { NATS-SEFI iso-ir-8-1 csNATSSEFI }
10331 { NATS-SEFI-ADD iso-ir-8-2 csNATSSEFIADD }
10332 { NATS-DANO iso-ir-9-1 csNATSDANO }
10333 { NATS-DANO-ADD iso-ir-9-2 csNATSDANOADD }
10334 { SEN_850200_B iso-ir-10 FI ISO646-FI ISO646-SE se csISO10Swedish }
10335 { SEN_850200_C iso-ir-11 ISO646-SE2 se2 csISO11SwedishForNames }
10336 { KS_C_5601-1987 iso-ir-149 KS_C_5601-1989 KSC_5601 korean csKSC56011987 }
10337 { ISO-2022-KR csISO2022KR }
10338 { EUC-KR csEUCKR }
10339 { ISO-2022-JP csISO2022JP }
10340 { ISO-2022-JP-2 csISO2022JP2 }
10341 { JIS_C6220-1969-jp JIS_C6220-1969 iso-ir-13 katakana x0201-7
10342 csISO13JISC6220jp }
10343 { JIS_C6220-1969-ro iso-ir-14 jp ISO646-JP csISO14JISC6220ro }
10344 { IT iso-ir-15 ISO646-IT csISO15Italian }
10345 { PT iso-ir-16 ISO646-PT csISO16Portuguese }
10346 { ES iso-ir-17 ISO646-ES csISO17Spanish }
10347 { greek7-old iso-ir-18 csISO18Greek7Old }
10348 { latin-greek iso-ir-19 csISO19LatinGreek }
10349 { DIN_66003 iso-ir-21 de ISO646-DE csISO21German }
10350 { NF_Z_62-010_(1973) iso-ir-25 ISO646-FR1 csISO25French }
10351 { Latin-greek-1 iso-ir-27 csISO27LatinGreek1 }
10352 { ISO_5427 iso-ir-37 csISO5427Cyrillic }
10353 { JIS_C6226-1978 iso-ir-42 csISO42JISC62261978 }
10354 { BS_viewdata iso-ir-47 csISO47BSViewdata }
10355 { INIS iso-ir-49 csISO49INIS }
10356 { INIS-8 iso-ir-50 csISO50INIS8 }
10357 { INIS-cyrillic iso-ir-51 csISO51INISCyrillic }
10358 { ISO_5427:1981 iso-ir-54 ISO5427Cyrillic1981 }
10359 { ISO_5428:1980 iso-ir-55 csISO5428Greek }
10360 { GB_1988-80 iso-ir-57 cn ISO646-CN csISO57GB1988 }
10361 { GB_2312-80 iso-ir-58 chinese csISO58GB231280 }
10362 { NS_4551-1 iso-ir-60 ISO646-NO no csISO60DanishNorwegian
10363 csISO60Norwegian1 }
10364 { NS_4551-2 ISO646-NO2 iso-ir-61 no2 csISO61Norwegian2 }
10365 { NF_Z_62-010 iso-ir-69 ISO646-FR fr csISO69French }
10366 { videotex-suppl iso-ir-70 csISO70VideotexSupp1 }
10367 { PT2 iso-ir-84 ISO646-PT2 csISO84Portuguese2 }
10368 { ES2 iso-ir-85 ISO646-ES2 csISO85Spanish2 }
10369 { MSZ_7795.3 iso-ir-86 ISO646-HU hu csISO86Hungarian }
10370 { JIS_C6226-1983 iso-ir-87 x0208 JIS_X0208-1983 csISO87JISX0208 }
10371 { greek7 iso-ir-88 csISO88Greek7 }
10372 { ASMO_449 ISO_9036 arabic7 iso-ir-89 csISO89ASMO449 }
10373 { iso-ir-90 csISO90 }
10374 { JIS_C6229-1984-a iso-ir-91 jp-ocr-a csISO91JISC62291984a }
10375 { JIS_C6229-1984-b iso-ir-92 ISO646-JP-OCR-B jp-ocr-b
10376 csISO92JISC62991984b }
10377 { JIS_C6229-1984-b-add iso-ir-93 jp-ocr-b-add csISO93JIS62291984badd }
10378 { JIS_C6229-1984-hand iso-ir-94 jp-ocr-hand csISO94JIS62291984hand }
10379 { JIS_C6229-1984-hand-add iso-ir-95 jp-ocr-hand-add
10380 csISO95JIS62291984handadd }
10381 { JIS_C6229-1984-kana iso-ir-96 csISO96JISC62291984kana }
10382 { ISO_2033-1983 iso-ir-98 e13b csISO2033 }
10383 { ANSI_X3.110-1983 iso-ir-99 CSA_T500-1983 NAPLPS csISO99NAPLPS }
10384 { ISO_8859-1:1987 iso-ir-100 ISO_8859-1 ISO-8859-1 latin1 l1 IBM819
10385 CP819 csISOLatin1 }
10386 { ISO_8859-2:1987 iso-ir-101 ISO_8859-2 ISO-8859-2 latin2 l2 csISOLatin2 }
10387 { T.61-7bit iso-ir-102 csISO102T617bit }
10388 { T.61-8bit T.61 iso-ir-103 csISO103T618bit }
10389 { ISO_8859-3:1988 iso-ir-109 ISO_8859-3 ISO-8859-3 latin3 l3 csISOLatin3 }
10390 { ISO_8859-4:1988 iso-ir-110 ISO_8859-4 ISO-8859-4 latin4 l4 csISOLatin4 }
10391 { ECMA-cyrillic iso-ir-111 KOI8-E csISO111ECMACyrillic }
10392 { CSA_Z243.4-1985-1 iso-ir-121 ISO646-CA csa7-1 ca csISO121Canadian1 }
10393 { CSA_Z243.4-1985-2 iso-ir-122 ISO646-CA2 csa7-2 csISO122Canadian2 }
10394 { CSA_Z243.4-1985-gr iso-ir-123 csISO123CSAZ24341985gr }
10395 { ISO_8859-6:1987 iso-ir-127 ISO_8859-6 ISO-8859-6 ECMA-114 ASMO-708
10396 arabic csISOLatinArabic }
10397 { ISO_8859-6-E csISO88596E ISO-8859-6-E }
10398 { ISO_8859-6-I csISO88596I ISO-8859-6-I }
10399 { ISO_8859-7:1987 iso-ir-126 ISO_8859-7 ISO-8859-7 ELOT_928 ECMA-118
10400 greek greek8 csISOLatinGreek }
10401 { T.101-G2 iso-ir-128 csISO128T101G2 }
10402 { ISO_8859-8:1988 iso-ir-138 ISO_8859-8 ISO-8859-8 hebrew
10403 csISOLatinHebrew }
10404 { ISO_8859-8-E csISO88598E ISO-8859-8-E }
10405 { ISO_8859-8-I csISO88598I ISO-8859-8-I }
10406 { CSN_369103 iso-ir-139 csISO139CSN369103 }
10407 { JUS_I.B1.002 iso-ir-141 ISO646-YU js yu csISO141JUSIB1002 }
10408 { ISO_6937-2-add iso-ir-142 csISOTextComm }
10409 { IEC_P27-1 iso-ir-143 csISO143IECP271 }
10410 { ISO_8859-5:1988 iso-ir-144 ISO_8859-5 ISO-8859-5 cyrillic
10411 csISOLatinCyrillic }
10412 { JUS_I.B1.003-serb iso-ir-146 serbian csISO146Serbian }
10413 { JUS_I.B1.003-mac macedonian iso-ir-147 csISO147Macedonian }
10414 { ISO_8859-9:1989 iso-ir-148 ISO_8859-9 ISO-8859-9 latin5 l5 csISOLatin5 }
10415 { greek-ccitt iso-ir-150 csISO150 csISO150GreekCCITT }
10416 { NC_NC00-10:81 cuba iso-ir-151 ISO646-CU csISO151Cuba }
10417 { ISO_6937-2-25 iso-ir-152 csISO6937Add }
10418 { GOST_19768-74 ST_SEV_358-88 iso-ir-153 csISO153GOST1976874 }
10419 { ISO_8859-supp iso-ir-154 latin1-2-5 csISO8859Supp }
10420 { ISO_10367-box iso-ir-155 csISO10367Box }
10421 { ISO-8859-10 iso-ir-157 l6 ISO_8859-10:1992 csISOLatin6 latin6 }
10422 { latin-lap lap iso-ir-158 csISO158Lap }
10423 { JIS_X0212-1990 x0212 iso-ir-159 csISO159JISX02121990 }
10424 { DS_2089 DS2089 ISO646-DK dk csISO646Danish }
10425 { us-dk csUSDK }
10426 { dk-us csDKUS }
10427 { JIS_X0201 X0201 csHalfWidthKatakana }
10428 { KSC5636 ISO646-KR csKSC5636 }
10429 { ISO-10646-UCS-2 csUnicode }
10430 { ISO-10646-UCS-4 csUCS4 }
10431 { DEC-MCS dec csDECMCS }
10432 { hp-roman8 roman8 r8 csHPRoman8 }
10433 { macintosh mac csMacintosh }
10434 { IBM037 cp037 ebcdic-cp-us ebcdic-cp-ca ebcdic-cp-wt ebcdic-cp-nl
10435 csIBM037 }
10436 { IBM038 EBCDIC-INT cp038 csIBM038 }
10437 { IBM273 CP273 csIBM273 }
10438 { IBM274 EBCDIC-BE CP274 csIBM274 }
10439 { IBM275 EBCDIC-BR cp275 csIBM275 }
10440 { IBM277 EBCDIC-CP-DK EBCDIC-CP-NO csIBM277 }
10441 { IBM278 CP278 ebcdic-cp-fi ebcdic-cp-se csIBM278 }
10442 { IBM280 CP280 ebcdic-cp-it csIBM280 }
10443 { IBM281 EBCDIC-JP-E cp281 csIBM281 }
10444 { IBM284 CP284 ebcdic-cp-es csIBM284 }
10445 { IBM285 CP285 ebcdic-cp-gb csIBM285 }
10446 { IBM290 cp290 EBCDIC-JP-kana csIBM290 }
10447 { IBM297 cp297 ebcdic-cp-fr csIBM297 }
10448 { IBM420 cp420 ebcdic-cp-ar1 csIBM420 }
10449 { IBM423 cp423 ebcdic-cp-gr csIBM423 }
10450 { IBM424 cp424 ebcdic-cp-he csIBM424 }
10451 { IBM437 cp437 437 csPC8CodePage437 }
10452 { IBM500 CP500 ebcdic-cp-be ebcdic-cp-ch csIBM500 }
10453 { IBM775 cp775 csPC775Baltic }
10454 { IBM850 cp850 850 csPC850Multilingual }
10455 { IBM851 cp851 851 csIBM851 }
10456 { IBM852 cp852 852 csPCp852 }
10457 { IBM855 cp855 855 csIBM855 }
10458 { IBM857 cp857 857 csIBM857 }
10459 { IBM860 cp860 860 csIBM860 }
10460 { IBM861 cp861 861 cp-is csIBM861 }
10461 { IBM862 cp862 862 csPC862LatinHebrew }
10462 { IBM863 cp863 863 csIBM863 }
10463 { IBM864 cp864 csIBM864 }
10464 { IBM865 cp865 865 csIBM865 }
10465 { IBM866 cp866 866 csIBM866 }
10466 { IBM868 CP868 cp-ar csIBM868 }
10467 { IBM869 cp869 869 cp-gr csIBM869 }
10468 { IBM870 CP870 ebcdic-cp-roece ebcdic-cp-yu csIBM870 }
10469 { IBM871 CP871 ebcdic-cp-is csIBM871 }
10470 { IBM880 cp880 EBCDIC-Cyrillic csIBM880 }
10471 { IBM891 cp891 csIBM891 }
10472 { IBM903 cp903 csIBM903 }
10473 { IBM904 cp904 904 csIBBM904 }
10474 { IBM905 CP905 ebcdic-cp-tr csIBM905 }
10475 { IBM918 CP918 ebcdic-cp-ar2 csIBM918 }
10476 { IBM1026 CP1026 csIBM1026 }
10477 { EBCDIC-AT-DE csIBMEBCDICATDE }
10478 { EBCDIC-AT-DE-A csEBCDICATDEA }
10479 { EBCDIC-CA-FR csEBCDICCAFR }
10480 { EBCDIC-DK-NO csEBCDICDKNO }
10481 { EBCDIC-DK-NO-A csEBCDICDKNOA }
10482 { EBCDIC-FI-SE csEBCDICFISE }
10483 { EBCDIC-FI-SE-A csEBCDICFISEA }
10484 { EBCDIC-FR csEBCDICFR }
10485 { EBCDIC-IT csEBCDICIT }
10486 { EBCDIC-PT csEBCDICPT }
10487 { EBCDIC-ES csEBCDICES }
10488 { EBCDIC-ES-A csEBCDICESA }
10489 { EBCDIC-ES-S csEBCDICESS }
10490 { EBCDIC-UK csEBCDICUK }
10491 { EBCDIC-US csEBCDICUS }
10492 { UNKNOWN-8BIT csUnknown8BiT }
10493 { MNEMONIC csMnemonic }
10494 { MNEM csMnem }
10495 { VISCII csVISCII }
10496 { VIQR csVIQR }
10497 { KOI8-R csKOI8R }
10498 { IBM00858 CCSID00858 CP00858 PC-Multilingual-850+euro }
10499 { IBM00924 CCSID00924 CP00924 ebcdic-Latin9--euro }
10500 { IBM01140 CCSID01140 CP01140 ebcdic-us-37+euro }
10501 { IBM01141 CCSID01141 CP01141 ebcdic-de-273+euro }
10502 { IBM01142 CCSID01142 CP01142 ebcdic-dk-277+euro ebcdic-no-277+euro }
10503 { IBM01143 CCSID01143 CP01143 ebcdic-fi-278+euro ebcdic-se-278+euro }
10504 { IBM01144 CCSID01144 CP01144 ebcdic-it-280+euro }
10505 { IBM01145 CCSID01145 CP01145 ebcdic-es-284+euro }
10506 { IBM01146 CCSID01146 CP01146 ebcdic-gb-285+euro }
10507 { IBM01147 CCSID01147 CP01147 ebcdic-fr-297+euro }
10508 { IBM01148 CCSID01148 CP01148 ebcdic-international-500+euro }
10509 { IBM01149 CCSID01149 CP01149 ebcdic-is-871+euro }
10510 { IBM1047 IBM-1047 }
10511 { PTCP154 csPTCP154 PT154 CP154 Cyrillic-Asian }
10512 { Amiga-1251 Ami1251 Amiga1251 Ami-1251 }
10513 { UNICODE-1-1 csUnicode11 }
10514 { CESU-8 csCESU-8 }
10515 { BOCU-1 csBOCU-1 }
10516 { UNICODE-1-1-UTF-7 csUnicode11UTF7 }
10517 { ISO-8859-14 iso-ir-199 ISO_8859-14:1998 ISO_8859-14 latin8 iso-celtic
10518 l8 }
10519 { ISO-8859-15 ISO_8859-15 Latin-9 }
10520 { ISO-8859-16 iso-ir-226 ISO_8859-16:2001 ISO_8859-16 latin10 l10 }
10521 { GBK CP936 MS936 windows-936 }
10522 { JIS_Encoding csJISEncoding }
Alexander Gavrilov09c70292008-10-13 12:12:31 +040010523 { Shift_JIS MS_Kanji csShiftJIS ShiftJIS Shift-JIS }
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +110010524 { Extended_UNIX_Code_Packed_Format_for_Japanese csEUCPkdFmtJapanese
10525 EUC-JP }
10526 { Extended_UNIX_Code_Fixed_Width_for_Japanese csEUCFixWidJapanese }
10527 { ISO-10646-UCS-Basic csUnicodeASCII }
10528 { ISO-10646-Unicode-Latin1 csUnicodeLatin1 ISO-10646 }
10529 { ISO-Unicode-IBM-1261 csUnicodeIBM1261 }
10530 { ISO-Unicode-IBM-1268 csUnicodeIBM1268 }
10531 { ISO-Unicode-IBM-1276 csUnicodeIBM1276 }
10532 { ISO-Unicode-IBM-1264 csUnicodeIBM1264 }
10533 { ISO-Unicode-IBM-1265 csUnicodeIBM1265 }
10534 { ISO-8859-1-Windows-3.0-Latin-1 csWindows30Latin1 }
10535 { ISO-8859-1-Windows-3.1-Latin-1 csWindows31Latin1 }
10536 { ISO-8859-2-Windows-Latin-2 csWindows31Latin2 }
10537 { ISO-8859-9-Windows-Latin-5 csWindows31Latin5 }
10538 { Adobe-Standard-Encoding csAdobeStandardEncoding }
10539 { Ventura-US csVenturaUS }
10540 { Ventura-International csVenturaInternational }
10541 { PC8-Danish-Norwegian csPC8DanishNorwegian }
10542 { PC8-Turkish csPC8Turkish }
10543 { IBM-Symbols csIBMSymbols }
10544 { IBM-Thai csIBMThai }
10545 { HP-Legal csHPLegal }
10546 { HP-Pi-font csHPPiFont }
10547 { HP-Math8 csHPMath8 }
10548 { Adobe-Symbol-Encoding csHPPSMath }
10549 { HP-DeskTop csHPDesktop }
10550 { Ventura-Math csVenturaMath }
10551 { Microsoft-Publishing csMicrosoftPublishing }
10552 { Windows-31J csWindows31J }
10553 { GB2312 csGB2312 }
10554 { Big5 csBig5 }
10555}
10556
10557proc tcl_encoding {enc} {
Paul Mackerras39ee47e2008-10-15 22:23:03 +110010558 global encoding_aliases tcl_encoding_cache
10559 if {[info exists tcl_encoding_cache($enc)]} {
10560 return $tcl_encoding_cache($enc)
10561 }
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +110010562 set names [encoding names]
10563 set lcnames [string tolower $names]
10564 set enc [string tolower $enc]
10565 set i [lsearch -exact $lcnames $enc]
10566 if {$i < 0} {
10567 # look for "isonnn" instead of "iso-nnn" or "iso_nnn"
Alexander Gavrilov09c70292008-10-13 12:12:31 +040010568 if {[regsub {^(iso|cp|ibm|jis)[-_]} $enc {\1} encx]} {
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +110010569 set i [lsearch -exact $lcnames $encx]
10570 }
10571 }
10572 if {$i < 0} {
10573 foreach l $encoding_aliases {
10574 set ll [string tolower $l]
10575 if {[lsearch -exact $ll $enc] < 0} continue
10576 # look through the aliases for one that tcl knows about
10577 foreach e $ll {
10578 set i [lsearch -exact $lcnames $e]
10579 if {$i < 0} {
Alexander Gavrilov09c70292008-10-13 12:12:31 +040010580 if {[regsub {^(iso|cp|ibm|jis)[-_]} $e {\1} ex]} {
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +110010581 set i [lsearch -exact $lcnames $ex]
10582 }
10583 }
10584 if {$i >= 0} break
10585 }
10586 break
10587 }
10588 }
Paul Mackerras39ee47e2008-10-15 22:23:03 +110010589 set tclenc {}
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +110010590 if {$i >= 0} {
Paul Mackerras39ee47e2008-10-15 22:23:03 +110010591 set tclenc [lindex $names $i]
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +110010592 }
Paul Mackerras39ee47e2008-10-15 22:23:03 +110010593 set tcl_encoding_cache($enc) $tclenc
10594 return $tclenc
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +110010595}
10596
Alexander Gavrilov09c70292008-10-13 12:12:31 +040010597proc gitattr {path attr default} {
Paul Mackerras39ee47e2008-10-15 22:23:03 +110010598 global path_attr_cache
10599 if {[info exists path_attr_cache($attr,$path)]} {
10600 set r $path_attr_cache($attr,$path)
10601 } else {
10602 set r "unspecified"
10603 if {![catch {set line [exec git check-attr $attr -- $path]}]} {
10604 regexp "(.*): encoding: (.*)" $line m f r
Alexander Gavrilov09c70292008-10-13 12:12:31 +040010605 }
Alexander Gavrilov4db09302008-10-13 12:12:33 +040010606 set path_attr_cache($attr,$path) $r
Paul Mackerras39ee47e2008-10-15 22:23:03 +110010607 }
10608 if {$r eq "unspecified"} {
10609 return $default
10610 }
10611 return $r
Alexander Gavrilov09c70292008-10-13 12:12:31 +040010612}
10613
Alexander Gavrilov4db09302008-10-13 12:12:33 +040010614proc cache_gitattr {attr pathlist} {
Paul Mackerras39ee47e2008-10-15 22:23:03 +110010615 global path_attr_cache
10616 set newlist {}
10617 foreach path $pathlist {
10618 if {![info exists path_attr_cache($attr,$path)]} {
10619 lappend newlist $path
Alexander Gavrilov4db09302008-10-13 12:12:33 +040010620 }
Paul Mackerras39ee47e2008-10-15 22:23:03 +110010621 }
10622 set lim 1000
10623 if {[tk windowingsystem] == "win32"} {
10624 # windows has a 32k limit on the arguments to a command...
10625 set lim 30
10626 }
10627 while {$newlist ne {}} {
10628 set head [lrange $newlist 0 [expr {$lim - 1}]]
10629 set newlist [lrange $newlist $lim end]
10630 if {![catch {set rlist [eval exec git check-attr $attr -- $head]}]} {
10631 foreach row [split $rlist "\n"] {
10632 if {[regexp "(.*): encoding: (.*)" $row m path value]} {
10633 if {[string index $path 0] eq "\""} {
10634 set path [encoding convertfrom [lindex $path 0]]
10635 }
10636 set path_attr_cache($attr,$path) $value
Alexander Gavrilov4db09302008-10-13 12:12:33 +040010637 }
Paul Mackerras39ee47e2008-10-15 22:23:03 +110010638 }
Alexander Gavrilov4db09302008-10-13 12:12:33 +040010639 }
Paul Mackerras39ee47e2008-10-15 22:23:03 +110010640 }
Alexander Gavrilov4db09302008-10-13 12:12:33 +040010641}
10642
Alexander Gavrilov09c70292008-10-13 12:12:31 +040010643proc get_path_encoding {path} {
Paul Mackerras39ee47e2008-10-15 22:23:03 +110010644 global gui_encoding perfile_attrs
10645 set tcl_enc $gui_encoding
10646 if {$path ne {} && $perfile_attrs} {
10647 set enc2 [tcl_encoding [gitattr $path encoding $tcl_enc]]
10648 if {$enc2 ne {}} {
10649 set tcl_enc $enc2
Alexander Gavrilov09c70292008-10-13 12:12:31 +040010650 }
Paul Mackerras39ee47e2008-10-15 22:23:03 +110010651 }
10652 return $tcl_enc
Alexander Gavrilov09c70292008-10-13 12:12:31 +040010653}
10654
Paul Mackerras5d7589d2007-10-20 21:21:03 +100010655# First check that Tcl/Tk is recent enough
10656if {[catch {package require Tk 8.4} err]} {
Christian Stimmingd990ced2007-11-07 18:42:55 +010010657 show_error {} . [mc "Sorry, gitk cannot run with this version of Tcl/Tk.\n\
10658 Gitk requires at least Tcl/Tk 8.4."]
Paul Mackerras5d7589d2007-10-20 21:21:03 +100010659 exit 1
10660}
10661
Paul Mackerras1d10f362005-05-15 12:55:47 +000010662# defaults...
Timo Hirvonen8974c6f2006-05-24 10:57:40 +030010663set wrcomcmd "git diff-tree --stdin -p --pretty"
Junio C Hamano671bc152005-11-27 16:12:51 -080010664
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +110010665set gitencoding {}
Junio C Hamano671bc152005-11-27 16:12:51 -080010666catch {
Paul Mackerras27cb61c2007-02-15 08:54:34 +110010667 set gitencoding [exec git config --get i18n.commitencoding]
Junio C Hamano671bc152005-11-27 16:12:51 -080010668}
Alexander Gavrilov590915d2008-11-09 18:06:07 +030010669catch {
10670 set gitencoding [exec git config --get i18n.logoutputencoding]
10671}
Junio C Hamano671bc152005-11-27 16:12:51 -080010672if {$gitencoding == ""} {
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +110010673 set gitencoding "utf-8"
10674}
10675set tclencoding [tcl_encoding $gitencoding]
10676if {$tclencoding == {}} {
10677 puts stderr "Warning: encoding $gitencoding is not supported by Tcl/Tk"
Junio C Hamano671bc152005-11-27 16:12:51 -080010678}
Paul Mackerras1d10f362005-05-15 12:55:47 +000010679
Alexander Gavrilov09c70292008-10-13 12:12:31 +040010680set gui_encoding [encoding system]
10681catch {
Paul Mackerras39ee47e2008-10-15 22:23:03 +110010682 set enc [exec git config --get gui.encoding]
10683 if {$enc ne {}} {
10684 set tclenc [tcl_encoding $enc]
10685 if {$tclenc ne {}} {
10686 set gui_encoding $tclenc
10687 } else {
10688 puts stderr "Warning: encoding $enc is not supported by Tcl/Tk"
10689 }
10690 }
Alexander Gavrilov09c70292008-10-13 12:12:31 +040010691}
10692
Paul Mackerras1d10f362005-05-15 12:55:47 +000010693set mainfont {Helvetica 9}
Paul Mackerras1d10f362005-05-15 12:55:47 +000010694set textfont {Courier 9}
Keith Packard4840be62006-04-04 00:19:45 -070010695set uifont {Helvetica 9 bold}
Mark Levedahl7e12f1a2007-05-20 11:45:50 -040010696set tabstop 8
Paul Mackerrasb74fd572005-07-16 07:46:13 -040010697set findmergefiles 0
Paul Mackerras8d858d12005-08-05 09:52:16 +100010698set maxgraphpct 50
Paul Mackerrasf6075eb2005-08-18 09:30:10 +100010699set maxwidth 16
Paul Mackerras232475d2005-11-15 10:34:03 +110010700set revlistorder 0
Paul Mackerras757f17b2005-11-21 09:56:07 +110010701set fastdate 0
Paul Mackerras6e8c8702007-07-31 21:03:06 +100010702set uparrowlen 5
10703set downarrowlen 5
10704set mingaplen 100
Paul Mackerrasf8b28a42006-05-01 09:50:57 +100010705set cmitmode "patch"
Sergey Vlasovf1b86292006-05-15 19:13:14 +040010706set wrapcomment "none"
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +100010707set showneartags 1
Paul Mackerras0a4dd8b2007-06-16 21:21:57 +100010708set maxrefs 20
Paul Mackerras322a8cc2006-10-15 18:03:46 +100010709set maxlinelen 200
Paul Mackerras219ea3a2006-09-07 10:21:39 +100010710set showlocalchanges 1
Paul Mackerras7a39a172007-10-23 10:15:11 +100010711set limitdiffs 1
Arjen Laarhovene8b5f4b2007-08-14 22:02:04 +020010712set datetimeformat "%Y-%m-%d %H:%M:%S"
Jeff King95293b52008-03-06 06:49:25 -050010713set autoselect 1
Paul Mackerras39ee47e2008-10-15 22:23:03 +110010714set perfile_attrs 0
Paul Mackerras1d10f362005-05-15 12:55:47 +000010715
Thomas Arcila314f5de2008-03-24 12:55:36 +010010716set extdifftool "meld"
10717
Paul Mackerras1d10f362005-05-15 12:55:47 +000010718set colors {green red blue magenta darkgrey brown orange}
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +100010719set bgcolor white
10720set fgcolor black
10721set diffcolors {red "#00a000" blue}
Steffen Prohaska890fae72007-08-12 12:05:46 +020010722set diffcontext 3
Steffen Prohaskab9b86002008-01-17 23:42:55 +010010723set ignorespace 0
Mark Levedahl60378c02007-05-20 12:12:48 -040010724set selectbgcolor gray85
Paul Mackerrase3e901b2008-10-27 22:37:21 +110010725set markbgcolor "#e0e0ff"
Paul Mackerras1d10f362005-05-15 12:55:47 +000010726
Paul Mackerrasc11ff122008-05-26 10:11:33 +100010727set circlecolors {white blue gray blue blue}
10728
Paul Mackerrasd277e892008-09-21 18:11:37 -050010729# button for popping up context menus
10730if {[tk windowingsystem] eq "aqua"} {
10731 set ctxbut <Button-2>
10732} else {
10733 set ctxbut <Button-3>
10734}
10735
Christian Stimming663c3aa2007-11-07 18:40:59 +010010736## For msgcat loading, first locate the installation location.
10737if { [info exists ::env(GITK_MSGSDIR)] } {
10738 ## Msgsdir was manually set in the environment.
10739 set gitk_msgsdir $::env(GITK_MSGSDIR)
10740} else {
10741 ## Let's guess the prefix from argv0.
10742 set gitk_prefix [file dirname [file dirname [file normalize $argv0]]]
10743 set gitk_libdir [file join $gitk_prefix share gitk lib]
10744 set gitk_msgsdir [file join $gitk_libdir msgs]
10745 unset gitk_prefix
10746}
10747
10748## Internationalization (i18n) through msgcat and gettext. See
10749## http://www.gnu.org/software/gettext/manual/html_node/Tcl.html
10750package require msgcat
10751namespace import ::msgcat::mc
10752## And eventually load the actual message catalog
10753::msgcat::mcload $gitk_msgsdir
10754
Paul Mackerras1d10f362005-05-15 12:55:47 +000010755catch {source ~/.gitk}
10756
Paul Mackerras712fcc02005-11-30 09:28:16 +110010757font create optionfont -family sans-serif -size -12
Paul Mackerras17386062005-05-18 22:51:00 +000010758
Paul Mackerras0ed1dd32007-10-06 18:27:37 +100010759parsefont mainfont $mainfont
10760eval font create mainfont [fontflags mainfont]
10761eval font create mainfontbold [fontflags mainfont 1]
10762
10763parsefont textfont $textfont
10764eval font create textfont [fontflags textfont]
10765eval font create textfontbold [fontflags textfont 1]
10766
10767parsefont uifont $uifont
10768eval font create uifont [fontflags uifont]
Paul Mackerras1db95b02005-05-09 04:08:39 +000010769
Paul Mackerrasb039f0a2008-01-06 15:54:46 +110010770setoptions
10771
Paul Mackerrasaa81d972006-02-28 11:27:12 +110010772# check that we can find a .git directory somewhere...
Alex Riesen6c87d602007-07-29 22:29:45 +020010773if {[catch {set gitdir [gitdir]}]} {
Christian Stimmingd990ced2007-11-07 18:42:55 +010010774 show_error {} . [mc "Cannot find a git repository here."]
Alex Riesen6c87d602007-07-29 22:29:45 +020010775 exit 1
10776}
Paul Mackerrasaa81d972006-02-28 11:27:12 +110010777if {![file isdirectory $gitdir]} {
Christian Stimmingd990ced2007-11-07 18:42:55 +010010778 show_error {} . [mc "Cannot find the git directory \"%s\"." $gitdir]
Paul Mackerrasaa81d972006-02-28 11:27:12 +110010779 exit 1
10780}
10781
Alexander Gavrilov39816d62008-08-23 12:27:44 +040010782set selecthead {}
10783set selectheadid {}
10784
Paul Mackerrascdaee5d2007-07-12 22:29:49 +100010785set revtreeargs {}
Paul Mackerras098dd8a2006-05-03 09:32:53 +100010786set cmdline_files {}
Paul Mackerrascdaee5d2007-07-12 22:29:49 +100010787set i 0
Yann Dirson2d480852008-02-21 21:23:31 +010010788set revtreeargscmd {}
Paul Mackerrascdaee5d2007-07-12 22:29:49 +100010789foreach arg $argv {
Yann Dirson2d480852008-02-21 21:23:31 +010010790 switch -glob -- $arg {
Paul Mackerras6ebedab2007-07-13 13:45:55 +100010791 "" { }
Paul Mackerrascdaee5d2007-07-12 22:29:49 +100010792 "--" {
10793 set cmdline_files [lrange $argv [expr {$i + 1}] end]
10794 break
10795 }
Alexander Gavrilov39816d62008-08-23 12:27:44 +040010796 "--select-commit=*" {
10797 set selecthead [string range $arg 16 end]
10798 }
Yann Dirson2d480852008-02-21 21:23:31 +010010799 "--argscmd=*" {
10800 set revtreeargscmd [string range $arg 10 end]
10801 }
Paul Mackerrascdaee5d2007-07-12 22:29:49 +100010802 default {
10803 lappend revtreeargs $arg
10804 }
10805 }
10806 incr i
10807}
10808
Alexander Gavrilov39816d62008-08-23 12:27:44 +040010809if {$selecthead eq "HEAD"} {
10810 set selecthead {}
10811}
10812
Paul Mackerrascdaee5d2007-07-12 22:29:49 +100010813if {$i >= [llength $argv] && $revtreeargs ne {}} {
Paul Mackerras3ed31a82008-04-26 16:00:00 +100010814 # no -- on command line, but some arguments (other than --argscmd)
Paul Mackerras098dd8a2006-05-03 09:32:53 +100010815 if {[catch {
Timo Hirvonen8974c6f2006-05-24 10:57:40 +030010816 set f [eval exec git rev-parse --no-revs --no-flags $revtreeargs]
Paul Mackerras098dd8a2006-05-03 09:32:53 +100010817 set cmdline_files [split $f "\n"]
10818 set n [llength $cmdline_files]
10819 set revtreeargs [lrange $revtreeargs 0 end-$n]
Paul Mackerrascdaee5d2007-07-12 22:29:49 +100010820 # Unfortunately git rev-parse doesn't produce an error when
10821 # something is both a revision and a filename. To be consistent
10822 # with git log and git rev-list, check revtreeargs for filenames.
10823 foreach arg $revtreeargs {
10824 if {[file exists $arg]} {
Christian Stimmingd990ced2007-11-07 18:42:55 +010010825 show_error {} . [mc "Ambiguous argument '%s': both revision\
10826 and filename" $arg]
Paul Mackerrascdaee5d2007-07-12 22:29:49 +100010827 exit 1
10828 }
10829 }
Paul Mackerras098dd8a2006-05-03 09:32:53 +100010830 } err]} {
10831 # unfortunately we get both stdout and stderr in $err,
10832 # so look for "fatal:".
10833 set i [string first "fatal:" $err]
10834 if {$i > 0} {
Junio C Hamanob5e09632006-05-26 00:07:15 -070010835 set err [string range $err [expr {$i + 6}] end]
Paul Mackerras098dd8a2006-05-03 09:32:53 +100010836 }
Christian Stimmingd990ced2007-11-07 18:42:55 +010010837 show_error {} . "[mc "Bad arguments to gitk:"]\n$err"
Paul Mackerras098dd8a2006-05-03 09:32:53 +100010838 exit 1
10839 }
10840}
10841
Paul Mackerras219ea3a2006-09-07 10:21:39 +100010842set nullid "0000000000000000000000000000000000000000"
Paul Mackerras8f489362007-07-13 19:49:37 +100010843set nullid2 "0000000000000000000000000000000000000001"
Thomas Arcila314f5de2008-03-24 12:55:36 +010010844set nullfile "/dev/null"
Paul Mackerras8f489362007-07-13 19:49:37 +100010845
Paul Mackerras32f1b3e2007-09-28 21:27:39 +100010846set have_tk85 [expr {[package vcompare $tk_version "8.5"] >= 0}]
Paul Mackerras219ea3a2006-09-07 10:21:39 +100010847
Paul Mackerras7eb3cb92007-06-17 14:45:00 +100010848set runq {}
Paul Mackerrasd6982062005-08-06 22:06:06 +100010849set history {}
10850set historyindex 0
Paul Mackerras908c3582006-05-20 09:38:11 +100010851set fh_serial 0
Paul Mackerras908c3582006-05-20 09:38:11 +100010852set nhl_names {}
Paul Mackerras63b79192006-05-20 21:31:52 +100010853set highlight_paths {}
Paul Mackerras687c8762007-09-22 12:49:33 +100010854set findpattern {}
Paul Mackerras1902c272006-05-25 21:25:13 +100010855set searchdirn -forwards
Paul Mackerras28593d32008-11-13 23:01:46 +110010856set boldids {}
10857set boldnameids {}
Paul Mackerrasa8d610a2007-04-19 11:39:12 +100010858set diffelide {0 0}
Paul Mackerras4fb0fa12007-07-04 19:43:51 +100010859set markingmatches 0
Paul Mackerras97645682007-08-23 22:24:38 +100010860set linkentercount 0
Paul Mackerras03800812007-08-29 21:45:21 +100010861set need_redisplay 0
10862set nrows_drawn 0
Paul Mackerras32f1b3e2007-09-28 21:27:39 +100010863set firsttabstop 0
Paul Mackerras9f1afe02006-02-19 22:44:47 +110010864
Paul Mackerras50b44ec2006-04-04 10:16:22 +100010865set nextviewnum 1
10866set curview 0
Paul Mackerrasa90a6d22006-04-25 17:12:46 +100010867set selectedview 0
Christian Stimmingb007ee22007-11-07 18:44:35 +010010868set selectedhlview [mc "None"]
10869set highlight_related [mc "None"]
Paul Mackerras687c8762007-09-22 12:49:33 +100010870set highlight_files {}
Paul Mackerras50b44ec2006-04-04 10:16:22 +100010871set viewfiles(0) {}
Paul Mackerrasa90a6d22006-04-25 17:12:46 +100010872set viewperm(0) 0
Paul Mackerras098dd8a2006-05-03 09:32:53 +100010873set viewargs(0) {}
Yann Dirson2d480852008-02-21 21:23:31 +010010874set viewargscmd(0) {}
Paul Mackerras50b44ec2006-04-04 10:16:22 +100010875
Paul Mackerras94b4a692008-05-20 20:51:06 +100010876set selectedline {}
Paul Mackerras6df74032008-05-11 22:13:02 +100010877set numcommits 0
Paul Mackerras7fcc92b2007-12-03 10:33:01 +110010878set loginstance 0
Paul Mackerras098dd8a2006-05-03 09:32:53 +100010879set cmdlineok 0
Paul Mackerras1db95b02005-05-09 04:08:39 +000010880set stopped 0
Paul Mackerras1db95b02005-05-09 04:08:39 +000010881set stuffsaved 0
Paul Mackerras74daedb2005-06-27 19:27:32 +100010882set patchnum 0
Paul Mackerras219ea3a2006-09-07 10:21:39 +100010883set lserial 0
David Aguilarcb8329a2008-03-10 03:54:56 -070010884set isworktree [expr {[exec git rev-parse --is-inside-work-tree] == "true"}]
Paul Mackerras1db95b02005-05-09 04:08:39 +000010885setcoords
Paul Mackerrasd94f8cd2006-04-06 10:18:23 +100010886makewindow
Giuseppe Bilotta37871b72009-03-19 01:54:17 -070010887catch {
10888 image create photo gitlogo -width 16 -height 16
10889
10890 image create photo gitlogominus -width 4 -height 2
10891 gitlogominus put #C00000 -to 0 0 4 2
10892 gitlogo copy gitlogominus -to 1 5
10893 gitlogo copy gitlogominus -to 6 5
10894 gitlogo copy gitlogominus -to 11 5
10895 image delete gitlogominus
10896
10897 image create photo gitlogoplus -width 4 -height 4
10898 gitlogoplus put #008000 -to 1 0 3 4
10899 gitlogoplus put #008000 -to 0 1 4 3
10900 gitlogo copy gitlogoplus -to 1 9
10901 gitlogo copy gitlogoplus -to 6 9
10902 gitlogo copy gitlogoplus -to 11 9
10903 image delete gitlogoplus
10904
Stephen Boydd38d7d42009-03-19 01:54:18 -070010905 image create photo gitlogo32 -width 32 -height 32
10906 gitlogo32 copy gitlogo -zoom 2 2
10907
10908 wm iconphoto . -default gitlogo gitlogo32
Giuseppe Bilotta37871b72009-03-19 01:54:17 -070010909}
Paul Mackerras0eafba12007-07-23 21:35:03 +100010910# wait for the window to become visible
10911tkwait visibility .
Doug Maxey6c283322006-12-10 14:31:46 -060010912wm title . "[file tail $argv0]: [file tail [pwd]]"
Paul Mackerras887fe3c2005-05-21 07:35:37 +000010913readrefs
Paul Mackerrasa8aaf192006-04-23 22:45:55 +100010914
Yann Dirson2d480852008-02-21 21:23:31 +010010915if {$cmdline_files ne {} || $revtreeargs ne {} || $revtreeargscmd ne {}} {
Paul Mackerras50b44ec2006-04-04 10:16:22 +100010916 # create a view for the files/dirs specified on the command line
10917 set curview 1
Paul Mackerrasa90a6d22006-04-25 17:12:46 +100010918 set selectedview 1
Paul Mackerras50b44ec2006-04-04 10:16:22 +100010919 set nextviewnum 2
Christian Stimmingd990ced2007-11-07 18:42:55 +010010920 set viewname(1) [mc "Command line"]
Paul Mackerras50b44ec2006-04-04 10:16:22 +100010921 set viewfiles(1) $cmdline_files
Paul Mackerras098dd8a2006-05-03 09:32:53 +100010922 set viewargs(1) $revtreeargs
Yann Dirson2d480852008-02-21 21:23:31 +010010923 set viewargscmd(1) $revtreeargscmd
Paul Mackerrasa90a6d22006-04-25 17:12:46 +100010924 set viewperm(1) 0
Paul Mackerras3ed31a82008-04-26 16:00:00 +100010925 set vdatemode(1) 0
Paul Mackerrasda7c24d2006-05-02 11:15:29 +100010926 addviewmenu 1
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +110010927 .bar.view entryconf [mca "Edit view..."] -state normal
10928 .bar.view entryconf [mca "Delete view"] -state normal
Paul Mackerras50b44ec2006-04-04 10:16:22 +100010929}
Paul Mackerrasa90a6d22006-04-25 17:12:46 +100010930
10931if {[info exists permviews]} {
10932 foreach v $permviews {
10933 set n $nextviewnum
10934 incr nextviewnum
10935 set viewname($n) [lindex $v 0]
10936 set viewfiles($n) [lindex $v 1]
Paul Mackerras098dd8a2006-05-03 09:32:53 +100010937 set viewargs($n) [lindex $v 2]
Yann Dirson2d480852008-02-21 21:23:31 +010010938 set viewargscmd($n) [lindex $v 3]
Paul Mackerrasa90a6d22006-04-25 17:12:46 +100010939 set viewperm($n) 1
Paul Mackerrasda7c24d2006-05-02 11:15:29 +100010940 addviewmenu $n
Paul Mackerrasa90a6d22006-04-25 17:12:46 +100010941 }
10942}
Johannes Sixte4df5192008-12-18 08:30:49 +010010943
10944if {[tk windowingsystem] eq "win32"} {
10945 focus -force .
10946}
10947
Alexander Gavrilov567c34e2008-07-26 20:13:45 +040010948getcommits {}