blob: 3520bdaebc29fd6c93724b0a46484ee5e9403831 [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 Mackerras6c626a02014-01-21 22:02:27 +11005# Copyright © 2005-2014 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
Pat Thoytsd93f1712009-04-17 01:24:35 +010010package require Tk
11
Martin von Zweigbergk74cb8842011-05-23 22:44:08 -040012proc hasworktree {} {
13 return [expr {[exec git rev-parse --is-bare-repository] == "false" &&
14 [exec git rev-parse --is-inside-git-dir] == "false"}]
15}
16
Zbigniew Jędrzejewski-Szmek3878e632011-11-09 17:28:28 +010017proc reponame {} {
18 global gitdir
19 set n [file normalize $gitdir]
20 if {[string match "*/.git" $n]} {
21 set n [string range $n 0 end-5]
22 }
23 return [file tail $n]
24}
25
Pat Thoyts65bb0bd2011-12-13 16:50:50 +000026proc gitworktree {} {
27 variable _gitworktree
28 if {[info exists _gitworktree]} {
29 return $_gitworktree
30 }
31 # v1.7.0 introduced --show-toplevel to return the canonical work-tree
32 if {[catch {set _gitworktree [exec git rev-parse --show-toplevel]}]} {
33 # try to set work tree from environment, core.worktree or use
34 # cdup to obtain a relative path to the top of the worktree. If
35 # run from the top, the ./ prefix ensures normalize expands pwd.
36 if {[catch { set _gitworktree $env(GIT_WORK_TREE) }]} {
37 catch {set _gitworktree [exec git config --get core.worktree]}
38 if {$_gitworktree eq ""} {
39 set _gitworktree [file normalize ./[exec git rev-parse --show-cdup]]
40 }
41 }
42 }
43 return $_gitworktree
44}
45
Paul Mackerras7eb3cb92007-06-17 14:45:00 +100046# A simple scheduler for compute-intensive stuff.
47# The aim is to make sure that event handlers for GUI actions can
48# run at least every 50-100 ms. Unfortunately fileevent handlers are
49# run before X event handlers, so reading from a fast source can
50# make the GUI completely unresponsive.
51proc run args {
Alexander Gavrilovdf75e862008-08-09 14:41:50 +040052 global isonrunq runq currunq
Paul Mackerras7eb3cb92007-06-17 14:45:00 +100053
54 set script $args
55 if {[info exists isonrunq($script)]} return
Alexander Gavrilovdf75e862008-08-09 14:41:50 +040056 if {$runq eq {} && ![info exists currunq]} {
Paul Mackerras7eb3cb92007-06-17 14:45:00 +100057 after idle dorunq
58 }
59 lappend runq [list {} $script]
60 set isonrunq($script) 1
61}
62
63proc filerun {fd script} {
64 fileevent $fd readable [list filereadable $fd $script]
65}
66
67proc filereadable {fd script} {
Alexander Gavrilovdf75e862008-08-09 14:41:50 +040068 global runq currunq
Paul Mackerras7eb3cb92007-06-17 14:45:00 +100069
70 fileevent $fd readable {}
Alexander Gavrilovdf75e862008-08-09 14:41:50 +040071 if {$runq eq {} && ![info exists currunq]} {
Paul Mackerras7eb3cb92007-06-17 14:45:00 +100072 after idle dorunq
73 }
74 lappend runq [list $fd $script]
75}
76
Paul Mackerras7fcc92b2007-12-03 10:33:01 +110077proc nukefile {fd} {
78 global runq
79
80 for {set i 0} {$i < [llength $runq]} {} {
81 if {[lindex $runq $i 0] eq $fd} {
82 set runq [lreplace $runq $i $i]
83 } else {
84 incr i
85 }
86 }
87}
88
Paul Mackerras7eb3cb92007-06-17 14:45:00 +100089proc dorunq {} {
Alexander Gavrilovdf75e862008-08-09 14:41:50 +040090 global isonrunq runq currunq
Paul Mackerras7eb3cb92007-06-17 14:45:00 +100091
92 set tstart [clock clicks -milliseconds]
93 set t0 $tstart
Paul Mackerras7fcc92b2007-12-03 10:33:01 +110094 while {[llength $runq] > 0} {
Paul Mackerras7eb3cb92007-06-17 14:45:00 +100095 set fd [lindex $runq 0 0]
96 set script [lindex $runq 0 1]
Alexander Gavrilovdf75e862008-08-09 14:41:50 +040097 set currunq [lindex $runq 0]
98 set runq [lrange $runq 1 end]
Paul Mackerras7eb3cb92007-06-17 14:45:00 +100099 set repeat [eval $script]
Alexander Gavrilovdf75e862008-08-09 14:41:50 +0400100 unset currunq
Paul Mackerras7eb3cb92007-06-17 14:45:00 +1000101 set t1 [clock clicks -milliseconds]
102 set t [expr {$t1 - $t0}]
Paul Mackerras7eb3cb92007-06-17 14:45:00 +1000103 if {$repeat ne {} && $repeat} {
104 if {$fd eq {} || $repeat == 2} {
105 # script returns 1 if it wants to be readded
106 # file readers return 2 if they could do more straight away
107 lappend runq [list $fd $script]
108 } else {
109 fileevent $fd readable [list filereadable $fd $script]
110 }
111 } elseif {$fd eq {}} {
112 unset isonrunq($script)
113 }
114 set t0 $t1
115 if {$t1 - $tstart >= 80} break
116 }
117 if {$runq ne {}} {
118 after idle dorunq
119 }
120}
121
Alexander Gavrilove439e092008-07-13 16:40:47 +0400122proc reg_instance {fd} {
123 global commfd leftover loginstance
124
125 set i [incr loginstance]
126 set commfd($i) $fd
127 set leftover($i) {}
128 return $i
129}
130
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000131proc unmerged_files {files} {
132 global nr_unmerged
133
134 # find the list of unmerged files
135 set mlist {}
136 set nr_unmerged 0
137 if {[catch {
138 set fd [open "| git ls-files -u" r]
139 } err]} {
140 show_error {} . "[mc "Couldn't get list of unmerged files:"] $err"
141 exit 1
142 }
143 while {[gets $fd line] >= 0} {
144 set i [string first "\t" $line]
145 if {$i < 0} continue
146 set fname [string range $line [expr {$i+1}] end]
147 if {[lsearch -exact $mlist $fname] >= 0} continue
148 incr nr_unmerged
149 if {$files eq {} || [path_filter $files $fname]} {
150 lappend mlist $fname
151 }
152 }
153 catch {close $fd}
154 return $mlist
155}
156
157proc parseviewargs {n arglist} {
Christian Couderc2f2dab2009-12-12 05:52:39 +0100158 global vdatemode vmergeonly vflags vdflags vrevs vfiltered vorigargs env
Thomas Rast9403bd02013-11-16 18:37:43 +0100159 global vinlinediff
Thomas Rastae4e3ff2010-10-16 12:15:10 +0200160 global worddiff git_version
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000161
162 set vdatemode($n) 0
163 set vmergeonly($n) 0
Thomas Rast9403bd02013-11-16 18:37:43 +0100164 set vinlinediff($n) 0
Paul Mackerrasee66e082008-05-09 10:14:07 +1000165 set glflags {}
166 set diffargs {}
167 set nextisval 0
168 set revargs {}
169 set origargs $arglist
170 set allknown 1
171 set filtered 0
172 set i -1
173 foreach arg $arglist {
174 incr i
175 if {$nextisval} {
176 lappend glflags $arg
177 set nextisval 0
178 continue
179 }
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000180 switch -glob -- $arg {
181 "-d" -
182 "--date-order" {
183 set vdatemode($n) 1
Paul Mackerrasee66e082008-05-09 10:14:07 +1000184 # remove from origargs in case we hit an unknown option
185 set origargs [lreplace $origargs $i $i]
186 incr i -1
187 }
Paul Mackerrasee66e082008-05-09 10:14:07 +1000188 "-[puabwcrRBMC]" -
189 "--no-renames" - "--full-index" - "--binary" - "--abbrev=*" -
190 "--find-copies-harder" - "-l*" - "--ext-diff" - "--no-ext-diff" -
191 "--src-prefix=*" - "--dst-prefix=*" - "--no-prefix" -
192 "-O*" - "--text" - "--full-diff" - "--ignore-space-at-eol" -
193 "--ignore-space-change" - "-U*" - "--unified=*" {
Paul Mackerras29582282008-11-18 19:44:20 +1100194 # These request or affect diff output, which we don't want.
195 # Some could be used to set our defaults for diff display.
Paul Mackerrasee66e082008-05-09 10:14:07 +1000196 lappend diffargs $arg
197 }
Paul Mackerrasee66e082008-05-09 10:14:07 +1000198 "--raw" - "--patch-with-raw" - "--patch-with-stat" -
Thomas Rastae4e3ff2010-10-16 12:15:10 +0200199 "--name-only" - "--name-status" - "--color" -
Paul Mackerrasee66e082008-05-09 10:14:07 +1000200 "--log-size" - "--pretty=*" - "--decorate" - "--abbrev-commit" -
201 "--cc" - "-z" - "--header" - "--parents" - "--boundary" -
202 "--no-color" - "-g" - "--walk-reflogs" - "--no-walk" -
203 "--timestamp" - "relative-date" - "--date=*" - "--stdin" -
204 "--objects" - "--objects-edge" - "--reverse" {
Paul Mackerras29582282008-11-18 19:44:20 +1100205 # These cause our parsing of git log's output to fail, or else
206 # they're options we want to set ourselves, so ignore them.
Paul Mackerrasee66e082008-05-09 10:14:07 +1000207 }
Thomas Rastae4e3ff2010-10-16 12:15:10 +0200208 "--color-words*" - "--word-diff=color" {
209 # These trigger a word diff in the console interface,
210 # so help the user by enabling our own support
211 if {[package vcompare $git_version "1.7.2"] >= 0} {
212 set worddiff [mc "Color words"]
213 }
214 }
215 "--word-diff*" {
216 if {[package vcompare $git_version "1.7.2"] >= 0} {
217 set worddiff [mc "Markup words"]
218 }
219 }
Paul Mackerrasee66e082008-05-09 10:14:07 +1000220 "--stat=*" - "--numstat" - "--shortstat" - "--summary" -
221 "--check" - "--exit-code" - "--quiet" - "--topo-order" -
222 "--full-history" - "--dense" - "--sparse" -
223 "--follow" - "--left-right" - "--encoding=*" {
Paul Mackerras29582282008-11-18 19:44:20 +1100224 # These are harmless, and some are even useful
Paul Mackerrasee66e082008-05-09 10:14:07 +1000225 lappend glflags $arg
226 }
Paul Mackerrasee66e082008-05-09 10:14:07 +1000227 "--diff-filter=*" - "--no-merges" - "--unpacked" -
228 "--max-count=*" - "--skip=*" - "--since=*" - "--after=*" -
229 "--until=*" - "--before=*" - "--max-age=*" - "--min-age=*" -
230 "--author=*" - "--committer=*" - "--grep=*" - "-[iE]" -
231 "--remove-empty" - "--first-parent" - "--cherry-pick" -
Thomas Rast71846c52013-11-16 18:37:40 +0100232 "-S*" - "-G*" - "--pickaxe-all" - "--pickaxe-regex" -
Dirk Suesserottf687aaa2009-05-21 15:35:40 +0200233 "--simplify-by-decoration" {
Paul Mackerras29582282008-11-18 19:44:20 +1100234 # These mean that we get a subset of the commits
Paul Mackerrasee66e082008-05-09 10:14:07 +1000235 set filtered 1
236 lappend glflags $arg
237 }
Thomas Rastce2c58c2013-11-16 18:37:44 +0100238 "-L*" {
239 # Line-log with 'stuck' argument (unstuck form is
240 # not supported)
241 set filtered 1
242 set vinlinediff($n) 1
243 set allknown 0
244 lappend glflags $arg
245 }
Paul Mackerrasee66e082008-05-09 10:14:07 +1000246 "-n" {
Paul Mackerras29582282008-11-18 19:44:20 +1100247 # This appears to be the only one that has a value as a
248 # separate word following it
Paul Mackerrasee66e082008-05-09 10:14:07 +1000249 set filtered 1
250 set nextisval 1
251 lappend glflags $arg
252 }
Paul Mackerras6e7e87c2008-12-02 09:17:46 +1100253 "--not" - "--all" {
Paul Mackerrasee66e082008-05-09 10:14:07 +1000254 lappend revargs $arg
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000255 }
256 "--merge" {
257 set vmergeonly($n) 1
Paul Mackerrasee66e082008-05-09 10:14:07 +1000258 # git rev-parse doesn't understand --merge
259 lappend revargs --gitk-symmetric-diff-marker MERGE_HEAD...HEAD
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000260 }
Christian Couderc2f2dab2009-12-12 05:52:39 +0100261 "--no-replace-objects" {
262 set env(GIT_NO_REPLACE_OBJECTS) "1"
263 }
Paul Mackerrasee66e082008-05-09 10:14:07 +1000264 "-*" {
Paul Mackerras29582282008-11-18 19:44:20 +1100265 # Other flag arguments including -<n>
Paul Mackerrasee66e082008-05-09 10:14:07 +1000266 if {[string is digit -strict [string range $arg 1 end]]} {
267 set filtered 1
268 } else {
269 # a flag argument that we don't recognize;
270 # that means we can't optimize
271 set allknown 0
272 }
273 lappend glflags $arg
274 }
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000275 default {
Paul Mackerras29582282008-11-18 19:44:20 +1100276 # Non-flag arguments specify commits or ranges of commits
Paul Mackerrasee66e082008-05-09 10:14:07 +1000277 if {[string match "*...*" $arg]} {
278 lappend revargs --gitk-symmetric-diff-marker
279 }
280 lappend revargs $arg
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000281 }
282 }
283 }
Paul Mackerrasee66e082008-05-09 10:14:07 +1000284 set vdflags($n) $diffargs
285 set vflags($n) $glflags
286 set vrevs($n) $revargs
287 set vfiltered($n) $filtered
288 set vorigargs($n) $origargs
289 return $allknown
290}
291
292proc parseviewrevs {view revs} {
293 global vposids vnegids
294
295 if {$revs eq {}} {
296 set revs HEAD
297 }
298 if {[catch {set ids [eval exec git rev-parse $revs]} err]} {
299 # we get stdout followed by stderr in $err
300 # for an unknown rev, git rev-parse echoes it and then errors out
301 set errlines [split $err "\n"]
302 set badrev {}
303 for {set l 0} {$l < [llength $errlines]} {incr l} {
304 set line [lindex $errlines $l]
305 if {!([string length $line] == 40 && [string is xdigit $line])} {
306 if {[string match "fatal:*" $line]} {
307 if {[string match "fatal: ambiguous argument*" $line]
308 && $badrev ne {}} {
309 if {[llength $badrev] == 1} {
310 set err "unknown revision $badrev"
311 } else {
312 set err "unknown revisions: [join $badrev ", "]"
313 }
314 } else {
315 set err [join [lrange $errlines $l end] "\n"]
316 }
317 break
318 }
319 lappend badrev $line
320 }
Pat Thoytsd93f1712009-04-17 01:24:35 +0100321 }
Christian Stimming3945d2c2008-09-12 11:39:43 +0200322 error_popup "[mc "Error parsing revisions:"] $err"
Paul Mackerrasee66e082008-05-09 10:14:07 +1000323 return {}
324 }
325 set ret {}
326 set pos {}
327 set neg {}
328 set sdm 0
329 foreach id [split $ids "\n"] {
330 if {$id eq "--gitk-symmetric-diff-marker"} {
331 set sdm 4
332 } elseif {[string match "^*" $id]} {
333 if {$sdm != 1} {
334 lappend ret $id
335 if {$sdm == 3} {
336 set sdm 0
337 }
338 }
339 lappend neg [string range $id 1 end]
340 } else {
341 if {$sdm != 2} {
342 lappend ret $id
343 } else {
Thomas Rast2b1fbf92009-08-05 23:15:36 +0200344 lset ret end $id...[lindex $ret end]
Paul Mackerrasee66e082008-05-09 10:14:07 +1000345 }
346 lappend pos $id
347 }
348 incr sdm -1
349 }
350 set vposids($view) $pos
351 set vnegids($view) $neg
352 return $ret
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000353}
354
Paul Mackerrasf9e0b6f2008-03-04 21:14:17 +1100355# Start off a git log process and arrange to read its output
Paul Mackerrasda7c24d2006-05-02 11:15:29 +1000356proc start_rev_list {view} {
Paul Mackerras6df74032008-05-11 22:13:02 +1000357 global startmsecs commitidx viewcomplete curview
Alexander Gavrilove439e092008-07-13 16:40:47 +0400358 global tclencoding
Paul Mackerrasee66e082008-05-09 10:14:07 +1000359 global viewargs viewargscmd viewfiles vfilelimit
Paul Mackerrasd375ef92008-10-21 10:18:12 +1100360 global showlocalchanges
Alexander Gavrilove439e092008-07-13 16:40:47 +0400361 global viewactive viewinstances vmergeonly
Paul Mackerrascdc84292008-11-18 19:54:14 +1100362 global mainheadid viewmainheadid viewmainheadid_orig
Paul Mackerrasee66e082008-05-09 10:14:07 +1000363 global vcanopt vflags vrevs vorigargs
Kirill Smelkov7defefb2010-05-20 13:50:41 +0400364 global show_notes
Paul Mackerras38ad0912005-12-01 22:42:46 +1100365
366 set startmsecs [clock clicks -milliseconds]
Paul Mackerrasda7c24d2006-05-02 11:15:29 +1000367 set commitidx($view) 0
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000368 # these are set this way for the error exits
369 set viewcomplete($view) 1
370 set viewactive($view) 0
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100371 varcinit $view
372
Yann Dirson2d480852008-02-21 21:23:31 +0100373 set args $viewargs($view)
374 if {$viewargscmd($view) ne {}} {
375 if {[catch {
376 set str [exec sh -c $viewargscmd($view)]
377 } err]} {
Christian Stimming3945d2c2008-09-12 11:39:43 +0200378 error_popup "[mc "Error executing --argscmd command:"] $err"
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000379 return 0
Yann Dirson2d480852008-02-21 21:23:31 +0100380 }
381 set args [concat $args [split $str "\n"]]
382 }
Paul Mackerrasee66e082008-05-09 10:14:07 +1000383 set vcanopt($view) [parseviewargs $view $args]
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000384
385 set files $viewfiles($view)
386 if {$vmergeonly($view)} {
387 set files [unmerged_files $files]
388 if {$files eq {}} {
389 global nr_unmerged
390 if {$nr_unmerged == 0} {
391 error_popup [mc "No files selected: --merge specified but\
392 no files are unmerged."]
393 } else {
394 error_popup [mc "No files selected: --merge specified but\
395 no unmerged files are within file limit."]
396 }
397 return 0
398 }
399 }
400 set vfilelimit($view) $files
401
Paul Mackerrasee66e082008-05-09 10:14:07 +1000402 if {$vcanopt($view)} {
403 set revs [parseviewrevs $view $vrevs($view)]
404 if {$revs eq {}} {
405 return 0
406 }
407 set args [concat $vflags($view) $revs]
408 } else {
409 set args $vorigargs($view)
410 }
411
Paul Mackerras418c4c72006-02-07 09:10:18 +1100412 if {[catch {
Kirill Smelkov7defefb2010-05-20 13:50:41 +0400413 set fd [open [concat | git log --no-color -z --pretty=raw $show_notes \
414 --parents --boundary $args "--" $files] r]
Paul Mackerras418c4c72006-02-07 09:10:18 +1100415 } err]} {
Paul Mackerras00abadb2007-12-20 10:25:50 +1100416 error_popup "[mc "Error executing git log:"] $err"
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000417 return 0
Paul Mackerras38ad0912005-12-01 22:42:46 +1100418 }
Alexander Gavrilove439e092008-07-13 16:40:47 +0400419 set i [reg_instance $fd]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100420 set viewinstances($view) [list $i]
Paul Mackerrascdc84292008-11-18 19:54:14 +1100421 set viewmainheadid($view) $mainheadid
422 set viewmainheadid_orig($view) $mainheadid
423 if {$files ne {} && $mainheadid ne {}} {
424 get_viewmainhead $view
425 }
426 if {$showlocalchanges && $viewmainheadid($view) ne {}} {
427 interestedin $viewmainheadid($view) dodiffindex
Paul Mackerras3e6b8932007-09-15 09:33:39 +1000428 }
Mark Levedahl86da5b62007-07-17 18:42:04 -0400429 fconfigure $fd -blocking 0 -translation lf -eofchar {}
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +1100430 if {$tclencoding != {}} {
Paul Mackerrasda7c24d2006-05-02 11:15:29 +1000431 fconfigure $fd -encoding $tclencoding
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +1100432 }
Paul Mackerrasf806f0f2008-02-24 12:16:56 +1100433 filerun $fd [list getcommitlines $fd $i $view 0]
Christian Stimmingd990ced2007-11-07 18:42:55 +0100434 nowbusy $view [mc "Reading"]
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000435 set viewcomplete($view) 0
436 set viewactive($view) 1
437 return 1
Paul Mackerras38ad0912005-12-01 22:42:46 +1100438}
439
Alexander Gavrilove2f90ee2008-07-12 16:09:28 +0400440proc stop_instance {inst} {
441 global commfd leftover
442
443 set fd $commfd($inst)
444 catch {
445 set pid [pid $fd]
Alexander Gavrilovb6326e92008-07-15 00:35:42 +0400446
447 if {$::tcl_platform(platform) eq {windows}} {
448 exec kill -f $pid
449 } else {
450 exec kill $pid
451 }
Alexander Gavrilove2f90ee2008-07-12 16:09:28 +0400452 }
453 catch {close $fd}
454 nukefile $fd
455 unset commfd($inst)
456 unset leftover($inst)
457}
458
459proc stop_backends {} {
460 global commfd
461
462 foreach inst [array names commfd] {
463 stop_instance $inst
464 }
465}
466
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100467proc stop_rev_list {view} {
Alexander Gavrilove2f90ee2008-07-12 16:09:28 +0400468 global viewinstances
Paul Mackerras22626ef2006-04-17 09:56:02 +1000469
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100470 foreach inst $viewinstances($view) {
Alexander Gavrilove2f90ee2008-07-12 16:09:28 +0400471 stop_instance $inst
Paul Mackerras22626ef2006-04-17 09:56:02 +1000472 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100473 set viewinstances($view) {}
Paul Mackerras22626ef2006-04-17 09:56:02 +1000474}
475
Alexander Gavrilov567c34e2008-07-26 20:13:45 +0400476proc reset_pending_select {selid} {
Alexander Gavrilov39816d62008-08-23 12:27:44 +0400477 global pending_select mainheadid selectheadid
Alexander Gavrilov567c34e2008-07-26 20:13:45 +0400478
479 if {$selid ne {}} {
480 set pending_select $selid
Alexander Gavrilov39816d62008-08-23 12:27:44 +0400481 } elseif {$selectheadid ne {}} {
482 set pending_select $selectheadid
Alexander Gavrilov567c34e2008-07-26 20:13:45 +0400483 } else {
484 set pending_select $mainheadid
485 }
486}
487
488proc getcommits {selid} {
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000489 global canv curview need_redisplay viewactive
Sven Verdoolaegeb5c2f302005-11-29 22:15:51 +0100490
Paul Mackerrasda7c24d2006-05-02 11:15:29 +1000491 initlayout
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000492 if {[start_rev_list $curview]} {
Alexander Gavrilov567c34e2008-07-26 20:13:45 +0400493 reset_pending_select $selid
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000494 show_status [mc "Reading commits..."]
495 set need_redisplay 1
496 } else {
497 show_status [mc "No commits selected"]
498 }
Paul Mackerras1d10f362005-05-15 12:55:47 +0000499}
500
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100501proc updatecommits {} {
Paul Mackerrasee66e082008-05-09 10:14:07 +1000502 global curview vcanopt vorigargs vfilelimit viewinstances
Alexander Gavrilove439e092008-07-13 16:40:47 +0400503 global viewactive viewcomplete tclencoding
504 global startmsecs showneartags showlocalchanges
Paul Mackerrascdc84292008-11-18 19:54:14 +1100505 global mainheadid viewmainheadid viewmainheadid_orig pending_select
Martin von Zweigbergk74cb8842011-05-23 22:44:08 -0400506 global hasworktree
Paul Mackerrasee66e082008-05-09 10:14:07 +1000507 global varcid vposids vnegids vflags vrevs
Kirill Smelkov7defefb2010-05-20 13:50:41 +0400508 global show_notes
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100509
Martin von Zweigbergk74cb8842011-05-23 22:44:08 -0400510 set hasworktree [hasworktree]
Paul Mackerrasfc2a2562007-12-26 23:03:43 +1100511 rereadrefs
Paul Mackerrascdc84292008-11-18 19:54:14 +1100512 set view $curview
513 if {$mainheadid ne $viewmainheadid_orig($view)} {
514 if {$showlocalchanges} {
Paul Mackerraseb5f8c92007-12-29 21:13:34 +1100515 dohidelocalchanges
516 }
Paul Mackerrascdc84292008-11-18 19:54:14 +1100517 set viewmainheadid($view) $mainheadid
518 set viewmainheadid_orig($view) $mainheadid
519 if {$vfilelimit($view) ne {}} {
520 get_viewmainhead $view
Paul Mackerraseb5f8c92007-12-29 21:13:34 +1100521 }
522 }
Paul Mackerrascdc84292008-11-18 19:54:14 +1100523 if {$showlocalchanges} {
524 doshowlocalchanges
525 }
Paul Mackerrasee66e082008-05-09 10:14:07 +1000526 if {$vcanopt($view)} {
527 set oldpos $vposids($view)
528 set oldneg $vnegids($view)
529 set revs [parseviewrevs $view $vrevs($view)]
530 if {$revs eq {}} {
531 return
532 }
533 # note: getting the delta when negative refs change is hard,
534 # and could require multiple git log invocations, so in that
535 # case we ask git log for all the commits (not just the delta)
536 if {$oldneg eq $vnegids($view)} {
537 set newrevs {}
538 set npos 0
539 # take out positive refs that we asked for before or
540 # that we have already seen
541 foreach rev $revs {
542 if {[string length $rev] == 40} {
543 if {[lsearch -exact $oldpos $rev] < 0
544 && ![info exists varcid($view,$rev)]} {
545 lappend newrevs $rev
546 incr npos
547 }
548 } else {
549 lappend $newrevs $rev
550 }
551 }
552 if {$npos == 0} return
553 set revs $newrevs
554 set vposids($view) [lsort -unique [concat $oldpos $vposids($view)]]
555 }
556 set args [concat $vflags($view) $revs --not $oldpos]
557 } else {
558 set args $vorigargs($view)
559 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100560 if {[catch {
Kirill Smelkov7defefb2010-05-20 13:50:41 +0400561 set fd [open [concat | git log --no-color -z --pretty=raw $show_notes \
562 --parents --boundary $args "--" $vfilelimit($view)] r]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100563 } err]} {
Christian Stimming3945d2c2008-09-12 11:39:43 +0200564 error_popup "[mc "Error executing git log:"] $err"
Paul Mackerrasee66e082008-05-09 10:14:07 +1000565 return
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100566 }
567 if {$viewactive($view) == 0} {
568 set startmsecs [clock clicks -milliseconds]
569 }
Alexander Gavrilove439e092008-07-13 16:40:47 +0400570 set i [reg_instance $fd]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100571 lappend viewinstances($view) $i
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100572 fconfigure $fd -blocking 0 -translation lf -eofchar {}
573 if {$tclencoding != {}} {
574 fconfigure $fd -encoding $tclencoding
575 }
Paul Mackerrasf806f0f2008-02-24 12:16:56 +1100576 filerun $fd [list getcommitlines $fd $i $view 1]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100577 incr viewactive($view)
578 set viewcomplete($view) 0
Alexander Gavrilov567c34e2008-07-26 20:13:45 +0400579 reset_pending_select {}
Michele Ballabiob56e0a92009-03-30 21:17:25 +0200580 nowbusy $view [mc "Reading"]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100581 if {$showneartags} {
582 getallcommits
583 }
584}
585
586proc reloadcommits {} {
587 global curview viewcomplete selectedline currentid thickerline
588 global showneartags treediffs commitinterest cached_commitrow
Paul Mackerras6df74032008-05-11 22:13:02 +1000589 global targetid
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100590
Alexander Gavrilov567c34e2008-07-26 20:13:45 +0400591 set selid {}
592 if {$selectedline ne {}} {
593 set selid $currentid
594 }
595
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100596 if {!$viewcomplete($curview)} {
597 stop_rev_list $curview
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100598 }
599 resetvarcs $curview
Paul Mackerras94b4a692008-05-20 20:51:06 +1000600 set selectedline {}
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100601 catch {unset currentid}
602 catch {unset thickerline}
603 catch {unset treediffs}
604 readrefs
605 changedrefs
606 if {$showneartags} {
607 getallcommits
608 }
609 clear_display
610 catch {unset commitinterest}
611 catch {unset cached_commitrow}
Paul Mackerras42a671f2008-01-02 09:59:39 +1100612 catch {unset targetid}
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100613 setcanvscroll
Alexander Gavrilov567c34e2008-07-26 20:13:45 +0400614 getcommits $selid
Paul Mackerrase7297a12008-01-15 22:30:40 +1100615 return 0
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100616}
617
Paul Mackerras6e8c8702007-07-31 21:03:06 +1000618# This makes a string representation of a positive integer which
619# sorts as a string in numerical order
620proc strrep {n} {
621 if {$n < 16} {
622 return [format "%x" $n]
623 } elseif {$n < 256} {
624 return [format "x%.2x" $n]
625 } elseif {$n < 65536} {
626 return [format "y%.4x" $n]
627 }
628 return [format "z%.8x" $n]
629}
630
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100631# Procedures used in reordering commits from git log (without
632# --topo-order) into the order for display.
633
634proc varcinit {view} {
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100635 global varcstart vupptr vdownptr vleftptr vbackptr varctok varcrow
636 global vtokmod varcmod vrowmod varcix vlastins
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100637
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100638 set varcstart($view) {{}}
639 set vupptr($view) {0}
640 set vdownptr($view) {0}
641 set vleftptr($view) {0}
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100642 set vbackptr($view) {0}
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100643 set varctok($view) {{}}
644 set varcrow($view) {{}}
645 set vtokmod($view) {}
646 set varcmod($view) 0
Paul Mackerrase5b37ac2007-12-12 18:13:51 +1100647 set vrowmod($view) 0
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100648 set varcix($view) {{}}
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100649 set vlastins($view) {0}
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100650}
651
652proc resetvarcs {view} {
653 global varcid varccommits parents children vseedcount ordertok
Paul Mackerras22387f22012-03-19 11:21:08 +1100654 global vshortids
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100655
656 foreach vid [array names varcid $view,*] {
657 unset varcid($vid)
658 unset children($vid)
659 unset parents($vid)
660 }
Paul Mackerras22387f22012-03-19 11:21:08 +1100661 foreach vid [array names vshortids $view,*] {
662 unset vshortids($vid)
663 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100664 # some commits might have children but haven't been seen yet
665 foreach vid [array names children $view,*] {
666 unset children($vid)
667 }
668 foreach va [array names varccommits $view,*] {
669 unset varccommits($va)
670 }
671 foreach vd [array names vseedcount $view,*] {
672 unset vseedcount($vd)
673 }
Paul Mackerras9257d8f2007-12-11 10:45:38 +1100674 catch {unset ordertok}
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100675}
676
Paul Mackerras468bcae2008-03-03 10:19:35 +1100677# returns a list of the commits with no children
678proc seeds {v} {
679 global vdownptr vleftptr varcstart
680
681 set ret {}
682 set a [lindex $vdownptr($v) 0]
683 while {$a != 0} {
684 lappend ret [lindex $varcstart($v) $a]
685 set a [lindex $vleftptr($v) $a]
686 }
687 return $ret
688}
689
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100690proc newvarc {view id} {
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000691 global varcid varctok parents children vdatemode
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100692 global vupptr vdownptr vleftptr vbackptr varcrow varcix varcstart
693 global commitdata commitinfo vseedcount varccommits vlastins
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100694
695 set a [llength $varctok($view)]
696 set vid $view,$id
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000697 if {[llength $children($vid)] == 0 || $vdatemode($view)} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100698 if {![info exists commitinfo($id)]} {
699 parsecommit $id $commitdata($id) 1
700 }
Anders Kaseorgf5974d92011-01-19 14:47:25 -0500701 set cdate [lindex [lindex $commitinfo($id) 4] 0]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100702 if {![string is integer -strict $cdate]} {
703 set cdate 0
704 }
705 if {![info exists vseedcount($view,$cdate)]} {
706 set vseedcount($view,$cdate) -1
707 }
708 set c [incr vseedcount($view,$cdate)]
709 set cdate [expr {$cdate ^ 0xffffffff}]
710 set tok "s[strrep $cdate][strrep $c]"
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100711 } else {
712 set tok {}
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100713 }
714 set ka 0
715 if {[llength $children($vid)] > 0} {
716 set kid [lindex $children($vid) end]
717 set k $varcid($view,$kid)
718 if {[string compare [lindex $varctok($view) $k] $tok] > 0} {
719 set ki $kid
720 set ka $k
721 set tok [lindex $varctok($view) $k]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100722 }
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100723 }
724 if {$ka != 0} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100725 set i [lsearch -exact $parents($view,$ki) $id]
726 set j [expr {[llength $parents($view,$ki)] - 1 - $i}]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100727 append tok [strrep $j]
728 }
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100729 set c [lindex $vlastins($view) $ka]
730 if {$c == 0 || [string compare $tok [lindex $varctok($view) $c]] < 0} {
731 set c $ka
732 set b [lindex $vdownptr($view) $ka]
733 } else {
734 set b [lindex $vleftptr($view) $c]
735 }
736 while {$b != 0 && [string compare $tok [lindex $varctok($view) $b]] >= 0} {
737 set c $b
738 set b [lindex $vleftptr($view) $c]
739 }
740 if {$c == $ka} {
741 lset vdownptr($view) $ka $a
742 lappend vbackptr($view) 0
743 } else {
744 lset vleftptr($view) $c $a
745 lappend vbackptr($view) $c
746 }
747 lset vlastins($view) $ka $a
748 lappend vupptr($view) $ka
749 lappend vleftptr($view) $b
750 if {$b != 0} {
751 lset vbackptr($view) $b $a
752 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100753 lappend varctok($view) $tok
754 lappend varcstart($view) $id
755 lappend vdownptr($view) 0
756 lappend varcrow($view) {}
757 lappend varcix($view) {}
Paul Mackerrase5b37ac2007-12-12 18:13:51 +1100758 set varccommits($view,$a) {}
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100759 lappend vlastins($view) 0
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100760 return $a
761}
762
763proc splitvarc {p v} {
Paul Mackerras52b8ea92009-03-02 09:38:17 +1100764 global varcid varcstart varccommits varctok vtokmod
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100765 global vupptr vdownptr vleftptr vbackptr varcix varcrow vlastins
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100766
767 set oa $varcid($v,$p)
Paul Mackerras52b8ea92009-03-02 09:38:17 +1100768 set otok [lindex $varctok($v) $oa]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100769 set ac $varccommits($v,$oa)
770 set i [lsearch -exact $varccommits($v,$oa) $p]
771 if {$i <= 0} return
772 set na [llength $varctok($v)]
773 # "%" sorts before "0"...
Paul Mackerras52b8ea92009-03-02 09:38:17 +1100774 set tok "$otok%[strrep $i]"
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100775 lappend varctok($v) $tok
776 lappend varcrow($v) {}
777 lappend varcix($v) {}
778 set varccommits($v,$oa) [lrange $ac 0 [expr {$i - 1}]]
779 set varccommits($v,$na) [lrange $ac $i end]
780 lappend varcstart($v) $p
781 foreach id $varccommits($v,$na) {
782 set varcid($v,$id) $na
783 }
784 lappend vdownptr($v) [lindex $vdownptr($v) $oa]
Paul Mackerras841ea822008-02-18 10:44:33 +1100785 lappend vlastins($v) [lindex $vlastins($v) $oa]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100786 lset vdownptr($v) $oa $na
Paul Mackerras841ea822008-02-18 10:44:33 +1100787 lset vlastins($v) $oa 0
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100788 lappend vupptr($v) $oa
789 lappend vleftptr($v) 0
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100790 lappend vbackptr($v) 0
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100791 for {set b [lindex $vdownptr($v) $na]} {$b != 0} {set b [lindex $vleftptr($v) $b]} {
792 lset vupptr($v) $b $na
793 }
Paul Mackerras52b8ea92009-03-02 09:38:17 +1100794 if {[string compare $otok $vtokmod($v)] <= 0} {
795 modify_arc $v $oa
796 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100797}
798
799proc renumbervarc {a v} {
800 global parents children varctok varcstart varccommits
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000801 global vupptr vdownptr vleftptr vbackptr vlastins varcid vtokmod vdatemode
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100802
803 set t1 [clock clicks -milliseconds]
804 set todo {}
805 set isrelated($a) 1
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100806 set kidchanged($a) 1
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100807 set ntot 0
808 while {$a != 0} {
809 if {[info exists isrelated($a)]} {
810 lappend todo $a
811 set id [lindex $varccommits($v,$a) end]
812 foreach p $parents($v,$id) {
813 if {[info exists varcid($v,$p)]} {
814 set isrelated($varcid($v,$p)) 1
815 }
816 }
817 }
818 incr ntot
819 set b [lindex $vdownptr($v) $a]
820 if {$b == 0} {
821 while {$a != 0} {
822 set b [lindex $vleftptr($v) $a]
823 if {$b != 0} break
824 set a [lindex $vupptr($v) $a]
825 }
826 }
827 set a $b
828 }
829 foreach a $todo {
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100830 if {![info exists kidchanged($a)]} continue
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100831 set id [lindex $varcstart($v) $a]
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100832 if {[llength $children($v,$id)] > 1} {
833 set children($v,$id) [lsort -command [list vtokcmp $v] \
834 $children($v,$id)]
835 }
836 set oldtok [lindex $varctok($v) $a]
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000837 if {!$vdatemode($v)} {
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100838 set tok {}
839 } else {
840 set tok $oldtok
841 }
842 set ka 0
Paul Mackerrasc8c9f3d2008-01-06 13:54:58 +1100843 set kid [last_real_child $v,$id]
844 if {$kid ne {}} {
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100845 set k $varcid($v,$kid)
846 if {[string compare [lindex $varctok($v) $k] $tok] > 0} {
847 set ki $kid
848 set ka $k
849 set tok [lindex $varctok($v) $k]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100850 }
851 }
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100852 if {$ka != 0} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100853 set i [lsearch -exact $parents($v,$ki) $id]
854 set j [expr {[llength $parents($v,$ki)] - 1 - $i}]
855 append tok [strrep $j]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100856 }
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100857 if {$tok eq $oldtok} {
858 continue
859 }
860 set id [lindex $varccommits($v,$a) end]
861 foreach p $parents($v,$id) {
862 if {[info exists varcid($v,$p)]} {
863 set kidchanged($varcid($v,$p)) 1
864 } else {
865 set sortkids($p) 1
866 }
867 }
868 lset varctok($v) $a $tok
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100869 set b [lindex $vupptr($v) $a]
870 if {$b != $ka} {
Paul Mackerras9257d8f2007-12-11 10:45:38 +1100871 if {[string compare [lindex $varctok($v) $ka] $vtokmod($v)] < 0} {
872 modify_arc $v $ka
Paul Mackerras38dfe932007-12-06 20:50:31 +1100873 }
Paul Mackerras9257d8f2007-12-11 10:45:38 +1100874 if {[string compare [lindex $varctok($v) $b] $vtokmod($v)] < 0} {
875 modify_arc $v $b
Paul Mackerras38dfe932007-12-06 20:50:31 +1100876 }
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100877 set c [lindex $vbackptr($v) $a]
878 set d [lindex $vleftptr($v) $a]
879 if {$c == 0} {
880 lset vdownptr($v) $b $d
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100881 } else {
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100882 lset vleftptr($v) $c $d
883 }
884 if {$d != 0} {
885 lset vbackptr($v) $d $c
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100886 }
Paul Mackerras841ea822008-02-18 10:44:33 +1100887 if {[lindex $vlastins($v) $b] == $a} {
888 lset vlastins($v) $b $c
889 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100890 lset vupptr($v) $a $ka
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100891 set c [lindex $vlastins($v) $ka]
892 if {$c == 0 || \
893 [string compare $tok [lindex $varctok($v) $c]] < 0} {
894 set c $ka
895 set b [lindex $vdownptr($v) $ka]
896 } else {
897 set b [lindex $vleftptr($v) $c]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100898 }
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100899 while {$b != 0 && \
900 [string compare $tok [lindex $varctok($v) $b]] >= 0} {
901 set c $b
902 set b [lindex $vleftptr($v) $c]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100903 }
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100904 if {$c == $ka} {
905 lset vdownptr($v) $ka $a
906 lset vbackptr($v) $a 0
907 } else {
908 lset vleftptr($v) $c $a
909 lset vbackptr($v) $a $c
910 }
911 lset vleftptr($v) $a $b
912 if {$b != 0} {
913 lset vbackptr($v) $b $a
914 }
915 lset vlastins($v) $ka $a
916 }
917 }
918 foreach id [array names sortkids] {
919 if {[llength $children($v,$id)] > 1} {
920 set children($v,$id) [lsort -command [list vtokcmp $v] \
921 $children($v,$id)]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100922 }
923 }
924 set t2 [clock clicks -milliseconds]
925 #puts "renumbervarc did [llength $todo] of $ntot arcs in [expr {$t2-$t1}]ms"
926}
927
Paul Mackerrasf806f0f2008-02-24 12:16:56 +1100928# Fix up the graph after we have found out that in view $v,
929# $p (a commit that we have already seen) is actually the parent
930# of the last commit in arc $a.
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100931proc fix_reversal {p a v} {
Paul Mackerras24f7a662007-12-19 09:35:33 +1100932 global varcid varcstart varctok vupptr
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100933
934 set pa $varcid($v,$p)
935 if {$p ne [lindex $varcstart($v) $pa]} {
936 splitvarc $p $v
937 set pa $varcid($v,$p)
938 }
Paul Mackerras24f7a662007-12-19 09:35:33 +1100939 # seeds always need to be renumbered
940 if {[lindex $vupptr($v) $pa] == 0 ||
941 [string compare [lindex $varctok($v) $a] \
942 [lindex $varctok($v) $pa]] > 0} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100943 renumbervarc $pa $v
944 }
945}
946
947proc insertrow {id p v} {
Paul Mackerrasb8a938c2008-02-13 22:12:31 +1100948 global cmitlisted children parents varcid varctok vtokmod
949 global varccommits ordertok commitidx numcommits curview
Paul Mackerras22387f22012-03-19 11:21:08 +1100950 global targetid targetrow vshortids
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100951
Paul Mackerrasb8a938c2008-02-13 22:12:31 +1100952 readcommit $id
953 set vid $v,$id
954 set cmitlisted($vid) 1
955 set children($vid) {}
956 set parents($vid) [list $p]
957 set a [newvarc $v $id]
958 set varcid($vid) $a
Paul Mackerras22387f22012-03-19 11:21:08 +1100959 lappend vshortids($v,[string range $id 0 3]) $id
Paul Mackerrasb8a938c2008-02-13 22:12:31 +1100960 if {[string compare [lindex $varctok($v) $a] $vtokmod($v)] < 0} {
961 modify_arc $v $a
962 }
963 lappend varccommits($v,$a) $id
964 set vp $v,$p
965 if {[llength [lappend children($vp) $id]] > 1} {
966 set children($vp) [lsort -command [list vtokcmp $v] $children($vp)]
967 catch {unset ordertok}
968 }
969 fix_reversal $p $a $v
970 incr commitidx($v)
971 if {$v == $curview} {
972 set numcommits $commitidx($v)
973 setcanvscroll
974 if {[info exists targetid]} {
975 if {![comes_before $targetid $p]} {
976 incr targetrow
977 }
978 }
979 }
980}
981
982proc insertfakerow {id p} {
983 global varcid varccommits parents children cmitlisted
984 global commitidx varctok vtokmod targetid targetrow curview numcommits
985
986 set v $curview
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100987 set a $varcid($v,$p)
988 set i [lsearch -exact $varccommits($v,$a) $p]
989 if {$i < 0} {
Paul Mackerrasb8a938c2008-02-13 22:12:31 +1100990 puts "oops: insertfakerow can't find [shortids $p] on arc $a"
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100991 return
992 }
993 set children($v,$id) {}
994 set parents($v,$id) [list $p]
995 set varcid($v,$id) $a
Paul Mackerras9257d8f2007-12-11 10:45:38 +1100996 lappend children($v,$p) $id
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100997 set cmitlisted($v,$id) 1
Paul Mackerrasb8a938c2008-02-13 22:12:31 +1100998 set numcommits [incr commitidx($v)]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100999 # note we deliberately don't update varcstart($v) even if $i == 0
1000 set varccommits($v,$a) [linsert $varccommits($v,$a) $i $id]
Paul Mackerrasc9cfdc92008-03-04 21:32:38 +11001001 modify_arc $v $a $i
Paul Mackerras42a671f2008-01-02 09:59:39 +11001002 if {[info exists targetid]} {
1003 if {![comes_before $targetid $p]} {
1004 incr targetrow
1005 }
1006 }
Paul Mackerrasb8a938c2008-02-13 22:12:31 +11001007 setcanvscroll
Paul Mackerras9257d8f2007-12-11 10:45:38 +11001008 drawvisible
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001009}
1010
Paul Mackerrasb8a938c2008-02-13 22:12:31 +11001011proc removefakerow {id} {
Paul Mackerras9257d8f2007-12-11 10:45:38 +11001012 global varcid varccommits parents children commitidx
Paul Mackerrasfc2a2562007-12-26 23:03:43 +11001013 global varctok vtokmod cmitlisted currentid selectedline
Paul Mackerrasb8a938c2008-02-13 22:12:31 +11001014 global targetid curview numcommits
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001015
Paul Mackerrasb8a938c2008-02-13 22:12:31 +11001016 set v $curview
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001017 if {[llength $parents($v,$id)] != 1} {
Paul Mackerrasb8a938c2008-02-13 22:12:31 +11001018 puts "oops: removefakerow [shortids $id] has [llength $parents($v,$id)] parents"
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001019 return
1020 }
1021 set p [lindex $parents($v,$id) 0]
1022 set a $varcid($v,$id)
1023 set i [lsearch -exact $varccommits($v,$a) $id]
1024 if {$i < 0} {
Paul Mackerrasb8a938c2008-02-13 22:12:31 +11001025 puts "oops: removefakerow can't find [shortids $id] on arc $a"
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001026 return
1027 }
1028 unset varcid($v,$id)
1029 set varccommits($v,$a) [lreplace $varccommits($v,$a) $i $i]
1030 unset parents($v,$id)
1031 unset children($v,$id)
1032 unset cmitlisted($v,$id)
Paul Mackerrasb8a938c2008-02-13 22:12:31 +11001033 set numcommits [incr commitidx($v) -1]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001034 set j [lsearch -exact $children($v,$p) $id]
1035 if {$j >= 0} {
1036 set children($v,$p) [lreplace $children($v,$p) $j $j]
1037 }
Paul Mackerrasc9cfdc92008-03-04 21:32:38 +11001038 modify_arc $v $a $i
Paul Mackerrasfc2a2562007-12-26 23:03:43 +11001039 if {[info exist currentid] && $id eq $currentid} {
1040 unset currentid
Paul Mackerras94b4a692008-05-20 20:51:06 +10001041 set selectedline {}
Paul Mackerrasfc2a2562007-12-26 23:03:43 +11001042 }
Paul Mackerras42a671f2008-01-02 09:59:39 +11001043 if {[info exists targetid] && $targetid eq $id} {
1044 set targetid $p
1045 }
Paul Mackerrasb8a938c2008-02-13 22:12:31 +11001046 setcanvscroll
Paul Mackerras9257d8f2007-12-11 10:45:38 +11001047 drawvisible
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001048}
1049
Paul Mackerrasaa435612009-09-10 21:58:40 +10001050proc real_children {vp} {
1051 global children nullid nullid2
1052
1053 set kids {}
1054 foreach id $children($vp) {
1055 if {$id ne $nullid && $id ne $nullid2} {
1056 lappend kids $id
1057 }
1058 }
1059 return $kids
1060}
1061
Paul Mackerrasc8c9f3d2008-01-06 13:54:58 +11001062proc first_real_child {vp} {
1063 global children nullid nullid2
1064
1065 foreach id $children($vp) {
1066 if {$id ne $nullid && $id ne $nullid2} {
1067 return $id
1068 }
1069 }
1070 return {}
1071}
1072
1073proc last_real_child {vp} {
1074 global children nullid nullid2
1075
1076 set kids $children($vp)
1077 for {set i [llength $kids]} {[incr i -1] >= 0} {} {
1078 set id [lindex $kids $i]
1079 if {$id ne $nullid && $id ne $nullid2} {
1080 return $id
1081 }
1082 }
1083 return {}
1084}
1085
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001086proc vtokcmp {v a b} {
1087 global varctok varcid
1088
1089 return [string compare [lindex $varctok($v) $varcid($v,$a)] \
1090 [lindex $varctok($v) $varcid($v,$b)]]
1091}
1092
Paul Mackerrasc9cfdc92008-03-04 21:32:38 +11001093# This assumes that if lim is not given, the caller has checked that
1094# arc a's token is less than $vtokmod($v)
Paul Mackerrase5b37ac2007-12-12 18:13:51 +11001095proc modify_arc {v a {lim {}}} {
1096 global varctok vtokmod varcmod varcrow vupptr curview vrowmod varccommits
Paul Mackerras9257d8f2007-12-11 10:45:38 +11001097
Paul Mackerrasc9cfdc92008-03-04 21:32:38 +11001098 if {$lim ne {}} {
1099 set c [string compare [lindex $varctok($v) $a] $vtokmod($v)]
1100 if {$c > 0} return
1101 if {$c == 0} {
1102 set r [lindex $varcrow($v) $a]
1103 if {$r ne {} && $vrowmod($v) <= $r + $lim} return
1104 }
1105 }
Paul Mackerras9257d8f2007-12-11 10:45:38 +11001106 set vtokmod($v) [lindex $varctok($v) $a]
1107 set varcmod($v) $a
1108 if {$v == $curview} {
1109 while {$a != 0 && [lindex $varcrow($v) $a] eq {}} {
1110 set a [lindex $vupptr($v) $a]
Paul Mackerrase5b37ac2007-12-12 18:13:51 +11001111 set lim {}
Paul Mackerras9257d8f2007-12-11 10:45:38 +11001112 }
Paul Mackerrase5b37ac2007-12-12 18:13:51 +11001113 set r 0
1114 if {$a != 0} {
1115 if {$lim eq {}} {
1116 set lim [llength $varccommits($v,$a)]
1117 }
1118 set r [expr {[lindex $varcrow($v) $a] + $lim}]
1119 }
1120 set vrowmod($v) $r
Paul Mackerras0c278862007-12-11 20:09:53 +11001121 undolayout $r
Paul Mackerras9257d8f2007-12-11 10:45:38 +11001122 }
1123}
1124
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001125proc update_arcrows {v} {
Paul Mackerrase5b37ac2007-12-12 18:13:51 +11001126 global vtokmod varcmod vrowmod varcrow commitidx currentid selectedline
Paul Mackerras24f7a662007-12-19 09:35:33 +11001127 global varcid vrownum varcorder varcix varccommits
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001128 global vupptr vdownptr vleftptr varctok
Paul Mackerras24f7a662007-12-19 09:35:33 +11001129 global displayorder parentlist curview cached_commitrow
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001130
Paul Mackerrasc9cfdc92008-03-04 21:32:38 +11001131 if {$vrowmod($v) == $commitidx($v)} return
1132 if {$v == $curview} {
1133 if {[llength $displayorder] > $vrowmod($v)} {
1134 set displayorder [lrange $displayorder 0 [expr {$vrowmod($v) - 1}]]
1135 set parentlist [lrange $parentlist 0 [expr {$vrowmod($v) - 1}]]
1136 }
1137 catch {unset cached_commitrow}
1138 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001139 set narctot [expr {[llength $varctok($v)] - 1}]
1140 set a $varcmod($v)
1141 while {$a != 0 && [lindex $varcix($v) $a] eq {}} {
1142 # go up the tree until we find something that has a row number,
1143 # or we get to a seed
1144 set a [lindex $vupptr($v) $a]
1145 }
1146 if {$a == 0} {
1147 set a [lindex $vdownptr($v) 0]
1148 if {$a == 0} return
1149 set vrownum($v) {0}
1150 set varcorder($v) [list $a]
1151 lset varcix($v) $a 0
1152 lset varcrow($v) $a 0
1153 set arcn 0
1154 set row 0
1155 } else {
1156 set arcn [lindex $varcix($v) $a]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001157 if {[llength $vrownum($v)] > $arcn + 1} {
1158 set vrownum($v) [lrange $vrownum($v) 0 $arcn]
1159 set varcorder($v) [lrange $varcorder($v) 0 $arcn]
1160 }
1161 set row [lindex $varcrow($v) $a]
1162 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001163 while {1} {
1164 set p $a
1165 incr row [llength $varccommits($v,$a)]
1166 # go down if possible
1167 set b [lindex $vdownptr($v) $a]
1168 if {$b == 0} {
1169 # if not, go left, or go up until we can go left
1170 while {$a != 0} {
1171 set b [lindex $vleftptr($v) $a]
1172 if {$b != 0} break
1173 set a [lindex $vupptr($v) $a]
1174 }
1175 if {$a == 0} break
1176 }
1177 set a $b
1178 incr arcn
1179 lappend vrownum($v) $row
1180 lappend varcorder($v) $a
1181 lset varcix($v) $a $arcn
1182 lset varcrow($v) $a $row
1183 }
Paul Mackerrase5b37ac2007-12-12 18:13:51 +11001184 set vtokmod($v) [lindex $varctok($v) $p]
1185 set varcmod($v) $p
1186 set vrowmod($v) $row
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001187 if {[info exists currentid]} {
1188 set selectedline [rowofcommit $currentid]
1189 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001190}
1191
1192# Test whether view $v contains commit $id
1193proc commitinview {id v} {
1194 global varcid
1195
1196 return [info exists varcid($v,$id)]
1197}
1198
1199# Return the row number for commit $id in the current view
1200proc rowofcommit {id} {
1201 global varcid varccommits varcrow curview cached_commitrow
Paul Mackerras9257d8f2007-12-11 10:45:38 +11001202 global varctok vtokmod
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001203
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001204 set v $curview
1205 if {![info exists varcid($v,$id)]} {
1206 puts "oops rowofcommit no arc for [shortids $id]"
1207 return {}
1208 }
1209 set a $varcid($v,$id)
Paul Mackerrasfc2a2562007-12-26 23:03:43 +11001210 if {[string compare [lindex $varctok($v) $a] $vtokmod($v)] >= 0} {
Paul Mackerras9257d8f2007-12-11 10:45:38 +11001211 update_arcrows $v
1212 }
Paul Mackerras31c0eaa2007-12-30 22:41:14 +11001213 if {[info exists cached_commitrow($id)]} {
1214 return $cached_commitrow($id)
1215 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001216 set i [lsearch -exact $varccommits($v,$a) $id]
1217 if {$i < 0} {
1218 puts "oops didn't find commit [shortids $id] in arc $a"
1219 return {}
1220 }
1221 incr i [lindex $varcrow($v) $a]
1222 set cached_commitrow($id) $i
1223 return $i
1224}
1225
Paul Mackerras42a671f2008-01-02 09:59:39 +11001226# Returns 1 if a is on an earlier row than b, otherwise 0
1227proc comes_before {a b} {
1228 global varcid varctok curview
1229
1230 set v $curview
1231 if {$a eq $b || ![info exists varcid($v,$a)] || \
1232 ![info exists varcid($v,$b)]} {
1233 return 0
1234 }
1235 if {$varcid($v,$a) != $varcid($v,$b)} {
1236 return [expr {[string compare [lindex $varctok($v) $varcid($v,$a)] \
1237 [lindex $varctok($v) $varcid($v,$b)]] < 0}]
1238 }
1239 return [expr {[rowofcommit $a] < [rowofcommit $b]}]
1240}
1241
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001242proc bsearch {l elt} {
1243 if {[llength $l] == 0 || $elt <= [lindex $l 0]} {
1244 return 0
1245 }
1246 set lo 0
1247 set hi [llength $l]
1248 while {$hi - $lo > 1} {
1249 set mid [expr {int(($lo + $hi) / 2)}]
1250 set t [lindex $l $mid]
1251 if {$elt < $t} {
1252 set hi $mid
1253 } elseif {$elt > $t} {
1254 set lo $mid
1255 } else {
1256 return $mid
1257 }
1258 }
1259 return $lo
1260}
1261
1262# Make sure rows $start..$end-1 are valid in displayorder and parentlist
1263proc make_disporder {start end} {
1264 global vrownum curview commitidx displayorder parentlist
Paul Mackerrase5b37ac2007-12-12 18:13:51 +11001265 global varccommits varcorder parents vrowmod varcrow
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001266 global d_valid_start d_valid_end
1267
Paul Mackerrase5b37ac2007-12-12 18:13:51 +11001268 if {$end > $vrowmod($curview)} {
Paul Mackerras9257d8f2007-12-11 10:45:38 +11001269 update_arcrows $curview
1270 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001271 set ai [bsearch $vrownum($curview) $start]
1272 set start [lindex $vrownum($curview) $ai]
1273 set narc [llength $vrownum($curview)]
1274 for {set r $start} {$ai < $narc && $r < $end} {incr ai} {
1275 set a [lindex $varcorder($curview) $ai]
1276 set l [llength $displayorder]
1277 set al [llength $varccommits($curview,$a)]
1278 if {$l < $r + $al} {
1279 if {$l < $r} {
1280 set pad [ntimes [expr {$r - $l}] {}]
1281 set displayorder [concat $displayorder $pad]
1282 set parentlist [concat $parentlist $pad]
1283 } elseif {$l > $r} {
1284 set displayorder [lrange $displayorder 0 [expr {$r - 1}]]
1285 set parentlist [lrange $parentlist 0 [expr {$r - 1}]]
1286 }
1287 foreach id $varccommits($curview,$a) {
1288 lappend displayorder $id
1289 lappend parentlist $parents($curview,$id)
1290 }
Paul Mackerras17529cf92008-01-12 21:46:31 +11001291 } elseif {[lindex $displayorder [expr {$r + $al - 1}]] eq {}} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001292 set i $r
1293 foreach id $varccommits($curview,$a) {
1294 lset displayorder $i $id
1295 lset parentlist $i $parents($curview,$id)
1296 incr i
1297 }
1298 }
1299 incr r $al
1300 }
1301}
1302
1303proc commitonrow {row} {
1304 global displayorder
1305
1306 set id [lindex $displayorder $row]
1307 if {$id eq {}} {
1308 make_disporder $row [expr {$row + 1}]
1309 set id [lindex $displayorder $row]
1310 }
1311 return $id
1312}
1313
1314proc closevarcs {v} {
1315 global varctok varccommits varcid parents children
Paul Mackerrasd375ef92008-10-21 10:18:12 +11001316 global cmitlisted commitidx vtokmod
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001317
1318 set missing_parents 0
1319 set scripts {}
1320 set narcs [llength $varctok($v)]
1321 for {set a 1} {$a < $narcs} {incr a} {
1322 set id [lindex $varccommits($v,$a) end]
1323 foreach p $parents($v,$id) {
1324 if {[info exists varcid($v,$p)]} continue
1325 # add p as a new commit
1326 incr missing_parents
1327 set cmitlisted($v,$p) 0
1328 set parents($v,$p) {}
1329 if {[llength $children($v,$p)] == 1 &&
1330 [llength $parents($v,$id)] == 1} {
1331 set b $a
1332 } else {
1333 set b [newvarc $v $p]
1334 }
1335 set varcid($v,$p) $b
Paul Mackerras9257d8f2007-12-11 10:45:38 +11001336 if {[string compare [lindex $varctok($v) $b] $vtokmod($v)] < 0} {
1337 modify_arc $v $b
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001338 }
Paul Mackerrase5b37ac2007-12-12 18:13:51 +11001339 lappend varccommits($v,$b) $p
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001340 incr commitidx($v)
Paul Mackerrasd375ef92008-10-21 10:18:12 +11001341 set scripts [check_interest $p $scripts]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001342 }
1343 }
1344 if {$missing_parents > 0} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001345 foreach s $scripts {
1346 eval $s
1347 }
1348 }
1349}
1350
Paul Mackerrasf806f0f2008-02-24 12:16:56 +11001351# Use $rwid as a substitute for $id, i.e. reparent $id's children to $rwid
1352# Assumes we already have an arc for $rwid.
1353proc rewrite_commit {v id rwid} {
1354 global children parents varcid varctok vtokmod varccommits
1355
1356 foreach ch $children($v,$id) {
1357 # make $rwid be $ch's parent in place of $id
1358 set i [lsearch -exact $parents($v,$ch) $id]
1359 if {$i < 0} {
1360 puts "oops rewrite_commit didn't find $id in parent list for $ch"
1361 }
1362 set parents($v,$ch) [lreplace $parents($v,$ch) $i $i $rwid]
1363 # add $ch to $rwid's children and sort the list if necessary
1364 if {[llength [lappend children($v,$rwid) $ch]] > 1} {
1365 set children($v,$rwid) [lsort -command [list vtokcmp $v] \
1366 $children($v,$rwid)]
1367 }
1368 # fix the graph after joining $id to $rwid
1369 set a $varcid($v,$ch)
1370 fix_reversal $rwid $a $v
Paul Mackerrasc9cfdc92008-03-04 21:32:38 +11001371 # parentlist is wrong for the last element of arc $a
1372 # even if displayorder is right, hence the 3rd arg here
1373 modify_arc $v $a [expr {[llength $varccommits($v,$a)] - 1}]
Paul Mackerrasf806f0f2008-02-24 12:16:56 +11001374 }
1375}
1376
Paul Mackerrasd375ef92008-10-21 10:18:12 +11001377# Mechanism for registering a command to be executed when we come
1378# across a particular commit. To handle the case when only the
1379# prefix of the commit is known, the commitinterest array is now
1380# indexed by the first 4 characters of the ID. Each element is a
1381# list of id, cmd pairs.
1382proc interestedin {id cmd} {
1383 global commitinterest
1384
1385 lappend commitinterest([string range $id 0 3]) $id $cmd
1386}
1387
1388proc check_interest {id scripts} {
1389 global commitinterest
1390
1391 set prefix [string range $id 0 3]
1392 if {[info exists commitinterest($prefix)]} {
1393 set newlist {}
1394 foreach {i script} $commitinterest($prefix) {
1395 if {[string match "$i*" $id]} {
1396 lappend scripts [string map [list "%I" $id "%P" $i] $script]
1397 } else {
1398 lappend newlist $i $script
1399 }
1400 }
1401 if {$newlist ne {}} {
1402 set commitinterest($prefix) $newlist
1403 } else {
1404 unset commitinterest($prefix)
1405 }
1406 }
1407 return $scripts
1408}
1409
Paul Mackerrasf806f0f2008-02-24 12:16:56 +11001410proc getcommitlines {fd inst view updating} {
Paul Mackerrasd375ef92008-10-21 10:18:12 +11001411 global cmitlisted leftover
Paul Mackerras3ed31a82008-04-26 16:00:00 +10001412 global commitidx commitdata vdatemode
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001413 global parents children curview hlview
Paul Mackerras468bcae2008-03-03 10:19:35 +11001414 global idpending ordertok
Paul Mackerras22387f22012-03-19 11:21:08 +11001415 global varccommits varcid varctok vtokmod vfilelimit vshortids
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +00001416
Paul Mackerrasd1e46752006-08-16 20:02:32 +10001417 set stuff [read $fd 500000]
Paul Mackerras005a2f42007-07-26 22:36:39 +10001418 # git log doesn't terminate the last commit with a null...
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001419 if {$stuff == {} && $leftover($inst) ne {} && [eof $fd]} {
Paul Mackerras005a2f42007-07-26 22:36:39 +10001420 set stuff "\0"
1421 }
Paul Mackerrasb490a992005-06-22 10:25:38 +10001422 if {$stuff == {}} {
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10001423 if {![eof $fd]} {
1424 return 1
1425 }
Paul Mackerras6df74032008-05-11 22:13:02 +10001426 global commfd viewcomplete viewactive viewname
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001427 global viewinstances
1428 unset commfd($inst)
1429 set i [lsearch -exact $viewinstances($view) $inst]
1430 if {$i >= 0} {
1431 set viewinstances($view) [lreplace $viewinstances($view) $i $i]
Paul Mackerrasb0cdca92007-08-23 19:35:51 +10001432 }
Paul Mackerrasf0654862005-07-18 14:29:03 -04001433 # set it blocking so we wait for the process to terminate
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10001434 fconfigure $fd -blocking 1
Paul Mackerras098dd8a2006-05-03 09:32:53 +10001435 if {[catch {close $fd} err]} {
1436 set fv {}
1437 if {$view != $curview} {
1438 set fv " for the \"$viewname($view)\" view"
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10001439 }
Paul Mackerras098dd8a2006-05-03 09:32:53 +10001440 if {[string range $err 0 4] == "usage"} {
1441 set err "Gitk: error reading commits$fv:\
Paul Mackerrasf9e0b6f2008-03-04 21:14:17 +11001442 bad arguments to git log."
Paul Mackerras098dd8a2006-05-03 09:32:53 +10001443 if {$viewname($view) eq "Command line"} {
1444 append err \
Paul Mackerrasf9e0b6f2008-03-04 21:14:17 +11001445 " (Note: arguments to gitk are passed to git log\
Paul Mackerras098dd8a2006-05-03 09:32:53 +10001446 to allow selection of commits to be displayed.)"
1447 }
1448 } else {
1449 set err "Error reading commits$fv: $err"
1450 }
1451 error_popup $err
Paul Mackerras1d10f362005-05-15 12:55:47 +00001452 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001453 if {[incr viewactive($view) -1] <= 0} {
1454 set viewcomplete($view) 1
1455 # Check if we have seen any ids listed as parents that haven't
1456 # appeared in the list
1457 closevarcs $view
1458 notbusy $view
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001459 }
Paul Mackerras098dd8a2006-05-03 09:32:53 +10001460 if {$view == $curview} {
Paul Mackerrasac1276a2008-03-03 10:11:08 +11001461 run chewcommits
Paul Mackerras9a40c502005-05-12 23:46:16 +00001462 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10001463 return 0
Paul Mackerras9a40c502005-05-12 23:46:16 +00001464 }
Paul Mackerrasb490a992005-06-22 10:25:38 +10001465 set start 0
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11001466 set gotsome 0
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001467 set scripts {}
Paul Mackerrasb490a992005-06-22 10:25:38 +10001468 while 1 {
1469 set i [string first "\0" $stuff $start]
1470 if {$i < 0} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001471 append leftover($inst) [string range $stuff $start end]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11001472 break
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +00001473 }
Paul Mackerrasb490a992005-06-22 10:25:38 +10001474 if {$start == 0} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001475 set cmit $leftover($inst)
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11001476 append cmit [string range $stuff 0 [expr {$i - 1}]]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001477 set leftover($inst) {}
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11001478 } else {
1479 set cmit [string range $stuff $start [expr {$i - 1}]]
Paul Mackerrasb490a992005-06-22 10:25:38 +10001480 }
1481 set start [expr {$i + 1}]
Paul Mackerrase5ea7012005-08-18 20:40:39 +10001482 set j [string first "\n" $cmit]
1483 set ok 0
Paul Mackerras16c1ff92006-03-30 18:43:51 +11001484 set listed 1
Paul Mackerrasc961b222007-07-09 22:45:47 +10001485 if {$j >= 0 && [string match "commit *" $cmit]} {
1486 set ids [string range $cmit 7 [expr {$j - 1}]]
Linus Torvalds1407ade2008-02-09 14:02:07 -08001487 if {[string match {[-^<>]*} $ids]} {
Paul Mackerrasc961b222007-07-09 22:45:47 +10001488 switch -- [string index $ids 0] {
1489 "-" {set listed 0}
Linus Torvalds1407ade2008-02-09 14:02:07 -08001490 "^" {set listed 2}
1491 "<" {set listed 3}
1492 ">" {set listed 4}
Paul Mackerrasc961b222007-07-09 22:45:47 +10001493 }
Paul Mackerras16c1ff92006-03-30 18:43:51 +11001494 set ids [string range $ids 1 end]
1495 }
Paul Mackerrase5ea7012005-08-18 20:40:39 +10001496 set ok 1
1497 foreach id $ids {
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11001498 if {[string length $id] != 40} {
Paul Mackerrase5ea7012005-08-18 20:40:39 +10001499 set ok 0
1500 break
1501 }
1502 }
1503 }
1504 if {!$ok} {
Paul Mackerras7e952e72005-06-27 20:04:26 +10001505 set shortcmit $cmit
1506 if {[string length $shortcmit] > 80} {
1507 set shortcmit "[string range $shortcmit 0 80]..."
1508 }
Christian Stimmingd990ced2007-11-07 18:42:55 +01001509 error_popup "[mc "Can't parse git log output:"] {$shortcmit}"
Paul Mackerrasb490a992005-06-22 10:25:38 +10001510 exit 1
1511 }
Paul Mackerrase5ea7012005-08-18 20:40:39 +10001512 set id [lindex $ids 0]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001513 set vid $view,$id
Paul Mackerrasf806f0f2008-02-24 12:16:56 +11001514
Paul Mackerras22387f22012-03-19 11:21:08 +11001515 lappend vshortids($view,[string range $id 0 3]) $id
1516
Paul Mackerrasf806f0f2008-02-24 12:16:56 +11001517 if {!$listed && $updating && ![info exists varcid($vid)] &&
Paul Mackerras3ed31a82008-04-26 16:00:00 +10001518 $vfilelimit($view) ne {}} {
Paul Mackerrasf806f0f2008-02-24 12:16:56 +11001519 # git log doesn't rewrite parents for unlisted commits
1520 # when doing path limiting, so work around that here
1521 # by working out the rewritten parent with git rev-list
1522 # and if we already know about it, using the rewritten
1523 # parent as a substitute parent for $id's children.
1524 if {![catch {
1525 set rwid [exec git rev-list --first-parent --max-count=1 \
Paul Mackerras3ed31a82008-04-26 16:00:00 +10001526 $id -- $vfilelimit($view)]
Paul Mackerrasf806f0f2008-02-24 12:16:56 +11001527 }]} {
1528 if {$rwid ne {} && [info exists varcid($view,$rwid)]} {
1529 # use $rwid in place of $id
1530 rewrite_commit $view $id $rwid
1531 continue
1532 }
1533 }
1534 }
1535
Paul Mackerrasf1bf4ee2008-02-16 17:47:31 +11001536 set a 0
1537 if {[info exists varcid($vid)]} {
1538 if {$cmitlisted($vid) || !$listed} continue
1539 set a $varcid($vid)
1540 }
Paul Mackerras16c1ff92006-03-30 18:43:51 +11001541 if {$listed} {
1542 set olds [lrange $ids 1 end]
Paul Mackerras16c1ff92006-03-30 18:43:51 +11001543 } else {
1544 set olds {}
1545 }
Paul Mackerrasf7a3e8d2006-03-18 10:04:48 +11001546 set commitdata($id) [string range $cmit [expr {$j + 1}] end]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001547 set cmitlisted($vid) $listed
1548 set parents($vid) $olds
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001549 if {![info exists children($vid)]} {
1550 set children($vid) {}
Paul Mackerrasf1bf4ee2008-02-16 17:47:31 +11001551 } elseif {$a == 0 && [llength $children($vid)] == 1} {
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +11001552 set k [lindex $children($vid) 0]
1553 if {[llength $parents($view,$k)] == 1 &&
Paul Mackerras3ed31a82008-04-26 16:00:00 +10001554 (!$vdatemode($view) ||
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +11001555 $varcid($view,$k) == [llength $varctok($view)] - 1)} {
1556 set a $varcid($view,$k)
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001557 }
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10001558 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001559 if {$a == 0} {
1560 # new arc
1561 set a [newvarc $view $id]
1562 }
Paul Mackerrase5b37ac2007-12-12 18:13:51 +11001563 if {[string compare [lindex $varctok($view) $a] $vtokmod($view)] < 0} {
1564 modify_arc $view $a
1565 }
Paul Mackerrasf1bf4ee2008-02-16 17:47:31 +11001566 if {![info exists varcid($vid)]} {
1567 set varcid($vid) $a
1568 lappend varccommits($view,$a) $id
1569 incr commitidx($view)
1570 }
Paul Mackerrase5b37ac2007-12-12 18:13:51 +11001571
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001572 set i 0
1573 foreach p $olds {
1574 if {$i == 0 || [lsearch -exact $olds $p] >= $i} {
1575 set vp $view,$p
1576 if {[llength [lappend children($vp) $id]] > 1 &&
1577 [vtokcmp $view [lindex $children($vp) end-1] $id] > 0} {
1578 set children($vp) [lsort -command [list vtokcmp $view] \
1579 $children($vp)]
Paul Mackerras9257d8f2007-12-11 10:45:38 +11001580 catch {unset ordertok}
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001581 }
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +11001582 if {[info exists varcid($view,$p)]} {
1583 fix_reversal $p $a $view
1584 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001585 }
1586 incr i
1587 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001588
Paul Mackerrasd375ef92008-10-21 10:18:12 +11001589 set scripts [check_interest $id $scripts]
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11001590 set gotsome 1
Paul Mackerras9f1afe02006-02-19 22:44:47 +11001591 }
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11001592 if {$gotsome} {
Paul Mackerrasac1276a2008-03-03 10:11:08 +11001593 global numcommits hlview
1594
1595 if {$view == $curview} {
1596 set numcommits $commitidx($view)
1597 run chewcommits
1598 }
1599 if {[info exists hlview] && $view == $hlview} {
1600 # we never actually get here...
1601 run vhighlightmore
1602 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001603 foreach s $scripts {
1604 eval $s
1605 }
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11001606 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10001607 return 2
Paul Mackerrascfb45632005-05-31 12:14:42 +00001608}
1609
Paul Mackerrasac1276a2008-03-03 10:11:08 +11001610proc chewcommits {} {
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10001611 global curview hlview viewcomplete
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001612 global pending_select
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +00001613
Paul Mackerrasac1276a2008-03-03 10:11:08 +11001614 layoutmore
1615 if {$viewcomplete($curview)} {
1616 global commitidx varctok
1617 global numcommits startmsecs
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10001618
Paul Mackerrasac1276a2008-03-03 10:11:08 +11001619 if {[info exists pending_select]} {
Alexander Gavrilov835e62a2008-07-26 20:15:54 +04001620 update
1621 reset_pending_select {}
1622
1623 if {[commitinview $pending_select $curview]} {
1624 selectline [rowofcommit $pending_select] 1
1625 } else {
1626 set row [first_real_row]
1627 selectline $row 1
1628 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10001629 }
Paul Mackerrasac1276a2008-03-03 10:11:08 +11001630 if {$commitidx($curview) > 0} {
1631 #set ms [expr {[clock clicks -milliseconds] - $startmsecs}]
1632 #puts "overall $ms ms for $numcommits commits"
1633 #puts "[llength $varctok($view)] arcs, $commitidx($view) commits"
1634 } else {
1635 show_status [mc "No commits selected"]
1636 }
1637 notbusy layout
Paul Mackerrasb6645502005-08-11 09:56:23 +10001638 }
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10001639 return 0
Paul Mackerras1db95b02005-05-09 04:08:39 +00001640}
1641
Alexander Gavrilov590915d2008-11-09 18:06:07 +03001642proc do_readcommit {id} {
1643 global tclencoding
1644
1645 # Invoke git-log to handle automatic encoding conversion
1646 set fd [open [concat | git log --no-color --pretty=raw -1 $id] r]
1647 # Read the results using i18n.logoutputencoding
1648 fconfigure $fd -translation lf -eofchar {}
1649 if {$tclencoding != {}} {
1650 fconfigure $fd -encoding $tclencoding
1651 }
1652 set contents [read $fd]
1653 close $fd
1654 # Remove the heading line
1655 regsub {^commit [0-9a-f]+\n} $contents {} contents
1656
1657 return $contents
1658}
1659
Paul Mackerras1db95b02005-05-09 04:08:39 +00001660proc readcommit {id} {
Alexander Gavrilov590915d2008-11-09 18:06:07 +03001661 if {[catch {set contents [do_readcommit $id]}]} return
1662 parsecommit $id $contents 1
Paul Mackerrasb490a992005-06-22 10:25:38 +10001663}
1664
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11001665proc parsecommit {id contents listed} {
Anders Kaseorgef738962011-01-19 14:46:59 -05001666 global commitinfo
Sven Verdoolaegeb5c2f302005-11-29 22:15:51 +01001667
1668 set inhdr 1
1669 set comment {}
1670 set headline {}
1671 set auname {}
1672 set audate {}
1673 set comname {}
1674 set comdate {}
Paul Mackerras232475d2005-11-15 10:34:03 +11001675 set hdrend [string first "\n\n" $contents]
1676 if {$hdrend < 0} {
1677 # should never happen...
1678 set hdrend [string length $contents]
1679 }
1680 set header [string range $contents 0 [expr {$hdrend - 1}]]
1681 set comment [string range $contents [expr {$hdrend + 2}] end]
1682 foreach line [split $header "\n"] {
Kevin Ballard61f57cb2008-12-18 01:26:48 -08001683 set line [split $line " "]
Paul Mackerras232475d2005-11-15 10:34:03 +11001684 set tag [lindex $line 0]
1685 if {$tag == "author"} {
Anders Kaseorgf5974d92011-01-19 14:47:25 -05001686 set audate [lrange $line end-1 end]
Kevin Ballard61f57cb2008-12-18 01:26:48 -08001687 set auname [join [lrange $line 1 end-2] " "]
Paul Mackerras232475d2005-11-15 10:34:03 +11001688 } elseif {$tag == "committer"} {
Anders Kaseorgf5974d92011-01-19 14:47:25 -05001689 set comdate [lrange $line end-1 end]
Kevin Ballard61f57cb2008-12-18 01:26:48 -08001690 set comname [join [lrange $line 1 end-2] " "]
Paul Mackerras1db95b02005-05-09 04:08:39 +00001691 }
1692 }
Paul Mackerras232475d2005-11-15 10:34:03 +11001693 set headline {}
Paul Mackerras43c25072006-09-27 10:56:02 +10001694 # take the first non-blank line of the comment as the headline
1695 set headline [string trimleft $comment]
1696 set i [string first "\n" $headline]
Paul Mackerras232475d2005-11-15 10:34:03 +11001697 if {$i >= 0} {
Paul Mackerras43c25072006-09-27 10:56:02 +10001698 set headline [string range $headline 0 $i]
1699 }
1700 set headline [string trimright $headline]
1701 set i [string first "\r" $headline]
1702 if {$i >= 0} {
1703 set headline [string trimright [string range $headline 0 $i]]
Paul Mackerras232475d2005-11-15 10:34:03 +11001704 }
1705 if {!$listed} {
Paul Mackerrasf9e0b6f2008-03-04 21:14:17 +11001706 # git log indents the comment by 4 spaces;
Timo Hirvonen8974c6f2006-05-24 10:57:40 +03001707 # if we got this via git cat-file, add the indentation
Paul Mackerras232475d2005-11-15 10:34:03 +11001708 set newcomment {}
1709 foreach line [split $comment "\n"] {
1710 append newcomment " "
1711 append newcomment $line
Paul Mackerrasf6e28692005-11-20 23:08:22 +11001712 append newcomment "\n"
Paul Mackerras232475d2005-11-15 10:34:03 +11001713 }
1714 set comment $newcomment
Paul Mackerras1db95b02005-05-09 04:08:39 +00001715 }
Raphael Zimmerer36242492011-04-19 22:37:09 +02001716 set hasnote [string first "\nNotes:\n" $contents]
Thomas Rastb449eb22013-11-16 18:37:42 +01001717 set diff ""
1718 # If there is diff output shown in the git-log stream, split it
1719 # out. But get rid of the empty line that always precedes the
1720 # diff.
1721 set i [string first "\n\ndiff" $comment]
1722 if {$i >= 0} {
1723 set diff [string range $comment $i+1 end]
1724 set comment [string range $comment 0 $i-1]
1725 }
Paul Mackerrase5c2d852005-05-11 23:44:54 +00001726 set commitinfo($id) [list $headline $auname $audate \
Thomas Rastb449eb22013-11-16 18:37:42 +01001727 $comname $comdate $comment $hasnote $diff]
Paul Mackerras1db95b02005-05-09 04:08:39 +00001728}
1729
Paul Mackerrasf7a3e8d2006-03-18 10:04:48 +11001730proc getcommit {id} {
Paul Mackerras79b2c752006-04-02 20:47:40 +10001731 global commitdata commitinfo
Paul Mackerras8ed16482006-03-02 22:56:44 +11001732
Paul Mackerrasf7a3e8d2006-03-18 10:04:48 +11001733 if {[info exists commitdata($id)]} {
1734 parsecommit $id $commitdata($id) 1
Paul Mackerras8ed16482006-03-02 22:56:44 +11001735 } else {
1736 readcommit $id
1737 if {![info exists commitinfo($id)]} {
Christian Stimmingd990ced2007-11-07 18:42:55 +01001738 set commitinfo($id) [list [mc "No commit information available"]]
Paul Mackerras8ed16482006-03-02 22:56:44 +11001739 }
1740 }
1741 return 1
1742}
1743
Paul Mackerrasd375ef92008-10-21 10:18:12 +11001744# Expand an abbreviated commit ID to a list of full 40-char IDs that match
1745# and are present in the current view.
1746# This is fairly slow...
1747proc longid {prefix} {
Paul Mackerras22387f22012-03-19 11:21:08 +11001748 global varcid curview vshortids
Paul Mackerrasd375ef92008-10-21 10:18:12 +11001749
1750 set ids {}
Paul Mackerras22387f22012-03-19 11:21:08 +11001751 if {[string length $prefix] >= 4} {
1752 set vshortid $curview,[string range $prefix 0 3]
1753 if {[info exists vshortids($vshortid)]} {
1754 foreach id $vshortids($vshortid) {
1755 if {[string match "$prefix*" $id]} {
1756 if {[lsearch -exact $ids $id] < 0} {
1757 lappend ids $id
1758 if {[llength $ids] >= 2} break
1759 }
1760 }
1761 }
1762 }
1763 } else {
1764 foreach match [array names varcid "$curview,$prefix*"] {
1765 lappend ids [lindex [split $match ","] 1]
1766 if {[llength $ids] >= 2} break
1767 }
Paul Mackerrasd375ef92008-10-21 10:18:12 +11001768 }
1769 return $ids
1770}
1771
Paul Mackerras887fe3c2005-05-21 07:35:37 +00001772proc readrefs {} {
Paul Mackerras62d3ea62006-09-11 10:36:53 +10001773 global tagids idtags headids idheads tagobjid
Paul Mackerras219ea3a2006-09-07 10:21:39 +10001774 global otherrefids idotherrefs mainhead mainheadid
Alexander Gavrilov39816d62008-08-23 12:27:44 +04001775 global selecthead selectheadid
Thomas Rastffe15292009-08-03 23:53:36 +02001776 global hideremotes
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10001777
Sven Verdoolaegeb5c2f302005-11-29 22:15:51 +01001778 foreach v {tagids idtags headids idheads otherrefids idotherrefs} {
1779 catch {unset $v}
1780 }
Paul Mackerras62d3ea62006-09-11 10:36:53 +10001781 set refd [open [list | git show-ref -d] r]
1782 while {[gets $refd line] >= 0} {
1783 if {[string index $line 40] ne " "} continue
1784 set id [string range $line 0 39]
1785 set ref [string range $line 41 end]
1786 if {![string match "refs/*" $ref]} continue
1787 set name [string range $ref 5 end]
1788 if {[string match "remotes/*" $name]} {
Thomas Rastffe15292009-08-03 23:53:36 +02001789 if {![string match "*/HEAD" $name] && !$hideremotes} {
Paul Mackerras62d3ea62006-09-11 10:36:53 +10001790 set headids($name) $id
1791 lappend idheads($id) $name
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10001792 }
Paul Mackerras62d3ea62006-09-11 10:36:53 +10001793 } elseif {[string match "heads/*" $name]} {
1794 set name [string range $name 6 end]
Junio C Hamano36a7cad2005-11-18 23:54:17 -08001795 set headids($name) $id
1796 lappend idheads($id) $name
Paul Mackerras62d3ea62006-09-11 10:36:53 +10001797 } elseif {[string match "tags/*" $name]} {
1798 # this lets refs/tags/foo^{} overwrite refs/tags/foo,
1799 # which is what we want since the former is the commit ID
1800 set name [string range $name 5 end]
1801 if {[string match "*^{}" $name]} {
1802 set name [string range $name 0 end-3]
1803 } else {
1804 set tagobjid($name) $id
1805 }
1806 set tagids($name) $id
1807 lappend idtags($id) $name
Junio C Hamano36a7cad2005-11-18 23:54:17 -08001808 } else {
1809 set otherrefids($name) $id
1810 lappend idotherrefs($id) $name
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10001811 }
1812 }
Alex Riesen062d6712007-07-29 22:28:40 +02001813 catch {close $refd}
Paul Mackerras8a485712006-07-06 10:21:23 +10001814 set mainhead {}
Paul Mackerras219ea3a2006-09-07 10:21:39 +10001815 set mainheadid {}
Paul Mackerras8a485712006-07-06 10:21:23 +10001816 catch {
Paul Mackerrasc11ff122008-05-26 10:11:33 +10001817 set mainheadid [exec git rev-parse HEAD]
Paul Mackerras8a485712006-07-06 10:21:23 +10001818 set thehead [exec git symbolic-ref HEAD]
1819 if {[string match "refs/heads/*" $thehead]} {
1820 set mainhead [string range $thehead 11 end]
1821 }
1822 }
Alexander Gavrilov39816d62008-08-23 12:27:44 +04001823 set selectheadid {}
1824 if {$selecthead ne {}} {
1825 catch {
1826 set selectheadid [exec git rev-parse --verify $selecthead]
1827 }
1828 }
Paul Mackerras887fe3c2005-05-21 07:35:37 +00001829}
1830
Paul Mackerras8f489362007-07-13 19:49:37 +10001831# skip over fake commits
1832proc first_real_row {} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001833 global nullid nullid2 numcommits
Paul Mackerras8f489362007-07-13 19:49:37 +10001834
1835 for {set row 0} {$row < $numcommits} {incr row} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001836 set id [commitonrow $row]
Paul Mackerras8f489362007-07-13 19:49:37 +10001837 if {$id ne $nullid && $id ne $nullid2} {
1838 break
1839 }
1840 }
1841 return $row
1842}
1843
Paul Mackerrase11f1232007-06-16 20:29:25 +10001844# update things for a head moved to a child of its previous location
1845proc movehead {id name} {
1846 global headids idheads
1847
1848 removehead $headids($name) $name
1849 set headids($name) $id
1850 lappend idheads($id) $name
1851}
1852
1853# update things when a head has been removed
1854proc removehead {id name} {
1855 global headids idheads
1856
1857 if {$idheads($id) eq $name} {
1858 unset idheads($id)
1859 } else {
1860 set i [lsearch -exact $idheads($id) $name]
1861 if {$i >= 0} {
1862 set idheads($id) [lreplace $idheads($id) $i $i]
1863 }
1864 }
1865 unset headids($name)
1866}
1867
Pat Thoytsd93f1712009-04-17 01:24:35 +01001868proc ttk_toplevel {w args} {
1869 global use_ttk
1870 eval [linsert $args 0 ::toplevel $w]
1871 if {$use_ttk} {
1872 place [ttk::frame $w._toplevel_background] -x 0 -y 0 -relwidth 1 -relheight 1
1873 }
1874 return $w
1875}
1876
Alexander Gavrilove7d64002008-11-11 23:55:42 +03001877proc make_transient {window origin} {
1878 global have_tk85
1879
1880 # In MacOS Tk 8.4 transient appears to work by setting
1881 # overrideredirect, which is utterly useless, since the
1882 # windows get no border, and are not even kept above
1883 # the parent.
1884 if {!$have_tk85 && [tk windowingsystem] eq {aqua}} return
1885
1886 wm transient $window $origin
1887
1888 # Windows fails to place transient windows normally, so
1889 # schedule a callback to center them on the parent.
1890 if {[tk windowingsystem] eq {win32}} {
1891 after idle [list tk::PlaceWindow $window widget $origin]
1892 }
1893}
1894
Bernt Hansen8d849952009-11-02 07:41:00 -05001895proc show_error {w top msg {mc mc}} {
Pat Thoytsd93f1712009-04-17 01:24:35 +01001896 global NS
Pat Thoyts3cb1f9c2009-05-12 15:45:06 +01001897 if {![info exists NS]} {set NS ""}
Pat Thoytsd93f1712009-04-17 01:24:35 +01001898 if {[wm state $top] eq "withdrawn"} { wm deiconify $top }
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00001899 message $w.m -text $msg -justify center -aspect 400
1900 pack $w.m -side top -fill x -padx 20 -pady 20
Paul Mackerras7a0ebbf2009-11-14 21:26:31 +11001901 ${NS}::button $w.ok -default active -text [$mc OK] -command "destroy $top"
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00001902 pack $w.ok -side bottom -fill x
Paul Mackerrase54be9e2006-05-26 22:34:30 +10001903 bind $top <Visibility> "grab $top; focus $top"
1904 bind $top <Key-Return> "destroy $top"
Alexander Gavrilov76f15942008-11-02 21:59:44 +03001905 bind $top <Key-space> "destroy $top"
1906 bind $top <Key-Escape> "destroy $top"
Paul Mackerrase54be9e2006-05-26 22:34:30 +10001907 tkwait window $top
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00001908}
1909
Alexander Gavrilov84a76f12008-11-02 21:59:45 +03001910proc error_popup {msg {owner .}} {
Pat Thoytsd93f1712009-04-17 01:24:35 +01001911 if {[tk windowingsystem] eq "win32"} {
1912 tk_messageBox -icon error -type ok -title [wm title .] \
1913 -parent $owner -message $msg
1914 } else {
1915 set w .error
1916 ttk_toplevel $w
1917 make_transient $w $owner
1918 show_error $w $w $msg
1919 }
Paul Mackerras098dd8a2006-05-03 09:32:53 +10001920}
1921
Alexander Gavrilov84a76f12008-11-02 21:59:45 +03001922proc confirm_popup {msg {owner .}} {
Pat Thoytsd93f1712009-04-17 01:24:35 +01001923 global confirm_ok NS
Paul Mackerras10299152006-08-02 09:52:01 +10001924 set confirm_ok 0
1925 set w .confirm
Pat Thoytsd93f1712009-04-17 01:24:35 +01001926 ttk_toplevel $w
Alexander Gavrilove7d64002008-11-11 23:55:42 +03001927 make_transient $w $owner
Paul Mackerras10299152006-08-02 09:52:01 +10001928 message $w.m -text $msg -justify center -aspect 400
1929 pack $w.m -side top -fill x -padx 20 -pady 20
Pat Thoytsd93f1712009-04-17 01:24:35 +01001930 ${NS}::button $w.ok -text [mc OK] -command "set confirm_ok 1; destroy $w"
Paul Mackerras10299152006-08-02 09:52:01 +10001931 pack $w.ok -side left -fill x
Pat Thoytsd93f1712009-04-17 01:24:35 +01001932 ${NS}::button $w.cancel -text [mc Cancel] -command "destroy $w"
Paul Mackerras10299152006-08-02 09:52:01 +10001933 pack $w.cancel -side right -fill x
1934 bind $w <Visibility> "grab $w; focus $w"
Alexander Gavrilov76f15942008-11-02 21:59:44 +03001935 bind $w <Key-Return> "set confirm_ok 1; destroy $w"
1936 bind $w <Key-space> "set confirm_ok 1; destroy $w"
1937 bind $w <Key-Escape> "destroy $w"
Pat Thoytsd93f1712009-04-17 01:24:35 +01001938 tk::PlaceWindow $w widget $owner
Paul Mackerras10299152006-08-02 09:52:01 +10001939 tkwait window $w
1940 return $confirm_ok
1941}
1942
Paul Mackerrasb039f0a2008-01-06 15:54:46 +11001943proc setoptions {} {
Pat Thoytsd93f1712009-04-17 01:24:35 +01001944 if {[tk windowingsystem] ne "win32"} {
1945 option add *Panedwindow.showHandle 1 startupFile
1946 option add *Panedwindow.sashRelief raised startupFile
1947 if {[tk windowingsystem] ne "aqua"} {
1948 option add *Menu.font uifont startupFile
1949 }
1950 } else {
1951 option add *Menu.TearOff 0 startupFile
1952 }
Paul Mackerrasb039f0a2008-01-06 15:54:46 +11001953 option add *Button.font uifont startupFile
1954 option add *Checkbutton.font uifont startupFile
1955 option add *Radiobutton.font uifont startupFile
Paul Mackerrasb039f0a2008-01-06 15:54:46 +11001956 option add *Menubutton.font uifont startupFile
1957 option add *Label.font uifont startupFile
1958 option add *Message.font uifont startupFile
Mark Hillsb9b142f2010-01-13 20:40:22 +00001959 option add *Entry.font textfont startupFile
1960 option add *Text.font textfont startupFile
Pat Thoytsd93f1712009-04-17 01:24:35 +01001961 option add *Labelframe.font uifont startupFile
Mark Hills0933b042010-01-13 20:40:19 +00001962 option add *Spinbox.font textfont startupFile
Mark Hills207ad7b2010-01-13 20:40:20 +00001963 option add *Listbox.font mainfont startupFile
Paul Mackerrasb039f0a2008-01-06 15:54:46 +11001964}
1965
Paul Mackerras79056032008-10-18 16:24:46 +11001966# Make a menu and submenus.
1967# m is the window name for the menu, items is the list of menu items to add.
1968# Each item is a list {mc label type description options...}
1969# mc is ignored; it's so we can put mc there to alert xgettext
1970# label is the string that appears in the menu
1971# type is cascade, command or radiobutton (should add checkbutton)
1972# description depends on type; it's the sublist for cascade, the
1973# command to invoke for command, or {variable value} for radiobutton
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11001974proc makemenu {m items} {
1975 menu $m
Alexander Gavrilovcea07cf2008-11-09 13:00:45 +03001976 if {[tk windowingsystem] eq {aqua}} {
1977 set Meta1 Cmd
1978 } else {
1979 set Meta1 Ctrl
1980 }
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11001981 foreach i $items {
Paul Mackerras79056032008-10-18 16:24:46 +11001982 set name [mc [lindex $i 1]]
1983 set type [lindex $i 2]
1984 set thing [lindex $i 3]
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11001985 set params [list $type]
1986 if {$name ne {}} {
1987 set u [string first "&" [string map {&& x} $name]]
1988 lappend params -label [string map {&& & & {}} $name]
1989 if {$u >= 0} {
1990 lappend params -underline $u
1991 }
1992 }
1993 switch -- $type {
1994 "cascade" {
Paul Mackerras79056032008-10-18 16:24:46 +11001995 set submenu [string tolower [string map {& ""} [lindex $i 1]]]
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11001996 lappend params -menu $m.$submenu
1997 }
1998 "command" {
1999 lappend params -command $thing
2000 }
2001 "radiobutton" {
2002 lappend params -variable [lindex $thing 0] \
2003 -value [lindex $thing 1]
2004 }
2005 }
Alexander Gavrilovcea07cf2008-11-09 13:00:45 +03002006 set tail [lrange $i 4 end]
2007 regsub -all {\yMeta1\y} $tail $Meta1 tail
2008 eval $m add $params $tail
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11002009 if {$type eq "cascade"} {
2010 makemenu $m.$submenu $thing
2011 }
2012 }
2013}
2014
2015# translate string and remove ampersands
2016proc mca {str} {
2017 return [string map {&& & & {}} [mc $str]]
2018}
2019
Paul Mackerras39c12692013-05-11 17:08:41 +10002020proc cleardropsel {w} {
2021 $w selection clear
2022}
Pat Thoytsd93f1712009-04-17 01:24:35 +01002023proc makedroplist {w varname args} {
2024 global use_ttk
2025 if {$use_ttk} {
Pat Thoyts3cb1f9c2009-05-12 15:45:06 +01002026 set width 0
2027 foreach label $args {
2028 set cx [string length $label]
2029 if {$cx > $width} {set width $cx}
2030 }
2031 set gm [ttk::combobox $w -width $width -state readonly\
Paul Mackerras39c12692013-05-11 17:08:41 +10002032 -textvariable $varname -values $args \
2033 -exportselection false]
2034 bind $gm <<ComboboxSelected>> [list $gm selection clear]
Pat Thoytsd93f1712009-04-17 01:24:35 +01002035 } else {
2036 set gm [eval [linsert $args 0 tk_optionMenu $w $varname]]
2037 }
2038 return $gm
2039}
2040
Paul Mackerrasd94f8cd2006-04-06 10:18:23 +10002041proc makewindow {} {
Paul Mackerras31c0eaa2007-12-30 22:41:14 +11002042 global canv canv2 canv3 linespc charspc ctext cflist cscroll
Paul Mackerras9c311b32007-10-04 22:27:13 +10002043 global tabstop
Paul Mackerrasb74fd572005-07-16 07:46:13 -04002044 global findtype findtypemenu findloc findstring fstring geometry
Paul Mackerras887fe3c2005-05-21 07:35:37 +00002045 global entries sha1entry sha1string sha1but
Steffen Prohaska890fae72007-08-12 12:05:46 +02002046 global diffcontextstring diffcontext
Steffen Prohaskab9b86002008-01-17 23:42:55 +01002047 global ignorespace
Paul Mackerras94a2eed2005-08-07 15:27:57 +10002048 global maincursor textcursor curtextcursor
Paul Mackerras219ea3a2006-09-07 10:21:39 +10002049 global rowctxmenu fakerowmenu mergemax wrapcomment
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10002050 global highlight_files gdttype
Paul Mackerras3ea06f92006-05-24 10:16:03 +10002051 global searchstring sstring
Mark Levedahl60378c02007-05-20 12:12:48 -04002052 global bgcolor fgcolor bglist fglist diffcolors selectbgcolor
Gauthier Östervall252c52d2013-03-27 14:40:51 +01002053 global uifgcolor uifgdisabledcolor
2054 global filesepbgcolor filesepfgcolor
2055 global mergecolors foundbgcolor currentsearchhitbgcolor
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10002056 global headctxmenu progresscanv progressitem progresscoords statusw
2057 global fprogitem fprogcoord lastprogupdate progupdatepending
Paul Mackerras6df74032008-05-11 22:13:02 +10002058 global rprogitem rprogcoord rownumsel numcommits
Pat Thoytsd93f1712009-04-17 01:24:35 +01002059 global have_tk85 use_ttk NS
Thomas Rastae4e3ff2010-10-16 12:15:10 +02002060 global git_version
2061 global worddiff
Paul Mackerras9a40c502005-05-12 23:46:16 +00002062
Paul Mackerras79056032008-10-18 16:24:46 +11002063 # The "mc" arguments here are purely so that xgettext
2064 # sees the following string as needing to be translated
Daniel A. Steffen5fdcbb12009-03-23 12:17:38 +01002065 set file {
2066 mc "File" cascade {
Paul Mackerras79056032008-10-18 16:24:46 +11002067 {mc "Update" command updatecommits -accelerator F5}
Felipe Contrerasa135f212012-04-07 03:29:38 +03002068 {mc "Reload" command reloadcommits -accelerator Shift-F5}
Paul Mackerras79056032008-10-18 16:24:46 +11002069 {mc "Reread references" command rereadrefs}
Alexander Gavrilovcea07cf2008-11-09 13:00:45 +03002070 {mc "List references" command showrefs -accelerator F2}
Alexander Gavrilov7fb0abb2008-11-13 23:12:42 +03002071 {xx "" separator}
2072 {mc "Start git gui" command {exec git gui &}}
2073 {xx "" separator}
Alexander Gavrilovcea07cf2008-11-09 13:00:45 +03002074 {mc "Quit" command doquit -accelerator Meta1-Q}
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11002075 }}
Daniel A. Steffen5fdcbb12009-03-23 12:17:38 +01002076 set edit {
2077 mc "Edit" cascade {
Paul Mackerras79056032008-10-18 16:24:46 +11002078 {mc "Preferences" command doprefs}
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11002079 }}
Daniel A. Steffen5fdcbb12009-03-23 12:17:38 +01002080 set view {
2081 mc "View" cascade {
Alexander Gavrilovcea07cf2008-11-09 13:00:45 +03002082 {mc "New view..." command {newview 0} -accelerator Shift-F4}
2083 {mc "Edit view..." command editview -state disabled -accelerator F4}
Paul Mackerras79056032008-10-18 16:24:46 +11002084 {mc "Delete view" command delview -state disabled}
2085 {xx "" separator}
2086 {mc "All files" radiobutton {selectedview 0} -command {showview 0}}
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11002087 }}
Daniel A. Steffen5fdcbb12009-03-23 12:17:38 +01002088 if {[tk windowingsystem] ne "aqua"} {
2089 set help {
2090 mc "Help" cascade {
Paul Mackerras79056032008-10-18 16:24:46 +11002091 {mc "About gitk" command about}
2092 {mc "Key bindings" command keys}
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11002093 }}
Daniel A. Steffen5fdcbb12009-03-23 12:17:38 +01002094 set bar [list $file $edit $view $help]
2095 } else {
2096 proc ::tk::mac::ShowPreferences {} {doprefs}
2097 proc ::tk::mac::Quit {} {doquit}
2098 lset file end [lreplace [lindex $file end] end-1 end]
2099 set apple {
2100 xx "Apple" cascade {
2101 {mc "About gitk" command about}
2102 {xx "" separator}
2103 }}
2104 set help {
2105 mc "Help" cascade {
2106 {mc "Key bindings" command keys}
2107 }}
2108 set bar [list $apple $file $view $help]
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11002109 }
Daniel A. Steffen5fdcbb12009-03-23 12:17:38 +01002110 makemenu .bar $bar
Paul Mackerras9a40c502005-05-12 23:46:16 +00002111 . configure -menu .bar
2112
Pat Thoytsd93f1712009-04-17 01:24:35 +01002113 if {$use_ttk} {
2114 # cover the non-themed toplevel with a themed frame.
2115 place [ttk::frame ._main_background] -x 0 -y 0 -relwidth 1 -relheight 1
2116 }
2117
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002118 # the gui has upper and lower half, parts of a paned window.
Pat Thoytsd93f1712009-04-17 01:24:35 +01002119 ${NS}::panedwindow .ctop -orient vertical
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002120
2121 # possibly use assumed geometry
Mark Levedahl9ca72f42007-02-12 19:19:34 -05002122 if {![info exists geometry(pwsash0)]} {
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002123 set geometry(topheight) [expr {15 * $linespc}]
2124 set geometry(topwidth) [expr {80 * $charspc}]
2125 set geometry(botheight) [expr {15 * $linespc}]
2126 set geometry(botwidth) [expr {50 * $charspc}]
Pat Thoytsd93f1712009-04-17 01:24:35 +01002127 set geometry(pwsash0) [list [expr {40 * $charspc}] 2]
2128 set geometry(pwsash1) [list [expr {60 * $charspc}] 2]
Paul Mackerras0fba86b2005-05-16 23:54:58 +00002129 }
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002130
2131 # the upper half will have a paned window, a scroll bar to the right, and some stuff below
Pat Thoytsd93f1712009-04-17 01:24:35 +01002132 ${NS}::frame .tf -height $geometry(topheight) -width $geometry(topwidth)
2133 ${NS}::frame .tf.histframe
2134 ${NS}::panedwindow .tf.histframe.pwclist -orient horizontal
2135 if {!$use_ttk} {
2136 .tf.histframe.pwclist configure -sashpad 0 -handlesize 4
2137 }
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002138
2139 # create three canvases
2140 set cscroll .tf.histframe.csb
2141 set canv .tf.histframe.pwclist.canv
Mark Levedahl9ca72f42007-02-12 19:19:34 -05002142 canvas $canv \
Mark Levedahl60378c02007-05-20 12:12:48 -04002143 -selectbackground $selectbgcolor \
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10002144 -background $bgcolor -bd 0 \
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002145 -yscrollincr $linespc -yscrollcommand "scrollcanv $cscroll"
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002146 .tf.histframe.pwclist add $canv
2147 set canv2 .tf.histframe.pwclist.canv2
Mark Levedahl9ca72f42007-02-12 19:19:34 -05002148 canvas $canv2 \
Mark Levedahl60378c02007-05-20 12:12:48 -04002149 -selectbackground $selectbgcolor \
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10002150 -background $bgcolor -bd 0 -yscrollincr $linespc
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002151 .tf.histframe.pwclist add $canv2
2152 set canv3 .tf.histframe.pwclist.canv3
Mark Levedahl9ca72f42007-02-12 19:19:34 -05002153 canvas $canv3 \
Mark Levedahl60378c02007-05-20 12:12:48 -04002154 -selectbackground $selectbgcolor \
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10002155 -background $bgcolor -bd 0 -yscrollincr $linespc
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002156 .tf.histframe.pwclist add $canv3
Pat Thoytsd93f1712009-04-17 01:24:35 +01002157 if {$use_ttk} {
2158 bind .tf.histframe.pwclist <Map> {
2159 bind %W <Map> {}
2160 .tf.histframe.pwclist sashpos 1 [lindex $::geometry(pwsash1) 0]
2161 .tf.histframe.pwclist sashpos 0 [lindex $::geometry(pwsash0) 0]
2162 }
2163 } else {
2164 eval .tf.histframe.pwclist sash place 0 $geometry(pwsash0)
2165 eval .tf.histframe.pwclist sash place 1 $geometry(pwsash1)
2166 }
Paul Mackerras98f350e2005-05-15 05:56:51 +00002167
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002168 # a scroll bar to rule them
Pat Thoytsd93f1712009-04-17 01:24:35 +01002169 ${NS}::scrollbar $cscroll -command {allcanvs yview}
2170 if {!$use_ttk} {$cscroll configure -highlightthickness 0}
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002171 pack $cscroll -side right -fill y
2172 bind .tf.histframe.pwclist <Configure> {resizeclistpanes %W %w}
2173 lappend bglist $canv $canv2 $canv3
2174 pack .tf.histframe.pwclist -fill both -expand 1 -side left
2175
2176 # we have two button bars at bottom of top frame. Bar 1
Pat Thoytsd93f1712009-04-17 01:24:35 +01002177 ${NS}::frame .tf.bar
2178 ${NS}::frame .tf.lbar -height 15
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002179
2180 set sha1entry .tf.bar.sha1
Paul Mackerras887fe3c2005-05-21 07:35:37 +00002181 set entries $sha1entry
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002182 set sha1but .tf.bar.sha1label
Markus Heidelberg0359ba72010-01-09 23:11:12 +01002183 button $sha1but -text "[mc "SHA1 ID:"] " -state disabled -relief flat \
Paul Mackerrasb039f0a2008-01-06 15:54:46 +11002184 -command gotocommit -width 8
Paul Mackerras887fe3c2005-05-21 07:35:37 +00002185 $sha1but conf -disabledforeground [$sha1but cget -foreground]
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002186 pack .tf.bar.sha1label -side left
Pat Thoytsd93f1712009-04-17 01:24:35 +01002187 ${NS}::entry $sha1entry -width 40 -font textfont -textvariable sha1string
Paul Mackerras887fe3c2005-05-21 07:35:37 +00002188 trace add variable sha1string write sha1change
Paul Mackerras98f350e2005-05-15 05:56:51 +00002189 pack $sha1entry -side left -pady 2
Paul Mackerrasd6982062005-08-06 22:06:06 +10002190
Stefan Hallerf062e502012-09-22 09:46:48 +02002191 set bm_left_data {
Paul Mackerrasd6982062005-08-06 22:06:06 +10002192 #define left_width 16
2193 #define left_height 16
2194 static unsigned char left_bits[] = {
2195 0x00, 0x00, 0xc0, 0x01, 0xe0, 0x00, 0x70, 0x00, 0x38, 0x00, 0x1c, 0x00,
2196 0x0e, 0x00, 0xff, 0x7f, 0xff, 0x7f, 0xff, 0x7f, 0x0e, 0x00, 0x1c, 0x00,
2197 0x38, 0x00, 0x70, 0x00, 0xe0, 0x00, 0xc0, 0x01};
2198 }
Stefan Hallerf062e502012-09-22 09:46:48 +02002199 set bm_right_data {
Paul Mackerrasd6982062005-08-06 22:06:06 +10002200 #define right_width 16
2201 #define right_height 16
2202 static unsigned char right_bits[] = {
2203 0x00, 0x00, 0xc0, 0x01, 0x80, 0x03, 0x00, 0x07, 0x00, 0x0e, 0x00, 0x1c,
2204 0x00, 0x38, 0xff, 0x7f, 0xff, 0x7f, 0xff, 0x7f, 0x00, 0x38, 0x00, 0x1c,
2205 0x00, 0x0e, 0x00, 0x07, 0x80, 0x03, 0xc0, 0x01};
2206 }
Gauthier Östervall252c52d2013-03-27 14:40:51 +01002207 image create bitmap bm-left -data $bm_left_data -foreground $uifgcolor
2208 image create bitmap bm-left-gray -data $bm_left_data -foreground $uifgdisabledcolor
2209 image create bitmap bm-right -data $bm_right_data -foreground $uifgcolor
2210 image create bitmap bm-right-gray -data $bm_right_data -foreground $uifgdisabledcolor
Stefan Hallerf062e502012-09-22 09:46:48 +02002211
Marcus Karlsson62e9ac52012-10-07 23:21:14 +02002212 ${NS}::button .tf.bar.leftbut -command goback -state disabled -width 26
2213 if {$use_ttk} {
2214 .tf.bar.leftbut configure -image [list bm-left disabled bm-left-gray]
2215 } else {
2216 .tf.bar.leftbut configure -image bm-left
2217 }
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002218 pack .tf.bar.leftbut -side left -fill y
Marcus Karlsson62e9ac52012-10-07 23:21:14 +02002219 ${NS}::button .tf.bar.rightbut -command goforw -state disabled -width 26
2220 if {$use_ttk} {
2221 .tf.bar.rightbut configure -image [list bm-right disabled bm-right-gray]
2222 } else {
2223 .tf.bar.rightbut configure -image bm-right
2224 }
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002225 pack .tf.bar.rightbut -side left -fill y
Paul Mackerrasd6982062005-08-06 22:06:06 +10002226
Pat Thoytsd93f1712009-04-17 01:24:35 +01002227 ${NS}::label .tf.bar.rowlabel -text [mc "Row"]
Paul Mackerras6df74032008-05-11 22:13:02 +10002228 set rownumsel {}
Pat Thoytsd93f1712009-04-17 01:24:35 +01002229 ${NS}::label .tf.bar.rownum -width 7 -textvariable rownumsel \
Paul Mackerras6df74032008-05-11 22:13:02 +10002230 -relief sunken -anchor e
Pat Thoytsd93f1712009-04-17 01:24:35 +01002231 ${NS}::label .tf.bar.rowlabel2 -text "/"
2232 ${NS}::label .tf.bar.numcommits -width 7 -textvariable numcommits \
Paul Mackerras6df74032008-05-11 22:13:02 +10002233 -relief sunken -anchor e
2234 pack .tf.bar.rowlabel .tf.bar.rownum .tf.bar.rowlabel2 .tf.bar.numcommits \
2235 -side left
Pat Thoytsd93f1712009-04-17 01:24:35 +01002236 if {!$use_ttk} {
2237 foreach w {rownum numcommits} {.tf.bar.$w configure -font textfont}
2238 }
Paul Mackerras6df74032008-05-11 22:13:02 +10002239 global selectedline
Paul Mackerras94b4a692008-05-20 20:51:06 +10002240 trace add variable selectedline write selectedline_change
Paul Mackerras6df74032008-05-11 22:13:02 +10002241
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10002242 # Status label and progress bar
2243 set statusw .tf.bar.status
Pat Thoytsd93f1712009-04-17 01:24:35 +01002244 ${NS}::label $statusw -width 15 -relief sunken
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10002245 pack $statusw -side left -padx 5
Pat Thoytsd93f1712009-04-17 01:24:35 +01002246 if {$use_ttk} {
2247 set progresscanv [ttk::progressbar .tf.bar.progress]
2248 } else {
2249 set h [expr {[font metrics uifont -linespace] + 2}]
2250 set progresscanv .tf.bar.progress
2251 canvas $progresscanv -relief sunken -height $h -borderwidth 2
2252 set progressitem [$progresscanv create rect -1 0 0 $h -fill green]
2253 set fprogitem [$progresscanv create rect -1 0 0 $h -fill yellow]
2254 set rprogitem [$progresscanv create rect -1 0 0 $h -fill red]
2255 }
2256 pack $progresscanv -side right -expand 1 -fill x -padx {0 2}
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10002257 set progresscoords {0 0}
2258 set fprogcoord 0
Paul Mackerrasa137a902007-10-23 21:12:49 +10002259 set rprogcoord 0
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10002260 bind $progresscanv <Configure> adjustprogress
2261 set lastprogupdate [clock clicks -milliseconds]
2262 set progupdatepending 0
Paul Mackerrasb5721c72005-05-10 12:08:22 +00002263
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002264 # build up the bottom bar of upper window
Pat Thoytsd93f1712009-04-17 01:24:35 +01002265 ${NS}::label .tf.lbar.flabel -text "[mc "Find"] "
Marc Branchaud786f15c2013-12-18 11:04:13 -05002266
2267 set bm_down_data {
2268 #define down_width 16
2269 #define down_height 16
2270 static unsigned char down_bits[] = {
2271 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01,
2272 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01,
2273 0x87, 0xe1, 0x8e, 0x71, 0x9c, 0x39, 0xb8, 0x1d,
2274 0xf0, 0x0f, 0xe0, 0x07, 0xc0, 0x03, 0x80, 0x01};
2275 }
2276 image create bitmap bm-down -data $bm_down_data -foreground $uifgcolor
2277 ${NS}::button .tf.lbar.fnext -width 26 -command {dofind 1 1}
2278 .tf.lbar.fnext configure -image bm-down
2279
2280 set bm_up_data {
2281 #define up_width 16
2282 #define up_height 16
2283 static unsigned char up_bits[] = {
2284 0x80, 0x01, 0xc0, 0x03, 0xe0, 0x07, 0xf0, 0x0f,
2285 0xb8, 0x1d, 0x9c, 0x39, 0x8e, 0x71, 0x87, 0xe1,
2286 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01,
2287 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01};
2288 }
2289 image create bitmap bm-up -data $bm_up_data -foreground $uifgcolor
2290 ${NS}::button .tf.lbar.fprev -width 26 -command {dofind -1 1}
2291 .tf.lbar.fprev configure -image bm-up
2292
Pat Thoytsd93f1712009-04-17 01:24:35 +01002293 ${NS}::label .tf.lbar.flab2 -text " [mc "commit"] "
Marc Branchaud786f15c2013-12-18 11:04:13 -05002294
Paul Mackerras687c8762007-09-22 12:49:33 +10002295 pack .tf.lbar.flabel .tf.lbar.fnext .tf.lbar.fprev .tf.lbar.flab2 \
2296 -side left -fill y
Christian Stimmingb007ee22007-11-07 18:44:35 +01002297 set gdttype [mc "containing:"]
Pat Thoyts3cb1f9c2009-05-12 15:45:06 +01002298 set gm [makedroplist .tf.lbar.gdttype gdttype \
Christian Stimmingb007ee22007-11-07 18:44:35 +01002299 [mc "containing:"] \
2300 [mc "touching paths:"] \
Martin Langhoffc33cb902012-06-14 20:34:11 +02002301 [mc "adding/removing string:"] \
2302 [mc "changing lines matching:"]]
Paul Mackerras687c8762007-09-22 12:49:33 +10002303 trace add variable gdttype write gdttype_change
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002304 pack .tf.lbar.gdttype -side left -fill y
Paul Mackerras687c8762007-09-22 12:49:33 +10002305
2306 set findstring {}
2307 set fstring .tf.lbar.findstring
2308 lappend entries $fstring
Mark Hillsb9b142f2010-01-13 20:40:22 +00002309 ${NS}::entry $fstring -width 30 -textvariable findstring
Paul Mackerras687c8762007-09-22 12:49:33 +10002310 trace add variable findstring write find_change
Christian Stimmingb007ee22007-11-07 18:44:35 +01002311 set findtype [mc "Exact"]
Pat Thoytsd93f1712009-04-17 01:24:35 +01002312 set findtypemenu [makedroplist .tf.lbar.findtype \
2313 findtype [mc "Exact"] [mc "IgnCase"] [mc "Regexp"]]
Paul Mackerras687c8762007-09-22 12:49:33 +10002314 trace add variable findtype write findcom_change
Christian Stimmingb007ee22007-11-07 18:44:35 +01002315 set findloc [mc "All fields"]
Pat Thoytsd93f1712009-04-17 01:24:35 +01002316 makedroplist .tf.lbar.findloc findloc [mc "All fields"] [mc "Headline"] \
Christian Stimmingb007ee22007-11-07 18:44:35 +01002317 [mc "Comments"] [mc "Author"] [mc "Committer"]
Paul Mackerras687c8762007-09-22 12:49:33 +10002318 trace add variable findloc write find_change
Paul Mackerras687c8762007-09-22 12:49:33 +10002319 pack .tf.lbar.findloc -side right
2320 pack .tf.lbar.findtype -side right
2321 pack $fstring -side left -expand 1 -fill x
Paul Mackerras908c3582006-05-20 09:38:11 +10002322
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002323 # Finish putting the upper half of the viewer together
2324 pack .tf.lbar -in .tf -side bottom -fill x
2325 pack .tf.bar -in .tf -side bottom -fill x
2326 pack .tf.histframe -fill both -side top -expand 1
2327 .ctop add .tf
Pat Thoytsd93f1712009-04-17 01:24:35 +01002328 if {!$use_ttk} {
2329 .ctop paneconfigure .tf -height $geometry(topheight)
2330 .ctop paneconfigure .tf -width $geometry(topwidth)
2331 }
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002332
2333 # now build up the bottom
Pat Thoytsd93f1712009-04-17 01:24:35 +01002334 ${NS}::panedwindow .pwbottom -orient horizontal
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002335
2336 # lower left, a text box over search bar, scroll bar to the right
2337 # if we know window height, then that will set the lower text height, otherwise
2338 # we set lower text height which will drive window height
2339 if {[info exists geometry(main)]} {
Pat Thoytsd93f1712009-04-17 01:24:35 +01002340 ${NS}::frame .bleft -width $geometry(botwidth)
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002341 } else {
Pat Thoytsd93f1712009-04-17 01:24:35 +01002342 ${NS}::frame .bleft -width $geometry(botwidth) -height $geometry(botheight)
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002343 }
Pat Thoytsd93f1712009-04-17 01:24:35 +01002344 ${NS}::frame .bleft.top
2345 ${NS}::frame .bleft.mid
2346 ${NS}::frame .bleft.bottom
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002347
Pat Thoytsd93f1712009-04-17 01:24:35 +01002348 ${NS}::button .bleft.top.search -text [mc "Search"] -command dosearch
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002349 pack .bleft.top.search -side left -padx 5
2350 set sstring .bleft.top.sstring
Pat Thoytsd93f1712009-04-17 01:24:35 +01002351 set searchstring ""
Mark Hillsb9b142f2010-01-13 20:40:22 +00002352 ${NS}::entry $sstring -width 20 -textvariable searchstring
Paul Mackerras3ea06f92006-05-24 10:16:03 +10002353 lappend entries $sstring
2354 trace add variable searchstring write incrsearch
2355 pack $sstring -side left -expand 1 -fill x
Pat Thoytsd93f1712009-04-17 01:24:35 +01002356 ${NS}::radiobutton .bleft.mid.diff -text [mc "Diff"] \
Paul Mackerrasa8d610a2007-04-19 11:39:12 +10002357 -command changediffdisp -variable diffelide -value {0 0}
Pat Thoytsd93f1712009-04-17 01:24:35 +01002358 ${NS}::radiobutton .bleft.mid.old -text [mc "Old version"] \
Paul Mackerrasa8d610a2007-04-19 11:39:12 +10002359 -command changediffdisp -variable diffelide -value {0 1}
Pat Thoytsd93f1712009-04-17 01:24:35 +01002360 ${NS}::radiobutton .bleft.mid.new -text [mc "New version"] \
Paul Mackerrasa8d610a2007-04-19 11:39:12 +10002361 -command changediffdisp -variable diffelide -value {1 0}
Pat Thoytsd93f1712009-04-17 01:24:35 +01002362 ${NS}::label .bleft.mid.labeldiffcontext -text " [mc "Lines of context"]: "
Paul Mackerrasa8d610a2007-04-19 11:39:12 +10002363 pack .bleft.mid.diff .bleft.mid.old .bleft.mid.new -side left
Mark Hills0933b042010-01-13 20:40:19 +00002364 spinbox .bleft.mid.diffcontext -width 5 \
Markus Heidelberga41ddbb2009-05-23 19:31:37 +02002365 -from 0 -increment 1 -to 10000000 \
Steffen Prohaska890fae72007-08-12 12:05:46 +02002366 -validate all -validatecommand "diffcontextvalidate %P" \
2367 -textvariable diffcontextstring
2368 .bleft.mid.diffcontext set $diffcontext
2369 trace add variable diffcontextstring write diffcontextchange
2370 lappend entries .bleft.mid.diffcontext
2371 pack .bleft.mid.labeldiffcontext .bleft.mid.diffcontext -side left
Pat Thoytsd93f1712009-04-17 01:24:35 +01002372 ${NS}::checkbutton .bleft.mid.ignspace -text [mc "Ignore space change"] \
Steffen Prohaskab9b86002008-01-17 23:42:55 +01002373 -command changeignorespace -variable ignorespace
2374 pack .bleft.mid.ignspace -side left -padx 5
Thomas Rastae4e3ff2010-10-16 12:15:10 +02002375
2376 set worddiff [mc "Line diff"]
2377 if {[package vcompare $git_version "1.7.2"] >= 0} {
2378 makedroplist .bleft.mid.worddiff worddiff [mc "Line diff"] \
2379 [mc "Markup words"] [mc "Color words"]
2380 trace add variable worddiff write changeworddiff
2381 pack .bleft.mid.worddiff -side left -padx 5
2382 }
2383
Pekka Kaitaniemi8809d692008-03-08 14:27:23 +02002384 set ctext .bleft.bottom.ctext
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10002385 text $ctext -background $bgcolor -foreground $fgcolor \
Paul Mackerras9c311b32007-10-04 22:27:13 +10002386 -state disabled -font textfont \
Pekka Kaitaniemi8809d692008-03-08 14:27:23 +02002387 -yscrollcommand scrolltext -wrap none \
2388 -xscrollcommand ".bleft.bottom.sbhorizontal set"
Paul Mackerras32f1b3e2007-09-28 21:27:39 +10002389 if {$have_tk85} {
2390 $ctext conf -tabstyle wordprocessor
2391 }
Pat Thoytsd93f1712009-04-17 01:24:35 +01002392 ${NS}::scrollbar .bleft.bottom.sb -command "$ctext yview"
2393 ${NS}::scrollbar .bleft.bottom.sbhorizontal -command "$ctext xview" -orient h
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002394 pack .bleft.top -side top -fill x
Paul Mackerrasa8d610a2007-04-19 11:39:12 +10002395 pack .bleft.mid -side top -fill x
Pekka Kaitaniemi8809d692008-03-08 14:27:23 +02002396 grid $ctext .bleft.bottom.sb -sticky nsew
2397 grid .bleft.bottom.sbhorizontal -sticky ew
2398 grid columnconfigure .bleft.bottom 0 -weight 1
2399 grid rowconfigure .bleft.bottom 0 -weight 1
2400 grid rowconfigure .bleft.bottom 1 -weight 0
2401 pack .bleft.bottom -side top -fill both -expand 1
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10002402 lappend bglist $ctext
2403 lappend fglist $ctext
Paul Mackerrasd2610d12005-05-11 00:45:38 +00002404
Sergey Vlasovf1b86292006-05-15 19:13:14 +04002405 $ctext tag conf comment -wrap $wrapcomment
Gauthier Östervall252c52d2013-03-27 14:40:51 +01002406 $ctext tag conf filesep -font textfontbold -fore $filesepfgcolor -back $filesepbgcolor
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10002407 $ctext tag conf hunksep -fore [lindex $diffcolors 2]
2408 $ctext tag conf d0 -fore [lindex $diffcolors 0]
Paul Mackerras8b07dca2008-11-02 22:34:47 +11002409 $ctext tag conf dresult -fore [lindex $diffcolors 1]
Gauthier Östervall252c52d2013-03-27 14:40:51 +01002410 $ctext tag conf m0 -fore [lindex $mergecolors 0]
2411 $ctext tag conf m1 -fore [lindex $mergecolors 1]
2412 $ctext tag conf m2 -fore [lindex $mergecolors 2]
2413 $ctext tag conf m3 -fore [lindex $mergecolors 3]
2414 $ctext tag conf m4 -fore [lindex $mergecolors 4]
2415 $ctext tag conf m5 -fore [lindex $mergecolors 5]
2416 $ctext tag conf m6 -fore [lindex $mergecolors 6]
2417 $ctext tag conf m7 -fore [lindex $mergecolors 7]
2418 $ctext tag conf m8 -fore [lindex $mergecolors 8]
2419 $ctext tag conf m9 -fore [lindex $mergecolors 9]
2420 $ctext tag conf m10 -fore [lindex $mergecolors 10]
2421 $ctext tag conf m11 -fore [lindex $mergecolors 11]
2422 $ctext tag conf m12 -fore [lindex $mergecolors 12]
2423 $ctext tag conf m13 -fore [lindex $mergecolors 13]
2424 $ctext tag conf m14 -fore [lindex $mergecolors 14]
2425 $ctext tag conf m15 -fore [lindex $mergecolors 15]
Paul Mackerras712fcc02005-11-30 09:28:16 +11002426 $ctext tag conf mmax -fore darkgrey
Paul Mackerrasb77b0272006-02-07 09:13:52 +11002427 set mergemax 16
Paul Mackerras9c311b32007-10-04 22:27:13 +10002428 $ctext tag conf mresult -font textfontbold
2429 $ctext tag conf msep -font textfontbold
Gauthier Östervall252c52d2013-03-27 14:40:51 +01002430 $ctext tag conf found -back $foundbgcolor
2431 $ctext tag conf currentsearchhit -back $currentsearchhitbgcolor
Paul Mackerras76d64ca2014-01-23 22:06:22 +11002432 $ctext tag conf wwrap -wrap word -lmargin2 1c
Paul Mackerras4399fe32013-01-03 10:10:31 +11002433 $ctext tag conf bold -font textfontbold
Paul Mackerrase5c2d852005-05-11 23:44:54 +00002434
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002435 .pwbottom add .bleft
Pat Thoytsd93f1712009-04-17 01:24:35 +01002436 if {!$use_ttk} {
2437 .pwbottom paneconfigure .bleft -width $geometry(botwidth)
2438 }
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002439
2440 # lower right
Pat Thoytsd93f1712009-04-17 01:24:35 +01002441 ${NS}::frame .bright
2442 ${NS}::frame .bright.mode
2443 ${NS}::radiobutton .bright.mode.patch -text [mc "Patch"] \
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10002444 -command reselectline -variable cmitmode -value "patch"
Pat Thoytsd93f1712009-04-17 01:24:35 +01002445 ${NS}::radiobutton .bright.mode.tree -text [mc "Tree"] \
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10002446 -command reselectline -variable cmitmode -value "tree"
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002447 grid .bright.mode.patch .bright.mode.tree -sticky ew
2448 pack .bright.mode -side top -fill x
2449 set cflist .bright.cfiles
Paul Mackerras9c311b32007-10-04 22:27:13 +10002450 set indent [font measure mainfont "nn"]
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002451 text $cflist \
Mark Levedahl60378c02007-05-20 12:12:48 -04002452 -selectbackground $selectbgcolor \
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10002453 -background $bgcolor -foreground $fgcolor \
Paul Mackerras9c311b32007-10-04 22:27:13 +10002454 -font mainfont \
Paul Mackerras7fcceed2006-04-27 19:21:49 +10002455 -tabs [list $indent [expr {2 * $indent}]] \
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002456 -yscrollcommand ".bright.sb set" \
Paul Mackerras7fcceed2006-04-27 19:21:49 +10002457 -cursor [. cget -cursor] \
2458 -spacing1 1 -spacing3 1
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10002459 lappend bglist $cflist
2460 lappend fglist $cflist
Pat Thoytsd93f1712009-04-17 01:24:35 +01002461 ${NS}::scrollbar .bright.sb -command "$cflist yview"
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002462 pack .bright.sb -side right -fill y
Paul Mackerrasd2610d12005-05-11 00:45:38 +00002463 pack $cflist -side left -fill both -expand 1
Paul Mackerras89b11d32006-05-02 19:55:31 +10002464 $cflist tag configure highlight \
2465 -background [$cflist cget -selectbackground]
Paul Mackerras9c311b32007-10-04 22:27:13 +10002466 $cflist tag configure bold -font mainfontbold
Paul Mackerrasd2610d12005-05-11 00:45:38 +00002467
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002468 .pwbottom add .bright
2469 .ctop add .pwbottom
Paul Mackerras1db95b02005-05-09 04:08:39 +00002470
Paul Mackerrasb9bee112008-03-10 16:50:34 +11002471 # restore window width & height if known
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002472 if {[info exists geometry(main)]} {
Paul Mackerrasb9bee112008-03-10 16:50:34 +11002473 if {[scan $geometry(main) "%dx%d" w h] >= 2} {
2474 if {$w > [winfo screenwidth .]} {
2475 set w [winfo screenwidth .]
2476 }
2477 if {$h > [winfo screenheight .]} {
2478 set h [winfo screenheight .]
2479 }
2480 wm geometry . "${w}x$h"
2481 }
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002482 }
2483
Pat Thoytsc876dba2009-04-14 22:09:53 +01002484 if {[info exists geometry(state)] && $geometry(state) eq "zoomed"} {
2485 wm state . $geometry(state)
2486 }
2487
Shawn O. Pearced23d98d2007-07-19 00:37:58 -04002488 if {[tk windowingsystem] eq {aqua}} {
2489 set M1B M1
Daniel A. Steffen5fdcbb12009-03-23 12:17:38 +01002490 set ::BM "3"
Shawn O. Pearced23d98d2007-07-19 00:37:58 -04002491 } else {
2492 set M1B Control
Daniel A. Steffen5fdcbb12009-03-23 12:17:38 +01002493 set ::BM "2"
Shawn O. Pearced23d98d2007-07-19 00:37:58 -04002494 }
2495
Pat Thoytsd93f1712009-04-17 01:24:35 +01002496 if {$use_ttk} {
2497 bind .ctop <Map> {
2498 bind %W <Map> {}
2499 %W sashpos 0 $::geometry(topheight)
2500 }
2501 bind .pwbottom <Map> {
2502 bind %W <Map> {}
2503 %W sashpos 0 $::geometry(botwidth)
2504 }
2505 }
2506
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002507 bind .pwbottom <Configure> {resizecdetpanes %W %w}
2508 pack .ctop -fill both -expand 1
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10002509 bindall <1> {selcanvline %W %x %y}
2510 #bindall <B1-Motion> {selcanvline %W %x %y}
Mark Levedahl314c3092007-08-07 21:40:35 -04002511 if {[tk windowingsystem] == "win32"} {
2512 bind . <MouseWheel> { windows_mousewheel_redirector %W %X %Y %D }
2513 bind $ctext <MouseWheel> { windows_mousewheel_redirector %W %X %Y %D ; break }
2514 } else {
2515 bindall <ButtonRelease-4> "allcanvs yview scroll -5 units"
2516 bindall <ButtonRelease-5> "allcanvs yview scroll 5 units"
Jonathan del Strother5dd57d52007-10-15 10:33:07 +01002517 if {[tk windowingsystem] eq "aqua"} {
2518 bindall <MouseWheel> {
2519 set delta [expr {- (%D)}]
2520 allcanvs yview scroll $delta units
2521 }
Daniel A. Steffen5fdcbb12009-03-23 12:17:38 +01002522 bindall <Shift-MouseWheel> {
2523 set delta [expr {- (%D)}]
2524 $canv xview scroll $delta units
2525 }
Jonathan del Strother5dd57d52007-10-15 10:33:07 +01002526 }
Mark Levedahl314c3092007-08-07 21:40:35 -04002527 }
Daniel A. Steffen5fdcbb12009-03-23 12:17:38 +01002528 bindall <$::BM> "canvscan mark %W %x %y"
2529 bindall <B$::BM-Motion> "canvscan dragto %W %x %y"
Jens Lehmanndecd0a12010-02-02 23:11:28 +01002530 bind all <$M1B-Key-w> {destroy [winfo toplevel %W]}
2531 bind . <$M1B-Key-w> doquit
Rutger Nijlunsing6e5f7202006-04-05 10:24:03 +10002532 bindkey <Home> selfirstline
2533 bindkey <End> sellastline
Paul Mackerras17386062005-05-18 22:51:00 +00002534 bind . <Key-Up> "selnextline -1"
2535 bind . <Key-Down> "selnextline 1"
Paul Mackerrascca5d942007-10-27 21:16:56 +10002536 bind . <Shift-Key-Up> "dofind -1 0"
2537 bind . <Shift-Key-Down> "dofind 1 0"
Rutger Nijlunsing6e5f7202006-04-05 10:24:03 +10002538 bindkey <Key-Right> "goforw"
2539 bindkey <Key-Left> "goback"
2540 bind . <Key-Prior> "selnextpage -1"
2541 bind . <Key-Next> "selnextpage 1"
Shawn O. Pearced23d98d2007-07-19 00:37:58 -04002542 bind . <$M1B-Home> "allcanvs yview moveto 0.0"
2543 bind . <$M1B-End> "allcanvs yview moveto 1.0"
2544 bind . <$M1B-Key-Up> "allcanvs yview scroll -1 units"
2545 bind . <$M1B-Key-Down> "allcanvs yview scroll 1 units"
2546 bind . <$M1B-Key-Prior> "allcanvs yview scroll -1 pages"
2547 bind . <$M1B-Key-Next> "allcanvs yview scroll 1 pages"
Paul Mackerrascfb45632005-05-31 12:14:42 +00002548 bindkey <Key-Delete> "$ctext yview scroll -1 pages"
2549 bindkey <Key-BackSpace> "$ctext yview scroll -1 pages"
2550 bindkey <Key-space> "$ctext yview scroll 1 pages"
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00002551 bindkey p "selnextline -1"
2552 bindkey n "selnextline 1"
Robert Suetterlin6e2dda32005-09-22 10:07:36 +10002553 bindkey z "goback"
2554 bindkey x "goforw"
Jonathan Nieder811c70f2011-09-19 11:49:50 -05002555 bindkey k "selnextline -1"
2556 bindkey j "selnextline 1"
2557 bindkey h "goback"
Robert Suetterlin6e2dda32005-09-22 10:07:36 +10002558 bindkey l "goforw"
Paul Mackerrasf4c54b32008-05-10 13:15:36 +10002559 bindkey b prevfile
Paul Mackerrascfb45632005-05-31 12:14:42 +00002560 bindkey d "$ctext yview scroll 18 units"
2561 bindkey u "$ctext yview scroll -18 units"
Giuseppe Bilotta97bed032008-12-02 02:19:22 +01002562 bindkey / {focus $fstring}
Michele Ballabiob6e192d2009-03-30 14:55:21 +02002563 bindkey <Key-KP_Divide> {focus $fstring}
Paul Mackerrascca5d942007-10-27 21:16:56 +10002564 bindkey <Key-Return> {dofind 1 1}
2565 bindkey ? {dofind -1 1}
Paul Mackerras39ad8572005-05-19 12:35:53 +00002566 bindkey f nextfile
Alexander Gavrilovcea07cf2008-11-09 13:00:45 +03002567 bind . <F5> updatecommits
Andrew Wongebb91db2012-10-02 11:04:45 -04002568 bindmodfunctionkey Shift 5 reloadcommits
Alexander Gavrilovcea07cf2008-11-09 13:00:45 +03002569 bind . <F2> showrefs
Andrew Wong69ecfcd2012-10-02 11:04:44 -04002570 bindmodfunctionkey Shift 4 {newview 0}
Alexander Gavrilovcea07cf2008-11-09 13:00:45 +03002571 bind . <F4> edit_or_newview
Shawn O. Pearced23d98d2007-07-19 00:37:58 -04002572 bind . <$M1B-q> doquit
Paul Mackerrascca5d942007-10-27 21:16:56 +10002573 bind . <$M1B-f> {dofind 1 1}
2574 bind . <$M1B-g> {dofind 1 0}
Shawn O. Pearced23d98d2007-07-19 00:37:58 -04002575 bind . <$M1B-r> dosearchback
2576 bind . <$M1B-s> dosearch
2577 bind . <$M1B-equal> {incrfont 1}
Johannes Schindelin646f3a12008-01-11 12:39:33 +00002578 bind . <$M1B-plus> {incrfont 1}
Shawn O. Pearced23d98d2007-07-19 00:37:58 -04002579 bind . <$M1B-KP_Add> {incrfont 1}
2580 bind . <$M1B-minus> {incrfont -1}
2581 bind . <$M1B-KP_Subtract> {incrfont -1}
Mark Levedahlb6047c52007-02-08 22:22:24 -05002582 wm protocol . WM_DELETE_WINDOW doquit
Alexander Gavrilove2f90ee2008-07-12 16:09:28 +04002583 bind . <Destroy> {stop_backends}
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00002584 bind . <Button-1> "click %W"
Paul Mackerrascca5d942007-10-27 21:16:56 +10002585 bind $fstring <Key-Return> {dofind 1 1}
Paul Mackerras968ce452008-10-16 09:57:02 +11002586 bind $sha1entry <Key-Return> {gotocommit; break}
Paul Mackerrasee3dc722005-06-25 16:37:13 +10002587 bind $sha1entry <<PasteSelection>> clearsha1
Ilya Bobyrada2ea12014-03-20 01:58:51 -07002588 bind $sha1entry <<Paste>> clearsha1
Paul Mackerras7fcceed2006-04-27 19:21:49 +10002589 bind $cflist <1> {sel_flist %W %x %y; break}
2590 bind $cflist <B1-Motion> {sel_flist %W %x %y; break}
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10002591 bind $cflist <ButtonRelease-1> {treeclick %W %x %y}
Paul Mackerrasd277e892008-09-21 18:11:37 -05002592 global ctxbut
2593 bind $cflist $ctxbut {pop_flist_menu %W %X %Y %x %y}
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04002594 bind $ctext $ctxbut {pop_diff_menu %W %X %Y %x %y}
Stefan Haller4adcbea2010-11-14 13:22:56 +01002595 bind $ctext <Button-1> {focus %W}
Stefan Hallerc4614992012-09-22 09:40:24 +02002596 bind $ctext <<Selection>> rehighlight_search_results
Max Kirillovd4ec30b2014-07-08 23:45:35 +03002597 for {set i 1} {$i < 10} {incr i} {
2598 bind . <$M1B-Key-$i> [list go_to_parent $i]
2599 }
Paul Mackerrasea13cba2005-06-16 10:54:04 +00002600
2601 set maincursor [. cget -cursor]
2602 set textcursor [$ctext cget -cursor]
Paul Mackerras94a2eed2005-08-07 15:27:57 +10002603 set curtextcursor $textcursor
Paul Mackerras84ba7342005-06-17 00:12:26 +00002604
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10002605 set rowctxmenu .rowctxmenu
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11002606 makemenu $rowctxmenu {
Paul Mackerras79056032008-10-18 16:24:46 +11002607 {mc "Diff this -> selected" command {diffvssel 0}}
2608 {mc "Diff selected -> this" command {diffvssel 1}}
2609 {mc "Make patch" command mkpatch}
2610 {mc "Create tag" command mktag}
2611 {mc "Write commit to file" command writecommit}
2612 {mc "Create new branch" command mkbranch}
2613 {mc "Cherry-pick this commit" command cherrypick}
2614 {mc "Reset HEAD branch to here" command resethead}
Paul Mackerrasb9fdba72009-04-09 09:34:46 +10002615 {mc "Mark this commit" command markhere}
2616 {mc "Return to mark" command gotomark}
2617 {mc "Find descendant of this and mark" command find_common_desc}
Paul Mackerras010509f2009-04-09 22:10:20 +10002618 {mc "Compare with marked commit" command compare_commits}
Paul Mackerras6febded2012-03-23 22:07:27 +11002619 {mc "Diff this -> marked commit" command {diffvsmark 0}}
2620 {mc "Diff marked commit -> this" command {diffvsmark 1}}
Knut Franke8f3ff932013-04-27 16:36:13 +02002621 {mc "Revert this commit" command revert}
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11002622 }
2623 $rowctxmenu configure -tearoff 0
Paul Mackerras10299152006-08-02 09:52:01 +10002624
Paul Mackerras219ea3a2006-09-07 10:21:39 +10002625 set fakerowmenu .fakerowmenu
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11002626 makemenu $fakerowmenu {
Paul Mackerras79056032008-10-18 16:24:46 +11002627 {mc "Diff this -> selected" command {diffvssel 0}}
2628 {mc "Diff selected -> this" command {diffvssel 1}}
2629 {mc "Make patch" command mkpatch}
Paul Mackerras6febded2012-03-23 22:07:27 +11002630 {mc "Diff this -> marked commit" command {diffvsmark 0}}
2631 {mc "Diff marked commit -> this" command {diffvsmark 1}}
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11002632 }
2633 $fakerowmenu configure -tearoff 0
Paul Mackerras219ea3a2006-09-07 10:21:39 +10002634
Paul Mackerras10299152006-08-02 09:52:01 +10002635 set headctxmenu .headctxmenu
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11002636 makemenu $headctxmenu {
Paul Mackerras79056032008-10-18 16:24:46 +11002637 {mc "Check out this branch" command cobranch}
2638 {mc "Remove this branch" command rmbranch}
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11002639 }
2640 $headctxmenu configure -tearoff 0
Paul Mackerras32447292007-07-27 22:30:15 +10002641
2642 global flist_menu
2643 set flist_menu .flistctxmenu
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11002644 makemenu $flist_menu {
Paul Mackerras79056032008-10-18 16:24:46 +11002645 {mc "Highlight this too" command {flist_hl 0}}
2646 {mc "Highlight this only" command {flist_hl 1}}
2647 {mc "External diff" command {external_diff}}
2648 {mc "Blame parent commit" command {external_blame 1}}
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11002649 }
2650 $flist_menu configure -tearoff 0
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04002651
2652 global diff_menu
2653 set diff_menu .diffctxmenu
2654 makemenu $diff_menu {
Paul Mackerras8a897742008-10-27 21:36:25 +11002655 {mc "Show origin of this line" command show_line_source}
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04002656 {mc "Run git gui blame on this line" command {external_blame_diff}}
2657 }
2658 $diff_menu configure -tearoff 0
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00002659}
2660
Mark Levedahl314c3092007-08-07 21:40:35 -04002661# Windows sends all mouse wheel events to the current focused window, not
2662# the one where the mouse hovers, so bind those events here and redirect
2663# to the correct window
2664proc windows_mousewheel_redirector {W X Y D} {
2665 global canv canv2 canv3
2666 set w [winfo containing -displayof $W $X $Y]
2667 if {$w ne ""} {
2668 set u [expr {$D < 0 ? 5 : -5}]
2669 if {$w == $canv || $w == $canv2 || $w == $canv3} {
2670 allcanvs yview scroll $u units
2671 } else {
2672 catch {
2673 $w yview scroll $u units
2674 }
2675 }
2676 }
2677}
2678
Paul Mackerras6df74032008-05-11 22:13:02 +10002679# Update row number label when selectedline changes
2680proc selectedline_change {n1 n2 op} {
2681 global selectedline rownumsel
2682
Paul Mackerras94b4a692008-05-20 20:51:06 +10002683 if {$selectedline eq {}} {
Paul Mackerras6df74032008-05-11 22:13:02 +10002684 set rownumsel {}
2685 } else {
2686 set rownumsel [expr {$selectedline + 1}]
2687 }
2688}
2689
Paul Mackerrasbe0cd092006-03-31 09:55:11 +11002690# mouse-2 makes all windows scan vertically, but only the one
2691# the cursor is in scans horizontally
2692proc canvscan {op w x y} {
2693 global canv canv2 canv3
2694 foreach c [list $canv $canv2 $canv3] {
2695 if {$c == $w} {
2696 $c scan $op $x $y
2697 } else {
2698 $c scan $op 0 $y
2699 }
2700 }
2701}
2702
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002703proc scrollcanv {cscroll f0 f1} {
2704 $cscroll set $f0 $f1
Paul Mackerras31c0eaa2007-12-30 22:41:14 +11002705 drawvisible
Paul Mackerras908c3582006-05-20 09:38:11 +10002706 flushhighlights
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002707}
2708
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00002709# when we make a key binding for the toplevel, make sure
2710# it doesn't get triggered when that key is pressed in the
2711# find string entry widget.
2712proc bindkey {ev script} {
Paul Mackerras887fe3c2005-05-21 07:35:37 +00002713 global entries
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00002714 bind . $ev $script
2715 set escript [bind Entry $ev]
2716 if {$escript == {}} {
2717 set escript [bind Entry <Key>]
2718 }
Paul Mackerras887fe3c2005-05-21 07:35:37 +00002719 foreach e $entries {
2720 bind $e $ev "$escript; break"
2721 }
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00002722}
2723
Andrew Wong69ecfcd2012-10-02 11:04:44 -04002724proc bindmodfunctionkey {mod n script} {
2725 bind . <$mod-F$n> $script
2726 catch { bind . <$mod-XF86_Switch_VT_$n> $script }
2727}
2728
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00002729# set the focus back to the toplevel for any click outside
Paul Mackerras887fe3c2005-05-21 07:35:37 +00002730# the entry widgets
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00002731proc click {w} {
Mark Levedahlbd441de2007-08-07 21:40:34 -04002732 global ctext entries
2733 foreach e [concat $entries $ctext] {
Paul Mackerras887fe3c2005-05-21 07:35:37 +00002734 if {$w == $e} return
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00002735 }
Paul Mackerras887fe3c2005-05-21 07:35:37 +00002736 focus .
Paul Mackerras0fba86b2005-05-16 23:54:58 +00002737}
2738
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10002739# Adjust the progress bar for a change in requested extent or canvas size
2740proc adjustprogress {} {
2741 global progresscanv progressitem progresscoords
2742 global fprogitem fprogcoord lastprogupdate progupdatepending
Pat Thoytsd93f1712009-04-17 01:24:35 +01002743 global rprogitem rprogcoord use_ttk
2744
2745 if {$use_ttk} {
2746 $progresscanv configure -value [expr {int($fprogcoord * 100)}]
2747 return
2748 }
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10002749
2750 set w [expr {[winfo width $progresscanv] - 4}]
2751 set x0 [expr {$w * [lindex $progresscoords 0]}]
2752 set x1 [expr {$w * [lindex $progresscoords 1]}]
2753 set h [winfo height $progresscanv]
2754 $progresscanv coords $progressitem $x0 0 $x1 $h
2755 $progresscanv coords $fprogitem 0 0 [expr {$w * $fprogcoord}] $h
Paul Mackerrasa137a902007-10-23 21:12:49 +10002756 $progresscanv coords $rprogitem 0 0 [expr {$w * $rprogcoord}] $h
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10002757 set now [clock clicks -milliseconds]
2758 if {$now >= $lastprogupdate + 100} {
2759 set progupdatepending 0
2760 update
2761 } elseif {!$progupdatepending} {
2762 set progupdatepending 1
2763 after [expr {$lastprogupdate + 100 - $now}] doprogupdate
2764 }
2765}
2766
2767proc doprogupdate {} {
2768 global lastprogupdate progupdatepending
2769
2770 if {$progupdatepending} {
2771 set progupdatepending 0
2772 set lastprogupdate [clock clicks -milliseconds]
2773 update
2774 }
2775}
2776
Paul Mackerras0fba86b2005-05-16 23:54:58 +00002777proc savestuff {w} {
Paul Mackerras32f1b3e2007-09-28 21:27:39 +10002778 global canv canv2 canv3 mainfont textfont uifont tabstop
Paul Mackerras712fcc02005-11-30 09:28:16 +11002779 global stuffsaved findmergefiles maxgraphpct
Paul Mackerras219ea3a2006-09-07 10:21:39 +10002780 global maxwidth showneartags showlocalchanges
Yann Dirson2d480852008-02-21 21:23:31 +01002781 global viewname viewfiles viewargs viewargscmd viewperm nextviewnum
Paul Mackerras7a39a172007-10-23 10:15:11 +10002782 global cmitmode wrapcomment datetimeformat limitdiffs
Guillermo S. Romero5497f7a2009-10-15 18:51:49 +02002783 global colors uicolor bgcolor fgcolor diffcolors diffcontext selectbgcolor
Gauthier Östervall252c52d2013-03-27 14:40:51 +01002784 global uifgcolor uifgdisabledcolor
2785 global headbgcolor headfgcolor headoutlinecolor remotebgcolor
2786 global tagbgcolor tagfgcolor tagoutlinecolor
2787 global reflinecolor filesepbgcolor filesepfgcolor
2788 global mergecolors foundbgcolor currentsearchhitbgcolor
2789 global linehoverbgcolor linehoverfgcolor linehoveroutlinecolor circlecolors
2790 global mainheadcirclecolor workingfilescirclecolor indexcirclecolor
2791 global linkfgcolor circleoutlinecolor
Paul Mackerras21ac8a82011-03-09 20:52:38 +11002792 global autoselect autosellen extdifftool perfile_attrs markbgcolor use_ttk
Max Kirillovbde4a0f2014-06-24 08:19:44 +03002793 global hideremotes want_ttk maxrefs visiblerefs
Astril Hayato8f863392014-01-21 19:10:16 +00002794 global config_file config_file_tmp
Paul Mackerras4ef17532005-07-27 22:16:51 -05002795
Paul Mackerras0fba86b2005-05-16 23:54:58 +00002796 if {$stuffsaved} return
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00002797 if {![winfo viewable .]} return
Paul Mackerras0fba86b2005-05-16 23:54:58 +00002798 catch {
Astril Hayato8f863392014-01-21 19:10:16 +00002799 if {[file exists $config_file_tmp]} {
2800 file delete -force $config_file_tmp
2801 }
2802 set f [open $config_file_tmp w]
Paul Mackerras9832e4f2009-03-23 21:37:51 +11002803 if {$::tcl_platform(platform) eq {windows}} {
Astril Hayato8f863392014-01-21 19:10:16 +00002804 file attributes $config_file_tmp -hidden true
Paul Mackerras9832e4f2009-03-23 21:37:51 +11002805 }
Paul Mackerrasf0654862005-07-18 14:29:03 -04002806 puts $f [list set mainfont $mainfont]
2807 puts $f [list set textfont $textfont]
Keith Packard4840be62006-04-04 00:19:45 -07002808 puts $f [list set uifont $uifont]
Mark Levedahl7e12f1a2007-05-20 11:45:50 -04002809 puts $f [list set tabstop $tabstop]
Paul Mackerrasf0654862005-07-18 14:29:03 -04002810 puts $f [list set findmergefiles $findmergefiles]
Paul Mackerras8d858d12005-08-05 09:52:16 +10002811 puts $f [list set maxgraphpct $maxgraphpct]
Paul Mackerras04c13d32005-08-19 10:22:24 +10002812 puts $f [list set maxwidth $maxwidth]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10002813 puts $f [list set cmitmode $cmitmode]
Sergey Vlasovf1b86292006-05-15 19:13:14 +04002814 puts $f [list set wrapcomment $wrapcomment]
Jeff King95293b52008-03-06 06:49:25 -05002815 puts $f [list set autoselect $autoselect]
Paul Mackerras21ac8a82011-03-09 20:52:38 +11002816 puts $f [list set autosellen $autosellen]
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10002817 puts $f [list set showneartags $showneartags]
Paul Mackerrasd34835c2013-01-01 23:08:12 +11002818 puts $f [list set maxrefs $maxrefs]
Max Kirillovbde4a0f2014-06-24 08:19:44 +03002819 puts $f [list set visiblerefs $visiblerefs]
Thomas Rastffe15292009-08-03 23:53:36 +02002820 puts $f [list set hideremotes $hideremotes]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10002821 puts $f [list set showlocalchanges $showlocalchanges]
Arjen Laarhovene8b5f4b2007-08-14 22:02:04 +02002822 puts $f [list set datetimeformat $datetimeformat]
Paul Mackerras7a39a172007-10-23 10:15:11 +10002823 puts $f [list set limitdiffs $limitdiffs]
Guillermo S. Romero5497f7a2009-10-15 18:51:49 +02002824 puts $f [list set uicolor $uicolor]
Paul Mackerras0cc08ff2009-09-05 22:06:46 +10002825 puts $f [list set want_ttk $want_ttk]
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10002826 puts $f [list set bgcolor $bgcolor]
2827 puts $f [list set fgcolor $fgcolor]
Gauthier Östervall252c52d2013-03-27 14:40:51 +01002828 puts $f [list set uifgcolor $uifgcolor]
2829 puts $f [list set uifgdisabledcolor $uifgdisabledcolor]
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10002830 puts $f [list set colors $colors]
2831 puts $f [list set diffcolors $diffcolors]
Gauthier Östervall252c52d2013-03-27 14:40:51 +01002832 puts $f [list set mergecolors $mergecolors]
Paul Mackerrase3e901b2008-10-27 22:37:21 +11002833 puts $f [list set markbgcolor $markbgcolor]
Steffen Prohaska890fae72007-08-12 12:05:46 +02002834 puts $f [list set diffcontext $diffcontext]
Mark Levedahl60378c02007-05-20 12:12:48 -04002835 puts $f [list set selectbgcolor $selectbgcolor]
Gauthier Östervall252c52d2013-03-27 14:40:51 +01002836 puts $f [list set foundbgcolor $foundbgcolor]
2837 puts $f [list set currentsearchhitbgcolor $currentsearchhitbgcolor]
Thomas Arcila314f5de2008-03-24 12:55:36 +01002838 puts $f [list set extdifftool $extdifftool]
Paul Mackerras39ee47e2008-10-15 22:23:03 +11002839 puts $f [list set perfile_attrs $perfile_attrs]
Gauthier Östervall252c52d2013-03-27 14:40:51 +01002840 puts $f [list set headbgcolor $headbgcolor]
2841 puts $f [list set headfgcolor $headfgcolor]
2842 puts $f [list set headoutlinecolor $headoutlinecolor]
2843 puts $f [list set remotebgcolor $remotebgcolor]
2844 puts $f [list set tagbgcolor $tagbgcolor]
2845 puts $f [list set tagfgcolor $tagfgcolor]
2846 puts $f [list set tagoutlinecolor $tagoutlinecolor]
2847 puts $f [list set reflinecolor $reflinecolor]
2848 puts $f [list set filesepbgcolor $filesepbgcolor]
2849 puts $f [list set filesepfgcolor $filesepfgcolor]
2850 puts $f [list set linehoverbgcolor $linehoverbgcolor]
2851 puts $f [list set linehoverfgcolor $linehoverfgcolor]
2852 puts $f [list set linehoveroutlinecolor $linehoveroutlinecolor]
2853 puts $f [list set mainheadcirclecolor $mainheadcirclecolor]
2854 puts $f [list set workingfilescirclecolor $workingfilescirclecolor]
2855 puts $f [list set indexcirclecolor $indexcirclecolor]
2856 puts $f [list set circlecolors $circlecolors]
2857 puts $f [list set linkfgcolor $linkfgcolor]
2858 puts $f [list set circleoutlinecolor $circleoutlinecolor]
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002859
Mark Levedahlb6047c52007-02-08 22:22:24 -05002860 puts $f "set geometry(main) [wm geometry .]"
Pat Thoytsc876dba2009-04-14 22:09:53 +01002861 puts $f "set geometry(state) [wm state .]"
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002862 puts $f "set geometry(topwidth) [winfo width .tf]"
2863 puts $f "set geometry(topheight) [winfo height .tf]"
Pat Thoytsd93f1712009-04-17 01:24:35 +01002864 if {$use_ttk} {
2865 puts $f "set geometry(pwsash0) \"[.tf.histframe.pwclist sashpos 0] 1\""
2866 puts $f "set geometry(pwsash1) \"[.tf.histframe.pwclist sashpos 1] 1\""
2867 } else {
2868 puts $f "set geometry(pwsash0) \"[.tf.histframe.pwclist sash coord 0]\""
2869 puts $f "set geometry(pwsash1) \"[.tf.histframe.pwclist sash coord 1]\""
2870 }
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002871 puts $f "set geometry(botwidth) [winfo width .bleft]"
2872 puts $f "set geometry(botheight) [winfo height .bleft]"
2873
Paul Mackerrasa90a6d22006-04-25 17:12:46 +10002874 puts -nonewline $f "set permviews {"
2875 for {set v 0} {$v < $nextviewnum} {incr v} {
2876 if {$viewperm($v)} {
Yann Dirson2d480852008-02-21 21:23:31 +01002877 puts $f "{[list $viewname($v) $viewfiles($v) $viewargs($v) $viewargscmd($v)]}"
Paul Mackerrasa90a6d22006-04-25 17:12:46 +10002878 }
2879 }
2880 puts $f "}"
Paul Mackerras0fba86b2005-05-16 23:54:58 +00002881 close $f
Astril Hayato8f863392014-01-21 19:10:16 +00002882 file rename -force $config_file_tmp $config_file
Paul Mackerras0fba86b2005-05-16 23:54:58 +00002883 }
2884 set stuffsaved 1
Paul Mackerras1db95b02005-05-09 04:08:39 +00002885}
2886
Paul Mackerras43bddeb2005-05-15 23:19:18 +00002887proc resizeclistpanes {win w} {
Pat Thoytsd93f1712009-04-17 01:24:35 +01002888 global oldwidth use_ttk
Paul Mackerras418c4c72006-02-07 09:10:18 +11002889 if {[info exists oldwidth($win)]} {
Pat Thoytsd93f1712009-04-17 01:24:35 +01002890 if {$use_ttk} {
2891 set s0 [$win sashpos 0]
2892 set s1 [$win sashpos 1]
2893 } else {
2894 set s0 [$win sash coord 0]
2895 set s1 [$win sash coord 1]
2896 }
Paul Mackerras43bddeb2005-05-15 23:19:18 +00002897 if {$w < 60} {
2898 set sash0 [expr {int($w/2 - 2)}]
2899 set sash1 [expr {int($w*5/6 - 2)}]
2900 } else {
2901 set factor [expr {1.0 * $w / $oldwidth($win)}]
2902 set sash0 [expr {int($factor * [lindex $s0 0])}]
2903 set sash1 [expr {int($factor * [lindex $s1 0])}]
2904 if {$sash0 < 30} {
2905 set sash0 30
2906 }
2907 if {$sash1 < $sash0 + 20} {
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08002908 set sash1 [expr {$sash0 + 20}]
Paul Mackerras43bddeb2005-05-15 23:19:18 +00002909 }
2910 if {$sash1 > $w - 10} {
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08002911 set sash1 [expr {$w - 10}]
Paul Mackerras43bddeb2005-05-15 23:19:18 +00002912 if {$sash0 > $sash1 - 20} {
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08002913 set sash0 [expr {$sash1 - 20}]
Paul Mackerras43bddeb2005-05-15 23:19:18 +00002914 }
2915 }
2916 }
Pat Thoytsd93f1712009-04-17 01:24:35 +01002917 if {$use_ttk} {
2918 $win sashpos 0 $sash0
2919 $win sashpos 1 $sash1
2920 } else {
2921 $win sash place 0 $sash0 [lindex $s0 1]
2922 $win sash place 1 $sash1 [lindex $s1 1]
2923 }
Paul Mackerras43bddeb2005-05-15 23:19:18 +00002924 }
2925 set oldwidth($win) $w
2926}
2927
2928proc resizecdetpanes {win w} {
Pat Thoytsd93f1712009-04-17 01:24:35 +01002929 global oldwidth use_ttk
Paul Mackerras418c4c72006-02-07 09:10:18 +11002930 if {[info exists oldwidth($win)]} {
Pat Thoytsd93f1712009-04-17 01:24:35 +01002931 if {$use_ttk} {
2932 set s0 [$win sashpos 0]
2933 } else {
2934 set s0 [$win sash coord 0]
2935 }
Paul Mackerras43bddeb2005-05-15 23:19:18 +00002936 if {$w < 60} {
2937 set sash0 [expr {int($w*3/4 - 2)}]
2938 } else {
2939 set factor [expr {1.0 * $w / $oldwidth($win)}]
2940 set sash0 [expr {int($factor * [lindex $s0 0])}]
2941 if {$sash0 < 45} {
2942 set sash0 45
2943 }
2944 if {$sash0 > $w - 15} {
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08002945 set sash0 [expr {$w - 15}]
Paul Mackerras43bddeb2005-05-15 23:19:18 +00002946 }
2947 }
Pat Thoytsd93f1712009-04-17 01:24:35 +01002948 if {$use_ttk} {
2949 $win sashpos 0 $sash0
2950 } else {
2951 $win sash place 0 $sash0 [lindex $s0 1]
2952 }
Paul Mackerras43bddeb2005-05-15 23:19:18 +00002953 }
2954 set oldwidth($win) $w
2955}
2956
Paul Mackerrasb5721c72005-05-10 12:08:22 +00002957proc allcanvs args {
2958 global canv canv2 canv3
2959 eval $canv $args
2960 eval $canv2 $args
2961 eval $canv3 $args
2962}
2963
2964proc bindall {event action} {
2965 global canv canv2 canv3
2966 bind $canv $event $action
2967 bind $canv2 $event $action
2968 bind $canv3 $event $action
2969}
2970
Paul Mackerras9a40c502005-05-12 23:46:16 +00002971proc about {} {
Pat Thoytsd93f1712009-04-17 01:24:35 +01002972 global uifont NS
Paul Mackerras9a40c502005-05-12 23:46:16 +00002973 set w .about
2974 if {[winfo exists $w]} {
2975 raise $w
2976 return
2977 }
Pat Thoytsd93f1712009-04-17 01:24:35 +01002978 ttk_toplevel $w
Christian Stimmingd990ced2007-11-07 18:42:55 +01002979 wm title $w [mc "About gitk"]
Alexander Gavrilove7d64002008-11-11 23:55:42 +03002980 make_transient $w .
Christian Stimmingd990ced2007-11-07 18:42:55 +01002981 message $w.m -text [mc "
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002982Gitk - a commit viewer for git
Paul Mackerras9a40c502005-05-12 23:46:16 +00002983
Paul Mackerras6c626a02014-01-21 22:02:27 +11002984Copyright \u00a9 2005-2014 Paul Mackerras
Paul Mackerras9a40c502005-05-12 23:46:16 +00002985
Christian Stimmingd990ced2007-11-07 18:42:55 +01002986Use and redistribute under the terms of the GNU General Public License"] \
Eygene Ryabinkin3a950e92007-03-27 14:36:59 +04002987 -justify center -aspect 400 -border 2 -bg white -relief groove
2988 pack $w.m -side top -fill x -padx 2 -pady 2
Pat Thoytsd93f1712009-04-17 01:24:35 +01002989 ${NS}::button $w.ok -text [mc "Close"] -command "destroy $w" -default active
Paul Mackerras9a40c502005-05-12 23:46:16 +00002990 pack $w.ok -side bottom
Eygene Ryabinkin3a950e92007-03-27 14:36:59 +04002991 bind $w <Visibility> "focus $w.ok"
2992 bind $w <Key-Escape> "destroy $w"
2993 bind $w <Key-Return> "destroy $w"
Pat Thoytsd93f1712009-04-17 01:24:35 +01002994 tk::PlaceWindow $w widget .
Paul Mackerras9a40c502005-05-12 23:46:16 +00002995}
2996
Paul Mackerras4e95e1f2006-04-05 09:39:51 +10002997proc keys {} {
Pat Thoytsd93f1712009-04-17 01:24:35 +01002998 global NS
Paul Mackerras4e95e1f2006-04-05 09:39:51 +10002999 set w .keys
3000 if {[winfo exists $w]} {
3001 raise $w
3002 return
3003 }
Shawn O. Pearced23d98d2007-07-19 00:37:58 -04003004 if {[tk windowingsystem] eq {aqua}} {
3005 set M1T Cmd
3006 } else {
3007 set M1T Ctrl
3008 }
Pat Thoytsd93f1712009-04-17 01:24:35 +01003009 ttk_toplevel $w
Christian Stimmingd990ced2007-11-07 18:42:55 +01003010 wm title $w [mc "Gitk key bindings"]
Alexander Gavrilove7d64002008-11-11 23:55:42 +03003011 make_transient $w .
Michele Ballabio3d2c9982008-01-15 23:31:49 +01003012 message $w.m -text "
3013[mc "Gitk key bindings:"]
Paul Mackerras4e95e1f2006-04-05 09:39:51 +10003014
Michele Ballabio3d2c9982008-01-15 23:31:49 +01003015[mc "<%s-Q> Quit" $M1T]
Jens Lehmanndecd0a12010-02-02 23:11:28 +01003016[mc "<%s-W> Close window" $M1T]
Michele Ballabio3d2c9982008-01-15 23:31:49 +01003017[mc "<Home> Move to first commit"]
3018[mc "<End> Move to last commit"]
Jonathan Nieder811c70f2011-09-19 11:49:50 -05003019[mc "<Up>, p, k Move up one commit"]
3020[mc "<Down>, n, j Move down one commit"]
3021[mc "<Left>, z, h Go back in history list"]
Michele Ballabio3d2c9982008-01-15 23:31:49 +01003022[mc "<Right>, x, l Go forward in history list"]
Max Kirillovd4ec30b2014-07-08 23:45:35 +03003023[mc "<%s-n> Go to n-th parent of current commit in history list" $M1T]
Michele Ballabio3d2c9982008-01-15 23:31:49 +01003024[mc "<PageUp> Move up one page in commit list"]
3025[mc "<PageDown> Move down one page in commit list"]
3026[mc "<%s-Home> Scroll to top of commit list" $M1T]
3027[mc "<%s-End> Scroll to bottom of commit list" $M1T]
3028[mc "<%s-Up> Scroll commit list up one line" $M1T]
3029[mc "<%s-Down> Scroll commit list down one line" $M1T]
3030[mc "<%s-PageUp> Scroll commit list up one page" $M1T]
3031[mc "<%s-PageDown> Scroll commit list down one page" $M1T]
3032[mc "<Shift-Up> Find backwards (upwards, later commits)"]
3033[mc "<Shift-Down> Find forwards (downwards, earlier commits)"]
3034[mc "<Delete>, b Scroll diff view up one page"]
3035[mc "<Backspace> Scroll diff view up one page"]
3036[mc "<Space> Scroll diff view down one page"]
3037[mc "u Scroll diff view up 18 lines"]
3038[mc "d Scroll diff view down 18 lines"]
3039[mc "<%s-F> Find" $M1T]
3040[mc "<%s-G> Move to next find hit" $M1T]
3041[mc "<Return> Move to next find hit"]
Giuseppe Bilotta97bed032008-12-02 02:19:22 +01003042[mc "/ Focus the search box"]
Michele Ballabio3d2c9982008-01-15 23:31:49 +01003043[mc "? Move to previous find hit"]
3044[mc "f Scroll diff view to next file"]
3045[mc "<%s-S> Search for next hit in diff view" $M1T]
3046[mc "<%s-R> Search for previous hit in diff view" $M1T]
3047[mc "<%s-KP+> Increase font size" $M1T]
3048[mc "<%s-plus> Increase font size" $M1T]
3049[mc "<%s-KP-> Decrease font size" $M1T]
3050[mc "<%s-minus> Decrease font size" $M1T]
3051[mc "<F5> Update"]
3052" \
Eygene Ryabinkin3a950e92007-03-27 14:36:59 +04003053 -justify left -bg white -border 2 -relief groove
3054 pack $w.m -side top -fill both -padx 2 -pady 2
Pat Thoytsd93f1712009-04-17 01:24:35 +01003055 ${NS}::button $w.ok -text [mc "Close"] -command "destroy $w" -default active
Alexander Gavrilov76f15942008-11-02 21:59:44 +03003056 bind $w <Key-Escape> [list destroy $w]
Paul Mackerras4e95e1f2006-04-05 09:39:51 +10003057 pack $w.ok -side bottom
Eygene Ryabinkin3a950e92007-03-27 14:36:59 +04003058 bind $w <Visibility> "focus $w.ok"
3059 bind $w <Key-Escape> "destroy $w"
3060 bind $w <Key-Return> "destroy $w"
Paul Mackerras4e95e1f2006-04-05 09:39:51 +10003061}
3062
Paul Mackerras7fcceed2006-04-27 19:21:49 +10003063# Procedures for manipulating the file list window at the
3064# bottom right of the overall window.
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10003065
3066proc treeview {w l openlevs} {
3067 global treecontents treediropen treeheight treeparent treeindex
3068
3069 set ix 0
3070 set treeindex() 0
3071 set lev 0
3072 set prefix {}
3073 set prefixend -1
3074 set prefendstack {}
3075 set htstack {}
3076 set ht 0
3077 set treecontents() {}
3078 $w conf -state normal
3079 foreach f $l {
3080 while {[string range $f 0 $prefixend] ne $prefix} {
3081 if {$lev <= $openlevs} {
3082 $w mark set e:$treeindex($prefix) "end -1c"
3083 $w mark gravity e:$treeindex($prefix) left
3084 }
3085 set treeheight($prefix) $ht
3086 incr ht [lindex $htstack end]
3087 set htstack [lreplace $htstack end end]
3088 set prefixend [lindex $prefendstack end]
3089 set prefendstack [lreplace $prefendstack end end]
3090 set prefix [string range $prefix 0 $prefixend]
3091 incr lev -1
3092 }
3093 set tail [string range $f [expr {$prefixend+1}] end]
3094 while {[set slash [string first "/" $tail]] >= 0} {
3095 lappend htstack $ht
3096 set ht 0
3097 lappend prefendstack $prefixend
3098 incr prefixend [expr {$slash + 1}]
3099 set d [string range $tail 0 $slash]
3100 lappend treecontents($prefix) $d
3101 set oldprefix $prefix
3102 append prefix $d
3103 set treecontents($prefix) {}
3104 set treeindex($prefix) [incr ix]
3105 set treeparent($prefix) $oldprefix
3106 set tail [string range $tail [expr {$slash+1}] end]
3107 if {$lev <= $openlevs} {
3108 set ht 1
3109 set treediropen($prefix) [expr {$lev < $openlevs}]
3110 set bm [expr {$lev == $openlevs? "tri-rt": "tri-dn"}]
3111 $w mark set d:$ix "end -1c"
3112 $w mark gravity d:$ix left
3113 set str "\n"
3114 for {set i 0} {$i < $lev} {incr i} {append str "\t"}
3115 $w insert end $str
3116 $w image create end -align center -image $bm -padx 1 \
3117 -name a:$ix
Paul Mackerras45a9d502006-05-20 22:56:27 +10003118 $w insert end $d [highlight_tag $prefix]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10003119 $w mark set s:$ix "end -1c"
3120 $w mark gravity s:$ix left
3121 }
3122 incr lev
3123 }
3124 if {$tail ne {}} {
3125 if {$lev <= $openlevs} {
3126 incr ht
3127 set str "\n"
3128 for {set i 0} {$i < $lev} {incr i} {append str "\t"}
3129 $w insert end $str
Paul Mackerras45a9d502006-05-20 22:56:27 +10003130 $w insert end $tail [highlight_tag $f]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10003131 }
3132 lappend treecontents($prefix) $tail
3133 }
3134 }
3135 while {$htstack ne {}} {
3136 set treeheight($prefix) $ht
3137 incr ht [lindex $htstack end]
3138 set htstack [lreplace $htstack end end]
Brian Downing096e96b2007-07-05 06:33:02 -05003139 set prefixend [lindex $prefendstack end]
3140 set prefendstack [lreplace $prefendstack end end]
3141 set prefix [string range $prefix 0 $prefixend]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10003142 }
3143 $w conf -state disabled
3144}
3145
3146proc linetoelt {l} {
3147 global treeheight treecontents
3148
3149 set y 2
3150 set prefix {}
3151 while {1} {
3152 foreach e $treecontents($prefix) {
3153 if {$y == $l} {
3154 return "$prefix$e"
3155 }
3156 set n 1
3157 if {[string index $e end] eq "/"} {
3158 set n $treeheight($prefix$e)
3159 if {$y + $n > $l} {
3160 append prefix $e
3161 incr y
3162 break
3163 }
3164 }
3165 incr y $n
3166 }
3167 }
3168}
3169
Paul Mackerras45a9d502006-05-20 22:56:27 +10003170proc highlight_tree {y prefix} {
3171 global treeheight treecontents cflist
3172
3173 foreach e $treecontents($prefix) {
3174 set path $prefix$e
3175 if {[highlight_tag $path] ne {}} {
3176 $cflist tag add bold $y.0 "$y.0 lineend"
3177 }
3178 incr y
3179 if {[string index $e end] eq "/" && $treeheight($path) > 1} {
3180 set y [highlight_tree $y $path]
3181 }
3182 }
3183 return $y
3184}
3185
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10003186proc treeclosedir {w dir} {
3187 global treediropen treeheight treeparent treeindex
3188
3189 set ix $treeindex($dir)
3190 $w conf -state normal
3191 $w delete s:$ix e:$ix
3192 set treediropen($dir) 0
3193 $w image configure a:$ix -image tri-rt
3194 $w conf -state disabled
3195 set n [expr {1 - $treeheight($dir)}]
3196 while {$dir ne {}} {
3197 incr treeheight($dir) $n
3198 set dir $treeparent($dir)
3199 }
3200}
3201
3202proc treeopendir {w dir} {
3203 global treediropen treeheight treeparent treecontents treeindex
3204
3205 set ix $treeindex($dir)
3206 $w conf -state normal
3207 $w image configure a:$ix -image tri-dn
3208 $w mark set e:$ix s:$ix
3209 $w mark gravity e:$ix right
3210 set lev 0
3211 set str "\n"
3212 set n [llength $treecontents($dir)]
3213 for {set x $dir} {$x ne {}} {set x $treeparent($x)} {
3214 incr lev
3215 append str "\t"
3216 incr treeheight($x) $n
3217 }
3218 foreach e $treecontents($dir) {
Paul Mackerras45a9d502006-05-20 22:56:27 +10003219 set de $dir$e
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10003220 if {[string index $e end] eq "/"} {
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10003221 set iy $treeindex($de)
3222 $w mark set d:$iy e:$ix
3223 $w mark gravity d:$iy left
3224 $w insert e:$ix $str
3225 set treediropen($de) 0
3226 $w image create e:$ix -align center -image tri-rt -padx 1 \
3227 -name a:$iy
Paul Mackerras45a9d502006-05-20 22:56:27 +10003228 $w insert e:$ix $e [highlight_tag $de]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10003229 $w mark set s:$iy e:$ix
3230 $w mark gravity s:$iy left
3231 set treeheight($de) 1
3232 } else {
3233 $w insert e:$ix $str
Paul Mackerras45a9d502006-05-20 22:56:27 +10003234 $w insert e:$ix $e [highlight_tag $de]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10003235 }
3236 }
Alexander Gavrilovb8a640e2008-09-08 11:28:16 +04003237 $w mark gravity e:$ix right
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10003238 $w conf -state disabled
3239 set treediropen($dir) 1
3240 set top [lindex [split [$w index @0,0] .] 0]
3241 set ht [$w cget -height]
3242 set l [lindex [split [$w index s:$ix] .] 0]
3243 if {$l < $top} {
3244 $w yview $l.0
3245 } elseif {$l + $n + 1 > $top + $ht} {
3246 set top [expr {$l + $n + 2 - $ht}]
3247 if {$l < $top} {
3248 set top $l
3249 }
3250 $w yview $top.0
3251 }
3252}
3253
3254proc treeclick {w x y} {
3255 global treediropen cmitmode ctext cflist cflist_top
3256
3257 if {$cmitmode ne "tree"} return
3258 if {![info exists cflist_top]} return
3259 set l [lindex [split [$w index "@$x,$y"] "."] 0]
3260 $cflist tag remove highlight $cflist_top.0 "$cflist_top.0 lineend"
3261 $cflist tag add highlight $l.0 "$l.0 lineend"
3262 set cflist_top $l
3263 if {$l == 1} {
3264 $ctext yview 1.0
3265 return
3266 }
3267 set e [linetoelt $l]
3268 if {[string index $e end] ne "/"} {
3269 showfile $e
3270 } elseif {$treediropen($e)} {
3271 treeclosedir $w $e
3272 } else {
3273 treeopendir $w $e
3274 }
3275}
3276
3277proc setfilelist {id} {
Paul Mackerras8a897742008-10-27 21:36:25 +11003278 global treefilelist cflist jump_to_here
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10003279
3280 treeview $cflist $treefilelist($id) 0
Paul Mackerras8a897742008-10-27 21:36:25 +11003281 if {$jump_to_here ne {}} {
3282 set f [lindex $jump_to_here 0]
3283 if {[lsearch -exact $treefilelist($id) $f] >= 0} {
3284 showfile $f
3285 }
3286 }
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10003287}
3288
3289image create bitmap tri-rt -background black -foreground blue -data {
3290 #define tri-rt_width 13
3291 #define tri-rt_height 13
3292 static unsigned char tri-rt_bits[] = {
3293 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x30, 0x00, 0x70, 0x00, 0xf0, 0x00,
3294 0xf0, 0x01, 0xf0, 0x00, 0x70, 0x00, 0x30, 0x00, 0x10, 0x00, 0x00, 0x00,
3295 0x00, 0x00};
3296} -maskdata {
3297 #define tri-rt-mask_width 13
3298 #define tri-rt-mask_height 13
3299 static unsigned char tri-rt-mask_bits[] = {
3300 0x08, 0x00, 0x18, 0x00, 0x38, 0x00, 0x78, 0x00, 0xf8, 0x00, 0xf8, 0x01,
3301 0xf8, 0x03, 0xf8, 0x01, 0xf8, 0x00, 0x78, 0x00, 0x38, 0x00, 0x18, 0x00,
3302 0x08, 0x00};
3303}
3304image create bitmap tri-dn -background black -foreground blue -data {
3305 #define tri-dn_width 13
3306 #define tri-dn_height 13
3307 static unsigned char tri-dn_bits[] = {
3308 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x07, 0xf8, 0x03,
3309 0xf0, 0x01, 0xe0, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3310 0x00, 0x00};
3311} -maskdata {
3312 #define tri-dn-mask_width 13
3313 #define tri-dn-mask_height 13
3314 static unsigned char tri-dn-mask_bits[] = {
3315 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x1f, 0xfe, 0x0f, 0xfc, 0x07,
3316 0xf8, 0x03, 0xf0, 0x01, 0xe0, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00,
3317 0x00, 0x00};
3318}
3319
Paul Mackerras887c9962007-08-20 19:36:20 +10003320image create bitmap reficon-T -background black -foreground yellow -data {
3321 #define tagicon_width 13
3322 #define tagicon_height 9
3323 static unsigned char tagicon_bits[] = {
3324 0x00, 0x00, 0x00, 0x00, 0xf0, 0x07, 0xf8, 0x07,
3325 0xfc, 0x07, 0xf8, 0x07, 0xf0, 0x07, 0x00, 0x00, 0x00, 0x00};
3326} -maskdata {
3327 #define tagicon-mask_width 13
3328 #define tagicon-mask_height 9
3329 static unsigned char tagicon-mask_bits[] = {
3330 0x00, 0x00, 0xf0, 0x0f, 0xf8, 0x0f, 0xfc, 0x0f,
3331 0xfe, 0x0f, 0xfc, 0x0f, 0xf8, 0x0f, 0xf0, 0x0f, 0x00, 0x00};
3332}
3333set rectdata {
3334 #define headicon_width 13
3335 #define headicon_height 9
3336 static unsigned char headicon_bits[] = {
3337 0x00, 0x00, 0x00, 0x00, 0xf8, 0x07, 0xf8, 0x07,
3338 0xf8, 0x07, 0xf8, 0x07, 0xf8, 0x07, 0x00, 0x00, 0x00, 0x00};
3339}
3340set rectmask {
3341 #define headicon-mask_width 13
3342 #define headicon-mask_height 9
3343 static unsigned char headicon-mask_bits[] = {
3344 0x00, 0x00, 0xfc, 0x0f, 0xfc, 0x0f, 0xfc, 0x0f,
3345 0xfc, 0x0f, 0xfc, 0x0f, 0xfc, 0x0f, 0xfc, 0x0f, 0x00, 0x00};
3346}
3347image create bitmap reficon-H -background black -foreground green \
3348 -data $rectdata -maskdata $rectmask
3349image create bitmap reficon-o -background black -foreground "#ddddff" \
3350 -data $rectdata -maskdata $rectmask
3351
Paul Mackerras7fcceed2006-04-27 19:21:49 +10003352proc init_flist {first} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11003353 global cflist cflist_top difffilestart
Paul Mackerras7fcceed2006-04-27 19:21:49 +10003354
3355 $cflist conf -state normal
3356 $cflist delete 0.0 end
3357 if {$first ne {}} {
3358 $cflist insert end $first
3359 set cflist_top 1
Paul Mackerras7fcceed2006-04-27 19:21:49 +10003360 $cflist tag add highlight 1.0 "1.0 lineend"
3361 } else {
3362 catch {unset cflist_top}
3363 }
3364 $cflist conf -state disabled
3365 set difffilestart {}
3366}
3367
Paul Mackerras63b79192006-05-20 21:31:52 +10003368proc highlight_tag {f} {
3369 global highlight_paths
3370
3371 foreach p $highlight_paths {
3372 if {[string match $p $f]} {
3373 return "bold"
3374 }
3375 }
3376 return {}
3377}
3378
3379proc highlight_filelist {} {
Paul Mackerras45a9d502006-05-20 22:56:27 +10003380 global cmitmode cflist
Paul Mackerras63b79192006-05-20 21:31:52 +10003381
Paul Mackerras45a9d502006-05-20 22:56:27 +10003382 $cflist conf -state normal
3383 if {$cmitmode ne "tree"} {
Paul Mackerras63b79192006-05-20 21:31:52 +10003384 set end [lindex [split [$cflist index end] .] 0]
3385 for {set l 2} {$l < $end} {incr l} {
3386 set line [$cflist get $l.0 "$l.0 lineend"]
3387 if {[highlight_tag $line] ne {}} {
3388 $cflist tag add bold $l.0 "$l.0 lineend"
3389 }
3390 }
Paul Mackerras45a9d502006-05-20 22:56:27 +10003391 } else {
3392 highlight_tree 2 {}
Paul Mackerras63b79192006-05-20 21:31:52 +10003393 }
Paul Mackerras45a9d502006-05-20 22:56:27 +10003394 $cflist conf -state disabled
Paul Mackerras63b79192006-05-20 21:31:52 +10003395}
3396
3397proc unhighlight_filelist {} {
Paul Mackerras45a9d502006-05-20 22:56:27 +10003398 global cflist
Paul Mackerras63b79192006-05-20 21:31:52 +10003399
Paul Mackerras45a9d502006-05-20 22:56:27 +10003400 $cflist conf -state normal
3401 $cflist tag remove bold 1.0 end
3402 $cflist conf -state disabled
Paul Mackerras63b79192006-05-20 21:31:52 +10003403}
3404
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10003405proc add_flist {fl} {
Paul Mackerras45a9d502006-05-20 22:56:27 +10003406 global cflist
Paul Mackerras7fcceed2006-04-27 19:21:49 +10003407
Paul Mackerras45a9d502006-05-20 22:56:27 +10003408 $cflist conf -state normal
3409 foreach f $fl {
3410 $cflist insert end "\n"
3411 $cflist insert end $f [highlight_tag $f]
Paul Mackerras7fcceed2006-04-27 19:21:49 +10003412 }
Paul Mackerras45a9d502006-05-20 22:56:27 +10003413 $cflist conf -state disabled
Paul Mackerras7fcceed2006-04-27 19:21:49 +10003414}
3415
3416proc sel_flist {w x y} {
Paul Mackerras45a9d502006-05-20 22:56:27 +10003417 global ctext difffilestart cflist cflist_top cmitmode
Paul Mackerras7fcceed2006-04-27 19:21:49 +10003418
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10003419 if {$cmitmode eq "tree"} return
Paul Mackerras7fcceed2006-04-27 19:21:49 +10003420 if {![info exists cflist_top]} return
3421 set l [lindex [split [$w index "@$x,$y"] "."] 0]
Paul Mackerras89b11d32006-05-02 19:55:31 +10003422 $cflist tag remove highlight $cflist_top.0 "$cflist_top.0 lineend"
3423 $cflist tag add highlight $l.0 "$l.0 lineend"
3424 set cflist_top $l
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10003425 if {$l == 1} {
3426 $ctext yview 1.0
3427 } else {
3428 catch {$ctext yview [lindex $difffilestart [expr {$l - 2}]]}
Paul Mackerras7fcceed2006-04-27 19:21:49 +10003429 }
Stefan Hallerb9671352012-09-19 20:17:27 +02003430 suppress_highlighting_file_for_current_scrollpos
Paul Mackerras7fcceed2006-04-27 19:21:49 +10003431}
3432
Paul Mackerras32447292007-07-27 22:30:15 +10003433proc pop_flist_menu {w X Y x y} {
3434 global ctext cflist cmitmode flist_menu flist_menu_file
3435 global treediffs diffids
3436
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10003437 stopfinding
Paul Mackerras32447292007-07-27 22:30:15 +10003438 set l [lindex [split [$w index "@$x,$y"] "."] 0]
3439 if {$l <= 1} return
3440 if {$cmitmode eq "tree"} {
3441 set e [linetoelt $l]
3442 if {[string index $e end] eq "/"} return
3443 } else {
3444 set e [lindex $treediffs($diffids) [expr {$l-2}]]
3445 }
3446 set flist_menu_file $e
Thomas Arcila314f5de2008-03-24 12:55:36 +01003447 set xdiffstate "normal"
3448 if {$cmitmode eq "tree"} {
3449 set xdiffstate "disabled"
3450 }
3451 # Disable "External diff" item in tree mode
3452 $flist_menu entryconf 2 -state $xdiffstate
Paul Mackerras32447292007-07-27 22:30:15 +10003453 tk_popup $flist_menu $X $Y
3454}
3455
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003456proc find_ctext_fileinfo {line} {
3457 global ctext_file_names ctext_file_lines
3458
3459 set ok [bsearch $ctext_file_lines $line]
3460 set tline [lindex $ctext_file_lines $ok]
3461
3462 if {$ok >= [llength $ctext_file_lines] || $line < $tline} {
3463 return {}
3464 } else {
3465 return [list [lindex $ctext_file_names $ok] $tline]
3466 }
3467}
3468
3469proc pop_diff_menu {w X Y x y} {
3470 global ctext diff_menu flist_menu_file
3471 global diff_menu_txtpos diff_menu_line
3472 global diff_menu_filebase
3473
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003474 set diff_menu_txtpos [split [$w index "@$x,$y"] "."]
3475 set diff_menu_line [lindex $diff_menu_txtpos 0]
Paul Mackerras190ec522008-10-27 21:13:37 +11003476 # don't pop up the menu on hunk-separator or file-separator lines
3477 if {[lsearch -glob [$ctext tag names $diff_menu_line.0] "*sep"] >= 0} {
3478 return
3479 }
3480 stopfinding
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003481 set f [find_ctext_fileinfo $diff_menu_line]
3482 if {$f eq {}} return
3483 set flist_menu_file [lindex $f 0]
3484 set diff_menu_filebase [lindex $f 1]
3485 tk_popup $diff_menu $X $Y
3486}
3487
Paul Mackerras32447292007-07-27 22:30:15 +10003488proc flist_hl {only} {
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10003489 global flist_menu_file findstring gdttype
Paul Mackerras32447292007-07-27 22:30:15 +10003490
3491 set x [shellquote $flist_menu_file]
Christian Stimmingb007ee22007-11-07 18:44:35 +01003492 if {$only || $findstring eq {} || $gdttype ne [mc "touching paths:"]} {
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10003493 set findstring $x
Paul Mackerras32447292007-07-27 22:30:15 +10003494 } else {
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10003495 append findstring " " $x
Paul Mackerras32447292007-07-27 22:30:15 +10003496 }
Christian Stimmingb007ee22007-11-07 18:44:35 +01003497 set gdttype [mc "touching paths:"]
Paul Mackerras32447292007-07-27 22:30:15 +10003498}
3499
Paul Mackerrasc21398b2009-09-07 10:08:21 +10003500proc gitknewtmpdir {} {
David Aguilarc7664f12014-06-13 14:13:37 -07003501 global diffnum gitktmpdir gitdir env
Paul Mackerrasc21398b2009-09-07 10:08:21 +10003502
3503 if {![info exists gitktmpdir]} {
David Aguilarc7664f12014-06-13 14:13:37 -07003504 if {[info exists env(GITK_TMPDIR)]} {
3505 set tmpdir $env(GITK_TMPDIR)
3506 } elseif {[info exists env(TMPDIR)]} {
3507 set tmpdir $env(TMPDIR)
3508 } else {
3509 set tmpdir $gitdir
3510 }
David Aguilar105b5d32014-06-13 14:43:48 -07003511 set gitktmpformat [file join $tmpdir ".gitk-tmp.XXXXXX"]
David Aguilarac54a4b2014-06-18 19:53:14 -07003512 if {[catch {set gitktmpdir [exec mktemp -d $gitktmpformat]}]} {
3513 set gitktmpdir [file join $gitdir [format ".gitk-tmp.%s" [pid]]]
3514 }
Paul Mackerrasc21398b2009-09-07 10:08:21 +10003515 if {[catch {file mkdir $gitktmpdir} err]} {
3516 error_popup "[mc "Error creating temporary directory %s:" $gitktmpdir] $err"
3517 unset gitktmpdir
3518 return {}
3519 }
3520 set diffnum 0
3521 }
3522 incr diffnum
3523 set diffdir [file join $gitktmpdir $diffnum]
3524 if {[catch {file mkdir $diffdir} err]} {
3525 error_popup "[mc "Error creating temporary directory %s:" $diffdir] $err"
3526 return {}
3527 }
3528 return $diffdir
3529}
3530
Thomas Arcila314f5de2008-03-24 12:55:36 +01003531proc save_file_from_commit {filename output what} {
3532 global nullfile
3533
3534 if {[catch {exec git show $filename -- > $output} err]} {
3535 if {[string match "fatal: bad revision *" $err]} {
3536 return $nullfile
3537 }
Christian Stimming3945d2c2008-09-12 11:39:43 +02003538 error_popup "[mc "Error getting \"%s\" from %s:" $filename $what] $err"
Thomas Arcila314f5de2008-03-24 12:55:36 +01003539 return {}
3540 }
3541 return $output
3542}
3543
3544proc external_diff_get_one_file {diffid filename diffdir} {
3545 global nullid nullid2 nullfile
Martin von Zweigbergk784b7e22011-04-04 22:14:15 -04003546 global worktree
Thomas Arcila314f5de2008-03-24 12:55:36 +01003547
3548 if {$diffid == $nullid} {
Martin von Zweigbergk784b7e22011-04-04 22:14:15 -04003549 set difffile [file join $worktree $filename]
Thomas Arcila314f5de2008-03-24 12:55:36 +01003550 if {[file exists $difffile]} {
3551 return $difffile
3552 }
3553 return $nullfile
3554 }
3555 if {$diffid == $nullid2} {
3556 set difffile [file join $diffdir "\[index\] [file tail $filename]"]
3557 return [save_file_from_commit :$filename $difffile index]
3558 }
3559 set difffile [file join $diffdir "\[$diffid\] [file tail $filename]"]
3560 return [save_file_from_commit $diffid:$filename $difffile \
3561 "revision $diffid"]
3562}
3563
3564proc external_diff {} {
Paul Mackerrasc21398b2009-09-07 10:08:21 +10003565 global nullid nullid2
Thomas Arcila314f5de2008-03-24 12:55:36 +01003566 global flist_menu_file
3567 global diffids
Paul Mackerrasc21398b2009-09-07 10:08:21 +10003568 global extdifftool
Thomas Arcila314f5de2008-03-24 12:55:36 +01003569
3570 if {[llength $diffids] == 1} {
3571 # no reference commit given
3572 set diffidto [lindex $diffids 0]
3573 if {$diffidto eq $nullid} {
3574 # diffing working copy with index
3575 set diffidfrom $nullid2
3576 } elseif {$diffidto eq $nullid2} {
3577 # diffing index with HEAD
3578 set diffidfrom "HEAD"
3579 } else {
3580 # use first parent commit
3581 global parentlist selectedline
3582 set diffidfrom [lindex $parentlist $selectedline 0]
3583 }
3584 } else {
3585 set diffidfrom [lindex $diffids 0]
3586 set diffidto [lindex $diffids 1]
3587 }
3588
3589 # make sure that several diffs wont collide
Paul Mackerrasc21398b2009-09-07 10:08:21 +10003590 set diffdir [gitknewtmpdir]
3591 if {$diffdir eq {}} return
Thomas Arcila314f5de2008-03-24 12:55:36 +01003592
3593 # gather files to diff
3594 set difffromfile [external_diff_get_one_file $diffidfrom $flist_menu_file $diffdir]
3595 set difftofile [external_diff_get_one_file $diffidto $flist_menu_file $diffdir]
3596
3597 if {$difffromfile ne {} && $difftofile ne {}} {
Pat Thoytsb575b2f2009-04-15 16:54:19 +01003598 set cmd [list [shellsplit $extdifftool] $difffromfile $difftofile]
3599 if {[catch {set fl [open |$cmd r]} err]} {
Thomas Arcila314f5de2008-03-24 12:55:36 +01003600 file delete -force $diffdir
Christian Stimming3945d2c2008-09-12 11:39:43 +02003601 error_popup "$extdifftool: [mc "command failed:"] $err"
Thomas Arcila314f5de2008-03-24 12:55:36 +01003602 } else {
3603 fconfigure $fl -blocking 0
3604 filerun $fl [list delete_at_eof $fl $diffdir]
3605 }
3606 }
3607}
3608
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003609proc find_hunk_blamespec {base line} {
3610 global ctext
3611
3612 # Find and parse the hunk header
3613 set s_lix [$ctext search -backwards -regexp ^@@ "$line.0 lineend" $base.0]
3614 if {$s_lix eq {}} return
3615
3616 set s_line [$ctext get $s_lix "$s_lix + 1 lines"]
3617 if {![regexp {^@@@*(( -\d+(,\d+)?)+) \+(\d+)(,\d+)? @@} $s_line \
3618 s_line old_specs osz osz1 new_line nsz]} {
3619 return
3620 }
3621
3622 # base lines for the parents
3623 set base_lines [list $new_line]
3624 foreach old_spec [lrange [split $old_specs " "] 1 end] {
3625 if {![regexp -- {-(\d+)(,\d+)?} $old_spec \
3626 old_spec old_line osz]} {
3627 return
3628 }
3629 lappend base_lines $old_line
3630 }
3631
3632 # Now scan the lines to determine offset within the hunk
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003633 set max_parent [expr {[llength $base_lines]-2}]
3634 set dline 0
3635 set s_lno [lindex [split $s_lix "."] 0]
3636
Paul Mackerras190ec522008-10-27 21:13:37 +11003637 # Determine if the line is removed
3638 set chunk [$ctext get $line.0 "$line.1 + $max_parent chars"]
3639 if {[string match {[-+ ]*} $chunk]} {
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003640 set removed_idx [string first "-" $chunk]
3641 # Choose a parent index
Paul Mackerras190ec522008-10-27 21:13:37 +11003642 if {$removed_idx >= 0} {
3643 set parent $removed_idx
3644 } else {
3645 set unchanged_idx [string first " " $chunk]
3646 if {$unchanged_idx >= 0} {
3647 set parent $unchanged_idx
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003648 } else {
Paul Mackerras190ec522008-10-27 21:13:37 +11003649 # blame the current commit
3650 set parent -1
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003651 }
3652 }
3653 # then count other lines that belong to it
Paul Mackerras190ec522008-10-27 21:13:37 +11003654 for {set i $line} {[incr i -1] > $s_lno} {} {
3655 set chunk [$ctext get $i.0 "$i.1 + $max_parent chars"]
3656 # Determine if the line is removed
3657 set removed_idx [string first "-" $chunk]
3658 if {$parent >= 0} {
3659 set code [string index $chunk $parent]
3660 if {$code eq "-" || ($removed_idx < 0 && $code ne "+")} {
3661 incr dline
3662 }
3663 } else {
3664 if {$removed_idx < 0} {
3665 incr dline
3666 }
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003667 }
3668 }
Paul Mackerras190ec522008-10-27 21:13:37 +11003669 incr parent
3670 } else {
3671 set parent 0
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003672 }
3673
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003674 incr dline [lindex $base_lines $parent]
3675 return [list $parent $dline]
3676}
3677
3678proc external_blame_diff {} {
Paul Mackerras8b07dca2008-11-02 22:34:47 +11003679 global currentid cmitmode
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003680 global diff_menu_txtpos diff_menu_line
3681 global diff_menu_filebase flist_menu_file
3682
3683 if {$cmitmode eq "tree"} {
3684 set parent_idx 0
Paul Mackerras190ec522008-10-27 21:13:37 +11003685 set line [expr {$diff_menu_line - $diff_menu_filebase}]
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003686 } else {
3687 set hinfo [find_hunk_blamespec $diff_menu_filebase $diff_menu_line]
3688 if {$hinfo ne {}} {
3689 set parent_idx [lindex $hinfo 0]
3690 set line [lindex $hinfo 1]
3691 } else {
3692 set parent_idx 0
3693 set line 0
3694 }
3695 }
3696
3697 external_blame $parent_idx $line
3698}
3699
Paul Mackerrasfc4977e2008-11-04 12:57:44 +11003700# Find the SHA1 ID of the blob for file $fname in the index
3701# at stage 0 or 2
3702proc index_sha1 {fname} {
3703 set f [open [list | git ls-files -s $fname] r]
3704 while {[gets $f line] >= 0} {
3705 set info [lindex [split $line "\t"] 0]
3706 set stage [lindex $info 2]
3707 if {$stage eq "0" || $stage eq "2"} {
3708 close $f
3709 return [lindex $info 1]
3710 }
3711 }
3712 close $f
3713 return {}
3714}
3715
Paul Mackerras9712b812008-12-06 21:44:05 +11003716# Turn an absolute path into one relative to the current directory
3717proc make_relative {f} {
Markus Heidelberga4390ac2009-11-04 00:21:41 +01003718 if {[file pathtype $f] eq "relative"} {
3719 return $f
3720 }
Paul Mackerras9712b812008-12-06 21:44:05 +11003721 set elts [file split $f]
3722 set here [file split [pwd]]
3723 set ei 0
3724 set hi 0
3725 set res {}
3726 foreach d $here {
3727 if {$ei < $hi || $ei >= [llength $elts] || [lindex $elts $ei] ne $d} {
3728 lappend res ".."
3729 } else {
3730 incr ei
3731 }
3732 incr hi
3733 }
3734 set elts [concat $res [lrange $elts $ei end]]
3735 return [eval file join $elts]
3736}
3737
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003738proc external_blame {parent_idx {line {}}} {
Martin von Zweigbergk0a2a9792011-04-04 22:14:14 -04003739 global flist_menu_file cdup
Alexander Gavrilov77aa0ae2008-08-23 12:29:08 +04003740 global nullid nullid2
3741 global parentlist selectedline currentid
3742
3743 if {$parent_idx > 0} {
3744 set base_commit [lindex $parentlist $selectedline [expr {$parent_idx-1}]]
3745 } else {
3746 set base_commit $currentid
3747 }
3748
3749 if {$base_commit eq {} || $base_commit eq $nullid || $base_commit eq $nullid2} {
3750 error_popup [mc "No such commit"]
3751 return
3752 }
3753
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003754 set cmdline [list git gui blame]
3755 if {$line ne {} && $line > 1} {
3756 lappend cmdline "--line=$line"
3757 }
Martin von Zweigbergk0a2a9792011-04-04 22:14:14 -04003758 set f [file join $cdup $flist_menu_file]
Paul Mackerras9712b812008-12-06 21:44:05 +11003759 # Unfortunately it seems git gui blame doesn't like
3760 # being given an absolute path...
3761 set f [make_relative $f]
3762 lappend cmdline $base_commit $f
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003763 if {[catch {eval exec $cmdline &} err]} {
Christian Stimming3945d2c2008-09-12 11:39:43 +02003764 error_popup "[mc "git gui blame: command failed:"] $err"
Alexander Gavrilov77aa0ae2008-08-23 12:29:08 +04003765 }
3766}
3767
Paul Mackerras8a897742008-10-27 21:36:25 +11003768proc show_line_source {} {
3769 global cmitmode currentid parents curview blamestuff blameinst
3770 global diff_menu_line diff_menu_filebase flist_menu_file
Martin von Zweigbergk9b6adf32011-04-04 22:14:13 -04003771 global nullid nullid2 gitdir cdup
Paul Mackerras8a897742008-10-27 21:36:25 +11003772
Paul Mackerrasfc4977e2008-11-04 12:57:44 +11003773 set from_index {}
Paul Mackerras8a897742008-10-27 21:36:25 +11003774 if {$cmitmode eq "tree"} {
3775 set id $currentid
3776 set line [expr {$diff_menu_line - $diff_menu_filebase}]
3777 } else {
3778 set h [find_hunk_blamespec $diff_menu_filebase $diff_menu_line]
3779 if {$h eq {}} return
3780 set pi [lindex $h 0]
3781 if {$pi == 0} {
3782 mark_ctext_line $diff_menu_line
3783 return
3784 }
Paul Mackerrasfc4977e2008-11-04 12:57:44 +11003785 incr pi -1
3786 if {$currentid eq $nullid} {
3787 if {$pi > 0} {
3788 # must be a merge in progress...
3789 if {[catch {
3790 # get the last line from .git/MERGE_HEAD
3791 set f [open [file join $gitdir MERGE_HEAD] r]
3792 set id [lindex [split [read $f] "\n"] end-1]
3793 close $f
3794 } err]} {
3795 error_popup [mc "Couldn't read merge head: %s" $err]
3796 return
3797 }
3798 } elseif {$parents($curview,$currentid) eq $nullid2} {
3799 # need to do the blame from the index
3800 if {[catch {
3801 set from_index [index_sha1 $flist_menu_file]
3802 } err]} {
3803 error_popup [mc "Error reading index: %s" $err]
3804 return
3805 }
Paul Mackerras9712b812008-12-06 21:44:05 +11003806 } else {
3807 set id $parents($curview,$currentid)
Paul Mackerrasfc4977e2008-11-04 12:57:44 +11003808 }
3809 } else {
3810 set id [lindex $parents($curview,$currentid) $pi]
3811 }
Paul Mackerras8a897742008-10-27 21:36:25 +11003812 set line [lindex $h 1]
3813 }
Paul Mackerrasfc4977e2008-11-04 12:57:44 +11003814 set blameargs {}
3815 if {$from_index ne {}} {
3816 lappend blameargs | git cat-file blob $from_index
3817 }
3818 lappend blameargs | git blame -p -L$line,+1
3819 if {$from_index ne {}} {
3820 lappend blameargs --contents -
3821 } else {
3822 lappend blameargs $id
3823 }
Martin von Zweigbergk9b6adf32011-04-04 22:14:13 -04003824 lappend blameargs -- [file join $cdup $flist_menu_file]
Paul Mackerras8a897742008-10-27 21:36:25 +11003825 if {[catch {
Paul Mackerrasfc4977e2008-11-04 12:57:44 +11003826 set f [open $blameargs r]
Paul Mackerras8a897742008-10-27 21:36:25 +11003827 } err]} {
3828 error_popup [mc "Couldn't start git blame: %s" $err]
3829 return
3830 }
Alexander Gavrilovf3413072008-12-01 20:30:09 +03003831 nowbusy blaming [mc "Searching"]
Paul Mackerras8a897742008-10-27 21:36:25 +11003832 fconfigure $f -blocking 0
3833 set i [reg_instance $f]
3834 set blamestuff($i) {}
3835 set blameinst $i
3836 filerun $f [list read_line_source $f $i]
3837}
3838
3839proc stopblaming {} {
3840 global blameinst
3841
3842 if {[info exists blameinst]} {
3843 stop_instance $blameinst
3844 unset blameinst
Alexander Gavrilovf3413072008-12-01 20:30:09 +03003845 notbusy blaming
Paul Mackerras8a897742008-10-27 21:36:25 +11003846 }
3847}
3848
3849proc read_line_source {fd inst} {
Paul Mackerrasfc4977e2008-11-04 12:57:44 +11003850 global blamestuff curview commfd blameinst nullid nullid2
Paul Mackerras8a897742008-10-27 21:36:25 +11003851
3852 while {[gets $fd line] >= 0} {
3853 lappend blamestuff($inst) $line
3854 }
3855 if {![eof $fd]} {
3856 return 1
3857 }
3858 unset commfd($inst)
3859 unset blameinst
Alexander Gavrilovf3413072008-12-01 20:30:09 +03003860 notbusy blaming
Paul Mackerras8a897742008-10-27 21:36:25 +11003861 fconfigure $fd -blocking 1
3862 if {[catch {close $fd} err]} {
3863 error_popup [mc "Error running git blame: %s" $err]
3864 return 0
3865 }
3866
3867 set fname {}
3868 set line [split [lindex $blamestuff($inst) 0] " "]
3869 set id [lindex $line 0]
3870 set lnum [lindex $line 1]
3871 if {[string length $id] == 40 && [string is xdigit $id] &&
3872 [string is digit -strict $lnum]} {
3873 # look for "filename" line
3874 foreach l $blamestuff($inst) {
3875 if {[string match "filename *" $l]} {
3876 set fname [string range $l 9 end]
3877 break
3878 }
3879 }
3880 }
3881 if {$fname ne {}} {
3882 # all looks good, select it
Paul Mackerrasfc4977e2008-11-04 12:57:44 +11003883 if {$id eq $nullid} {
3884 # blame uses all-zeroes to mean not committed,
3885 # which would mean a change in the index
3886 set id $nullid2
3887 }
Paul Mackerras8a897742008-10-27 21:36:25 +11003888 if {[commitinview $id $curview]} {
Max Kirillov4135d362014-04-05 23:38:50 +03003889 selectline [rowofcommit $id] 1 [list $fname $lnum] 1
Paul Mackerras8a897742008-10-27 21:36:25 +11003890 } else {
3891 error_popup [mc "That line comes from commit %s, \
3892 which is not in this view" [shortids $id]]
3893 }
3894 } else {
3895 puts "oops couldn't parse git blame output"
3896 }
3897 return 0
3898}
3899
Thomas Arcila314f5de2008-03-24 12:55:36 +01003900# delete $dir when we see eof on $f (presumably because the child has exited)
3901proc delete_at_eof {f dir} {
3902 while {[gets $f line] >= 0} {}
3903 if {[eof $f]} {
3904 if {[catch {close $f} err]} {
Christian Stimming3945d2c2008-09-12 11:39:43 +02003905 error_popup "[mc "External diff viewer failed:"] $err"
Thomas Arcila314f5de2008-03-24 12:55:36 +01003906 }
3907 file delete -force $dir
3908 return 0
3909 }
3910 return 1
3911}
3912
Paul Mackerras098dd8a2006-05-03 09:32:53 +10003913# Functions for adding and removing shell-type quoting
3914
3915proc shellquote {str} {
3916 if {![string match "*\['\"\\ \t]*" $str]} {
3917 return $str
3918 }
3919 if {![string match "*\['\"\\]*" $str]} {
3920 return "\"$str\""
3921 }
3922 if {![string match "*'*" $str]} {
3923 return "'$str'"
3924 }
3925 return "\"[string map {\" \\\" \\ \\\\} $str]\""
3926}
3927
3928proc shellarglist {l} {
3929 set str {}
3930 foreach a $l {
3931 if {$str ne {}} {
3932 append str " "
3933 }
3934 append str [shellquote $a]
3935 }
3936 return $str
3937}
3938
3939proc shelldequote {str} {
3940 set ret {}
3941 set used -1
3942 while {1} {
3943 incr used
3944 if {![regexp -start $used -indices "\['\"\\\\ \t]" $str first]} {
3945 append ret [string range $str $used end]
3946 set used [string length $str]
3947 break
3948 }
3949 set first [lindex $first 0]
3950 set ch [string index $str $first]
3951 if {$first > $used} {
3952 append ret [string range $str $used [expr {$first - 1}]]
3953 set used $first
3954 }
3955 if {$ch eq " " || $ch eq "\t"} break
3956 incr used
3957 if {$ch eq "'"} {
3958 set first [string first "'" $str $used]
3959 if {$first < 0} {
3960 error "unmatched single-quote"
3961 }
3962 append ret [string range $str $used [expr {$first - 1}]]
3963 set used $first
3964 continue
3965 }
3966 if {$ch eq "\\"} {
3967 if {$used >= [string length $str]} {
3968 error "trailing backslash"
3969 }
3970 append ret [string index $str $used]
3971 continue
3972 }
3973 # here ch == "\""
3974 while {1} {
3975 if {![regexp -start $used -indices "\[\"\\\\]" $str first]} {
3976 error "unmatched double-quote"
3977 }
3978 set first [lindex $first 0]
3979 set ch [string index $str $first]
3980 if {$first > $used} {
3981 append ret [string range $str $used [expr {$first - 1}]]
3982 set used $first
3983 }
3984 if {$ch eq "\""} break
3985 incr used
3986 append ret [string index $str $used]
3987 incr used
3988 }
3989 }
3990 return [list $used $ret]
3991}
3992
3993proc shellsplit {str} {
3994 set l {}
3995 while {1} {
3996 set str [string trimleft $str]
3997 if {$str eq {}} break
3998 set dq [shelldequote $str]
3999 set n [lindex $dq 0]
4000 set word [lindex $dq 1]
4001 set str [string range $str $n end]
4002 lappend l $word
4003 }
4004 return $l
4005}
4006
Paul Mackerras7fcceed2006-04-27 19:21:49 +10004007# Code to implement multiple views
4008
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004009proc newview {ishighlight} {
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004010 global nextviewnum newviewname newishighlight
4011 global revtreeargs viewargscmd newviewopts curview
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004012
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004013 set newishighlight $ishighlight
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004014 set top .gitkview
4015 if {[winfo exists $top]} {
4016 raise $top
4017 return
4018 }
Jonathan Nieder5d11f792010-03-06 16:58:42 -06004019 decode_view_opts $nextviewnum $revtreeargs
Michele Ballabioa3a1f572008-03-03 21:12:47 +01004020 set newviewname($nextviewnum) "[mc "View"] $nextviewnum"
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004021 set newviewopts($nextviewnum,perm) 0
4022 set newviewopts($nextviewnum,cmd) $viewargscmd($curview)
Christian Stimmingd990ced2007-11-07 18:42:55 +01004023 vieweditor $top $nextviewnum [mc "Gitk view definition"]
Paul Mackerrasd16c0812006-04-25 21:21:10 +10004024}
4025
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004026set known_view_options {
Elijah Newren13d40b62009-03-23 11:57:46 -06004027 {perm b . {} {mc "Remember this view"}}
4028 {reflabel l + {} {mc "References (space separated list):"}}
4029 {refs t15 .. {} {mc "Branches & tags:"}}
4030 {allrefs b *. "--all" {mc "All refs"}}
4031 {branches b . "--branches" {mc "All (local) branches"}}
4032 {tags b . "--tags" {mc "All tags"}}
4033 {remotes b . "--remotes" {mc "All remote-tracking branches"}}
4034 {commitlbl l + {} {mc "Commit Info (regular expressions):"}}
4035 {author t15 .. "--author=*" {mc "Author:"}}
4036 {committer t15 . "--committer=*" {mc "Committer:"}}
4037 {loginfo t15 .. "--grep=*" {mc "Commit Message:"}}
4038 {allmatch b .. "--all-match" {mc "Matches all Commit Info criteria"}}
4039 {changes_l l + {} {mc "Changes to Files:"}}
4040 {pickaxe_s r0 . {} {mc "Fixed String"}}
4041 {pickaxe_t r1 . "--pickaxe-regex" {mc "Regular Expression"}}
4042 {pickaxe t15 .. "-S*" {mc "Search string:"}}
4043 {datelabel l + {} {mc "Commit Dates (\"2 weeks ago\", \"2009-03-17 15:27:38\", \"March 17, 2009 15:27:38\"):"}}
4044 {since t15 .. {"--since=*" "--after=*"} {mc "Since:"}}
4045 {until t15 . {"--until=*" "--before=*"} {mc "Until:"}}
4046 {limit_lbl l + {} {mc "Limit and/or skip a number of revisions (positive integer):"}}
4047 {limit t10 *. "--max-count=*" {mc "Number to show:"}}
4048 {skip t10 . "--skip=*" {mc "Number to skip:"}}
4049 {misc_lbl l + {} {mc "Miscellaneous options:"}}
4050 {dorder b *. {"--date-order" "-d"} {mc "Strictly sort by date"}}
4051 {lright b . "--left-right" {mc "Mark branch sides"}}
4052 {first b . "--first-parent" {mc "Limit to first parent"}}
Dirk Suesserottf687aaa2009-05-21 15:35:40 +02004053 {smplhst b . "--simplify-by-decoration" {mc "Simple history"}}
Elijah Newren13d40b62009-03-23 11:57:46 -06004054 {args t50 *. {} {mc "Additional arguments to git log:"}}
4055 {allpaths path + {} {mc "Enter files and directories to include, one per line:"}}
4056 {cmd t50= + {} {mc "Command to generate more commits to include:"}}
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004057 }
4058
Jonathan Niedere7feb692010-03-06 16:48:38 -06004059# Convert $newviewopts($n, ...) into args for git log.
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004060proc encode_view_opts {n} {
4061 global known_view_options newviewopts
4062
4063 set rargs [list]
4064 foreach opt $known_view_options {
4065 set patterns [lindex $opt 3]
4066 if {$patterns eq {}} continue
4067 set pattern [lindex $patterns 0]
4068
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004069 if {[lindex $opt 1] eq "b"} {
Elijah Newren13d40b62009-03-23 11:57:46 -06004070 set val $newviewopts($n,[lindex $opt 0])
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004071 if {$val} {
4072 lappend rargs $pattern
4073 }
Elijah Newren13d40b62009-03-23 11:57:46 -06004074 } elseif {[regexp {^r(\d+)$} [lindex $opt 1] type value]} {
4075 regexp {^(.*_)} [lindex $opt 0] uselessvar button_id
4076 set val $newviewopts($n,$button_id)
4077 if {$val eq $value} {
4078 lappend rargs $pattern
4079 }
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004080 } else {
Elijah Newren13d40b62009-03-23 11:57:46 -06004081 set val $newviewopts($n,[lindex $opt 0])
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004082 set val [string trim $val]
4083 if {$val ne {}} {
4084 set pfix [string range $pattern 0 end-1]
4085 lappend rargs $pfix$val
4086 }
4087 }
4088 }
Elijah Newren13d40b62009-03-23 11:57:46 -06004089 set rargs [concat $rargs [shellsplit $newviewopts($n,refs)]]
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004090 return [concat $rargs [shellsplit $newviewopts($n,args)]]
4091}
4092
Jonathan Niedere7feb692010-03-06 16:48:38 -06004093# Fill $newviewopts($n, ...) based on args for git log.
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004094proc decode_view_opts {n view_args} {
4095 global known_view_options newviewopts
4096
4097 foreach opt $known_view_options {
Elijah Newren13d40b62009-03-23 11:57:46 -06004098 set id [lindex $opt 0]
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004099 if {[lindex $opt 1] eq "b"} {
Elijah Newren13d40b62009-03-23 11:57:46 -06004100 # Checkboxes
4101 set val 0
4102 } elseif {[regexp {^r(\d+)$} [lindex $opt 1]]} {
4103 # Radiobuttons
4104 regexp {^(.*_)} $id uselessvar id
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004105 set val 0
4106 } else {
Elijah Newren13d40b62009-03-23 11:57:46 -06004107 # Text fields
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004108 set val {}
4109 }
Elijah Newren13d40b62009-03-23 11:57:46 -06004110 set newviewopts($n,$id) $val
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004111 }
4112 set oargs [list]
Elijah Newren13d40b62009-03-23 11:57:46 -06004113 set refargs [list]
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004114 foreach arg $view_args {
4115 if {[regexp -- {^-([0-9]+)$} $arg arg cnt]
4116 && ![info exists found(limit)]} {
4117 set newviewopts($n,limit) $cnt
4118 set found(limit) 1
4119 continue
4120 }
4121 catch { unset val }
4122 foreach opt $known_view_options {
4123 set id [lindex $opt 0]
4124 if {[info exists found($id)]} continue
4125 foreach pattern [lindex $opt 3] {
4126 if {![string match $pattern $arg]} continue
Elijah Newren13d40b62009-03-23 11:57:46 -06004127 if {[lindex $opt 1] eq "b"} {
4128 # Check buttons
4129 set val 1
4130 } elseif {[regexp {^r(\d+)$} [lindex $opt 1] match num]} {
4131 # Radio buttons
4132 regexp {^(.*_)} $id uselessvar id
4133 set val $num
4134 } else {
4135 # Text input fields
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004136 set size [string length $pattern]
4137 set val [string range $arg [expr {$size-1}] end]
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004138 }
4139 set newviewopts($n,$id) $val
4140 set found($id) 1
4141 break
4142 }
4143 if {[info exists val]} break
4144 }
4145 if {[info exists val]} continue
Elijah Newren13d40b62009-03-23 11:57:46 -06004146 if {[regexp {^-} $arg]} {
4147 lappend oargs $arg
4148 } else {
4149 lappend refargs $arg
4150 }
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004151 }
Elijah Newren13d40b62009-03-23 11:57:46 -06004152 set newviewopts($n,refs) [shellarglist $refargs]
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004153 set newviewopts($n,args) [shellarglist $oargs]
4154}
4155
Alexander Gavrilovcea07cf2008-11-09 13:00:45 +03004156proc edit_or_newview {} {
4157 global curview
4158
4159 if {$curview > 0} {
4160 editview
4161 } else {
4162 newview 0
4163 }
4164}
4165
Paul Mackerrasd16c0812006-04-25 21:21:10 +10004166proc editview {} {
4167 global curview
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004168 global viewname viewperm newviewname newviewopts
4169 global viewargs viewargscmd
Paul Mackerrasd16c0812006-04-25 21:21:10 +10004170
4171 set top .gitkvedit-$curview
4172 if {[winfo exists $top]} {
4173 raise $top
4174 return
4175 }
Jonathan Nieder5d11f792010-03-06 16:58:42 -06004176 decode_view_opts $curview $viewargs($curview)
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004177 set newviewname($curview) $viewname($curview)
4178 set newviewopts($curview,perm) $viewperm($curview)
4179 set newviewopts($curview,cmd) $viewargscmd($curview)
Michele Ballabiob56e0a92009-03-30 21:17:25 +02004180 vieweditor $top $curview "[mc "Gitk: edit view"] $viewname($curview)"
Paul Mackerrasd16c0812006-04-25 21:21:10 +10004181}
4182
4183proc vieweditor {top n title} {
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004184 global newviewname newviewopts viewfiles bgcolor
Pat Thoytsd93f1712009-04-17 01:24:35 +01004185 global known_view_options NS
Paul Mackerrasd16c0812006-04-25 21:21:10 +10004186
Pat Thoytsd93f1712009-04-17 01:24:35 +01004187 ttk_toplevel $top
Michele Ballabioe0a01992009-05-23 11:48:25 +02004188 wm title $top [concat $title [mc "-- criteria for selecting revisions"]]
Alexander Gavrilove7d64002008-11-11 23:55:42 +03004189 make_transient $top .
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004190
4191 # View name
Pat Thoytsd93f1712009-04-17 01:24:35 +01004192 ${NS}::frame $top.nfr
Paul Mackerraseae7d642009-09-05 17:34:03 +10004193 ${NS}::label $top.nl -text [mc "View Name"]
Pat Thoytsd93f1712009-04-17 01:24:35 +01004194 ${NS}::entry $top.name -width 20 -textvariable newviewname($n)
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004195 pack $top.nfr -in $top -fill x -pady 5 -padx 3
Elijah Newren13d40b62009-03-23 11:57:46 -06004196 pack $top.nl -in $top.nfr -side left -padx {0 5}
4197 pack $top.name -in $top.nfr -side left -padx {0 25}
Yann Dirson2d480852008-02-21 21:23:31 +01004198
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004199 # View options
4200 set cframe $top.nfr
4201 set cexpand 0
4202 set cnt 0
4203 foreach opt $known_view_options {
4204 set id [lindex $opt 0]
4205 set type [lindex $opt 1]
4206 set flags [lindex $opt 2]
4207 set title [eval [lindex $opt 4]]
4208 set lxpad 0
Yann Dirson2d480852008-02-21 21:23:31 +01004209
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004210 if {$flags eq "+" || $flags eq "*"} {
4211 set cframe $top.fr$cnt
4212 incr cnt
Pat Thoytsd93f1712009-04-17 01:24:35 +01004213 ${NS}::frame $cframe
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004214 pack $cframe -in $top -fill x -pady 3 -padx 3
4215 set cexpand [expr {$flags eq "*"}]
Elijah Newren13d40b62009-03-23 11:57:46 -06004216 } elseif {$flags eq ".." || $flags eq "*."} {
4217 set cframe $top.fr$cnt
4218 incr cnt
Paul Mackerraseae7d642009-09-05 17:34:03 +10004219 ${NS}::frame $cframe
Elijah Newren13d40b62009-03-23 11:57:46 -06004220 pack $cframe -in $top -fill x -pady 3 -padx [list 15 3]
4221 set cexpand [expr {$flags eq "*."}]
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004222 } else {
4223 set lxpad 5
4224 }
4225
Elijah Newren13d40b62009-03-23 11:57:46 -06004226 if {$type eq "l"} {
Paul Mackerraseae7d642009-09-05 17:34:03 +10004227 ${NS}::label $cframe.l_$id -text $title
Elijah Newren13d40b62009-03-23 11:57:46 -06004228 pack $cframe.l_$id -in $cframe -side left -pady [list 3 0] -anchor w
4229 } elseif {$type eq "b"} {
Pat Thoytsd93f1712009-04-17 01:24:35 +01004230 ${NS}::checkbutton $cframe.c_$id -text $title -variable newviewopts($n,$id)
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004231 pack $cframe.c_$id -in $cframe -side left \
4232 -padx [list $lxpad 0] -expand $cexpand -anchor w
Elijah Newren13d40b62009-03-23 11:57:46 -06004233 } elseif {[regexp {^r(\d+)$} $type type sz]} {
4234 regexp {^(.*_)} $id uselessvar button_id
Paul Mackerraseae7d642009-09-05 17:34:03 +10004235 ${NS}::radiobutton $cframe.c_$id -text $title -variable newviewopts($n,$button_id) -value $sz
Elijah Newren13d40b62009-03-23 11:57:46 -06004236 pack $cframe.c_$id -in $cframe -side left \
4237 -padx [list $lxpad 0] -expand $cexpand -anchor w
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004238 } elseif {[regexp {^t(\d+)$} $type type sz]} {
Pat Thoytsd93f1712009-04-17 01:24:35 +01004239 ${NS}::label $cframe.l_$id -text $title
4240 ${NS}::entry $cframe.e_$id -width $sz -background $bgcolor \
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004241 -textvariable newviewopts($n,$id)
4242 pack $cframe.l_$id -in $cframe -side left -padx [list $lxpad 0]
4243 pack $cframe.e_$id -in $cframe -side left -expand 1 -fill x
4244 } elseif {[regexp {^t(\d+)=$} $type type sz]} {
Pat Thoytsd93f1712009-04-17 01:24:35 +01004245 ${NS}::label $cframe.l_$id -text $title
4246 ${NS}::entry $cframe.e_$id -width $sz -background $bgcolor \
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004247 -textvariable newviewopts($n,$id)
4248 pack $cframe.l_$id -in $cframe -side top -pady [list 3 0] -anchor w
4249 pack $cframe.e_$id -in $cframe -side top -fill x
Elijah Newren13d40b62009-03-23 11:57:46 -06004250 } elseif {$type eq "path"} {
Paul Mackerraseae7d642009-09-05 17:34:03 +10004251 ${NS}::label $top.l -text $title
Elijah Newren13d40b62009-03-23 11:57:46 -06004252 pack $top.l -in $top -side top -pady [list 3 0] -anchor w -padx 3
Mark Hillsb9b142f2010-01-13 20:40:22 +00004253 text $top.t -width 40 -height 5 -background $bgcolor
Elijah Newren13d40b62009-03-23 11:57:46 -06004254 if {[info exists viewfiles($n)]} {
4255 foreach f $viewfiles($n) {
4256 $top.t insert end $f
4257 $top.t insert end "\n"
4258 }
4259 $top.t delete {end - 1c} end
4260 $top.t mark set insert 0.0
4261 }
4262 pack $top.t -in $top -side top -pady [list 0 5] -fill both -expand 1 -padx 3
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004263 }
4264 }
4265
Pat Thoytsd93f1712009-04-17 01:24:35 +01004266 ${NS}::frame $top.buts
4267 ${NS}::button $top.buts.ok -text [mc "OK"] -command [list newviewok $top $n]
4268 ${NS}::button $top.buts.apply -text [mc "Apply (F5)"] -command [list newviewok $top $n 1]
4269 ${NS}::button $top.buts.can -text [mc "Cancel"] -command [list destroy $top]
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004270 bind $top <Control-Return> [list newviewok $top $n]
4271 bind $top <F5> [list newviewok $top $n 1]
Alexander Gavrilov76f15942008-11-02 21:59:44 +03004272 bind $top <Escape> [list destroy $top]
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004273 grid $top.buts.ok $top.buts.apply $top.buts.can
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004274 grid columnconfigure $top.buts 0 -weight 1 -uniform a
4275 grid columnconfigure $top.buts 1 -weight 1 -uniform a
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004276 grid columnconfigure $top.buts 2 -weight 1 -uniform a
4277 pack $top.buts -in $top -side top -fill x
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004278 focus $top.t
4279}
4280
Paul Mackerras908c3582006-05-20 09:38:11 +10004281proc doviewmenu {m first cmd op argv} {
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004282 set nmenu [$m index end]
4283 for {set i $first} {$i <= $nmenu} {incr i} {
4284 if {[$m entrycget $i -command] eq $cmd} {
Paul Mackerras908c3582006-05-20 09:38:11 +10004285 eval $m $op $i $argv
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004286 break
Paul Mackerrasd16c0812006-04-25 21:21:10 +10004287 }
4288 }
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004289}
4290
4291proc allviewmenus {n op args} {
Paul Mackerras687c8762007-09-22 12:49:33 +10004292 # global viewhlmenu
Paul Mackerras908c3582006-05-20 09:38:11 +10004293
Paul Mackerras3cd204e2006-11-23 21:06:16 +11004294 doviewmenu .bar.view 5 [list showview $n] $op $args
Paul Mackerras687c8762007-09-22 12:49:33 +10004295 # doviewmenu $viewhlmenu 1 [list addvhighlight $n] $op $args
Paul Mackerrasd16c0812006-04-25 21:21:10 +10004296}
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004297
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004298proc newviewok {top n {apply 0}} {
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004299 global nextviewnum newviewperm newviewname newishighlight
Paul Mackerrasd16c0812006-04-25 21:21:10 +10004300 global viewname viewfiles viewperm selectedview curview
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004301 global viewargs viewargscmd newviewopts viewhlmenu
Paul Mackerrasd16c0812006-04-25 21:21:10 +10004302
Paul Mackerras098dd8a2006-05-03 09:32:53 +10004303 if {[catch {
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004304 set newargs [encode_view_opts $n]
Paul Mackerras098dd8a2006-05-03 09:32:53 +10004305 } err]} {
Alexander Gavrilov84a76f12008-11-02 21:59:45 +03004306 error_popup "[mc "Error in commit selection arguments:"] $err" $top
Paul Mackerras098dd8a2006-05-03 09:32:53 +10004307 return
4308 }
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004309 set files {}
Paul Mackerrasd16c0812006-04-25 21:21:10 +10004310 foreach f [split [$top.t get 0.0 end] "\n"] {
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004311 set ft [string trim $f]
4312 if {$ft ne {}} {
4313 lappend files $ft
4314 }
4315 }
Paul Mackerrasd16c0812006-04-25 21:21:10 +10004316 if {![info exists viewfiles($n)]} {
4317 # creating a new view
4318 incr nextviewnum
4319 set viewname($n) $newviewname($n)
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004320 set viewperm($n) $newviewopts($n,perm)
Paul Mackerrasd16c0812006-04-25 21:21:10 +10004321 set viewfiles($n) $files
Paul Mackerras098dd8a2006-05-03 09:32:53 +10004322 set viewargs($n) $newargs
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004323 set viewargscmd($n) $newviewopts($n,cmd)
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004324 addviewmenu $n
4325 if {!$newishighlight} {
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004326 run showview $n
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004327 } else {
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004328 run addvhighlight $n
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004329 }
Paul Mackerrasd16c0812006-04-25 21:21:10 +10004330 } else {
4331 # editing an existing view
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004332 set viewperm($n) $newviewopts($n,perm)
Paul Mackerrasd16c0812006-04-25 21:21:10 +10004333 if {$newviewname($n) ne $viewname($n)} {
4334 set viewname($n) $newviewname($n)
Paul Mackerras3cd204e2006-11-23 21:06:16 +11004335 doviewmenu .bar.view 5 [list showview $n] \
Paul Mackerras908c3582006-05-20 09:38:11 +10004336 entryconf [list -label $viewname($n)]
Paul Mackerras687c8762007-09-22 12:49:33 +10004337 # doviewmenu $viewhlmenu 1 [list addvhighlight $n] \
4338 # entryconf [list -label $viewname($n) -value $viewname($n)]
Paul Mackerrasd16c0812006-04-25 21:21:10 +10004339 }
Yann Dirson2d480852008-02-21 21:23:31 +01004340 if {$files ne $viewfiles($n) || $newargs ne $viewargs($n) || \
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004341 $newviewopts($n,cmd) ne $viewargscmd($n)} {
Paul Mackerrasd16c0812006-04-25 21:21:10 +10004342 set viewfiles($n) $files
Paul Mackerras098dd8a2006-05-03 09:32:53 +10004343 set viewargs($n) $newargs
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004344 set viewargscmd($n) $newviewopts($n,cmd)
Paul Mackerrasd16c0812006-04-25 21:21:10 +10004345 if {$curview == $n} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004346 run reloadcommits
Paul Mackerrasd16c0812006-04-25 21:21:10 +10004347 }
4348 }
4349 }
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004350 if {$apply} return
Paul Mackerrasd16c0812006-04-25 21:21:10 +10004351 catch {destroy $top}
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004352}
4353
4354proc delview {} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004355 global curview viewperm hlview selectedhlview
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004356
4357 if {$curview == 0} return
Paul Mackerras908c3582006-05-20 09:38:11 +10004358 if {[info exists hlview] && $hlview == $curview} {
Christian Stimmingb007ee22007-11-07 18:44:35 +01004359 set selectedhlview [mc "None"]
Paul Mackerras908c3582006-05-20 09:38:11 +10004360 unset hlview
4361 }
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004362 allviewmenus $curview delete
Paul Mackerrasa90a6d22006-04-25 17:12:46 +10004363 set viewperm($curview) 0
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004364 showview 0
4365}
4366
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004367proc addviewmenu {n} {
Paul Mackerras908c3582006-05-20 09:38:11 +10004368 global viewname viewhlmenu
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004369
4370 .bar.view add radiobutton -label $viewname($n) \
4371 -command [list showview $n] -variable selectedview -value $n
Paul Mackerras687c8762007-09-22 12:49:33 +10004372 #$viewhlmenu add radiobutton -label $viewname($n) \
4373 # -command [list addvhighlight $n] -variable selectedhlview
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004374}
4375
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004376proc showview {n} {
Paul Mackerras3ed31a82008-04-26 16:00:00 +10004377 global curview cached_commitrow ordertok
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10004378 global displayorder parentlist rowidlist rowisopt rowfinal
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004379 global colormap rowtextx nextcolor canvxmax
4380 global numcommits viewcomplete
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004381 global selectedline currentid canv canvy0
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004382 global treediffs
Paul Mackerras3e766082008-01-13 17:26:30 +11004383 global pending_select mainheadid
Paul Mackerras03800812007-08-29 21:45:21 +10004384 global commitidx
Paul Mackerras3e766082008-01-13 17:26:30 +11004385 global selectedview
Paul Mackerras97645682007-08-23 22:24:38 +10004386 global hlview selectedhlview commitinterest
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004387
4388 if {$n == $curview} return
4389 set selid {}
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004390 set ymax [lindex [$canv cget -scrollregion] 3]
4391 set span [$canv yview]
4392 set ytop [expr {[lindex $span 0] * $ymax}]
4393 set ybot [expr {[lindex $span 1] * $ymax}]
4394 set yscreen [expr {($ybot - $ytop) / 2}]
Paul Mackerras94b4a692008-05-20 20:51:06 +10004395 if {$selectedline ne {}} {
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004396 set selid $currentid
4397 set y [yc $selectedline]
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004398 if {$ytop < $y && $y < $ybot} {
4399 set yscreen [expr {$y - $ytop}]
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004400 }
Paul Mackerrase507fd42007-06-16 21:51:08 +10004401 } elseif {[info exists pending_select]} {
4402 set selid $pending_select
4403 unset pending_select
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004404 }
4405 unselectline
Paul Mackerrasfdedbcf2006-04-06 21:22:52 +10004406 normalline
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004407 catch {unset treediffs}
4408 clear_display
Paul Mackerras908c3582006-05-20 09:38:11 +10004409 if {[info exists hlview] && $hlview == $n} {
4410 unset hlview
Christian Stimmingb007ee22007-11-07 18:44:35 +01004411 set selectedhlview [mc "None"]
Paul Mackerras908c3582006-05-20 09:38:11 +10004412 }
Paul Mackerras97645682007-08-23 22:24:38 +10004413 catch {unset commitinterest}
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004414 catch {unset cached_commitrow}
Paul Mackerras9257d8f2007-12-11 10:45:38 +11004415 catch {unset ordertok}
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004416
4417 set curview $n
Paul Mackerrasa90a6d22006-04-25 17:12:46 +10004418 set selectedview $n
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11004419 .bar.view entryconf [mca "Edit view..."] -state [expr {$n == 0? "disabled": "normal"}]
4420 .bar.view entryconf [mca "Delete view"] -state [expr {$n == 0? "disabled": "normal"}]
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004421
Paul Mackerrasdf904492007-08-29 22:03:07 +10004422 run refill_reflist
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004423 if {![info exists viewcomplete($n)]} {
Alexander Gavrilov567c34e2008-07-26 20:13:45 +04004424 getcommits $selid
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004425 return
4426 }
4427
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004428 set displayorder {}
4429 set parentlist {}
4430 set rowidlist {}
4431 set rowisopt {}
4432 set rowfinal {}
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10004433 set numcommits $commitidx($n)
Paul Mackerras22626ef2006-04-17 09:56:02 +10004434
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004435 catch {unset colormap}
4436 catch {unset rowtextx}
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004437 set nextcolor 0
4438 set canvxmax [$canv cget -width]
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004439 set curview $n
4440 set row 0
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004441 setcanvscroll
4442 set yf 0
Paul Mackerrase507fd42007-06-16 21:51:08 +10004443 set row {}
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004444 if {$selid ne {} && [commitinview $selid $n]} {
4445 set row [rowofcommit $selid]
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004446 # try to get the selected row in the same position on the screen
4447 set ymax [lindex [$canv cget -scrollregion] 3]
4448 set ytop [expr {[yc $row] - $yscreen}]
4449 if {$ytop < 0} {
4450 set ytop 0
4451 }
4452 set yf [expr {$ytop * 1.0 / $ymax}]
4453 }
4454 allcanvs yview moveto $yf
4455 drawvisible
Paul Mackerrase507fd42007-06-16 21:51:08 +10004456 if {$row ne {}} {
4457 selectline $row 0
Paul Mackerras3e766082008-01-13 17:26:30 +11004458 } elseif {!$viewcomplete($n)} {
Alexander Gavrilov567c34e2008-07-26 20:13:45 +04004459 reset_pending_select $selid
Paul Mackerrase507fd42007-06-16 21:51:08 +10004460 } else {
Alexander Gavrilov835e62a2008-07-26 20:15:54 +04004461 reset_pending_select {}
4462
4463 if {[commitinview $pending_select $curview]} {
4464 selectline [rowofcommit $pending_select] 1
4465 } else {
4466 set row [first_real_row]
4467 if {$row < $numcommits} {
4468 selectline $row 0
4469 }
Paul Mackerrase507fd42007-06-16 21:51:08 +10004470 }
4471 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004472 if {!$viewcomplete($n)} {
4473 if {$numcommits == 0} {
Christian Stimmingd990ced2007-11-07 18:42:55 +01004474 show_status [mc "Reading commits..."]
Paul Mackerrasd16c0812006-04-25 21:21:10 +10004475 }
Paul Mackerras098dd8a2006-05-03 09:32:53 +10004476 } elseif {$numcommits == 0} {
Christian Stimmingd990ced2007-11-07 18:42:55 +01004477 show_status [mc "No commits selected"]
Paul Mackerras2516dae2006-04-21 10:35:31 +10004478 }
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004479}
4480
Paul Mackerras908c3582006-05-20 09:38:11 +10004481# Stuff relating to the highlighting facility
4482
Paul Mackerras476ca632008-01-07 22:16:31 +11004483proc ishighlighted {id} {
Paul Mackerras164ff272006-05-29 19:50:02 +10004484 global vhighlights fhighlights nhighlights rhighlights
Paul Mackerras908c3582006-05-20 09:38:11 +10004485
Paul Mackerras476ca632008-01-07 22:16:31 +11004486 if {[info exists nhighlights($id)] && $nhighlights($id) > 0} {
4487 return $nhighlights($id)
Paul Mackerras908c3582006-05-20 09:38:11 +10004488 }
Paul Mackerras476ca632008-01-07 22:16:31 +11004489 if {[info exists vhighlights($id)] && $vhighlights($id) > 0} {
4490 return $vhighlights($id)
Paul Mackerras908c3582006-05-20 09:38:11 +10004491 }
Paul Mackerras476ca632008-01-07 22:16:31 +11004492 if {[info exists fhighlights($id)] && $fhighlights($id) > 0} {
4493 return $fhighlights($id)
Paul Mackerras908c3582006-05-20 09:38:11 +10004494 }
Paul Mackerras476ca632008-01-07 22:16:31 +11004495 if {[info exists rhighlights($id)] && $rhighlights($id) > 0} {
4496 return $rhighlights($id)
Paul Mackerras164ff272006-05-29 19:50:02 +10004497 }
Paul Mackerras908c3582006-05-20 09:38:11 +10004498 return 0
4499}
4500
Paul Mackerras28593d32008-11-13 23:01:46 +11004501proc bolden {id font} {
Paul Mackerrasb9fdba72009-04-09 09:34:46 +10004502 global canv linehtag currentid boldids need_redisplay markedid
Paul Mackerras908c3582006-05-20 09:38:11 +10004503
Paul Mackerrasd98d50e2008-11-13 22:39:00 +11004504 # need_redisplay = 1 means the display is stale and about to be redrawn
4505 if {$need_redisplay} return
Paul Mackerras28593d32008-11-13 23:01:46 +11004506 lappend boldids $id
4507 $canv itemconf $linehtag($id) -font $font
4508 if {[info exists currentid] && $id eq $currentid} {
Paul Mackerras908c3582006-05-20 09:38:11 +10004509 $canv delete secsel
Paul Mackerras28593d32008-11-13 23:01:46 +11004510 set t [eval $canv create rect [$canv bbox $linehtag($id)] \
Paul Mackerras908c3582006-05-20 09:38:11 +10004511 -outline {{}} -tags secsel \
4512 -fill [$canv cget -selectbackground]]
4513 $canv lower $t
4514 }
Paul Mackerrasb9fdba72009-04-09 09:34:46 +10004515 if {[info exists markedid] && $id eq $markedid} {
4516 make_idmark $id
4517 }
Paul Mackerras908c3582006-05-20 09:38:11 +10004518}
4519
Paul Mackerras28593d32008-11-13 23:01:46 +11004520proc bolden_name {id font} {
4521 global canv2 linentag currentid boldnameids need_redisplay
Paul Mackerras908c3582006-05-20 09:38:11 +10004522
Paul Mackerrasd98d50e2008-11-13 22:39:00 +11004523 if {$need_redisplay} return
Paul Mackerras28593d32008-11-13 23:01:46 +11004524 lappend boldnameids $id
4525 $canv2 itemconf $linentag($id) -font $font
4526 if {[info exists currentid] && $id eq $currentid} {
Paul Mackerras908c3582006-05-20 09:38:11 +10004527 $canv2 delete secsel
Paul Mackerras28593d32008-11-13 23:01:46 +11004528 set t [eval $canv2 create rect [$canv2 bbox $linentag($id)] \
Paul Mackerras908c3582006-05-20 09:38:11 +10004529 -outline {{}} -tags secsel \
4530 -fill [$canv2 cget -selectbackground]]
4531 $canv2 lower $t
4532 }
4533}
4534
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004535proc unbolden {} {
Paul Mackerras28593d32008-11-13 23:01:46 +11004536 global boldids
Paul Mackerras908c3582006-05-20 09:38:11 +10004537
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004538 set stillbold {}
Paul Mackerras28593d32008-11-13 23:01:46 +11004539 foreach id $boldids {
4540 if {![ishighlighted $id]} {
4541 bolden $id mainfont
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004542 } else {
Paul Mackerras28593d32008-11-13 23:01:46 +11004543 lappend stillbold $id
Paul Mackerras908c3582006-05-20 09:38:11 +10004544 }
4545 }
Paul Mackerras28593d32008-11-13 23:01:46 +11004546 set boldids $stillbold
Paul Mackerras908c3582006-05-20 09:38:11 +10004547}
4548
4549proc addvhighlight {n} {
Paul Mackerras476ca632008-01-07 22:16:31 +11004550 global hlview viewcomplete curview vhl_done commitidx
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004551
4552 if {[info exists hlview]} {
Paul Mackerras908c3582006-05-20 09:38:11 +10004553 delvhighlight
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004554 }
4555 set hlview $n
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004556 if {$n != $curview && ![info exists viewcomplete($n)]} {
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004557 start_rev_list $n
Paul Mackerras908c3582006-05-20 09:38:11 +10004558 }
4559 set vhl_done $commitidx($hlview)
4560 if {$vhl_done > 0} {
4561 drawvisible
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004562 }
4563}
4564
Paul Mackerras908c3582006-05-20 09:38:11 +10004565proc delvhighlight {} {
4566 global hlview vhighlights
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004567
4568 if {![info exists hlview]} return
4569 unset hlview
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004570 catch {unset vhighlights}
4571 unbolden
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004572}
4573
Paul Mackerras908c3582006-05-20 09:38:11 +10004574proc vhighlightmore {} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004575 global hlview vhl_done commitidx vhighlights curview
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004576
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004577 set max $commitidx($hlview)
Paul Mackerras908c3582006-05-20 09:38:11 +10004578 set vr [visiblerows]
4579 set r0 [lindex $vr 0]
4580 set r1 [lindex $vr 1]
4581 for {set i $vhl_done} {$i < $max} {incr i} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004582 set id [commitonrow $i $hlview]
4583 if {[commitinview $id $curview]} {
4584 set row [rowofcommit $id]
Paul Mackerras908c3582006-05-20 09:38:11 +10004585 if {$r0 <= $row && $row <= $r1} {
4586 if {![highlighted $row]} {
Paul Mackerras28593d32008-11-13 23:01:46 +11004587 bolden $id mainfontbold
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004588 }
Paul Mackerras476ca632008-01-07 22:16:31 +11004589 set vhighlights($id) 1
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004590 }
4591 }
4592 }
Paul Mackerras908c3582006-05-20 09:38:11 +10004593 set vhl_done $max
Paul Mackerrasac1276a2008-03-03 10:11:08 +11004594 return 0
Paul Mackerras908c3582006-05-20 09:38:11 +10004595}
4596
4597proc askvhighlight {row id} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004598 global hlview vhighlights iddrawn
Paul Mackerras908c3582006-05-20 09:38:11 +10004599
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004600 if {[commitinview $id $hlview]} {
Paul Mackerras476ca632008-01-07 22:16:31 +11004601 if {[info exists iddrawn($id)] && ![ishighlighted $id]} {
Paul Mackerras28593d32008-11-13 23:01:46 +11004602 bolden $id mainfontbold
Paul Mackerras908c3582006-05-20 09:38:11 +10004603 }
Paul Mackerras476ca632008-01-07 22:16:31 +11004604 set vhighlights($id) 1
Paul Mackerras908c3582006-05-20 09:38:11 +10004605 } else {
Paul Mackerras476ca632008-01-07 22:16:31 +11004606 set vhighlights($id) 0
Paul Mackerras908c3582006-05-20 09:38:11 +10004607 }
4608}
4609
Paul Mackerras687c8762007-09-22 12:49:33 +10004610proc hfiles_change {} {
Paul Mackerras908c3582006-05-20 09:38:11 +10004611 global highlight_files filehighlight fhighlights fh_serial
Paul Mackerras8b39e042008-12-02 09:02:46 +11004612 global highlight_paths
Paul Mackerras908c3582006-05-20 09:38:11 +10004613
4614 if {[info exists filehighlight]} {
4615 # delete previous highlights
4616 catch {close $filehighlight}
4617 unset filehighlight
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004618 catch {unset fhighlights}
4619 unbolden
Paul Mackerras63b79192006-05-20 21:31:52 +10004620 unhighlight_filelist
Paul Mackerras908c3582006-05-20 09:38:11 +10004621 }
Paul Mackerras63b79192006-05-20 21:31:52 +10004622 set highlight_paths {}
Paul Mackerras908c3582006-05-20 09:38:11 +10004623 after cancel do_file_hl $fh_serial
4624 incr fh_serial
4625 if {$highlight_files ne {}} {
4626 after 300 do_file_hl $fh_serial
4627 }
4628}
4629
Paul Mackerras687c8762007-09-22 12:49:33 +10004630proc gdttype_change {name ix op} {
4631 global gdttype highlight_files findstring findpattern
4632
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10004633 stopfinding
Paul Mackerras687c8762007-09-22 12:49:33 +10004634 if {$findstring ne {}} {
Christian Stimmingb007ee22007-11-07 18:44:35 +01004635 if {$gdttype eq [mc "containing:"]} {
Paul Mackerras687c8762007-09-22 12:49:33 +10004636 if {$highlight_files ne {}} {
4637 set highlight_files {}
4638 hfiles_change
4639 }
4640 findcom_change
4641 } else {
4642 if {$findpattern ne {}} {
4643 set findpattern {}
4644 findcom_change
4645 }
4646 set highlight_files $findstring
4647 hfiles_change
4648 }
4649 drawvisible
4650 }
4651 # enable/disable findtype/findloc menus too
4652}
4653
4654proc find_change {name ix op} {
4655 global gdttype findstring highlight_files
4656
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10004657 stopfinding
Christian Stimmingb007ee22007-11-07 18:44:35 +01004658 if {$gdttype eq [mc "containing:"]} {
Paul Mackerras687c8762007-09-22 12:49:33 +10004659 findcom_change
4660 } else {
4661 if {$highlight_files ne $findstring} {
4662 set highlight_files $findstring
4663 hfiles_change
4664 }
4665 }
4666 drawvisible
4667}
4668
Paul Mackerras64b5f142007-10-04 22:19:24 +10004669proc findcom_change args {
Paul Mackerras28593d32008-11-13 23:01:46 +11004670 global nhighlights boldnameids
Paul Mackerras687c8762007-09-22 12:49:33 +10004671 global findpattern findtype findstring gdttype
4672
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10004673 stopfinding
Paul Mackerras687c8762007-09-22 12:49:33 +10004674 # delete previous highlights, if any
Paul Mackerras28593d32008-11-13 23:01:46 +11004675 foreach id $boldnameids {
4676 bolden_name $id mainfont
Paul Mackerras687c8762007-09-22 12:49:33 +10004677 }
Paul Mackerras28593d32008-11-13 23:01:46 +11004678 set boldnameids {}
Paul Mackerras687c8762007-09-22 12:49:33 +10004679 catch {unset nhighlights}
4680 unbolden
4681 unmarkmatches
Christian Stimmingb007ee22007-11-07 18:44:35 +01004682 if {$gdttype ne [mc "containing:"] || $findstring eq {}} {
Paul Mackerras687c8762007-09-22 12:49:33 +10004683 set findpattern {}
Christian Stimmingb007ee22007-11-07 18:44:35 +01004684 } elseif {$findtype eq [mc "Regexp"]} {
Paul Mackerras687c8762007-09-22 12:49:33 +10004685 set findpattern $findstring
4686 } else {
4687 set e [string map {"*" "\\*" "?" "\\?" "\[" "\\\[" "\\" "\\\\"} \
4688 $findstring]
4689 set findpattern "*$e*"
4690 }
4691}
4692
Paul Mackerras63b79192006-05-20 21:31:52 +10004693proc makepatterns {l} {
4694 set ret {}
4695 foreach e $l {
4696 set ee [string map {"*" "\\*" "?" "\\?" "\[" "\\\[" "\\" "\\\\"} $e]
4697 if {[string index $ee end] eq "/"} {
4698 lappend ret "$ee*"
4699 } else {
4700 lappend ret $ee
4701 lappend ret "$ee/*"
4702 }
4703 }
4704 return $ret
4705}
4706
Paul Mackerras908c3582006-05-20 09:38:11 +10004707proc do_file_hl {serial} {
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004708 global highlight_files filehighlight highlight_paths gdttype fhl_list
Yggy Kingde665fd2011-07-13 01:30:26 -07004709 global cdup findtype
Paul Mackerras908c3582006-05-20 09:38:11 +10004710
Christian Stimmingb007ee22007-11-07 18:44:35 +01004711 if {$gdttype eq [mc "touching paths:"]} {
Yggy Kingde665fd2011-07-13 01:30:26 -07004712 # If "exact" match then convert backslashes to forward slashes.
4713 # Most useful to support Windows-flavoured file paths.
4714 if {$findtype eq [mc "Exact"]} {
4715 set highlight_files [string map {"\\" "/"} $highlight_files]
4716 }
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10004717 if {[catch {set paths [shellsplit $highlight_files]}]} return
4718 set highlight_paths [makepatterns $paths]
4719 highlight_filelist
Martin von Zweigbergkc332f442011-04-04 22:14:12 -04004720 set relative_paths {}
4721 foreach path $paths {
4722 lappend relative_paths [file join $cdup $path]
4723 }
4724 set gdtargs [concat -- $relative_paths]
Christian Stimmingb007ee22007-11-07 18:44:35 +01004725 } elseif {$gdttype eq [mc "adding/removing string:"]} {
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10004726 set gdtargs [list "-S$highlight_files"]
Martin Langhoffc33cb902012-06-14 20:34:11 +02004727 } elseif {$gdttype eq [mc "changing lines matching:"]} {
4728 set gdtargs [list "-G$highlight_files"]
Paul Mackerras687c8762007-09-22 12:49:33 +10004729 } else {
4730 # must be "containing:", i.e. we're searching commit info
4731 return
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10004732 }
Brandon Casey1ce09dd2007-03-19 18:00:37 -05004733 set cmd [concat | git diff-tree -r -s --stdin $gdtargs]
Paul Mackerras908c3582006-05-20 09:38:11 +10004734 set filehighlight [open $cmd r+]
4735 fconfigure $filehighlight -blocking 0
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004736 filerun $filehighlight readfhighlight
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004737 set fhl_list {}
Paul Mackerras908c3582006-05-20 09:38:11 +10004738 drawvisible
4739 flushhighlights
4740}
4741
4742proc flushhighlights {} {
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004743 global filehighlight fhl_list
Paul Mackerras908c3582006-05-20 09:38:11 +10004744
4745 if {[info exists filehighlight]} {
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004746 lappend fhl_list {}
Paul Mackerras908c3582006-05-20 09:38:11 +10004747 puts $filehighlight ""
4748 flush $filehighlight
4749 }
4750}
4751
4752proc askfilehighlight {row id} {
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004753 global filehighlight fhighlights fhl_list
Paul Mackerras908c3582006-05-20 09:38:11 +10004754
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004755 lappend fhl_list $id
Paul Mackerras476ca632008-01-07 22:16:31 +11004756 set fhighlights($id) -1
Paul Mackerras908c3582006-05-20 09:38:11 +10004757 puts $filehighlight $id
4758}
4759
4760proc readfhighlight {} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004761 global filehighlight fhighlights curview iddrawn
Paul Mackerras687c8762007-09-22 12:49:33 +10004762 global fhl_list find_dirn
Paul Mackerras908c3582006-05-20 09:38:11 +10004763
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004764 if {![info exists filehighlight]} {
4765 return 0
4766 }
4767 set nr 0
4768 while {[incr nr] <= 100 && [gets $filehighlight line] >= 0} {
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004769 set line [string trim $line]
4770 set i [lsearch -exact $fhl_list $line]
4771 if {$i < 0} continue
4772 for {set j 0} {$j < $i} {incr j} {
4773 set id [lindex $fhl_list $j]
Paul Mackerras476ca632008-01-07 22:16:31 +11004774 set fhighlights($id) 0
Paul Mackerras908c3582006-05-20 09:38:11 +10004775 }
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004776 set fhl_list [lrange $fhl_list [expr {$i+1}] end]
4777 if {$line eq {}} continue
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004778 if {![commitinview $line $curview]} continue
Paul Mackerras476ca632008-01-07 22:16:31 +11004779 if {[info exists iddrawn($line)] && ![ishighlighted $line]} {
Paul Mackerras28593d32008-11-13 23:01:46 +11004780 bolden $line mainfontbold
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004781 }
Paul Mackerras476ca632008-01-07 22:16:31 +11004782 set fhighlights($line) 1
Paul Mackerras908c3582006-05-20 09:38:11 +10004783 }
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004784 if {[eof $filehighlight]} {
4785 # strange...
Brandon Casey1ce09dd2007-03-19 18:00:37 -05004786 puts "oops, git diff-tree died"
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004787 catch {close $filehighlight}
4788 unset filehighlight
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004789 return 0
Paul Mackerras908c3582006-05-20 09:38:11 +10004790 }
Paul Mackerras687c8762007-09-22 12:49:33 +10004791 if {[info exists find_dirn]} {
Paul Mackerrascca5d942007-10-27 21:16:56 +10004792 run findmore
Paul Mackerras687c8762007-09-22 12:49:33 +10004793 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004794 return 1
Paul Mackerras908c3582006-05-20 09:38:11 +10004795}
4796
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004797proc doesmatch {f} {
Paul Mackerras687c8762007-09-22 12:49:33 +10004798 global findtype findpattern
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004799
Christian Stimmingb007ee22007-11-07 18:44:35 +01004800 if {$findtype eq [mc "Regexp"]} {
Paul Mackerras687c8762007-09-22 12:49:33 +10004801 return [regexp $findpattern $f]
Christian Stimmingb007ee22007-11-07 18:44:35 +01004802 } elseif {$findtype eq [mc "IgnCase"]} {
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004803 return [string match -nocase $findpattern $f]
4804 } else {
4805 return [string match $findpattern $f]
4806 }
4807}
4808
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10004809proc askfindhighlight {row id} {
Paul Mackerras9c311b32007-10-04 22:27:13 +10004810 global nhighlights commitinfo iddrawn
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004811 global findloc
4812 global markingmatches
Paul Mackerras908c3582006-05-20 09:38:11 +10004813
4814 if {![info exists commitinfo($id)]} {
4815 getcommit $id
4816 }
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10004817 set info $commitinfo($id)
Paul Mackerras908c3582006-05-20 09:38:11 +10004818 set isbold 0
Frédéric Brière585c27c2010-03-14 18:59:09 -04004819 set fldtypes [list [mc Headline] [mc Author] "" [mc Committer] "" [mc Comments]]
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10004820 foreach f $info ty $fldtypes {
Frédéric Brière585c27c2010-03-14 18:59:09 -04004821 if {$ty eq ""} continue
Christian Stimmingb007ee22007-11-07 18:44:35 +01004822 if {($findloc eq [mc "All fields"] || $findloc eq $ty) &&
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004823 [doesmatch $f]} {
Christian Stimmingb007ee22007-11-07 18:44:35 +01004824 if {$ty eq [mc "Author"]} {
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10004825 set isbold 2
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004826 break
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10004827 }
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004828 set isbold 1
Paul Mackerras908c3582006-05-20 09:38:11 +10004829 }
4830 }
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004831 if {$isbold && [info exists iddrawn($id)]} {
Paul Mackerras476ca632008-01-07 22:16:31 +11004832 if {![ishighlighted $id]} {
Paul Mackerras28593d32008-11-13 23:01:46 +11004833 bolden $id mainfontbold
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004834 if {$isbold > 1} {
Paul Mackerras28593d32008-11-13 23:01:46 +11004835 bolden_name $id mainfontbold
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004836 }
Paul Mackerras908c3582006-05-20 09:38:11 +10004837 }
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004838 if {$markingmatches} {
Paul Mackerras005a2f42007-07-26 22:36:39 +10004839 markrowmatches $row $id
Paul Mackerras908c3582006-05-20 09:38:11 +10004840 }
4841 }
Paul Mackerras476ca632008-01-07 22:16:31 +11004842 set nhighlights($id) $isbold
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004843}
4844
Paul Mackerras005a2f42007-07-26 22:36:39 +10004845proc markrowmatches {row id} {
4846 global canv canv2 linehtag linentag commitinfo findloc
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004847
Paul Mackerras005a2f42007-07-26 22:36:39 +10004848 set headline [lindex $commitinfo($id) 0]
4849 set author [lindex $commitinfo($id) 1]
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004850 $canv delete match$row
4851 $canv2 delete match$row
Christian Stimmingb007ee22007-11-07 18:44:35 +01004852 if {$findloc eq [mc "All fields"] || $findloc eq [mc "Headline"]} {
Paul Mackerras005a2f42007-07-26 22:36:39 +10004853 set m [findmatches $headline]
4854 if {$m ne {}} {
Paul Mackerras28593d32008-11-13 23:01:46 +11004855 markmatches $canv $row $headline $linehtag($id) $m \
4856 [$canv itemcget $linehtag($id) -font] $row
Paul Mackerras005a2f42007-07-26 22:36:39 +10004857 }
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004858 }
Christian Stimmingb007ee22007-11-07 18:44:35 +01004859 if {$findloc eq [mc "All fields"] || $findloc eq [mc "Author"]} {
Paul Mackerras005a2f42007-07-26 22:36:39 +10004860 set m [findmatches $author]
4861 if {$m ne {}} {
Paul Mackerras28593d32008-11-13 23:01:46 +11004862 markmatches $canv2 $row $author $linentag($id) $m \
4863 [$canv2 itemcget $linentag($id) -font] $row
Paul Mackerras005a2f42007-07-26 22:36:39 +10004864 }
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004865 }
4866}
4867
Paul Mackerras164ff272006-05-29 19:50:02 +10004868proc vrel_change {name ix op} {
4869 global highlight_related
4870
4871 rhighlight_none
Christian Stimmingb007ee22007-11-07 18:44:35 +01004872 if {$highlight_related ne [mc "None"]} {
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004873 run drawvisible
Paul Mackerras164ff272006-05-29 19:50:02 +10004874 }
4875}
4876
4877# prepare for testing whether commits are descendents or ancestors of a
4878proc rhighlight_sel {a} {
4879 global descendent desc_todo ancestor anc_todo
Paul Mackerras476ca632008-01-07 22:16:31 +11004880 global highlight_related
Paul Mackerras164ff272006-05-29 19:50:02 +10004881
4882 catch {unset descendent}
4883 set desc_todo [list $a]
4884 catch {unset ancestor}
4885 set anc_todo [list $a]
Christian Stimmingb007ee22007-11-07 18:44:35 +01004886 if {$highlight_related ne [mc "None"]} {
Paul Mackerras164ff272006-05-29 19:50:02 +10004887 rhighlight_none
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004888 run drawvisible
Paul Mackerras164ff272006-05-29 19:50:02 +10004889 }
4890}
4891
4892proc rhighlight_none {} {
4893 global rhighlights
4894
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004895 catch {unset rhighlights}
4896 unbolden
Paul Mackerras164ff272006-05-29 19:50:02 +10004897}
4898
4899proc is_descendent {a} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004900 global curview children descendent desc_todo
Paul Mackerras164ff272006-05-29 19:50:02 +10004901
4902 set v $curview
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004903 set la [rowofcommit $a]
Paul Mackerras164ff272006-05-29 19:50:02 +10004904 set todo $desc_todo
4905 set leftover {}
4906 set done 0
4907 for {set i 0} {$i < [llength $todo]} {incr i} {
4908 set do [lindex $todo $i]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004909 if {[rowofcommit $do] < $la} {
Paul Mackerras164ff272006-05-29 19:50:02 +10004910 lappend leftover $do
4911 continue
4912 }
4913 foreach nk $children($v,$do) {
4914 if {![info exists descendent($nk)]} {
4915 set descendent($nk) 1
4916 lappend todo $nk
4917 if {$nk eq $a} {
4918 set done 1
4919 }
4920 }
4921 }
4922 if {$done} {
4923 set desc_todo [concat $leftover [lrange $todo [expr {$i+1}] end]]
4924 return
4925 }
4926 }
4927 set descendent($a) 0
4928 set desc_todo $leftover
4929}
4930
4931proc is_ancestor {a} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004932 global curview parents ancestor anc_todo
Paul Mackerras164ff272006-05-29 19:50:02 +10004933
4934 set v $curview
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004935 set la [rowofcommit $a]
Paul Mackerras164ff272006-05-29 19:50:02 +10004936 set todo $anc_todo
4937 set leftover {}
4938 set done 0
4939 for {set i 0} {$i < [llength $todo]} {incr i} {
4940 set do [lindex $todo $i]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004941 if {![commitinview $do $v] || [rowofcommit $do] > $la} {
Paul Mackerras164ff272006-05-29 19:50:02 +10004942 lappend leftover $do
4943 continue
4944 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004945 foreach np $parents($v,$do) {
Paul Mackerras164ff272006-05-29 19:50:02 +10004946 if {![info exists ancestor($np)]} {
4947 set ancestor($np) 1
4948 lappend todo $np
4949 if {$np eq $a} {
4950 set done 1
4951 }
4952 }
4953 }
4954 if {$done} {
4955 set anc_todo [concat $leftover [lrange $todo [expr {$i+1}] end]]
4956 return
4957 }
4958 }
4959 set ancestor($a) 0
4960 set anc_todo $leftover
4961}
4962
4963proc askrelhighlight {row id} {
Paul Mackerras9c311b32007-10-04 22:27:13 +10004964 global descendent highlight_related iddrawn rhighlights
Paul Mackerras164ff272006-05-29 19:50:02 +10004965 global selectedline ancestor
4966
Paul Mackerras94b4a692008-05-20 20:51:06 +10004967 if {$selectedline eq {}} return
Paul Mackerras164ff272006-05-29 19:50:02 +10004968 set isbold 0
Christian Stimming55e34432008-01-09 22:23:18 +01004969 if {$highlight_related eq [mc "Descendant"] ||
4970 $highlight_related eq [mc "Not descendant"]} {
Paul Mackerras164ff272006-05-29 19:50:02 +10004971 if {![info exists descendent($id)]} {
4972 is_descendent $id
4973 }
Christian Stimming55e34432008-01-09 22:23:18 +01004974 if {$descendent($id) == ($highlight_related eq [mc "Descendant"])} {
Paul Mackerras164ff272006-05-29 19:50:02 +10004975 set isbold 1
4976 }
Christian Stimmingb007ee22007-11-07 18:44:35 +01004977 } elseif {$highlight_related eq [mc "Ancestor"] ||
4978 $highlight_related eq [mc "Not ancestor"]} {
Paul Mackerras164ff272006-05-29 19:50:02 +10004979 if {![info exists ancestor($id)]} {
4980 is_ancestor $id
4981 }
Christian Stimmingb007ee22007-11-07 18:44:35 +01004982 if {$ancestor($id) == ($highlight_related eq [mc "Ancestor"])} {
Paul Mackerras164ff272006-05-29 19:50:02 +10004983 set isbold 1
4984 }
4985 }
4986 if {[info exists iddrawn($id)]} {
Paul Mackerras476ca632008-01-07 22:16:31 +11004987 if {$isbold && ![ishighlighted $id]} {
Paul Mackerras28593d32008-11-13 23:01:46 +11004988 bolden $id mainfontbold
Paul Mackerras164ff272006-05-29 19:50:02 +10004989 }
4990 }
Paul Mackerras476ca632008-01-07 22:16:31 +11004991 set rhighlights($id) $isbold
Paul Mackerras164ff272006-05-29 19:50:02 +10004992}
4993
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004994# Graph layout functions
4995
Paul Mackerras9f1afe02006-02-19 22:44:47 +11004996proc shortids {ids} {
4997 set res {}
4998 foreach id $ids {
4999 if {[llength $id] > 1} {
5000 lappend res [shortids $id]
5001 } elseif {[regexp {^[0-9a-f]{40}$} $id]} {
5002 lappend res [string range $id 0 7]
5003 } else {
5004 lappend res $id
5005 }
5006 }
5007 return $res
5008}
5009
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005010proc ntimes {n o} {
5011 set ret {}
Paul Mackerras03800812007-08-29 21:45:21 +10005012 set o [list $o]
5013 for {set mask 1} {$mask <= $n} {incr mask $mask} {
5014 if {($n & $mask) != 0} {
5015 set ret [concat $ret $o]
5016 }
5017 set o [concat $o $o]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005018 }
5019 return $ret
5020}
5021
Paul Mackerras9257d8f2007-12-11 10:45:38 +11005022proc ordertoken {id} {
5023 global ordertok curview varcid varcstart varctok curview parents children
5024 global nullid nullid2
5025
5026 if {[info exists ordertok($id)]} {
5027 return $ordertok($id)
5028 }
5029 set origid $id
5030 set todo {}
5031 while {1} {
5032 if {[info exists varcid($curview,$id)]} {
5033 set a $varcid($curview,$id)
5034 set p [lindex $varcstart($curview) $a]
5035 } else {
5036 set p [lindex $children($curview,$id) 0]
5037 }
5038 if {[info exists ordertok($p)]} {
5039 set tok $ordertok($p)
5040 break
5041 }
Paul Mackerrasc8c9f3d2008-01-06 13:54:58 +11005042 set id [first_real_child $curview,$p]
5043 if {$id eq {}} {
Paul Mackerras9257d8f2007-12-11 10:45:38 +11005044 # it's a root
Paul Mackerras46308ea2008-01-15 22:16:32 +11005045 set tok [lindex $varctok($curview) $varcid($curview,$p)]
Paul Mackerras9257d8f2007-12-11 10:45:38 +11005046 break
5047 }
Paul Mackerras9257d8f2007-12-11 10:45:38 +11005048 if {[llength $parents($curview,$id)] == 1} {
5049 lappend todo [list $p {}]
5050 } else {
5051 set j [lsearch -exact $parents($curview,$id) $p]
5052 if {$j < 0} {
5053 puts "oops didn't find [shortids $p] in parents of [shortids $id]"
5054 }
5055 lappend todo [list $p [strrep $j]]
5056 }
5057 }
5058 for {set i [llength $todo]} {[incr i -1] >= 0} {} {
5059 set p [lindex $todo $i 0]
5060 append tok [lindex $todo $i 1]
5061 set ordertok($p) $tok
5062 }
5063 set ordertok($origid) $tok
5064 return $tok
5065}
5066
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005067# Work out where id should go in idlist so that order-token
5068# values increase from left to right
5069proc idcol {idlist id {i 0}} {
Paul Mackerras9257d8f2007-12-11 10:45:38 +11005070 set t [ordertoken $id]
Paul Mackerrase5b37ac2007-12-12 18:13:51 +11005071 if {$i < 0} {
5072 set i 0
5073 }
Paul Mackerras9257d8f2007-12-11 10:45:38 +11005074 if {$i >= [llength $idlist] || $t < [ordertoken [lindex $idlist $i]]} {
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005075 if {$i > [llength $idlist]} {
5076 set i [llength $idlist]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005077 }
Paul Mackerras9257d8f2007-12-11 10:45:38 +11005078 while {[incr i -1] >= 0 && $t < [ordertoken [lindex $idlist $i]]} {}
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005079 incr i
5080 } else {
Paul Mackerras9257d8f2007-12-11 10:45:38 +11005081 if {$t > [ordertoken [lindex $idlist $i]]} {
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005082 while {[incr i] < [llength $idlist] &&
Paul Mackerras9257d8f2007-12-11 10:45:38 +11005083 $t >= [ordertoken [lindex $idlist $i]]} {}
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005084 }
5085 }
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005086 return $i
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005087}
5088
5089proc initlayout {} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005090 global rowidlist rowisopt rowfinal displayorder parentlist
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10005091 global numcommits canvxmax canv
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11005092 global nextcolor
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10005093 global colormap rowtextx
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005094
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11005095 set numcommits 0
5096 set displayorder {}
Paul Mackerras79b2c752006-04-02 20:47:40 +10005097 set parentlist {}
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11005098 set nextcolor 0
Paul Mackerras03800812007-08-29 21:45:21 +10005099 set rowidlist {}
5100 set rowisopt {}
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10005101 set rowfinal {}
Paul Mackerrasbe0cd092006-03-31 09:55:11 +11005102 set canvxmax [$canv cget -width]
Paul Mackerras50b44ec2006-04-04 10:16:22 +10005103 catch {unset colormap}
5104 catch {unset rowtextx}
Paul Mackerrasac1276a2008-03-03 10:11:08 +11005105 setcanvscroll
Paul Mackerrasbe0cd092006-03-31 09:55:11 +11005106}
5107
5108proc setcanvscroll {} {
5109 global canv canv2 canv3 numcommits linespc canvxmax canvy0
Paul Mackerrasac1276a2008-03-03 10:11:08 +11005110 global lastscrollset lastscrollrows
Paul Mackerrasbe0cd092006-03-31 09:55:11 +11005111
5112 set ymax [expr {$canvy0 + ($numcommits - 0.5) * $linespc + 2}]
5113 $canv conf -scrollregion [list 0 0 $canvxmax $ymax]
5114 $canv2 conf -scrollregion [list 0 0 0 $ymax]
5115 $canv3 conf -scrollregion [list 0 0 0 $ymax]
Paul Mackerrasac1276a2008-03-03 10:11:08 +11005116 set lastscrollset [clock clicks -milliseconds]
5117 set lastscrollrows $numcommits
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005118}
5119
5120proc visiblerows {} {
5121 global canv numcommits linespc
5122
5123 set ymax [lindex [$canv cget -scrollregion] 3]
5124 if {$ymax eq {} || $ymax == 0} return
5125 set f [$canv yview]
5126 set y0 [expr {int([lindex $f 0] * $ymax)}]
5127 set r0 [expr {int(($y0 - 3) / $linespc) - 1}]
5128 if {$r0 < 0} {
5129 set r0 0
5130 }
5131 set y1 [expr {int([lindex $f 1] * $ymax)}]
5132 set r1 [expr {int(($y1 - 3) / $linespc) + 1}]
5133 if {$r1 >= $numcommits} {
5134 set r1 [expr {$numcommits - 1}]
5135 }
5136 return [list $r0 $r1]
5137}
5138
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10005139proc layoutmore {} {
Paul Mackerras38dfe932007-12-06 20:50:31 +11005140 global commitidx viewcomplete curview
Paul Mackerras94b4a692008-05-20 20:51:06 +10005141 global numcommits pending_select curview
Paul Mackerrasd375ef92008-10-21 10:18:12 +11005142 global lastscrollset lastscrollrows
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005143
Paul Mackerrasac1276a2008-03-03 10:11:08 +11005144 if {$lastscrollrows < 100 || $viewcomplete($curview) ||
5145 [clock clicks -milliseconds] - $lastscrollset > 500} {
Paul Mackerrasa2c22362006-10-31 15:00:53 +11005146 setcanvscroll
5147 }
Paul Mackerrasd94f8cd2006-04-06 10:18:23 +10005148 if {[info exists pending_select] &&
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005149 [commitinview $pending_select $curview]} {
Alexander Gavrilov567c34e2008-07-26 20:13:45 +04005150 update
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005151 selectline [rowofcommit $pending_select] 1
Paul Mackerrasd94f8cd2006-04-06 10:18:23 +10005152 }
Paul Mackerrasac1276a2008-03-03 10:11:08 +11005153 drawvisible
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005154}
5155
Paul Mackerrascdc84292008-11-18 19:54:14 +11005156# With path limiting, we mightn't get the actual HEAD commit,
5157# so ask git rev-list what is the first ancestor of HEAD that
5158# touches a file in the path limit.
5159proc get_viewmainhead {view} {
5160 global viewmainheadid vfilelimit viewinstances mainheadid
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005161
Paul Mackerrascdc84292008-11-18 19:54:14 +11005162 catch {
5163 set rfd [open [concat | git rev-list -1 $mainheadid \
5164 -- $vfilelimit($view)] r]
5165 set j [reg_instance $rfd]
5166 lappend viewinstances($view) $j
5167 fconfigure $rfd -blocking 0
5168 filerun $rfd [list getviewhead $rfd $j $view]
5169 set viewmainheadid($curview) {}
5170 }
5171}
5172
5173# git rev-list should give us just 1 line to use as viewmainheadid($view)
5174proc getviewhead {fd inst view} {
5175 global viewmainheadid commfd curview viewinstances showlocalchanges
5176
5177 set id {}
5178 if {[gets $fd line] < 0} {
5179 if {![eof $fd]} {
5180 return 1
5181 }
5182 } elseif {[string length $line] == 40 && [string is xdigit $line]} {
5183 set id $line
5184 }
5185 set viewmainheadid($view) $id
5186 close $fd
5187 unset commfd($inst)
5188 set i [lsearch -exact $viewinstances($view) $inst]
5189 if {$i >= 0} {
5190 set viewinstances($view) [lreplace $viewinstances($view) $i $i]
5191 }
5192 if {$showlocalchanges && $id ne {} && $view == $curview} {
5193 doshowlocalchanges
5194 }
5195 return 0
5196}
5197
5198proc doshowlocalchanges {} {
5199 global curview viewmainheadid
5200
5201 if {$viewmainheadid($curview) eq {}} return
5202 if {[commitinview $viewmainheadid($curview) $curview]} {
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005203 dodiffindex
Paul Mackerras38dfe932007-12-06 20:50:31 +11005204 } else {
Paul Mackerrascdc84292008-11-18 19:54:14 +11005205 interestedin $viewmainheadid($curview) dodiffindex
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005206 }
5207}
5208
5209proc dohidelocalchanges {} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005210 global nullid nullid2 lserial curview
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005211
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005212 if {[commitinview $nullid $curview]} {
Paul Mackerrasb8a938c2008-02-13 22:12:31 +11005213 removefakerow $nullid
Paul Mackerras8f489362007-07-13 19:49:37 +10005214 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005215 if {[commitinview $nullid2 $curview]} {
Paul Mackerrasb8a938c2008-02-13 22:12:31 +11005216 removefakerow $nullid2
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005217 }
5218 incr lserial
5219}
5220
Paul Mackerras8f489362007-07-13 19:49:37 +10005221# spawn off a process to do git diff-index --cached HEAD
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005222proc dodiffindex {} {
Paul Mackerrascdc84292008-11-18 19:54:14 +11005223 global lserial showlocalchanges vfilelimit curview
Jens Lehmann17f98362014-04-08 21:36:08 +02005224 global hasworktree git_version
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005225
Martin von Zweigbergk74cb8842011-05-23 22:44:08 -04005226 if {!$showlocalchanges || !$hasworktree} return
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005227 incr lserial
Jens Lehmann17f98362014-04-08 21:36:08 +02005228 if {[package vcompare $git_version "1.7.2"] >= 0} {
5229 set cmd "|git diff-index --cached --ignore-submodules=dirty HEAD"
5230 } else {
5231 set cmd "|git diff-index --cached HEAD"
5232 }
Paul Mackerrascdc84292008-11-18 19:54:14 +11005233 if {$vfilelimit($curview) ne {}} {
5234 set cmd [concat $cmd -- $vfilelimit($curview)]
5235 }
5236 set fd [open $cmd r]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005237 fconfigure $fd -blocking 0
Alexander Gavrilove439e092008-07-13 16:40:47 +04005238 set i [reg_instance $fd]
5239 filerun $fd [list readdiffindex $fd $lserial $i]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005240}
5241
Alexander Gavrilove439e092008-07-13 16:40:47 +04005242proc readdiffindex {fd serial inst} {
Paul Mackerrascdc84292008-11-18 19:54:14 +11005243 global viewmainheadid nullid nullid2 curview commitinfo commitdata lserial
5244 global vfilelimit
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005245
Paul Mackerras8f489362007-07-13 19:49:37 +10005246 set isdiff 1
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005247 if {[gets $fd line] < 0} {
Paul Mackerras8f489362007-07-13 19:49:37 +10005248 if {![eof $fd]} {
5249 return 1
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005250 }
Paul Mackerras8f489362007-07-13 19:49:37 +10005251 set isdiff 0
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005252 }
5253 # we only need to see one line and we don't really care what it says...
Alexander Gavrilove439e092008-07-13 16:40:47 +04005254 stop_instance $inst
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005255
Paul Mackerras24f7a662007-12-19 09:35:33 +11005256 if {$serial != $lserial} {
5257 return 0
Paul Mackerras8f489362007-07-13 19:49:37 +10005258 }
5259
Paul Mackerras24f7a662007-12-19 09:35:33 +11005260 # now see if there are any local changes not checked in to the index
Paul Mackerrascdc84292008-11-18 19:54:14 +11005261 set cmd "|git diff-files"
5262 if {$vfilelimit($curview) ne {}} {
5263 set cmd [concat $cmd -- $vfilelimit($curview)]
5264 }
5265 set fd [open $cmd r]
Paul Mackerras24f7a662007-12-19 09:35:33 +11005266 fconfigure $fd -blocking 0
Alexander Gavrilove439e092008-07-13 16:40:47 +04005267 set i [reg_instance $fd]
5268 filerun $fd [list readdifffiles $fd $serial $i]
Paul Mackerras24f7a662007-12-19 09:35:33 +11005269
5270 if {$isdiff && ![commitinview $nullid2 $curview]} {
Paul Mackerras8f489362007-07-13 19:49:37 +10005271 # add the line for the changes in the index to the graph
Christian Stimmingd990ced2007-11-07 18:42:55 +01005272 set hl [mc "Local changes checked in to index but not committed"]
Paul Mackerras8f489362007-07-13 19:49:37 +10005273 set commitinfo($nullid2) [list $hl {} {} {} {} " $hl\n"]
5274 set commitdata($nullid2) "\n $hl\n"
Paul Mackerrasfc2a2562007-12-26 23:03:43 +11005275 if {[commitinview $nullid $curview]} {
Paul Mackerrasb8a938c2008-02-13 22:12:31 +11005276 removefakerow $nullid
Paul Mackerrasfc2a2562007-12-26 23:03:43 +11005277 }
Paul Mackerrascdc84292008-11-18 19:54:14 +11005278 insertfakerow $nullid2 $viewmainheadid($curview)
Paul Mackerras24f7a662007-12-19 09:35:33 +11005279 } elseif {!$isdiff && [commitinview $nullid2 $curview]} {
Paul Mackerrascdc84292008-11-18 19:54:14 +11005280 if {[commitinview $nullid $curview]} {
5281 removefakerow $nullid
5282 }
Paul Mackerrasb8a938c2008-02-13 22:12:31 +11005283 removefakerow $nullid2
Paul Mackerras8f489362007-07-13 19:49:37 +10005284 }
5285 return 0
5286}
5287
Alexander Gavrilove439e092008-07-13 16:40:47 +04005288proc readdifffiles {fd serial inst} {
Paul Mackerrascdc84292008-11-18 19:54:14 +11005289 global viewmainheadid nullid nullid2 curview
Paul Mackerras8f489362007-07-13 19:49:37 +10005290 global commitinfo commitdata lserial
5291
5292 set isdiff 1
5293 if {[gets $fd line] < 0} {
5294 if {![eof $fd]} {
5295 return 1
5296 }
5297 set isdiff 0
5298 }
5299 # we only need to see one line and we don't really care what it says...
Alexander Gavrilove439e092008-07-13 16:40:47 +04005300 stop_instance $inst
Paul Mackerras8f489362007-07-13 19:49:37 +10005301
Paul Mackerras24f7a662007-12-19 09:35:33 +11005302 if {$serial != $lserial} {
5303 return 0
5304 }
5305
5306 if {$isdiff && ![commitinview $nullid $curview]} {
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005307 # add the line for the local diff to the graph
Christian Stimmingd990ced2007-11-07 18:42:55 +01005308 set hl [mc "Local uncommitted changes, not checked in to index"]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005309 set commitinfo($nullid) [list $hl {} {} {} {} " $hl\n"]
5310 set commitdata($nullid) "\n $hl\n"
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005311 if {[commitinview $nullid2 $curview]} {
5312 set p $nullid2
5313 } else {
Paul Mackerrascdc84292008-11-18 19:54:14 +11005314 set p $viewmainheadid($curview)
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005315 }
Paul Mackerrasb8a938c2008-02-13 22:12:31 +11005316 insertfakerow $nullid $p
Paul Mackerras24f7a662007-12-19 09:35:33 +11005317 } elseif {!$isdiff && [commitinview $nullid $curview]} {
Paul Mackerrasb8a938c2008-02-13 22:12:31 +11005318 removefakerow $nullid
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005319 }
5320 return 0
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005321}
5322
Paul Mackerras8f0bc7e2007-08-24 22:16:42 +10005323proc nextuse {id row} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005324 global curview children
Paul Mackerras8f0bc7e2007-08-24 22:16:42 +10005325
5326 if {[info exists children($curview,$id)]} {
5327 foreach kid $children($curview,$id) {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005328 if {![commitinview $kid $curview]} {
Paul Mackerras03800812007-08-29 21:45:21 +10005329 return -1
5330 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005331 if {[rowofcommit $kid] > $row} {
5332 return [rowofcommit $kid]
Paul Mackerras8f0bc7e2007-08-24 22:16:42 +10005333 }
5334 }
5335 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005336 if {[commitinview $id $curview]} {
5337 return [rowofcommit $id]
Paul Mackerras8f0bc7e2007-08-24 22:16:42 +10005338 }
5339 return -1
5340}
5341
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10005342proc prevuse {id row} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005343 global curview children
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10005344
5345 set ret -1
5346 if {[info exists children($curview,$id)]} {
5347 foreach kid $children($curview,$id) {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005348 if {![commitinview $kid $curview]} break
5349 if {[rowofcommit $kid] < $row} {
5350 set ret [rowofcommit $kid]
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10005351 }
5352 }
5353 }
5354 return $ret
5355}
5356
Paul Mackerras03800812007-08-29 21:45:21 +10005357proc make_idlist {row} {
5358 global displayorder parentlist uparrowlen downarrowlen mingaplen
Paul Mackerras9257d8f2007-12-11 10:45:38 +11005359 global commitidx curview children
Paul Mackerras03800812007-08-29 21:45:21 +10005360
5361 set r [expr {$row - $mingaplen - $downarrowlen - 1}]
5362 if {$r < 0} {
5363 set r 0
5364 }
5365 set ra [expr {$row - $downarrowlen}]
5366 if {$ra < 0} {
5367 set ra 0
5368 }
5369 set rb [expr {$row + $uparrowlen}]
5370 if {$rb > $commitidx($curview)} {
5371 set rb $commitidx($curview)
5372 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005373 make_disporder $r [expr {$rb + 1}]
Paul Mackerras03800812007-08-29 21:45:21 +10005374 set ids {}
5375 for {} {$r < $ra} {incr r} {
5376 set nextid [lindex $displayorder [expr {$r + 1}]]
5377 foreach p [lindex $parentlist $r] {
5378 if {$p eq $nextid} continue
5379 set rn [nextuse $p $r]
5380 if {$rn >= $row &&
5381 $rn <= $r + $downarrowlen + $mingaplen + $uparrowlen} {
Paul Mackerras9257d8f2007-12-11 10:45:38 +11005382 lappend ids [list [ordertoken $p] $p]
Paul Mackerras03800812007-08-29 21:45:21 +10005383 }
5384 }
5385 }
5386 for {} {$r < $row} {incr r} {
5387 set nextid [lindex $displayorder [expr {$r + 1}]]
5388 foreach p [lindex $parentlist $r] {
5389 if {$p eq $nextid} continue
5390 set rn [nextuse $p $r]
5391 if {$rn < 0 || $rn >= $row} {
Paul Mackerras9257d8f2007-12-11 10:45:38 +11005392 lappend ids [list [ordertoken $p] $p]
Paul Mackerras03800812007-08-29 21:45:21 +10005393 }
5394 }
5395 }
5396 set id [lindex $displayorder $row]
Paul Mackerras9257d8f2007-12-11 10:45:38 +11005397 lappend ids [list [ordertoken $id] $id]
Paul Mackerras03800812007-08-29 21:45:21 +10005398 while {$r < $rb} {
5399 foreach p [lindex $parentlist $r] {
5400 set firstkid [lindex $children($curview,$p) 0]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005401 if {[rowofcommit $firstkid] < $row} {
Paul Mackerras9257d8f2007-12-11 10:45:38 +11005402 lappend ids [list [ordertoken $p] $p]
Paul Mackerras03800812007-08-29 21:45:21 +10005403 }
5404 }
5405 incr r
5406 set id [lindex $displayorder $r]
5407 if {$id ne {}} {
5408 set firstkid [lindex $children($curview,$id) 0]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005409 if {$firstkid ne {} && [rowofcommit $firstkid] < $row} {
Paul Mackerras9257d8f2007-12-11 10:45:38 +11005410 lappend ids [list [ordertoken $id] $id]
Paul Mackerras03800812007-08-29 21:45:21 +10005411 }
5412 }
5413 }
5414 set idlist {}
5415 foreach idx [lsort -unique $ids] {
5416 lappend idlist [lindex $idx 1]
5417 }
5418 return $idlist
5419}
5420
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10005421proc rowsequal {a b} {
5422 while {[set i [lsearch -exact $a {}]] >= 0} {
5423 set a [lreplace $a $i $i]
5424 }
5425 while {[set i [lsearch -exact $b {}]] >= 0} {
5426 set b [lreplace $b $i $i]
5427 }
5428 return [expr {$a eq $b}]
5429}
5430
5431proc makeupline {id row rend col} {
5432 global rowidlist uparrowlen downarrowlen mingaplen
5433
5434 for {set r $rend} {1} {set r $rstart} {
5435 set rstart [prevuse $id $r]
5436 if {$rstart < 0} return
5437 if {$rstart < $row} break
5438 }
5439 if {$rstart + $uparrowlen + $mingaplen + $downarrowlen < $rend} {
5440 set rstart [expr {$rend - $uparrowlen - 1}]
5441 }
5442 for {set r $rstart} {[incr r] <= $row} {} {
5443 set idlist [lindex $rowidlist $r]
5444 if {$idlist ne {} && [lsearch -exact $idlist $id] < 0} {
5445 set col [idcol $idlist $id $col]
5446 lset rowidlist $r [linsert $idlist $col $id]
5447 changedrow $r
5448 }
5449 }
5450}
5451
Paul Mackerras03800812007-08-29 21:45:21 +10005452proc layoutrows {row endrow} {
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10005453 global rowidlist rowisopt rowfinal displayorder
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005454 global uparrowlen downarrowlen maxwidth mingaplen
Paul Mackerras6a90bff2007-06-18 09:48:23 +10005455 global children parentlist
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005456 global commitidx viewcomplete curview
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005457
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005458 make_disporder [expr {$row - 1}] [expr {$endrow + $uparrowlen}]
Paul Mackerras03800812007-08-29 21:45:21 +10005459 set idlist {}
5460 if {$row > 0} {
Paul Mackerrasf56782a2007-09-15 09:04:11 +10005461 set rm1 [expr {$row - 1}]
5462 foreach id [lindex $rowidlist $rm1] {
Paul Mackerras03800812007-08-29 21:45:21 +10005463 if {$id ne {}} {
5464 lappend idlist $id
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005465 }
5466 }
Paul Mackerrasf56782a2007-09-15 09:04:11 +10005467 set final [lindex $rowfinal $rm1]
Paul Mackerras8f0bc7e2007-08-24 22:16:42 +10005468 }
Paul Mackerras03800812007-08-29 21:45:21 +10005469 for {} {$row < $endrow} {incr row} {
5470 set rm1 [expr {$row - 1}]
Paul Mackerrasf56782a2007-09-15 09:04:11 +10005471 if {$rm1 < 0 || $idlist eq {}} {
Paul Mackerras03800812007-08-29 21:45:21 +10005472 set idlist [make_idlist $row]
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10005473 set final 1
Paul Mackerras03800812007-08-29 21:45:21 +10005474 } else {
5475 set id [lindex $displayorder $rm1]
5476 set col [lsearch -exact $idlist $id]
5477 set idlist [lreplace $idlist $col $col]
5478 foreach p [lindex $parentlist $rm1] {
5479 if {[lsearch -exact $idlist $p] < 0} {
5480 set col [idcol $idlist $p $col]
5481 set idlist [linsert $idlist $col $p]
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10005482 # if not the first child, we have to insert a line going up
5483 if {$id ne [lindex $children($curview,$p) 0]} {
5484 makeupline $p $rm1 $row $col
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005485 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005486 }
5487 }
Paul Mackerras03800812007-08-29 21:45:21 +10005488 set id [lindex $displayorder $row]
5489 if {$row > $downarrowlen} {
5490 set termrow [expr {$row - $downarrowlen - 1}]
5491 foreach p [lindex $parentlist $termrow] {
5492 set i [lsearch -exact $idlist $p]
5493 if {$i < 0} continue
5494 set nr [nextuse $p $termrow]
5495 if {$nr < 0 || $nr >= $row + $mingaplen + $uparrowlen} {
5496 set idlist [lreplace $idlist $i $i]
5497 }
5498 }
5499 }
5500 set col [lsearch -exact $idlist $id]
5501 if {$col < 0} {
5502 set col [idcol $idlist $id]
5503 set idlist [linsert $idlist $col $id]
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10005504 if {$children($curview,$id) ne {}} {
5505 makeupline $id $rm1 $row $col
5506 }
Paul Mackerras03800812007-08-29 21:45:21 +10005507 }
5508 set r [expr {$row + $uparrowlen - 1}]
5509 if {$r < $commitidx($curview)} {
5510 set x $col
5511 foreach p [lindex $parentlist $r] {
5512 if {[lsearch -exact $idlist $p] >= 0} continue
5513 set fk [lindex $children($curview,$p) 0]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005514 if {[rowofcommit $fk] < $row} {
Paul Mackerras03800812007-08-29 21:45:21 +10005515 set x [idcol $idlist $p $x]
5516 set idlist [linsert $idlist $x $p]
5517 }
5518 }
5519 if {[incr r] < $commitidx($curview)} {
5520 set p [lindex $displayorder $r]
5521 if {[lsearch -exact $idlist $p] < 0} {
5522 set fk [lindex $children($curview,$p) 0]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005523 if {$fk ne {} && [rowofcommit $fk] < $row} {
Paul Mackerras03800812007-08-29 21:45:21 +10005524 set x [idcol $idlist $p $x]
5525 set idlist [linsert $idlist $x $p]
5526 }
5527 }
5528 }
Paul Mackerras7b459a12007-08-13 14:52:00 +10005529 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005530 }
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10005531 if {$final && !$viewcomplete($curview) &&
5532 $row + $uparrowlen + $mingaplen + $downarrowlen
5533 >= $commitidx($curview)} {
5534 set final 0
Paul Mackerras7b459a12007-08-13 14:52:00 +10005535 }
Paul Mackerras03800812007-08-29 21:45:21 +10005536 set l [llength $rowidlist]
5537 if {$row == $l} {
5538 lappend rowidlist $idlist
5539 lappend rowisopt 0
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10005540 lappend rowfinal $final
Paul Mackerras03800812007-08-29 21:45:21 +10005541 } elseif {$row < $l} {
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10005542 if {![rowsequal $idlist [lindex $rowidlist $row]]} {
Paul Mackerras03800812007-08-29 21:45:21 +10005543 lset rowidlist $row $idlist
5544 changedrow $row
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005545 }
Paul Mackerrasf56782a2007-09-15 09:04:11 +10005546 lset rowfinal $row $final
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005547 } else {
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10005548 set pad [ntimes [expr {$row - $l}] {}]
5549 set rowidlist [concat $rowidlist $pad]
Paul Mackerras03800812007-08-29 21:45:21 +10005550 lappend rowidlist $idlist
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10005551 set rowfinal [concat $rowfinal $pad]
5552 lappend rowfinal $final
Paul Mackerras03800812007-08-29 21:45:21 +10005553 set rowisopt [concat $rowisopt [ntimes [expr {$row - $l + 1}] 0]]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005554 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005555 }
5556 return $row
5557}
5558
Paul Mackerras03800812007-08-29 21:45:21 +10005559proc changedrow {row} {
5560 global displayorder iddrawn rowisopt need_redisplay
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005561
Paul Mackerras03800812007-08-29 21:45:21 +10005562 set l [llength $rowisopt]
5563 if {$row < $l} {
5564 lset rowisopt $row 0
5565 if {$row + 1 < $l} {
5566 lset rowisopt [expr {$row + 1}] 0
5567 if {$row + 2 < $l} {
5568 lset rowisopt [expr {$row + 2}] 0
5569 }
5570 }
Paul Mackerras79b2c752006-04-02 20:47:40 +10005571 }
Paul Mackerras03800812007-08-29 21:45:21 +10005572 set id [lindex $displayorder $row]
5573 if {[info exists iddrawn($id)]} {
5574 set need_redisplay 1
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005575 }
5576}
5577
5578proc insert_pad {row col npad} {
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005579 global rowidlist
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005580
5581 set pad [ntimes $npad {}]
Paul Mackerrase341c062007-08-12 12:42:57 +10005582 set idlist [lindex $rowidlist $row]
5583 set bef [lrange $idlist 0 [expr {$col - 1}]]
5584 set aft [lrange $idlist $col end]
5585 set i [lsearch -exact $aft {}]
5586 if {$i > 0} {
5587 set aft [lreplace $aft $i $i]
5588 }
5589 lset rowidlist $row [concat $bef $pad $aft]
Paul Mackerras03800812007-08-29 21:45:21 +10005590 changedrow $row
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005591}
5592
5593proc optimize_rows {row col endrow} {
Paul Mackerras03800812007-08-29 21:45:21 +10005594 global rowidlist rowisopt displayorder curview children
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005595
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005596 if {$row < 1} {
5597 set row 1
5598 }
Paul Mackerras03800812007-08-29 21:45:21 +10005599 for {} {$row < $endrow} {incr row; set col 0} {
5600 if {[lindex $rowisopt $row]} continue
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005601 set haspad 0
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005602 set y0 [expr {$row - 1}]
5603 set ym [expr {$row - 2}]
Paul Mackerras03800812007-08-29 21:45:21 +10005604 set idlist [lindex $rowidlist $row]
5605 set previdlist [lindex $rowidlist $y0]
5606 if {$idlist eq {} || $previdlist eq {}} continue
5607 if {$ym >= 0} {
5608 set pprevidlist [lindex $rowidlist $ym]
5609 if {$pprevidlist eq {}} continue
5610 } else {
5611 set pprevidlist {}
5612 }
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005613 set x0 -1
5614 set xm -1
5615 for {} {$col < [llength $idlist]} {incr col} {
5616 set id [lindex $idlist $col]
5617 if {[lindex $previdlist $col] eq $id} continue
5618 if {$id eq {}} {
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005619 set haspad 1
5620 continue
5621 }
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005622 set x0 [lsearch -exact $previdlist $id]
5623 if {$x0 < 0} continue
5624 set z [expr {$x0 - $col}]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005625 set isarrow 0
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005626 set z0 {}
5627 if {$ym >= 0} {
5628 set xm [lsearch -exact $pprevidlist $id]
5629 if {$xm >= 0} {
5630 set z0 [expr {$xm - $x0}]
5631 }
5632 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005633 if {$z0 eq {}} {
Paul Mackerras92ed6662007-08-22 22:35:28 +10005634 # if row y0 is the first child of $id then it's not an arrow
5635 if {[lindex $children($curview,$id) 0] ne
5636 [lindex $displayorder $y0]} {
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005637 set isarrow 1
5638 }
5639 }
Paul Mackerrase341c062007-08-12 12:42:57 +10005640 if {!$isarrow && $id ne [lindex $displayorder $row] &&
5641 [lsearch -exact [lindex $rowidlist [expr {$row+1}]] $id] < 0} {
5642 set isarrow 1
5643 }
Paul Mackerras3fc42792006-09-15 09:45:23 +10005644 # Looking at lines from this row to the previous row,
5645 # make them go straight up if they end in an arrow on
5646 # the previous row; otherwise make them go straight up
5647 # or at 45 degrees.
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005648 if {$z < -1 || ($z < 0 && $isarrow)} {
Paul Mackerras3fc42792006-09-15 09:45:23 +10005649 # Line currently goes left too much;
5650 # insert pads in the previous row, then optimize it
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005651 set npad [expr {-1 - $z + $isarrow}]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005652 insert_pad $y0 $x0 $npad
5653 if {$y0 > 0} {
5654 optimize_rows $y0 $x0 $row
5655 }
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005656 set previdlist [lindex $rowidlist $y0]
5657 set x0 [lsearch -exact $previdlist $id]
5658 set z [expr {$x0 - $col}]
5659 if {$z0 ne {}} {
5660 set pprevidlist [lindex $rowidlist $ym]
5661 set xm [lsearch -exact $pprevidlist $id]
5662 set z0 [expr {$xm - $x0}]
5663 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005664 } elseif {$z > 1 || ($z > 0 && $isarrow)} {
Paul Mackerras3fc42792006-09-15 09:45:23 +10005665 # Line currently goes right too much;
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005666 # insert pads in this line
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005667 set npad [expr {$z - 1 + $isarrow}]
Paul Mackerrase341c062007-08-12 12:42:57 +10005668 insert_pad $row $col $npad
5669 set idlist [lindex $rowidlist $row]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005670 incr col $npad
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005671 set z [expr {$x0 - $col}]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005672 set haspad 1
5673 }
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005674 if {$z0 eq {} && !$isarrow && $ym >= 0} {
Paul Mackerraseb447a12006-03-18 23:11:37 +11005675 # this line links to its first child on row $row-2
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005676 set id [lindex $displayorder $ym]
5677 set xc [lsearch -exact $pprevidlist $id]
Paul Mackerraseb447a12006-03-18 23:11:37 +11005678 if {$xc >= 0} {
5679 set z0 [expr {$xc - $x0}]
5680 }
5681 }
Paul Mackerras3fc42792006-09-15 09:45:23 +10005682 # avoid lines jigging left then immediately right
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005683 if {$z0 ne {} && $z < 0 && $z0 > 0} {
5684 insert_pad $y0 $x0 1
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005685 incr x0
5686 optimize_rows $y0 $x0 $row
5687 set previdlist [lindex $rowidlist $y0]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005688 }
5689 }
5690 if {!$haspad} {
Paul Mackerras3fc42792006-09-15 09:45:23 +10005691 # Find the first column that doesn't have a line going right
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005692 for {set col [llength $idlist]} {[incr col -1] >= 0} {} {
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005693 set id [lindex $idlist $col]
5694 if {$id eq {}} break
5695 set x0 [lsearch -exact $previdlist $id]
5696 if {$x0 < 0} {
Paul Mackerraseb447a12006-03-18 23:11:37 +11005697 # check if this is the link to the first child
Paul Mackerras92ed6662007-08-22 22:35:28 +10005698 set kid [lindex $displayorder $y0]
5699 if {[lindex $children($curview,$id) 0] eq $kid} {
Paul Mackerraseb447a12006-03-18 23:11:37 +11005700 # it is, work out offset to child
Paul Mackerras92ed6662007-08-22 22:35:28 +10005701 set x0 [lsearch -exact $previdlist $kid]
Paul Mackerraseb447a12006-03-18 23:11:37 +11005702 }
5703 }
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005704 if {$x0 <= $col} break
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005705 }
Paul Mackerras3fc42792006-09-15 09:45:23 +10005706 # Insert a pad at that column as long as it has a line and
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005707 # isn't the last column
5708 if {$x0 >= 0 && [incr col] < [llength $idlist]} {
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005709 set idlist [linsert $idlist $col {}]
Paul Mackerras03800812007-08-29 21:45:21 +10005710 lset rowidlist $row $idlist
5711 changedrow $row
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005712 }
5713 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005714 }
5715}
5716
5717proc xc {row col} {
5718 global canvx0 linespc
5719 return [expr {$canvx0 + $col * $linespc}]
5720}
5721
5722proc yc {row} {
5723 global canvy0 linespc
5724 return [expr {$canvy0 + $row * $linespc}]
5725}
5726
Paul Mackerrasc934a8a2006-03-02 23:00:44 +11005727proc linewidth {id} {
5728 global thickerline lthickness
5729
5730 set wid $lthickness
5731 if {[info exists thickerline] && $id eq $thickerline} {
5732 set wid [expr {2 * $lthickness}]
5733 }
5734 return $wid
5735}
5736
Paul Mackerras50b44ec2006-04-04 10:16:22 +10005737proc rowranges {id} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005738 global curview children uparrowlen downarrowlen
Paul Mackerras92ed6662007-08-22 22:35:28 +10005739 global rowidlist
Paul Mackerras50b44ec2006-04-04 10:16:22 +10005740
Paul Mackerras92ed6662007-08-22 22:35:28 +10005741 set kids $children($curview,$id)
5742 if {$kids eq {}} {
5743 return {}
Paul Mackerras50b44ec2006-04-04 10:16:22 +10005744 }
Paul Mackerras92ed6662007-08-22 22:35:28 +10005745 set ret {}
5746 lappend kids $id
5747 foreach child $kids {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005748 if {![commitinview $child $curview]} break
5749 set row [rowofcommit $child]
Paul Mackerras92ed6662007-08-22 22:35:28 +10005750 if {![info exists prev]} {
5751 lappend ret [expr {$row + 1}]
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005752 } else {
Paul Mackerras92ed6662007-08-22 22:35:28 +10005753 if {$row <= $prevrow} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005754 puts "oops children of [shortids $id] out of order [shortids $child] $row <= [shortids $prev] $prevrow"
Paul Mackerras92ed6662007-08-22 22:35:28 +10005755 }
5756 # see if the line extends the whole way from prevrow to row
5757 if {$row > $prevrow + $uparrowlen + $downarrowlen &&
5758 [lsearch -exact [lindex $rowidlist \
5759 [expr {int(($row + $prevrow) / 2)}]] $id] < 0} {
5760 # it doesn't, see where it ends
5761 set r [expr {$prevrow + $downarrowlen}]
5762 if {[lsearch -exact [lindex $rowidlist $r] $id] < 0} {
5763 while {[incr r -1] > $prevrow &&
5764 [lsearch -exact [lindex $rowidlist $r] $id] < 0} {}
5765 } else {
5766 while {[incr r] <= $row &&
5767 [lsearch -exact [lindex $rowidlist $r] $id] >= 0} {}
5768 incr r -1
5769 }
5770 lappend ret $r
5771 # see where it starts up again
5772 set r [expr {$row - $uparrowlen}]
5773 if {[lsearch -exact [lindex $rowidlist $r] $id] < 0} {
5774 while {[incr r] < $row &&
5775 [lsearch -exact [lindex $rowidlist $r] $id] < 0} {}
5776 } else {
5777 while {[incr r -1] >= $prevrow &&
5778 [lsearch -exact [lindex $rowidlist $r] $id] >= 0} {}
5779 incr r
5780 }
5781 lappend ret $r
5782 }
Paul Mackerraseb447a12006-03-18 23:11:37 +11005783 }
Paul Mackerras92ed6662007-08-22 22:35:28 +10005784 if {$child eq $id} {
5785 lappend ret $row
5786 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005787 set prev $child
Paul Mackerras92ed6662007-08-22 22:35:28 +10005788 set prevrow $row
Paul Mackerraseb447a12006-03-18 23:11:37 +11005789 }
Paul Mackerras92ed6662007-08-22 22:35:28 +10005790 return $ret
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005791}
5792
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005793proc drawlineseg {id row endrow arrowlow} {
5794 global rowidlist displayorder iddrawn linesegs
Paul Mackerrase341c062007-08-12 12:42:57 +10005795 global canv colormap linespc curview maxlinelen parentlist
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005796
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005797 set cols [list [lsearch -exact [lindex $rowidlist $row] $id]]
5798 set le [expr {$row + 1}]
5799 set arrowhigh 1
5800 while {1} {
5801 set c [lsearch -exact [lindex $rowidlist $le] $id]
5802 if {$c < 0} {
5803 incr le -1
5804 break
5805 }
5806 lappend cols $c
5807 set x [lindex $displayorder $le]
5808 if {$x eq $id} {
5809 set arrowhigh 0
5810 break
5811 }
5812 if {[info exists iddrawn($x)] || $le == $endrow} {
5813 set c [lsearch -exact [lindex $rowidlist [expr {$le+1}]] $id]
5814 if {$c >= 0} {
5815 lappend cols $c
5816 set arrowhigh 0
5817 }
5818 break
5819 }
5820 incr le
5821 }
5822 if {$le <= $row} {
5823 return $row
5824 }
5825
5826 set lines {}
5827 set i 0
5828 set joinhigh 0
5829 if {[info exists linesegs($id)]} {
5830 set lines $linesegs($id)
5831 foreach li $lines {
5832 set r0 [lindex $li 0]
5833 if {$r0 > $row} {
5834 if {$r0 == $le && [lindex $li 1] - $row <= $maxlinelen} {
5835 set joinhigh 1
5836 }
5837 break
5838 }
5839 incr i
5840 }
5841 }
5842 set joinlow 0
5843 if {$i > 0} {
5844 set li [lindex $lines [expr {$i-1}]]
5845 set r1 [lindex $li 1]
5846 if {$r1 == $row && $le - [lindex $li 0] <= $maxlinelen} {
5847 set joinlow 1
5848 }
5849 }
5850
5851 set x [lindex $cols [expr {$le - $row}]]
5852 set xp [lindex $cols [expr {$le - 1 - $row}]]
5853 set dir [expr {$xp - $x}]
5854 if {$joinhigh} {
5855 set ith [lindex $lines $i 2]
5856 set coords [$canv coords $ith]
5857 set ah [$canv itemcget $ith -arrow]
5858 set arrowhigh [expr {$ah eq "first" || $ah eq "both"}]
5859 set x2 [lindex $cols [expr {$le + 1 - $row}]]
5860 if {$x2 ne {} && $x - $x2 == $dir} {
5861 set coords [lrange $coords 0 end-2]
5862 }
5863 } else {
5864 set coords [list [xc $le $x] [yc $le]]
5865 }
5866 if {$joinlow} {
5867 set itl [lindex $lines [expr {$i-1}] 2]
5868 set al [$canv itemcget $itl -arrow]
5869 set arrowlow [expr {$al eq "last" || $al eq "both"}]
Paul Mackerrase341c062007-08-12 12:42:57 +10005870 } elseif {$arrowlow} {
5871 if {[lsearch -exact [lindex $rowidlist [expr {$row-1}]] $id] >= 0 ||
5872 [lsearch -exact [lindex $parentlist [expr {$row-1}]] $id] >= 0} {
5873 set arrowlow 0
5874 }
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005875 }
5876 set arrow [lindex {none first last both} [expr {$arrowhigh + 2*$arrowlow}]]
5877 for {set y $le} {[incr y -1] > $row} {} {
5878 set x $xp
5879 set xp [lindex $cols [expr {$y - 1 - $row}]]
5880 set ndir [expr {$xp - $x}]
5881 if {$dir != $ndir || $xp < 0} {
5882 lappend coords [xc $y $x] [yc $y]
5883 }
5884 set dir $ndir
5885 }
5886 if {!$joinlow} {
5887 if {$xp < 0} {
5888 # join parent line to first child
5889 set ch [lindex $displayorder $row]
5890 set xc [lsearch -exact [lindex $rowidlist $row] $ch]
5891 if {$xc < 0} {
5892 puts "oops: drawlineseg: child $ch not on row $row"
Paul Mackerrase341c062007-08-12 12:42:57 +10005893 } elseif {$xc != $x} {
5894 if {($arrowhigh && $le == $row + 1) || $dir == 0} {
5895 set d [expr {int(0.5 * $linespc)}]
5896 set x1 [xc $row $x]
5897 if {$xc < $x} {
5898 set x2 [expr {$x1 - $d}]
5899 } else {
5900 set x2 [expr {$x1 + $d}]
5901 }
5902 set y2 [yc $row]
5903 set y1 [expr {$y2 + $d}]
5904 lappend coords $x1 $y1 $x2 $y2
5905 } elseif {$xc < $x - 1} {
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005906 lappend coords [xc $row [expr {$x-1}]] [yc $row]
5907 } elseif {$xc > $x + 1} {
5908 lappend coords [xc $row [expr {$x+1}]] [yc $row]
5909 }
5910 set x $xc
5911 }
5912 lappend coords [xc $row $x] [yc $row]
5913 } else {
5914 set xn [xc $row $xp]
5915 set yn [yc $row]
Paul Mackerrase341c062007-08-12 12:42:57 +10005916 lappend coords $xn $yn
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005917 }
5918 if {!$joinhigh} {
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005919 assigncolor $id
5920 set t [$canv create line $coords -width [linewidth $id] \
5921 -fill $colormap($id) -tags lines.$id -arrow $arrow]
5922 $canv lower $t
5923 bindline $t $id
5924 set lines [linsert $lines $i [list $row $le $t]]
5925 } else {
5926 $canv coords $ith $coords
5927 if {$arrow ne $ah} {
5928 $canv itemconf $ith -arrow $arrow
5929 }
5930 lset lines $i 0 $row
5931 }
5932 } else {
5933 set xo [lsearch -exact [lindex $rowidlist [expr {$row - 1}]] $id]
5934 set ndir [expr {$xo - $xp}]
5935 set clow [$canv coords $itl]
5936 if {$dir == $ndir} {
5937 set clow [lrange $clow 2 end]
5938 }
5939 set coords [concat $coords $clow]
5940 if {!$joinhigh} {
5941 lset lines [expr {$i-1}] 1 $le
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005942 } else {
5943 # coalesce two pieces
5944 $canv delete $ith
5945 set b [lindex $lines [expr {$i-1}] 0]
5946 set e [lindex $lines $i 1]
5947 set lines [lreplace $lines [expr {$i-1}] $i [list $b $e $itl]]
5948 }
5949 $canv coords $itl $coords
5950 if {$arrow ne $al} {
5951 $canv itemconf $itl -arrow $arrow
5952 }
5953 }
5954
5955 set linesegs($id) $lines
5956 return $le
5957}
5958
5959proc drawparentlinks {id row} {
5960 global rowidlist canv colormap curview parentlist
Paul Mackerras513a54d2007-08-01 22:27:57 +10005961 global idpos linespc
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005962
5963 set rowids [lindex $rowidlist $row]
5964 set col [lsearch -exact $rowids $id]
5965 if {$col < 0} return
5966 set olds [lindex $parentlist $row]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005967 set row2 [expr {$row + 1}]
5968 set x [xc $row $col]
5969 set y [yc $row]
5970 set y2 [yc $row2]
Paul Mackerrase341c062007-08-12 12:42:57 +10005971 set d [expr {int(0.5 * $linespc)}]
Paul Mackerras513a54d2007-08-01 22:27:57 +10005972 set ymid [expr {$y + $d}]
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11005973 set ids [lindex $rowidlist $row2]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005974 # rmx = right-most X coord used
5975 set rmx 0
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005976 foreach p $olds {
Paul Mackerrasf3408442006-03-31 09:54:24 +11005977 set i [lsearch -exact $ids $p]
5978 if {$i < 0} {
5979 puts "oops, parent $p of $id not in list"
5980 continue
5981 }
5982 set x2 [xc $row2 $i]
5983 if {$x2 > $rmx} {
5984 set rmx $x2
5985 }
Paul Mackerras513a54d2007-08-01 22:27:57 +10005986 set j [lsearch -exact $rowids $p]
5987 if {$j < 0} {
Paul Mackerraseb447a12006-03-18 23:11:37 +11005988 # drawlineseg will do this one for us
5989 continue
5990 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005991 assigncolor $p
5992 # should handle duplicated parents here...
5993 set coords [list $x $y]
Paul Mackerras513a54d2007-08-01 22:27:57 +10005994 if {$i != $col} {
5995 # if attaching to a vertical segment, draw a smaller
5996 # slant for visual distinctness
5997 if {$i == $j} {
5998 if {$i < $col} {
5999 lappend coords [expr {$x2 + $d}] $y $x2 $ymid
6000 } else {
6001 lappend coords [expr {$x2 - $d}] $y $x2 $ymid
6002 }
6003 } elseif {$i < $col && $i < $j} {
6004 # segment slants towards us already
6005 lappend coords [xc $row $j] $y
6006 } else {
6007 if {$i < $col - 1} {
6008 lappend coords [expr {$x2 + $linespc}] $y
6009 } elseif {$i > $col + 1} {
6010 lappend coords [expr {$x2 - $linespc}] $y
6011 }
6012 lappend coords $x2 $y2
6013 }
6014 } else {
6015 lappend coords $x2 $y2
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006016 }
Paul Mackerrasc934a8a2006-03-02 23:00:44 +11006017 set t [$canv create line $coords -width [linewidth $p] \
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006018 -fill $colormap($p) -tags lines.$p]
6019 $canv lower $t
6020 bindline $t $p
6021 }
Paul Mackerras322a8cc2006-10-15 18:03:46 +10006022 if {$rmx > [lindex $idpos($id) 1]} {
6023 lset idpos($id) 1 $rmx
6024 redrawtags $id
6025 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006026}
6027
Paul Mackerrasc934a8a2006-03-02 23:00:44 +11006028proc drawlines {id} {
Paul Mackerras322a8cc2006-10-15 18:03:46 +10006029 global canv
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006030
Paul Mackerras322a8cc2006-10-15 18:03:46 +10006031 $canv itemconf lines.$id -width [linewidth $id]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006032}
6033
Paul Mackerras322a8cc2006-10-15 18:03:46 +10006034proc drawcmittext {id row col} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11006035 global linespc canv canv2 canv3 fgcolor curview
6036 global cmitlisted commitinfo rowidlist parentlist
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006037 global rowtextx idpos idtags idheads idotherrefs
Paul Mackerras03800812007-08-29 21:45:21 +10006038 global linehtag linentag linedtag selectedline
Paul Mackerrasb9fdba72009-04-09 09:34:46 +10006039 global canvxmax boldids boldnameids fgcolor markedid
Paul Mackerrasd277e892008-09-21 18:11:37 -05006040 global mainheadid nullid nullid2 circleitem circlecolors ctxbut
Gauthier Östervall252c52d2013-03-27 14:40:51 +01006041 global mainheadcirclecolor workingfilescirclecolor indexcirclecolor
6042 global circleoutlinecolor
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006043
Linus Torvalds1407ade2008-02-09 14:02:07 -08006044 # listed is 0 for boundary, 1 for normal, 2 for negative, 3 for left, 4 for right
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11006045 set listed $cmitlisted($curview,$id)
Paul Mackerras219ea3a2006-09-07 10:21:39 +10006046 if {$id eq $nullid} {
Gauthier Östervall252c52d2013-03-27 14:40:51 +01006047 set ofill $workingfilescirclecolor
Paul Mackerras8f489362007-07-13 19:49:37 +10006048 } elseif {$id eq $nullid2} {
Gauthier Östervall252c52d2013-03-27 14:40:51 +01006049 set ofill $indexcirclecolor
Paul Mackerrasc11ff122008-05-26 10:11:33 +10006050 } elseif {$id eq $mainheadid} {
Gauthier Östervall252c52d2013-03-27 14:40:51 +01006051 set ofill $mainheadcirclecolor
Paul Mackerras219ea3a2006-09-07 10:21:39 +10006052 } else {
Paul Mackerrasc11ff122008-05-26 10:11:33 +10006053 set ofill [lindex $circlecolors $listed]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10006054 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006055 set x [xc $row $col]
6056 set y [yc $row]
6057 set orad [expr {$linespc / 3}]
Linus Torvalds1407ade2008-02-09 14:02:07 -08006058 if {$listed <= 2} {
Paul Mackerrasc961b222007-07-09 22:45:47 +10006059 set t [$canv create oval [expr {$x - $orad}] [expr {$y - $orad}] \
6060 [expr {$x + $orad - 1}] [expr {$y + $orad - 1}] \
Gauthier Östervall252c52d2013-03-27 14:40:51 +01006061 -fill $ofill -outline $circleoutlinecolor -width 1 -tags circle]
Linus Torvalds1407ade2008-02-09 14:02:07 -08006062 } elseif {$listed == 3} {
Paul Mackerrasc961b222007-07-09 22:45:47 +10006063 # triangle pointing left for left-side commits
6064 set t [$canv create polygon \
6065 [expr {$x - $orad}] $y \
6066 [expr {$x + $orad - 1}] [expr {$y - $orad}] \
6067 [expr {$x + $orad - 1}] [expr {$y + $orad - 1}] \
Gauthier Östervall252c52d2013-03-27 14:40:51 +01006068 -fill $ofill -outline $circleoutlinecolor -width 1 -tags circle]
Paul Mackerrasc961b222007-07-09 22:45:47 +10006069 } else {
6070 # triangle pointing right for right-side commits
6071 set t [$canv create polygon \
6072 [expr {$x + $orad - 1}] $y \
6073 [expr {$x - $orad}] [expr {$y - $orad}] \
6074 [expr {$x - $orad}] [expr {$y + $orad - 1}] \
Gauthier Östervall252c52d2013-03-27 14:40:51 +01006075 -fill $ofill -outline $circleoutlinecolor -width 1 -tags circle]
Paul Mackerrasc961b222007-07-09 22:45:47 +10006076 }
Paul Mackerrasc11ff122008-05-26 10:11:33 +10006077 set circleitem($row) $t
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006078 $canv raise $t
6079 $canv bind $t <1> {selcanvline {} %x %y}
Paul Mackerras322a8cc2006-10-15 18:03:46 +10006080 set rmx [llength [lindex $rowidlist $row]]
6081 set olds [lindex $parentlist $row]
6082 if {$olds ne {}} {
6083 set nextids [lindex $rowidlist [expr {$row + 1}]]
6084 foreach p $olds {
6085 set i [lsearch -exact $nextids $p]
6086 if {$i > $rmx} {
6087 set rmx $i
6088 }
6089 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006090 }
Paul Mackerras322a8cc2006-10-15 18:03:46 +10006091 set xt [xc $row $rmx]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006092 set rowtextx($row) $xt
6093 set idpos($id) [list $x $xt $y]
6094 if {[info exists idtags($id)] || [info exists idheads($id)]
6095 || [info exists idotherrefs($id)]} {
6096 set xt [drawtags $id $x $xt $y]
6097 }
Raphael Zimmerer36242492011-04-19 22:37:09 +02006098 if {[lindex $commitinfo($id) 6] > 0} {
6099 set xt [drawnotesign $xt $y]
6100 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006101 set headline [lindex $commitinfo($id) 0]
6102 set name [lindex $commitinfo($id) 1]
6103 set date [lindex $commitinfo($id) 2]
6104 set date [formatdate $date]
Paul Mackerras9c311b32007-10-04 22:27:13 +10006105 set font mainfont
6106 set nfont mainfont
Paul Mackerras476ca632008-01-07 22:16:31 +11006107 set isbold [ishighlighted $id]
Paul Mackerras908c3582006-05-20 09:38:11 +10006108 if {$isbold > 0} {
Paul Mackerras28593d32008-11-13 23:01:46 +11006109 lappend boldids $id
Paul Mackerras9c311b32007-10-04 22:27:13 +10006110 set font mainfontbold
Paul Mackerras908c3582006-05-20 09:38:11 +10006111 if {$isbold > 1} {
Paul Mackerras28593d32008-11-13 23:01:46 +11006112 lappend boldnameids $id
Paul Mackerras9c311b32007-10-04 22:27:13 +10006113 set nfont mainfontbold
Paul Mackerras908c3582006-05-20 09:38:11 +10006114 }
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10006115 }
Paul Mackerras28593d32008-11-13 23:01:46 +11006116 set linehtag($id) [$canv create text $xt $y -anchor w -fill $fgcolor \
6117 -text $headline -font $font -tags text]
6118 $canv bind $linehtag($id) $ctxbut "rowmenu %X %Y $id"
6119 set linentag($id) [$canv2 create text 3 $y -anchor w -fill $fgcolor \
6120 -text $name -font $nfont -tags text]
6121 set linedtag($id) [$canv3 create text 3 $y -anchor w -fill $fgcolor \
6122 -text $date -font mainfont -tags text]
Paul Mackerras94b4a692008-05-20 20:51:06 +10006123 if {$selectedline == $row} {
Paul Mackerras28593d32008-11-13 23:01:46 +11006124 make_secsel $id
Paul Mackerras03800812007-08-29 21:45:21 +10006125 }
Paul Mackerrasb9fdba72009-04-09 09:34:46 +10006126 if {[info exists markedid] && $markedid eq $id} {
6127 make_idmark $id
6128 }
Paul Mackerras9c311b32007-10-04 22:27:13 +10006129 set xr [expr {$xt + [font measure $font $headline]}]
Paul Mackerrasbe0cd092006-03-31 09:55:11 +11006130 if {$xr > $canvxmax} {
6131 set canvxmax $xr
6132 setcanvscroll
6133 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006134}
6135
6136proc drawcmitrow {row} {
Paul Mackerras03800812007-08-29 21:45:21 +10006137 global displayorder rowidlist nrows_drawn
Paul Mackerras005a2f42007-07-26 22:36:39 +10006138 global iddrawn markingmatches
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11006139 global commitinfo numcommits
Paul Mackerras687c8762007-09-22 12:49:33 +10006140 global filehighlight fhighlights findpattern nhighlights
Paul Mackerras908c3582006-05-20 09:38:11 +10006141 global hlview vhighlights
Paul Mackerras164ff272006-05-29 19:50:02 +10006142 global highlight_related rhighlights
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006143
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11006144 if {$row >= $numcommits} return
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006145
6146 set id [lindex $displayorder $row]
Paul Mackerras476ca632008-01-07 22:16:31 +11006147 if {[info exists hlview] && ![info exists vhighlights($id)]} {
Paul Mackerras908c3582006-05-20 09:38:11 +10006148 askvhighlight $row $id
6149 }
Paul Mackerras476ca632008-01-07 22:16:31 +11006150 if {[info exists filehighlight] && ![info exists fhighlights($id)]} {
Paul Mackerras908c3582006-05-20 09:38:11 +10006151 askfilehighlight $row $id
6152 }
Paul Mackerras476ca632008-01-07 22:16:31 +11006153 if {$findpattern ne {} && ![info exists nhighlights($id)]} {
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10006154 askfindhighlight $row $id
Paul Mackerras908c3582006-05-20 09:38:11 +10006155 }
Paul Mackerras476ca632008-01-07 22:16:31 +11006156 if {$highlight_related ne [mc "None"] && ![info exists rhighlights($id)]} {
Paul Mackerras164ff272006-05-29 19:50:02 +10006157 askrelhighlight $row $id
6158 }
Paul Mackerras005a2f42007-07-26 22:36:39 +10006159 if {![info exists iddrawn($id)]} {
6160 set col [lsearch -exact [lindex $rowidlist $row] $id]
6161 if {$col < 0} {
6162 puts "oops, row $row id $id not in list"
6163 return
6164 }
6165 if {![info exists commitinfo($id)]} {
6166 getcommit $id
6167 }
6168 assigncolor $id
6169 drawcmittext $id $row $col
6170 set iddrawn($id) 1
Paul Mackerras03800812007-08-29 21:45:21 +10006171 incr nrows_drawn
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006172 }
Paul Mackerras005a2f42007-07-26 22:36:39 +10006173 if {$markingmatches} {
6174 markrowmatches $row $id
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006175 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006176}
6177
Paul Mackerras322a8cc2006-10-15 18:03:46 +10006178proc drawcommits {row {endrow {}}} {
Paul Mackerras03800812007-08-29 21:45:21 +10006179 global numcommits iddrawn displayorder curview need_redisplay
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10006180 global parentlist rowidlist rowfinal uparrowlen downarrowlen nrows_drawn
Paul Mackerras322a8cc2006-10-15 18:03:46 +10006181
6182 if {$row < 0} {
6183 set row 0
6184 }
6185 if {$endrow eq {}} {
6186 set endrow $row
6187 }
6188 if {$endrow >= $numcommits} {
6189 set endrow [expr {$numcommits - 1}]
6190 }
6191
Paul Mackerras03800812007-08-29 21:45:21 +10006192 set rl1 [expr {$row - $downarrowlen - 3}]
6193 if {$rl1 < 0} {
6194 set rl1 0
6195 }
6196 set ro1 [expr {$row - 3}]
6197 if {$ro1 < 0} {
6198 set ro1 0
6199 }
6200 set r2 [expr {$endrow + $uparrowlen + 3}]
6201 if {$r2 > $numcommits} {
6202 set r2 $numcommits
6203 }
6204 for {set r $rl1} {$r < $r2} {incr r} {
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10006205 if {[lindex $rowidlist $r] ne {} && [lindex $rowfinal $r]} {
Paul Mackerras03800812007-08-29 21:45:21 +10006206 if {$rl1 < $r} {
6207 layoutrows $rl1 $r
6208 }
6209 set rl1 [expr {$r + 1}]
6210 }
6211 }
6212 if {$rl1 < $r} {
6213 layoutrows $rl1 $r
6214 }
6215 optimize_rows $ro1 0 $r2
6216 if {$need_redisplay || $nrows_drawn > 2000} {
6217 clear_display
Paul Mackerras03800812007-08-29 21:45:21 +10006218 }
6219
Paul Mackerras322a8cc2006-10-15 18:03:46 +10006220 # make the lines join to already-drawn rows either side
6221 set r [expr {$row - 1}]
6222 if {$r < 0 || ![info exists iddrawn([lindex $displayorder $r])]} {
6223 set r $row
6224 }
6225 set er [expr {$endrow + 1}]
6226 if {$er >= $numcommits ||
6227 ![info exists iddrawn([lindex $displayorder $er])]} {
6228 set er $endrow
6229 }
6230 for {} {$r <= $er} {incr r} {
6231 set id [lindex $displayorder $r]
6232 set wasdrawn [info exists iddrawn($id)]
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006233 drawcmitrow $r
Paul Mackerras322a8cc2006-10-15 18:03:46 +10006234 if {$r == $er} break
6235 set nextid [lindex $displayorder [expr {$r + 1}]]
Paul Mackerrase5ef6f92007-10-21 12:58:42 +10006236 if {$wasdrawn && [info exists iddrawn($nextid)]} continue
Paul Mackerras322a8cc2006-10-15 18:03:46 +10006237 drawparentlinks $id $r
6238
Paul Mackerras322a8cc2006-10-15 18:03:46 +10006239 set rowids [lindex $rowidlist $r]
6240 foreach lid $rowids {
6241 if {$lid eq {}} continue
Paul Mackerrase5ef6f92007-10-21 12:58:42 +10006242 if {[info exists lineend($lid)] && $lineend($lid) > $r} continue
Paul Mackerras322a8cc2006-10-15 18:03:46 +10006243 if {$lid eq $id} {
6244 # see if this is the first child of any of its parents
6245 foreach p [lindex $parentlist $r] {
6246 if {[lsearch -exact $rowids $p] < 0} {
6247 # make this line extend up to the child
Paul Mackerrase5ef6f92007-10-21 12:58:42 +10006248 set lineend($p) [drawlineseg $p $r $er 0]
Paul Mackerras322a8cc2006-10-15 18:03:46 +10006249 }
6250 }
Paul Mackerrase5ef6f92007-10-21 12:58:42 +10006251 } else {
6252 set lineend($lid) [drawlineseg $lid $r $er 1]
Paul Mackerras322a8cc2006-10-15 18:03:46 +10006253 }
6254 }
6255 }
6256}
6257
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11006258proc undolayout {row} {
6259 global uparrowlen mingaplen downarrowlen
6260 global rowidlist rowisopt rowfinal need_redisplay
6261
6262 set r [expr {$row - ($uparrowlen + $mingaplen + $downarrowlen)}]
6263 if {$r < 0} {
6264 set r 0
6265 }
6266 if {[llength $rowidlist] > $r} {
6267 incr r -1
6268 set rowidlist [lrange $rowidlist 0 $r]
6269 set rowfinal [lrange $rowfinal 0 $r]
6270 set rowisopt [lrange $rowisopt 0 $r]
6271 set need_redisplay 1
6272 run drawvisible
6273 }
6274}
6275
Paul Mackerras31c0eaa2007-12-30 22:41:14 +11006276proc drawvisible {} {
6277 global canv linespc curview vrowmod selectedline targetrow targetid
Paul Mackerras42a671f2008-01-02 09:59:39 +11006278 global need_redisplay cscroll numcommits
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006279
Paul Mackerras31c0eaa2007-12-30 22:41:14 +11006280 set fs [$canv yview]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006281 set ymax [lindex [$canv cget -scrollregion] 3]
Paul Mackerras5a7f5772008-01-15 22:45:36 +11006282 if {$ymax eq {} || $ymax == 0 || $numcommits == 0} return
Paul Mackerras31c0eaa2007-12-30 22:41:14 +11006283 set f0 [lindex $fs 0]
6284 set f1 [lindex $fs 1]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006285 set y0 [expr {int($f0 * $ymax)}]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006286 set y1 [expr {int($f1 * $ymax)}]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006287
Paul Mackerras31c0eaa2007-12-30 22:41:14 +11006288 if {[info exists targetid]} {
Paul Mackerras42a671f2008-01-02 09:59:39 +11006289 if {[commitinview $targetid $curview]} {
6290 set r [rowofcommit $targetid]
6291 if {$r != $targetrow} {
6292 # Fix up the scrollregion and change the scrolling position
6293 # now that our target row has moved.
6294 set diff [expr {($r - $targetrow) * $linespc}]
6295 set targetrow $r
6296 setcanvscroll
6297 set ymax [lindex [$canv cget -scrollregion] 3]
6298 incr y0 $diff
6299 incr y1 $diff
6300 set f0 [expr {$y0 / $ymax}]
6301 set f1 [expr {$y1 / $ymax}]
6302 allcanvs yview moveto $f0
6303 $cscroll set $f0 $f1
6304 set need_redisplay 1
6305 }
6306 } else {
6307 unset targetid
Paul Mackerras31c0eaa2007-12-30 22:41:14 +11006308 }
6309 }
6310
6311 set row [expr {int(($y0 - 3) / $linespc) - 1}]
6312 set endrow [expr {int(($y1 - 3) / $linespc) + 1}]
6313 if {$endrow >= $vrowmod($curview)} {
6314 update_arcrows $curview
6315 }
Paul Mackerras94b4a692008-05-20 20:51:06 +10006316 if {$selectedline ne {} &&
Paul Mackerras31c0eaa2007-12-30 22:41:14 +11006317 $row <= $selectedline && $selectedline <= $endrow} {
6318 set targetrow $selectedline
Paul Mackerrasac1276a2008-03-03 10:11:08 +11006319 } elseif {[info exists targetid]} {
Paul Mackerras31c0eaa2007-12-30 22:41:14 +11006320 set targetrow [expr {int(($row + $endrow) / 2)}]
6321 }
Paul Mackerrasac1276a2008-03-03 10:11:08 +11006322 if {[info exists targetrow]} {
6323 if {$targetrow >= $numcommits} {
6324 set targetrow [expr {$numcommits - 1}]
6325 }
6326 set targetid [commitonrow $targetrow]
Paul Mackerras42a671f2008-01-02 09:59:39 +11006327 }
Paul Mackerras31c0eaa2007-12-30 22:41:14 +11006328 drawcommits $row $endrow
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006329}
6330
6331proc clear_display {} {
Paul Mackerras03800812007-08-29 21:45:21 +10006332 global iddrawn linesegs need_redisplay nrows_drawn
Paul Mackerras164ff272006-05-29 19:50:02 +10006333 global vhighlights fhighlights nhighlights rhighlights
Paul Mackerras28593d32008-11-13 23:01:46 +11006334 global linehtag linentag linedtag boldids boldnameids
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006335
6336 allcanvs delete all
6337 catch {unset iddrawn}
Paul Mackerras322a8cc2006-10-15 18:03:46 +10006338 catch {unset linesegs}
Paul Mackerras94503a62008-05-19 09:48:45 +10006339 catch {unset linehtag}
6340 catch {unset linentag}
6341 catch {unset linedtag}
Paul Mackerras28593d32008-11-13 23:01:46 +11006342 set boldids {}
6343 set boldnameids {}
Paul Mackerras908c3582006-05-20 09:38:11 +10006344 catch {unset vhighlights}
6345 catch {unset fhighlights}
6346 catch {unset nhighlights}
Paul Mackerras164ff272006-05-29 19:50:02 +10006347 catch {unset rhighlights}
Paul Mackerras03800812007-08-29 21:45:21 +10006348 set need_redisplay 0
6349 set nrows_drawn 0
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006350}
6351
Paul Mackerras50b44ec2006-04-04 10:16:22 +10006352proc findcrossings {id} {
Paul Mackerras6e8c8702007-07-31 21:03:06 +10006353 global rowidlist parentlist numcommits displayorder
Paul Mackerras50b44ec2006-04-04 10:16:22 +10006354
6355 set cross {}
6356 set ccross {}
6357 foreach {s e} [rowranges $id] {
6358 if {$e >= $numcommits} {
6359 set e [expr {$numcommits - 1}]
Paul Mackerras50b44ec2006-04-04 10:16:22 +10006360 }
Paul Mackerrasd94f8cd2006-04-06 10:18:23 +10006361 if {$e <= $s} continue
Paul Mackerras50b44ec2006-04-04 10:16:22 +10006362 for {set row $e} {[incr row -1] >= $s} {} {
Paul Mackerras6e8c8702007-07-31 21:03:06 +10006363 set x [lsearch -exact [lindex $rowidlist $row] $id]
6364 if {$x < 0} break
Paul Mackerras50b44ec2006-04-04 10:16:22 +10006365 set olds [lindex $parentlist $row]
6366 set kid [lindex $displayorder $row]
6367 set kidx [lsearch -exact [lindex $rowidlist $row] $kid]
6368 if {$kidx < 0} continue
6369 set nextrow [lindex $rowidlist [expr {$row + 1}]]
6370 foreach p $olds {
6371 set px [lsearch -exact $nextrow $p]
6372 if {$px < 0} continue
6373 if {($kidx < $x && $x < $px) || ($px < $x && $x < $kidx)} {
6374 if {[lsearch -exact $ccross $p] >= 0} continue
6375 if {$x == $px + ($kidx < $px? -1: 1)} {
6376 lappend ccross $p
6377 } elseif {[lsearch -exact $cross $p] < 0} {
6378 lappend cross $p
6379 }
6380 }
6381 }
Paul Mackerras50b44ec2006-04-04 10:16:22 +10006382 }
6383 }
6384 return [concat $ccross {{}} $cross]
6385}
6386
Paul Mackerrase5c2d852005-05-11 23:44:54 +00006387proc assigncolor {id} {
Paul Mackerrasaa81d972006-02-28 11:27:12 +11006388 global colormap colors nextcolor
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11006389 global parents children children curview
Paul Mackerras6c20ff32005-06-22 19:53:32 +10006390
Paul Mackerras418c4c72006-02-07 09:10:18 +11006391 if {[info exists colormap($id)]} return
Paul Mackerrase5c2d852005-05-11 23:44:54 +00006392 set ncolors [llength $colors]
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10006393 if {[info exists children($curview,$id)]} {
6394 set kids $children($curview,$id)
Paul Mackerras79b2c752006-04-02 20:47:40 +10006395 } else {
6396 set kids {}
6397 }
6398 if {[llength $kids] == 1} {
6399 set child [lindex $kids 0]
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +00006400 if {[info exists colormap($child)]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11006401 && [llength $parents($curview,$child)] == 1} {
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +00006402 set colormap($id) $colormap($child)
6403 return
Paul Mackerrase5c2d852005-05-11 23:44:54 +00006404 }
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +00006405 }
6406 set badcolors {}
Paul Mackerras50b44ec2006-04-04 10:16:22 +10006407 set origbad {}
6408 foreach x [findcrossings $id] {
6409 if {$x eq {}} {
6410 # delimiter between corner crossings and other crossings
6411 if {[llength $badcolors] >= $ncolors - 1} break
6412 set origbad $badcolors
Paul Mackerrase5c2d852005-05-11 23:44:54 +00006413 }
Paul Mackerras50b44ec2006-04-04 10:16:22 +10006414 if {[info exists colormap($x)]
6415 && [lsearch -exact $badcolors $colormap($x)] < 0} {
6416 lappend badcolors $colormap($x)
Paul Mackerras6c20ff32005-06-22 19:53:32 +10006417 }
6418 }
Paul Mackerras50b44ec2006-04-04 10:16:22 +10006419 if {[llength $badcolors] >= $ncolors} {
6420 set badcolors $origbad
6421 }
Paul Mackerras6c20ff32005-06-22 19:53:32 +10006422 set origbad $badcolors
6423 if {[llength $badcolors] < $ncolors - 1} {
Paul Mackerras79b2c752006-04-02 20:47:40 +10006424 foreach child $kids {
Paul Mackerras6c20ff32005-06-22 19:53:32 +10006425 if {[info exists colormap($child)]
6426 && [lsearch -exact $badcolors $colormap($child)] < 0} {
6427 lappend badcolors $colormap($child)
6428 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11006429 foreach p $parents($curview,$child) {
Paul Mackerras79b2c752006-04-02 20:47:40 +10006430 if {[info exists colormap($p)]
6431 && [lsearch -exact $badcolors $colormap($p)] < 0} {
6432 lappend badcolors $colormap($p)
Paul Mackerrase5c2d852005-05-11 23:44:54 +00006433 }
6434 }
6435 }
Paul Mackerras6c20ff32005-06-22 19:53:32 +10006436 if {[llength $badcolors] >= $ncolors} {
6437 set badcolors $origbad
6438 }
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +00006439 }
6440 for {set i 0} {$i <= $ncolors} {incr i} {
6441 set c [lindex $colors $nextcolor]
6442 if {[incr nextcolor] >= $ncolors} {
6443 set nextcolor 0
Paul Mackerrase5c2d852005-05-11 23:44:54 +00006444 }
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +00006445 if {[lsearch -exact $badcolors $c]} break
6446 }
6447 set colormap($id) $c
6448}
6449
Paul Mackerrasa823a912005-06-21 10:01:38 +10006450proc bindline {t id} {
6451 global canv
6452
Paul Mackerrasa823a912005-06-21 10:01:38 +10006453 $canv bind $t <Enter> "lineenter %x %y $id"
6454 $canv bind $t <Motion> "linemotion %x %y $id"
6455 $canv bind $t <Leave> "lineleave $id"
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10006456 $canv bind $t <Button-1> "lineclick %x %y $id 1"
Paul Mackerrasa823a912005-06-21 10:01:38 +10006457}
6458
Paul Mackerras4399fe32013-01-03 10:10:31 +11006459proc graph_pane_width {} {
6460 global use_ttk
6461
6462 if {$use_ttk} {
6463 set g [.tf.histframe.pwclist sashpos 0]
6464 } else {
6465 set g [.tf.histframe.pwclist sash coord 0]
6466 }
6467 return [lindex $g 0]
6468}
6469
6470proc totalwidth {l font extra} {
6471 set tot 0
6472 foreach str $l {
6473 set tot [expr {$tot + [font measure $font $str] + $extra}]
6474 }
6475 return $tot
6476}
6477
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006478proc drawtags {id x xt y1} {
Paul Mackerras8a485712006-07-06 10:21:23 +10006479 global idtags idheads idotherrefs mainhead
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006480 global linespc lthickness
Paul Mackerrasd277e892008-09-21 18:11:37 -05006481 global canv rowtextx curview fgcolor bgcolor ctxbut
Gauthier Östervall252c52d2013-03-27 14:40:51 +01006482 global headbgcolor headfgcolor headoutlinecolor remotebgcolor
6483 global tagbgcolor tagfgcolor tagoutlinecolor
6484 global reflinecolor
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006485
6486 set marks {}
6487 set ntags 0
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10006488 set nheads 0
Paul Mackerras4399fe32013-01-03 10:10:31 +11006489 set singletag 0
6490 set maxtags 3
6491 set maxtagpct 25
6492 set maxwidth [expr {[graph_pane_width] * $maxtagpct / 100}]
6493 set delta [expr {int(0.5 * ($linespc - $lthickness))}]
6494 set extra [expr {$delta + $lthickness + $linespc}]
6495
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006496 if {[info exists idtags($id)]} {
6497 set marks $idtags($id)
6498 set ntags [llength $marks]
Paul Mackerras4399fe32013-01-03 10:10:31 +11006499 if {$ntags > $maxtags ||
6500 [totalwidth $marks mainfont $extra] > $maxwidth} {
6501 # show just a single "n tags..." tag
6502 set singletag 1
6503 if {$ntags == 1} {
6504 set marks [list "tag..."]
6505 } else {
6506 set marks [list [format "%d tags..." $ntags]]
6507 }
6508 set ntags 1
6509 }
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006510 }
6511 if {[info exists idheads($id)]} {
6512 set marks [concat $marks $idheads($id)]
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10006513 set nheads [llength $idheads($id)]
6514 }
6515 if {[info exists idotherrefs($id)]} {
6516 set marks [concat $marks $idotherrefs($id)]
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006517 }
6518 if {$marks eq {}} {
6519 return $xt
6520 }
6521
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08006522 set yt [expr {$y1 - 0.5 * $linespc}]
6523 set yb [expr {$yt + $linespc - 1}]
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006524 set xvals {}
6525 set wvals {}
Paul Mackerras8a485712006-07-06 10:21:23 +10006526 set i -1
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006527 foreach tag $marks {
Paul Mackerras8a485712006-07-06 10:21:23 +10006528 incr i
6529 if {$i >= $ntags && $i < $ntags + $nheads && $tag eq $mainhead} {
Paul Mackerras9c311b32007-10-04 22:27:13 +10006530 set wid [font measure mainfontbold $tag]
Paul Mackerras8a485712006-07-06 10:21:23 +10006531 } else {
Paul Mackerras9c311b32007-10-04 22:27:13 +10006532 set wid [font measure mainfont $tag]
Paul Mackerras8a485712006-07-06 10:21:23 +10006533 }
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006534 lappend xvals $xt
6535 lappend wvals $wid
Paul Mackerras4399fe32013-01-03 10:10:31 +11006536 set xt [expr {$xt + $wid + $extra}]
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006537 }
6538 set t [$canv create line $x $y1 [lindex $xvals end] $y1 \
Gauthier Östervall252c52d2013-03-27 14:40:51 +01006539 -width $lthickness -fill $reflinecolor -tags tag.$id]
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006540 $canv lower $t
6541 foreach tag $marks x $xvals wid $wvals {
Pat Thoyts8dd60f52011-03-01 23:50:50 +00006542 set tag_quoted [string map {% %%} $tag]
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08006543 set xl [expr {$x + $delta}]
6544 set xr [expr {$x + $delta + $wid + $lthickness}]
Paul Mackerras9c311b32007-10-04 22:27:13 +10006545 set font mainfont
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006546 if {[incr ntags -1] >= 0} {
6547 # draw a tag
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08006548 set t [$canv create polygon $x [expr {$yt + $delta}] $xl $yt \
6549 $xr $yt $xr $yb $xl $yb $x [expr {$yb - $delta}] \
Gauthier Östervall252c52d2013-03-27 14:40:51 +01006550 -width 1 -outline $tagoutlinecolor -fill $tagbgcolor \
6551 -tags tag.$id]
Paul Mackerras4399fe32013-01-03 10:10:31 +11006552 if {$singletag} {
6553 set tagclick [list showtags $id 1]
6554 } else {
6555 set tagclick [list showtag $tag_quoted 1]
6556 }
6557 $canv bind $t <1> $tagclick
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11006558 set rowtextx([rowofcommit $id]) [expr {$xr + $linespc}]
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006559 } else {
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10006560 # draw a head or other ref
6561 if {[incr nheads -1] >= 0} {
Gauthier Östervall252c52d2013-03-27 14:40:51 +01006562 set col $headbgcolor
Paul Mackerras8a485712006-07-06 10:21:23 +10006563 if {$tag eq $mainhead} {
Paul Mackerras9c311b32007-10-04 22:27:13 +10006564 set font mainfontbold
Paul Mackerras8a485712006-07-06 10:21:23 +10006565 }
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10006566 } else {
6567 set col "#ddddff"
6568 }
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08006569 set xl [expr {$xl - $delta/2}]
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006570 $canv create polygon $x $yt $xr $yt $xr $yb $x $yb \
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10006571 -width 1 -outline black -fill $col -tags tag.$id
Josef Weidendorfera970fcf2006-04-18 23:53:07 +02006572 if {[regexp {^(remotes/.*/|remotes/)} $tag match remoteprefix]} {
Paul Mackerras9c311b32007-10-04 22:27:13 +10006573 set rwid [font measure mainfont $remoteprefix]
Josef Weidendorfera970fcf2006-04-18 23:53:07 +02006574 set xi [expr {$x + 1}]
6575 set yti [expr {$yt + 1}]
6576 set xri [expr {$x + $rwid}]
6577 $canv create polygon $xi $yti $xri $yti $xri $yb $xi $yb \
Gauthier Östervall252c52d2013-03-27 14:40:51 +01006578 -width 0 -fill $remotebgcolor -tags tag.$id
Josef Weidendorfera970fcf2006-04-18 23:53:07 +02006579 }
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006580 }
Gauthier Östervall252c52d2013-03-27 14:40:51 +01006581 set t [$canv create text $xl $y1 -anchor w -text $tag -fill $headfgcolor \
Paul Mackerras8a485712006-07-06 10:21:23 +10006582 -font $font -tags [list tag.$id text]]
Paul Mackerras106288c2005-08-19 23:11:39 +10006583 if {$ntags >= 0} {
Paul Mackerras4399fe32013-01-03 10:10:31 +11006584 $canv bind $t <1> $tagclick
Paul Mackerras10299152006-08-02 09:52:01 +10006585 } elseif {$nheads >= 0} {
Pat Thoyts8dd60f52011-03-01 23:50:50 +00006586 $canv bind $t $ctxbut [list headmenu %X %Y $id $tag_quoted]
Paul Mackerras106288c2005-08-19 23:11:39 +10006587 }
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006588 }
6589 return $xt
6590}
6591
Raphael Zimmerer36242492011-04-19 22:37:09 +02006592proc drawnotesign {xt y} {
6593 global linespc canv fgcolor
6594
6595 set orad [expr {$linespc / 3}]
6596 set t [$canv create rectangle [expr {$xt - $orad}] [expr {$y - $orad}] \
6597 [expr {$xt + $orad - 1}] [expr {$y + $orad - 1}] \
6598 -fill yellow -outline $fgcolor -width 1 -tags circle]
6599 set xt [expr {$xt + $orad * 3}]
6600 return $xt
6601}
6602
Paul Mackerras8d858d12005-08-05 09:52:16 +10006603proc xcoord {i level ln} {
6604 global canvx0 xspc1 xspc2
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +00006605
Paul Mackerras8d858d12005-08-05 09:52:16 +10006606 set x [expr {$canvx0 + $i * $xspc1($ln)}]
6607 if {$i > 0 && $i == $level} {
6608 set x [expr {$x + 0.5 * ($xspc2 - $xspc1($ln))}]
6609 } elseif {$i > $level} {
6610 set x [expr {$x + $xspc2 - $xspc1($ln)}]
6611 }
6612 return $x
6613}
6614
Paul Mackerras098dd8a2006-05-03 09:32:53 +10006615proc show_status {msg} {
Paul Mackerras9c311b32007-10-04 22:27:13 +10006616 global canv fgcolor
Paul Mackerras098dd8a2006-05-03 09:32:53 +10006617
6618 clear_display
Paul Mackerras9c311b32007-10-04 22:27:13 +10006619 $canv create text 3 3 -anchor nw -text $msg -font mainfont \
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10006620 -tags text -fill $fgcolor
Paul Mackerras098dd8a2006-05-03 09:32:53 +10006621}
6622
Paul Mackerras94a2eed2005-08-07 15:27:57 +10006623# Don't change the text pane cursor if it is currently the hand cursor,
6624# showing that we are over a sha1 ID link.
6625proc settextcursor {c} {
6626 global ctext curtextcursor
6627
6628 if {[$ctext cget -cursor] == $curtextcursor} {
6629 $ctext config -cursor $c
6630 }
6631 set curtextcursor $c
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +00006632}
6633
Paul Mackerrasa137a902007-10-23 21:12:49 +10006634proc nowbusy {what {name {}}} {
6635 global isbusy busyname statusw
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10006636
6637 if {[array names isbusy] eq {}} {
6638 . config -cursor watch
6639 settextcursor watch
6640 }
6641 set isbusy($what) 1
Paul Mackerrasa137a902007-10-23 21:12:49 +10006642 set busyname($what) $name
6643 if {$name ne {}} {
6644 $statusw conf -text $name
6645 }
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10006646}
6647
6648proc notbusy {what} {
Paul Mackerrasa137a902007-10-23 21:12:49 +10006649 global isbusy maincursor textcursor busyname statusw
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10006650
Paul Mackerrasa137a902007-10-23 21:12:49 +10006651 catch {
6652 unset isbusy($what)
6653 if {$busyname($what) ne {} &&
6654 [$statusw cget -text] eq $busyname($what)} {
6655 $statusw conf -text {}
6656 }
6657 }
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10006658 if {[array names isbusy] eq {}} {
6659 . config -cursor $maincursor
6660 settextcursor $textcursor
6661 }
6662}
6663
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00006664proc findmatches {f} {
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006665 global findtype findstring
Christian Stimmingb007ee22007-11-07 18:44:35 +01006666 if {$findtype == [mc "Regexp"]} {
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006667 set matches [regexp -indices -all -inline $findstring $f]
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00006668 } else {
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006669 set fs $findstring
Christian Stimmingb007ee22007-11-07 18:44:35 +01006670 if {$findtype == [mc "IgnCase"]} {
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006671 set f [string tolower $f]
6672 set fs [string tolower $fs]
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00006673 }
6674 set matches {}
6675 set i 0
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006676 set l [string length $fs]
6677 while {[set j [string first $fs $f $i]] >= 0} {
6678 lappend matches [list $j [expr {$j+$l-1}]]
6679 set i [expr {$j + $l}]
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00006680 }
6681 }
6682 return $matches
6683}
6684
Paul Mackerrascca5d942007-10-27 21:16:56 +10006685proc dofind {{dirn 1} {wrap 1}} {
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006686 global findstring findstartline findcurline selectedline numcommits
Paul Mackerrascca5d942007-10-27 21:16:56 +10006687 global gdttype filehighlight fh_serial find_dirn findallowwrap
Paul Mackerrasb74fd572005-07-16 07:46:13 -04006688
Paul Mackerrascca5d942007-10-27 21:16:56 +10006689 if {[info exists find_dirn]} {
6690 if {$find_dirn == $dirn} return
6691 stopfinding
6692 }
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00006693 focus .
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006694 if {$findstring eq {} || $numcommits == 0} return
Paul Mackerras94b4a692008-05-20 20:51:06 +10006695 if {$selectedline eq {}} {
Paul Mackerrascca5d942007-10-27 21:16:56 +10006696 set findstartline [lindex [visiblerows] [expr {$dirn < 0}]]
Paul Mackerras98f350e2005-05-15 05:56:51 +00006697 } else {
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006698 set findstartline $selectedline
Paul Mackerras98f350e2005-05-15 05:56:51 +00006699 }
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006700 set findcurline $findstartline
Christian Stimmingb007ee22007-11-07 18:44:35 +01006701 nowbusy finding [mc "Searching"]
6702 if {$gdttype ne [mc "containing:"] && ![info exists filehighlight]} {
Paul Mackerras687c8762007-09-22 12:49:33 +10006703 after cancel do_file_hl $fh_serial
6704 do_file_hl $fh_serial
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006705 }
Paul Mackerrascca5d942007-10-27 21:16:56 +10006706 set find_dirn $dirn
6707 set findallowwrap $wrap
6708 run findmore
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006709}
6710
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10006711proc stopfinding {} {
6712 global find_dirn findcurline fprogcoord
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006713
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10006714 if {[info exists find_dirn]} {
6715 unset find_dirn
6716 unset findcurline
6717 notbusy finding
6718 set fprogcoord 0
6719 adjustprogress
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006720 }
Paul Mackerras8a897742008-10-27 21:36:25 +11006721 stopblaming
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006722}
6723
6724proc findmore {} {
Paul Mackerras687c8762007-09-22 12:49:33 +10006725 global commitdata commitinfo numcommits findpattern findloc
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11006726 global findstartline findcurline findallowwrap
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10006727 global find_dirn gdttype fhighlights fprogcoord
Paul Mackerrascd2bcae2008-01-02 21:44:06 +11006728 global curview varcorder vrownum varccommits vrowmod
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006729
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10006730 if {![info exists find_dirn]} {
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006731 return 0
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00006732 }
Frédéric Brière585c27c2010-03-14 18:59:09 -04006733 set fldtypes [list [mc "Headline"] [mc "Author"] "" [mc "Committer"] "" [mc "Comments"]]
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006734 set l $findcurline
Paul Mackerrascca5d942007-10-27 21:16:56 +10006735 set moretodo 0
6736 if {$find_dirn > 0} {
6737 incr l
6738 if {$l >= $numcommits} {
6739 set l 0
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006740 }
Paul Mackerrascca5d942007-10-27 21:16:56 +10006741 if {$l <= $findstartline} {
6742 set lim [expr {$findstartline + 1}]
6743 } else {
6744 set lim $numcommits
6745 set moretodo $findallowwrap
6746 }
Paul Mackerras98f350e2005-05-15 05:56:51 +00006747 } else {
Paul Mackerrascca5d942007-10-27 21:16:56 +10006748 if {$l == 0} {
6749 set l $numcommits
6750 }
6751 incr l -1
6752 if {$l >= $findstartline} {
6753 set lim [expr {$findstartline - 1}]
6754 } else {
6755 set lim -1
6756 set moretodo $findallowwrap
6757 }
Paul Mackerras98f350e2005-05-15 05:56:51 +00006758 }
Paul Mackerrascca5d942007-10-27 21:16:56 +10006759 set n [expr {($lim - $l) * $find_dirn}]
6760 if {$n > 500} {
6761 set n 500
6762 set moretodo 1
Paul Mackerras98f350e2005-05-15 05:56:51 +00006763 }
Paul Mackerrascd2bcae2008-01-02 21:44:06 +11006764 if {$l + ($find_dirn > 0? $n: 1) > $vrowmod($curview)} {
6765 update_arcrows $curview
6766 }
Paul Mackerras687c8762007-09-22 12:49:33 +10006767 set found 0
6768 set domore 1
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11006769 set ai [bsearch $vrownum($curview) $l]
6770 set a [lindex $varcorder($curview) $ai]
6771 set arow [lindex $vrownum($curview) $ai]
6772 set ids [lindex $varccommits($curview,$a)]
6773 set arowend [expr {$arow + [llength $ids]}]
Christian Stimmingb007ee22007-11-07 18:44:35 +01006774 if {$gdttype eq [mc "containing:"]} {
Paul Mackerrascca5d942007-10-27 21:16:56 +10006775 for {} {$n > 0} {incr n -1; incr l $find_dirn} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11006776 if {$l < $arow || $l >= $arowend} {
6777 incr ai $find_dirn
6778 set a [lindex $varcorder($curview) $ai]
6779 set arow [lindex $vrownum($curview) $ai]
6780 set ids [lindex $varccommits($curview,$a)]
6781 set arowend [expr {$arow + [llength $ids]}]
6782 }
6783 set id [lindex $ids [expr {$l - $arow}]]
Paul Mackerras687c8762007-09-22 12:49:33 +10006784 # shouldn't happen unless git log doesn't give all the commits...
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11006785 if {![info exists commitdata($id)] ||
6786 ![doesmatch $commitdata($id)]} {
6787 continue
6788 }
Paul Mackerras687c8762007-09-22 12:49:33 +10006789 if {![info exists commitinfo($id)]} {
6790 getcommit $id
6791 }
6792 set info $commitinfo($id)
6793 foreach f $info ty $fldtypes {
Frédéric Brière585c27c2010-03-14 18:59:09 -04006794 if {$ty eq ""} continue
Christian Stimmingb007ee22007-11-07 18:44:35 +01006795 if {($findloc eq [mc "All fields"] || $findloc eq $ty) &&
Paul Mackerras687c8762007-09-22 12:49:33 +10006796 [doesmatch $f]} {
6797 set found 1
6798 break
6799 }
6800 }
6801 if {$found} break
Paul Mackerras98f350e2005-05-15 05:56:51 +00006802 }
Paul Mackerras687c8762007-09-22 12:49:33 +10006803 } else {
Paul Mackerrascca5d942007-10-27 21:16:56 +10006804 for {} {$n > 0} {incr n -1; incr l $find_dirn} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11006805 if {$l < $arow || $l >= $arowend} {
6806 incr ai $find_dirn
6807 set a [lindex $varcorder($curview) $ai]
6808 set arow [lindex $vrownum($curview) $ai]
6809 set ids [lindex $varccommits($curview,$a)]
6810 set arowend [expr {$arow + [llength $ids]}]
6811 }
6812 set id [lindex $ids [expr {$l - $arow}]]
Paul Mackerras476ca632008-01-07 22:16:31 +11006813 if {![info exists fhighlights($id)]} {
6814 # this sets fhighlights($id) to -1
Paul Mackerras687c8762007-09-22 12:49:33 +10006815 askfilehighlight $l $id
Paul Mackerrascd2bcae2008-01-02 21:44:06 +11006816 }
Paul Mackerras476ca632008-01-07 22:16:31 +11006817 if {$fhighlights($id) > 0} {
Paul Mackerrascd2bcae2008-01-02 21:44:06 +11006818 set found $domore
6819 break
6820 }
Paul Mackerras476ca632008-01-07 22:16:31 +11006821 if {$fhighlights($id) < 0} {
Paul Mackerras687c8762007-09-22 12:49:33 +10006822 if {$domore} {
6823 set domore 0
Paul Mackerrascca5d942007-10-27 21:16:56 +10006824 set findcurline [expr {$l - $find_dirn}]
Paul Mackerras687c8762007-09-22 12:49:33 +10006825 }
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006826 }
6827 }
6828 }
Paul Mackerrascca5d942007-10-27 21:16:56 +10006829 if {$found || ($domore && !$moretodo)} {
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006830 unset findcurline
Paul Mackerras687c8762007-09-22 12:49:33 +10006831 unset find_dirn
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006832 notbusy finding
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10006833 set fprogcoord 0
6834 adjustprogress
6835 if {$found} {
6836 findselectline $l
6837 } else {
6838 bell
6839 }
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006840 return 0
6841 }
Paul Mackerras687c8762007-09-22 12:49:33 +10006842 if {!$domore} {
6843 flushhighlights
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10006844 } else {
Paul Mackerrascca5d942007-10-27 21:16:56 +10006845 set findcurline [expr {$l - $find_dirn}]
Paul Mackerras687c8762007-09-22 12:49:33 +10006846 }
Paul Mackerrascca5d942007-10-27 21:16:56 +10006847 set n [expr {($findcurline - $findstartline) * $find_dirn - 1}]
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10006848 if {$n < 0} {
6849 incr n $numcommits
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006850 }
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10006851 set fprogcoord [expr {$n * 1.0 / $numcommits}]
6852 adjustprogress
6853 return $domore
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00006854}
6855
6856proc findselectline {l} {
Paul Mackerras687c8762007-09-22 12:49:33 +10006857 global findloc commentend ctext findcurline markingmatches gdttype
Paul Mackerras005a2f42007-07-26 22:36:39 +10006858
Paul Mackerras8b39e042008-12-02 09:02:46 +11006859 set markingmatches [expr {$gdttype eq [mc "containing:"]}]
Paul Mackerras005a2f42007-07-26 22:36:39 +10006860 set findcurline $l
Paul Mackerrasd6982062005-08-06 22:06:06 +10006861 selectline $l 1
Paul Mackerras8b39e042008-12-02 09:02:46 +11006862 if {$markingmatches &&
6863 ($findloc eq [mc "All fields"] || $findloc eq [mc "Comments"])} {
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00006864 # highlight the matches in the comments
6865 set f [$ctext get 1.0 $commentend]
6866 set matches [findmatches $f]
6867 foreach match $matches {
6868 set start [lindex $match 0]
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08006869 set end [expr {[lindex $match 1] + 1}]
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00006870 $ctext tag add found "1.0 + $start c" "1.0 + $end c"
6871 }
Paul Mackerras98f350e2005-05-15 05:56:51 +00006872 }
Paul Mackerras005a2f42007-07-26 22:36:39 +10006873 drawvisible
Paul Mackerras98f350e2005-05-15 05:56:51 +00006874}
6875
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006876# mark the bits of a headline or author that match a find string
Paul Mackerras005a2f42007-07-26 22:36:39 +10006877proc markmatches {canv l str tag matches font row} {
6878 global selectedline
6879
Paul Mackerras98f350e2005-05-15 05:56:51 +00006880 set bbox [$canv bbox $tag]
6881 set x0 [lindex $bbox 0]
6882 set y0 [lindex $bbox 1]
6883 set y1 [lindex $bbox 3]
6884 foreach match $matches {
6885 set start [lindex $match 0]
6886 set end [lindex $match 1]
6887 if {$start > $end} continue
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08006888 set xoff [font measure $font [string range $str 0 [expr {$start-1}]]]
6889 set xlen [font measure $font [string range $str 0 [expr {$end}]]]
6890 set t [$canv create rect [expr {$x0+$xoff}] $y0 \
6891 [expr {$x0+$xlen+2}] $y1 \
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006892 -outline {} -tags [list match$l matches] -fill yellow]
Paul Mackerras98f350e2005-05-15 05:56:51 +00006893 $canv lower $t
Paul Mackerras94b4a692008-05-20 20:51:06 +10006894 if {$row == $selectedline} {
Paul Mackerras005a2f42007-07-26 22:36:39 +10006895 $canv raise $t secsel
6896 }
Paul Mackerras98f350e2005-05-15 05:56:51 +00006897 }
6898}
6899
6900proc unmarkmatches {} {
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10006901 global markingmatches
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006902
Paul Mackerras98f350e2005-05-15 05:56:51 +00006903 allcanvs delete matches
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006904 set markingmatches 0
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10006905 stopfinding
Paul Mackerras98f350e2005-05-15 05:56:51 +00006906}
6907
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10006908proc selcanvline {w x y} {
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10006909 global canv canvy0 ctext linespc
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006910 global rowtextx
Paul Mackerras1db95b02005-05-09 04:08:39 +00006911 set ymax [lindex [$canv cget -scrollregion] 3]
Paul Mackerrascfb45632005-05-31 12:14:42 +00006912 if {$ymax == {}} return
Paul Mackerras1db95b02005-05-09 04:08:39 +00006913 set yfrac [lindex [$canv yview] 0]
6914 set y [expr {$y + $yfrac * $ymax}]
6915 set l [expr {int(($y - $canvy0) / $linespc + 0.5)}]
6916 if {$l < 0} {
6917 set l 0
6918 }
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10006919 if {$w eq $canv} {
Paul Mackerrasfc2a2562007-12-26 23:03:43 +11006920 set xmax [lindex [$canv cget -scrollregion] 2]
6921 set xleft [expr {[lindex [$canv xview] 0] * $xmax}]
6922 if {![info exists rowtextx($l)] || $xleft + $x < $rowtextx($l)} return
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10006923 }
Paul Mackerras98f350e2005-05-15 05:56:51 +00006924 unmarkmatches
Paul Mackerrasd6982062005-08-06 22:06:06 +10006925 selectline $l 1
Paul Mackerras5ad588d2005-05-10 01:02:55 +00006926}
6927
Linus Torvaldsb1ba39e2005-08-08 20:04:20 -07006928proc commit_descriptor {p} {
6929 global commitinfo
Paul Mackerrasb0934482006-05-15 09:56:08 +10006930 if {![info exists commitinfo($p)]} {
6931 getcommit $p
6932 }
Linus Torvaldsb1ba39e2005-08-08 20:04:20 -07006933 set l "..."
Paul Mackerrasb0934482006-05-15 09:56:08 +10006934 if {[llength $commitinfo($p)] > 1} {
Linus Torvaldsb1ba39e2005-08-08 20:04:20 -07006935 set l [lindex $commitinfo($p) 0]
6936 }
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10006937 return "$p ($l)\n"
Linus Torvaldsb1ba39e2005-08-08 20:04:20 -07006938}
6939
Paul Mackerras106288c2005-08-19 23:11:39 +10006940# append some text to the ctext widget, and make any SHA1 ID
6941# that we know about be a clickable link.
Sergey Vlasovf1b86292006-05-15 19:13:14 +04006942proc appendwithlinks {text tags} {
Paul Mackerrasd375ef92008-10-21 10:18:12 +11006943 global ctext linknum curview
Paul Mackerras106288c2005-08-19 23:11:39 +10006944
6945 set start [$ctext index "end - 1c"]
Sergey Vlasovf1b86292006-05-15 19:13:14 +04006946 $ctext insert end $text $tags
Jim Meyering6c9e2d12011-12-10 16:08:57 +01006947 set links [regexp -indices -all -inline {(?:\m|-g)[0-9a-f]{6,40}\M} $text]
Paul Mackerras106288c2005-08-19 23:11:39 +10006948 foreach l $links {
6949 set s [lindex $l 0]
6950 set e [lindex $l 1]
6951 set linkid [string range $text $s $e]
Paul Mackerras106288c2005-08-19 23:11:39 +10006952 incr e
Paul Mackerrasc73adce2007-09-27 10:35:05 +10006953 $ctext tag delete link$linknum
Paul Mackerras106288c2005-08-19 23:11:39 +10006954 $ctext tag add link$linknum "$start + $s c" "$start + $e c"
Paul Mackerras97645682007-08-23 22:24:38 +10006955 setlink $linkid link$linknum
Paul Mackerras106288c2005-08-19 23:11:39 +10006956 incr linknum
6957 }
Paul Mackerras97645682007-08-23 22:24:38 +10006958}
6959
6960proc setlink {id lk} {
Paul Mackerrasd375ef92008-10-21 10:18:12 +11006961 global curview ctext pendinglinks
Gauthier Östervall252c52d2013-03-27 14:40:51 +01006962 global linkfgcolor
Paul Mackerras97645682007-08-23 22:24:38 +10006963
Jim Meyering6c9e2d12011-12-10 16:08:57 +01006964 if {[string range $id 0 1] eq "-g"} {
6965 set id [string range $id 2 end]
6966 }
6967
Paul Mackerrasd375ef92008-10-21 10:18:12 +11006968 set known 0
6969 if {[string length $id] < 40} {
6970 set matches [longid $id]
6971 if {[llength $matches] > 0} {
6972 if {[llength $matches] > 1} return
6973 set known 1
6974 set id [lindex $matches 0]
6975 }
6976 } else {
6977 set known [commitinview $id $curview]
6978 }
6979 if {$known} {
Gauthier Östervall252c52d2013-03-27 14:40:51 +01006980 $ctext tag conf $lk -foreground $linkfgcolor -underline 1
Paul Mackerrasd375ef92008-10-21 10:18:12 +11006981 $ctext tag bind $lk <1> [list selbyid $id]
Paul Mackerras97645682007-08-23 22:24:38 +10006982 $ctext tag bind $lk <Enter> {linkcursor %W 1}
6983 $ctext tag bind $lk <Leave> {linkcursor %W -1}
6984 } else {
6985 lappend pendinglinks($id) $lk
Paul Mackerrasd375ef92008-10-21 10:18:12 +11006986 interestedin $id {makelink %P}
Paul Mackerras97645682007-08-23 22:24:38 +10006987 }
6988}
6989
Paul Mackerras6f63fc12009-04-21 22:22:31 +10006990proc appendshortlink {id {pre {}} {post {}}} {
6991 global ctext linknum
6992
6993 $ctext insert end $pre
6994 $ctext tag delete link$linknum
6995 $ctext insert end [string range $id 0 7] link$linknum
6996 $ctext insert end $post
6997 setlink $id link$linknum
6998 incr linknum
6999}
7000
Paul Mackerras97645682007-08-23 22:24:38 +10007001proc makelink {id} {
7002 global pendinglinks
7003
7004 if {![info exists pendinglinks($id)]} return
7005 foreach lk $pendinglinks($id) {
7006 setlink $id $lk
7007 }
7008 unset pendinglinks($id)
7009}
7010
7011proc linkcursor {w inc} {
7012 global linkentercount curtextcursor
7013
7014 if {[incr linkentercount $inc] > 0} {
7015 $w configure -cursor hand2
7016 } else {
7017 $w configure -cursor $curtextcursor
7018 if {$linkentercount < 0} {
7019 set linkentercount 0
7020 }
7021 }
Paul Mackerras106288c2005-08-19 23:11:39 +10007022}
7023
Rutger Nijlunsing6e5f7202006-04-05 10:24:03 +10007024proc viewnextline {dir} {
7025 global canv linespc
7026
7027 $canv delete hover
7028 set ymax [lindex [$canv cget -scrollregion] 3]
7029 set wnow [$canv yview]
7030 set wtop [expr {[lindex $wnow 0] * $ymax}]
7031 set newtop [expr {$wtop + $dir * $linespc}]
7032 if {$newtop < 0} {
7033 set newtop 0
7034 } elseif {$newtop > $ymax} {
7035 set newtop $ymax
7036 }
7037 allcanvs yview moveto [expr {$newtop * 1.0 / $ymax}]
7038}
7039
Paul Mackerrasef030b82006-06-04 11:50:38 +10007040# add a list of tag or branch names at position pos
7041# returns the number of names inserted
Paul Mackerrase11f1232007-06-16 20:29:25 +10007042proc appendrefs {pos ids var} {
Max Kirillovbde4a0f2014-06-24 08:19:44 +03007043 global ctext linknum curview $var maxrefs visiblerefs mainheadid
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10007044
Paul Mackerrasef030b82006-06-04 11:50:38 +10007045 if {[catch {$ctext index $pos}]} {
7046 return 0
7047 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10007048 $ctext conf -state normal
7049 $ctext delete $pos "$pos lineend"
7050 set tags {}
7051 foreach id $ids {
7052 foreach tag [set $var\($id\)] {
7053 lappend tags [list $tag $id]
7054 }
7055 }
Paul Mackerras386befb2013-01-02 15:25:29 +11007056
7057 set sep {}
7058 set tags [lsort -index 0 -decreasing $tags]
7059 set nutags 0
7060
Paul Mackerras0a4dd8b2007-06-16 21:21:57 +10007061 if {[llength $tags] > $maxrefs} {
Paul Mackerras386befb2013-01-02 15:25:29 +11007062 # If we are displaying heads, and there are too many,
7063 # see if there are some important heads to display.
Max Kirillovbde4a0f2014-06-24 08:19:44 +03007064 # Currently that are the current head and heads listed in $visiblerefs option
Paul Mackerras386befb2013-01-02 15:25:29 +11007065 set itags {}
7066 if {$var eq "idheads"} {
7067 set utags {}
7068 foreach ti $tags {
7069 set hname [lindex $ti 0]
7070 set id [lindex $ti 1]
Max Kirillovbde4a0f2014-06-24 08:19:44 +03007071 if {([lsearch -exact $visiblerefs $hname] != -1 || $id eq $mainheadid) &&
Paul Mackerras386befb2013-01-02 15:25:29 +11007072 [llength $itags] < $maxrefs} {
7073 lappend itags $ti
7074 } else {
7075 lappend utags $ti
7076 }
7077 }
7078 set tags $utags
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10007079 }
Paul Mackerras386befb2013-01-02 15:25:29 +11007080 if {$itags ne {}} {
7081 set str [mc "and many more"]
7082 set sep " "
7083 } else {
7084 set str [mc "many"]
7085 }
7086 $ctext insert $pos "$str ([llength $tags])"
7087 set nutags [llength $tags]
7088 set tags $itags
7089 }
7090
7091 foreach ti $tags {
7092 set id [lindex $ti 1]
7093 set lk link$linknum
7094 incr linknum
7095 $ctext tag delete $lk
7096 $ctext insert $pos $sep
7097 $ctext insert $pos [lindex $ti 0] $lk
7098 setlink $id $lk
7099 set sep ", "
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10007100 }
Paul Mackerrasd34835c2013-01-01 23:08:12 +11007101 $ctext tag add wwrap "$pos linestart" "$pos lineend"
Paul Mackerrase11f1232007-06-16 20:29:25 +10007102 $ctext conf -state disabled
Paul Mackerras386befb2013-01-02 15:25:29 +11007103 return [expr {[llength $tags] + $nutags}]
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10007104}
7105
7106# called when we have finished computing the nearby tags
Paul Mackerrase11f1232007-06-16 20:29:25 +10007107proc dispneartags {delay} {
7108 global selectedline currentid showneartags tagphase
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10007109
Paul Mackerras94b4a692008-05-20 20:51:06 +10007110 if {$selectedline eq {} || !$showneartags} return
Paul Mackerrase11f1232007-06-16 20:29:25 +10007111 after cancel dispnexttag
7112 if {$delay} {
7113 after 200 dispnexttag
7114 set tagphase -1
7115 } else {
7116 after idle dispnexttag
7117 set tagphase 0
7118 }
7119}
7120
7121proc dispnexttag {} {
7122 global selectedline currentid showneartags tagphase ctext
7123
Paul Mackerras94b4a692008-05-20 20:51:06 +10007124 if {$selectedline eq {} || !$showneartags} return
Paul Mackerrase11f1232007-06-16 20:29:25 +10007125 switch -- $tagphase {
7126 0 {
7127 set dtags [desctags $currentid]
7128 if {$dtags ne {}} {
7129 appendrefs precedes $dtags idtags
7130 }
7131 }
7132 1 {
7133 set atags [anctags $currentid]
7134 if {$atags ne {}} {
7135 appendrefs follows $atags idtags
7136 }
7137 }
7138 2 {
7139 set dheads [descheads $currentid]
7140 if {$dheads ne {}} {
7141 if {[appendrefs branch $dheads idheads] > 1
7142 && [$ctext get "branch -3c"] eq "h"} {
7143 # turn "Branch" into "Branches"
7144 $ctext conf -state normal
7145 $ctext insert "branch -2c" "es"
7146 $ctext conf -state disabled
7147 }
7148 }
Paul Mackerrasef030b82006-06-04 11:50:38 +10007149 }
7150 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10007151 if {[incr tagphase] <= 2} {
7152 after idle dispnexttag
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10007153 }
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10007154}
7155
Paul Mackerras28593d32008-11-13 23:01:46 +11007156proc make_secsel {id} {
Paul Mackerras03800812007-08-29 21:45:21 +10007157 global linehtag linentag linedtag canv canv2 canv3
7158
Paul Mackerras28593d32008-11-13 23:01:46 +11007159 if {![info exists linehtag($id)]} return
Paul Mackerras03800812007-08-29 21:45:21 +10007160 $canv delete secsel
Paul Mackerras28593d32008-11-13 23:01:46 +11007161 set t [eval $canv create rect [$canv bbox $linehtag($id)] -outline {{}} \
Paul Mackerras03800812007-08-29 21:45:21 +10007162 -tags secsel -fill [$canv cget -selectbackground]]
7163 $canv lower $t
7164 $canv2 delete secsel
Paul Mackerras28593d32008-11-13 23:01:46 +11007165 set t [eval $canv2 create rect [$canv2 bbox $linentag($id)] -outline {{}} \
Paul Mackerras03800812007-08-29 21:45:21 +10007166 -tags secsel -fill [$canv2 cget -selectbackground]]
7167 $canv2 lower $t
7168 $canv3 delete secsel
Paul Mackerras28593d32008-11-13 23:01:46 +11007169 set t [eval $canv3 create rect [$canv3 bbox $linedtag($id)] -outline {{}} \
Paul Mackerras03800812007-08-29 21:45:21 +10007170 -tags secsel -fill [$canv3 cget -selectbackground]]
7171 $canv3 lower $t
7172}
7173
Paul Mackerrasb9fdba72009-04-09 09:34:46 +10007174proc make_idmark {id} {
7175 global linehtag canv fgcolor
7176
7177 if {![info exists linehtag($id)]} return
7178 $canv delete markid
7179 set t [eval $canv create rect [$canv bbox $linehtag($id)] \
7180 -tags markid -outline $fgcolor]
7181 $canv raise $t
7182}
7183
Max Kirillov4135d362014-04-05 23:38:50 +03007184proc selectline {l isnew {desired_loc {}} {switch_to_patch 0}} {
Paul Mackerras03800812007-08-29 21:45:21 +10007185 global canv ctext commitinfo selectedline
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11007186 global canvy0 linespc parents children curview
Paul Mackerras7fcceed2006-04-27 19:21:49 +10007187 global currentid sha1entry
Paul Mackerras9f1afe02006-02-19 22:44:47 +11007188 global commentend idtags linknum
Paul Mackerrasd94f8cd2006-04-06 10:18:23 +10007189 global mergemax numcommits pending_select
Paul Mackerrase11f1232007-06-16 20:29:25 +10007190 global cmitmode showneartags allcommits
Paul Mackerrasc30acc72008-03-07 22:51:55 +11007191 global targetrow targetid lastscrollrows
Paul Mackerras21ac8a82011-03-09 20:52:38 +11007192 global autoselect autosellen jump_to_here
Thomas Rast9403bd02013-11-16 18:37:43 +01007193 global vinlinediff
Paul Mackerrasd6982062005-08-06 22:06:06 +10007194
Paul Mackerrasd94f8cd2006-04-06 10:18:23 +10007195 catch {unset pending_select}
Paul Mackerras84ba7342005-06-17 00:12:26 +00007196 $canv delete hover
Paul Mackerras9843c302005-08-30 10:57:11 +10007197 normalline
Paul Mackerras887c9962007-08-20 19:36:20 +10007198 unsel_reflist
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10007199 stopfinding
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11007200 if {$l < 0 || $l >= $numcommits} return
Paul Mackerrasac1276a2008-03-03 10:11:08 +11007201 set id [commitonrow $l]
7202 set targetid $id
7203 set targetrow $l
Paul Mackerrasc30acc72008-03-07 22:51:55 +11007204 set selectedline $l
7205 set currentid $id
7206 if {$lastscrollrows < $numcommits} {
7207 setcanvscroll
7208 }
Paul Mackerrasac1276a2008-03-03 10:11:08 +11007209
Max Kirillov4135d362014-04-05 23:38:50 +03007210 if {$cmitmode ne "patch" && $switch_to_patch} {
7211 set cmitmode "patch"
7212 }
7213
Paul Mackerras5ad588d2005-05-10 01:02:55 +00007214 set y [expr {$canvy0 + $l * $linespc}]
Paul Mackerras17386062005-05-18 22:51:00 +00007215 set ymax [lindex [$canv cget -scrollregion] 3]
Paul Mackerras58422152005-05-19 10:56:42 +00007216 set ytop [expr {$y - $linespc - 1}]
7217 set ybot [expr {$y + $linespc + 1}]
Paul Mackerras5ad588d2005-05-10 01:02:55 +00007218 set wnow [$canv yview]
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08007219 set wtop [expr {[lindex $wnow 0] * $ymax}]
7220 set wbot [expr {[lindex $wnow 1] * $ymax}]
Paul Mackerras58422152005-05-19 10:56:42 +00007221 set wh [expr {$wbot - $wtop}]
7222 set newtop $wtop
Paul Mackerras17386062005-05-18 22:51:00 +00007223 if {$ytop < $wtop} {
Paul Mackerras58422152005-05-19 10:56:42 +00007224 if {$ybot < $wtop} {
7225 set newtop [expr {$y - $wh / 2.0}]
7226 } else {
7227 set newtop $ytop
7228 if {$newtop > $wtop - $linespc} {
7229 set newtop [expr {$wtop - $linespc}]
7230 }
Paul Mackerras17386062005-05-18 22:51:00 +00007231 }
Paul Mackerras58422152005-05-19 10:56:42 +00007232 } elseif {$ybot > $wbot} {
7233 if {$ytop > $wbot} {
7234 set newtop [expr {$y - $wh / 2.0}]
7235 } else {
7236 set newtop [expr {$ybot - $wh}]
7237 if {$newtop < $wtop + $linespc} {
7238 set newtop [expr {$wtop + $linespc}]
7239 }
Paul Mackerras17386062005-05-18 22:51:00 +00007240 }
Paul Mackerras58422152005-05-19 10:56:42 +00007241 }
7242 if {$newtop != $wtop} {
7243 if {$newtop < 0} {
7244 set newtop 0
7245 }
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08007246 allcanvs yview moveto [expr {$newtop * 1.0 / $ymax}]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11007247 drawvisible
Paul Mackerras5ad588d2005-05-10 01:02:55 +00007248 }
Paul Mackerrasd6982062005-08-06 22:06:06 +10007249
Paul Mackerras28593d32008-11-13 23:01:46 +11007250 make_secsel $id
Paul Mackerras9f1afe02006-02-19 22:44:47 +11007251
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10007252 if {$isnew} {
Paul Mackerras354af6b2008-11-23 13:14:23 +11007253 addtohistory [list selbyid $id 0] savecmitpos
Paul Mackerrasd6982062005-08-06 22:06:06 +10007254 }
7255
Paul Mackerras98f350e2005-05-15 05:56:51 +00007256 $sha1entry delete 0 end
7257 $sha1entry insert 0 $id
Jeff King95293b52008-03-06 06:49:25 -05007258 if {$autoselect} {
Paul Mackerras21ac8a82011-03-09 20:52:38 +11007259 $sha1entry selection range 0 $autosellen
Jeff King95293b52008-03-06 06:49:25 -05007260 }
Paul Mackerras164ff272006-05-29 19:50:02 +10007261 rhighlight_sel $id
Paul Mackerras98f350e2005-05-15 05:56:51 +00007262
Paul Mackerras5ad588d2005-05-10 01:02:55 +00007263 $ctext conf -state normal
Paul Mackerras3ea06f92006-05-24 10:16:03 +10007264 clear_ctext
Paul Mackerras106288c2005-08-19 23:11:39 +10007265 set linknum 0
Paul Mackerrasd76afb12008-03-07 21:19:18 +11007266 if {![info exists commitinfo($id)]} {
7267 getcommit $id
7268 }
Paul Mackerras1db95b02005-05-09 04:08:39 +00007269 set info $commitinfo($id)
Paul Mackerras232475d2005-11-15 10:34:03 +11007270 set date [formatdate [lindex $info 2]]
Christian Stimmingd990ced2007-11-07 18:42:55 +01007271 $ctext insert end "[mc "Author"]: [lindex $info 1] $date\n"
Paul Mackerras232475d2005-11-15 10:34:03 +11007272 set date [formatdate [lindex $info 4]]
Christian Stimmingd990ced2007-11-07 18:42:55 +01007273 $ctext insert end "[mc "Committer"]: [lindex $info 3] $date\n"
Paul Mackerras887fe3c2005-05-21 07:35:37 +00007274 if {[info exists idtags($id)]} {
Christian Stimmingd990ced2007-11-07 18:42:55 +01007275 $ctext insert end [mc "Tags:"]
Paul Mackerras887fe3c2005-05-21 07:35:37 +00007276 foreach tag $idtags($id) {
7277 $ctext insert end " $tag"
7278 }
7279 $ctext insert end "\n"
7280 }
Mark Levedahl40b87ff2007-02-01 08:44:46 -05007281
Sergey Vlasovf1b86292006-05-15 19:13:14 +04007282 set headers {}
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11007283 set olds $parents($curview,$id)
Paul Mackerras79b2c752006-04-02 20:47:40 +10007284 if {[llength $olds] > 1} {
Paul Mackerrasb77b0272006-02-07 09:13:52 +11007285 set np 0
Paul Mackerras79b2c752006-04-02 20:47:40 +10007286 foreach p $olds {
Paul Mackerrasb77b0272006-02-07 09:13:52 +11007287 if {$np >= $mergemax} {
7288 set tag mmax
7289 } else {
7290 set tag m$np
7291 }
Christian Stimmingd990ced2007-11-07 18:42:55 +01007292 $ctext insert end "[mc "Parent"]: " $tag
Sergey Vlasovf1b86292006-05-15 19:13:14 +04007293 appendwithlinks [commit_descriptor $p] {}
Paul Mackerrasb77b0272006-02-07 09:13:52 +11007294 incr np
7295 }
7296 } else {
Paul Mackerras79b2c752006-04-02 20:47:40 +10007297 foreach p $olds {
Christian Stimmingd990ced2007-11-07 18:42:55 +01007298 append headers "[mc "Parent"]: [commit_descriptor $p]"
Linus Torvalds8b192802005-08-07 13:58:56 -07007299 }
Linus Torvaldsb1ba39e2005-08-08 20:04:20 -07007300 }
Paul Mackerrasb77b0272006-02-07 09:13:52 +11007301
Paul Mackerras6a90bff2007-06-18 09:48:23 +10007302 foreach c $children($curview,$id) {
Christian Stimmingd990ced2007-11-07 18:42:55 +01007303 append headers "[mc "Child"]: [commit_descriptor $c]"
Linus Torvalds8b192802005-08-07 13:58:56 -07007304 }
Paul Mackerrasd6982062005-08-06 22:06:06 +10007305
7306 # make anything that looks like a SHA1 ID be a clickable link
Sergey Vlasovf1b86292006-05-15 19:13:14 +04007307 appendwithlinks $headers {}
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10007308 if {$showneartags} {
7309 if {![info exists allcommits]} {
7310 getallcommits
7311 }
Christian Stimmingd990ced2007-11-07 18:42:55 +01007312 $ctext insert end "[mc "Branch"]: "
Paul Mackerrasef030b82006-06-04 11:50:38 +10007313 $ctext mark set branch "end -1c"
7314 $ctext mark gravity branch left
Christian Stimmingd990ced2007-11-07 18:42:55 +01007315 $ctext insert end "\n[mc "Follows"]: "
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10007316 $ctext mark set follows "end -1c"
7317 $ctext mark gravity follows left
Christian Stimmingd990ced2007-11-07 18:42:55 +01007318 $ctext insert end "\n[mc "Precedes"]: "
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10007319 $ctext mark set precedes "end -1c"
7320 $ctext mark gravity precedes left
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10007321 $ctext insert end "\n"
Paul Mackerrase11f1232007-06-16 20:29:25 +10007322 dispneartags 1
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10007323 }
7324 $ctext insert end "\n"
Paul Mackerras43c25072006-09-27 10:56:02 +10007325 set comment [lindex $info 5]
7326 if {[string first "\r" $comment] >= 0} {
7327 set comment [string map {"\r" "\n "} $comment]
7328 }
7329 appendwithlinks $comment {comment}
Paul Mackerrasd6982062005-08-06 22:06:06 +10007330
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00007331 $ctext tag remove found 1.0 end
Paul Mackerras5ad588d2005-05-10 01:02:55 +00007332 $ctext conf -state disabled
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00007333 set commentend [$ctext index "end - 1c"]
Paul Mackerras5ad588d2005-05-10 01:02:55 +00007334
Paul Mackerras8a897742008-10-27 21:36:25 +11007335 set jump_to_here $desired_loc
Christian Stimmingb007ee22007-11-07 18:44:35 +01007336 init_flist [mc "Comments"]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007337 if {$cmitmode eq "tree"} {
7338 gettree $id
Thomas Rast9403bd02013-11-16 18:37:43 +01007339 } elseif {$vinlinediff($curview) == 1} {
7340 showinlinediff $id
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007341 } elseif {[llength $olds] <= 1} {
Paul Mackerrasd3272442005-11-28 20:41:56 +11007342 startdiff $id
Paul Mackerras7b5ff7e2006-03-30 20:50:40 +11007343 } else {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11007344 mergediff $id
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10007345 }
7346}
7347
Rutger Nijlunsing6e5f7202006-04-05 10:24:03 +10007348proc selfirstline {} {
7349 unmarkmatches
7350 selectline 0 1
7351}
7352
7353proc sellastline {} {
7354 global numcommits
7355 unmarkmatches
7356 set l [expr {$numcommits - 1}]
7357 selectline $l 1
7358}
7359
Paul Mackerrase5c2d852005-05-11 23:44:54 +00007360proc selnextline {dir} {
7361 global selectedline
Mark Levedahlbd441de2007-08-07 21:40:34 -04007362 focus .
Paul Mackerras94b4a692008-05-20 20:51:06 +10007363 if {$selectedline eq {}} return
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08007364 set l [expr {$selectedline + $dir}]
Paul Mackerras98f350e2005-05-15 05:56:51 +00007365 unmarkmatches
Paul Mackerrasd6982062005-08-06 22:06:06 +10007366 selectline $l 1
7367}
7368
Rutger Nijlunsing6e5f7202006-04-05 10:24:03 +10007369proc selnextpage {dir} {
7370 global canv linespc selectedline numcommits
7371
7372 set lpp [expr {([winfo height $canv] - 2) / $linespc}]
7373 if {$lpp < 1} {
7374 set lpp 1
7375 }
7376 allcanvs yview scroll [expr {$dir * $lpp}] units
Paul Mackerrase72ee5e2006-05-20 09:58:49 +10007377 drawvisible
Paul Mackerras94b4a692008-05-20 20:51:06 +10007378 if {$selectedline eq {}} return
Rutger Nijlunsing6e5f7202006-04-05 10:24:03 +10007379 set l [expr {$selectedline + $dir * $lpp}]
7380 if {$l < 0} {
7381 set l 0
7382 } elseif {$l >= $numcommits} {
7383 set l [expr $numcommits - 1]
7384 }
7385 unmarkmatches
Mark Levedahl40b87ff2007-02-01 08:44:46 -05007386 selectline $l 1
Rutger Nijlunsing6e5f7202006-04-05 10:24:03 +10007387}
7388
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10007389proc unselectline {} {
Paul Mackerras50b44ec2006-04-04 10:16:22 +10007390 global selectedline currentid
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10007391
Paul Mackerras94b4a692008-05-20 20:51:06 +10007392 set selectedline {}
Paul Mackerras50b44ec2006-04-04 10:16:22 +10007393 catch {unset currentid}
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10007394 allcanvs delete secsel
Paul Mackerras164ff272006-05-29 19:50:02 +10007395 rhighlight_none
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10007396}
7397
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007398proc reselectline {} {
7399 global selectedline
7400
Paul Mackerras94b4a692008-05-20 20:51:06 +10007401 if {$selectedline ne {}} {
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007402 selectline $selectedline 0
7403 }
7404}
7405
Paul Mackerras354af6b2008-11-23 13:14:23 +11007406proc addtohistory {cmd {saveproc {}}} {
Paul Mackerras2516dae2006-04-21 10:35:31 +10007407 global history historyindex curview
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10007408
Paul Mackerras354af6b2008-11-23 13:14:23 +11007409 unset_posvars
7410 save_position
7411 set elt [list $curview $cmd $saveproc {}]
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10007412 if {$historyindex > 0
Paul Mackerras2516dae2006-04-21 10:35:31 +10007413 && [lindex $history [expr {$historyindex - 1}]] == $elt} {
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10007414 return
7415 }
7416
7417 if {$historyindex < [llength $history]} {
Paul Mackerras2516dae2006-04-21 10:35:31 +10007418 set history [lreplace $history $historyindex end $elt]
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10007419 } else {
Paul Mackerras2516dae2006-04-21 10:35:31 +10007420 lappend history $elt
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10007421 }
7422 incr historyindex
7423 if {$historyindex > 1} {
Junio C Hamanoe9937d22007-02-01 08:46:38 -05007424 .tf.bar.leftbut conf -state normal
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10007425 } else {
Junio C Hamanoe9937d22007-02-01 08:46:38 -05007426 .tf.bar.leftbut conf -state disabled
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10007427 }
Junio C Hamanoe9937d22007-02-01 08:46:38 -05007428 .tf.bar.rightbut conf -state disabled
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10007429}
7430
Paul Mackerras354af6b2008-11-23 13:14:23 +11007431# save the scrolling position of the diff display pane
7432proc save_position {} {
7433 global historyindex history
7434
7435 if {$historyindex < 1} return
7436 set hi [expr {$historyindex - 1}]
7437 set fn [lindex $history $hi 2]
7438 if {$fn ne {}} {
7439 lset history $hi 3 [eval $fn]
7440 }
7441}
7442
7443proc unset_posvars {} {
7444 global last_posvars
7445
7446 if {[info exists last_posvars]} {
7447 foreach {var val} $last_posvars {
7448 global $var
7449 catch {unset $var}
7450 }
7451 unset last_posvars
7452 }
7453}
7454
Paul Mackerras2516dae2006-04-21 10:35:31 +10007455proc godo {elt} {
Paul Mackerras354af6b2008-11-23 13:14:23 +11007456 global curview last_posvars
Paul Mackerras2516dae2006-04-21 10:35:31 +10007457
7458 set view [lindex $elt 0]
7459 set cmd [lindex $elt 1]
Paul Mackerras354af6b2008-11-23 13:14:23 +11007460 set pv [lindex $elt 3]
Paul Mackerras2516dae2006-04-21 10:35:31 +10007461 if {$curview != $view} {
7462 showview $view
7463 }
Paul Mackerras354af6b2008-11-23 13:14:23 +11007464 unset_posvars
7465 foreach {var val} $pv {
7466 global $var
7467 set $var $val
7468 }
7469 set last_posvars $pv
Paul Mackerras2516dae2006-04-21 10:35:31 +10007470 eval $cmd
7471}
7472
Paul Mackerrasd6982062005-08-06 22:06:06 +10007473proc goback {} {
7474 global history historyindex
Mark Levedahlbd441de2007-08-07 21:40:34 -04007475 focus .
Paul Mackerrasd6982062005-08-06 22:06:06 +10007476
7477 if {$historyindex > 1} {
Paul Mackerras354af6b2008-11-23 13:14:23 +11007478 save_position
Paul Mackerrasd6982062005-08-06 22:06:06 +10007479 incr historyindex -1
Paul Mackerras2516dae2006-04-21 10:35:31 +10007480 godo [lindex $history [expr {$historyindex - 1}]]
Junio C Hamanoe9937d22007-02-01 08:46:38 -05007481 .tf.bar.rightbut conf -state normal
Paul Mackerrasd6982062005-08-06 22:06:06 +10007482 }
7483 if {$historyindex <= 1} {
Junio C Hamanoe9937d22007-02-01 08:46:38 -05007484 .tf.bar.leftbut conf -state disabled
Paul Mackerrasd6982062005-08-06 22:06:06 +10007485 }
7486}
7487
7488proc goforw {} {
7489 global history historyindex
Mark Levedahlbd441de2007-08-07 21:40:34 -04007490 focus .
Paul Mackerrasd6982062005-08-06 22:06:06 +10007491
7492 if {$historyindex < [llength $history]} {
Paul Mackerras354af6b2008-11-23 13:14:23 +11007493 save_position
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10007494 set cmd [lindex $history $historyindex]
Paul Mackerrasd6982062005-08-06 22:06:06 +10007495 incr historyindex
Paul Mackerras2516dae2006-04-21 10:35:31 +10007496 godo $cmd
Junio C Hamanoe9937d22007-02-01 08:46:38 -05007497 .tf.bar.leftbut conf -state normal
Paul Mackerrasd6982062005-08-06 22:06:06 +10007498 }
7499 if {$historyindex >= [llength $history]} {
Junio C Hamanoe9937d22007-02-01 08:46:38 -05007500 .tf.bar.rightbut conf -state disabled
Paul Mackerrasd6982062005-08-06 22:06:06 +10007501 }
Paul Mackerras5ad588d2005-05-10 01:02:55 +00007502}
7503
Max Kirillovd4ec30b2014-07-08 23:45:35 +03007504proc go_to_parent {i} {
7505 global parents curview targetid
7506 set ps $parents($curview,$targetid)
7507 if {[llength $ps] >= $i} {
7508 selbyid [lindex $ps [expr $i - 1]]
7509 }
7510}
7511
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007512proc gettree {id} {
Paul Mackerras8f489362007-07-13 19:49:37 +10007513 global treefilelist treeidlist diffids diffmergeid treepending
7514 global nullid nullid2
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007515
7516 set diffids $id
7517 catch {unset diffmergeid}
7518 if {![info exists treefilelist($id)]} {
7519 if {![info exists treepending]} {
Paul Mackerras8f489362007-07-13 19:49:37 +10007520 if {$id eq $nullid} {
7521 set cmd [list | git ls-files]
7522 } elseif {$id eq $nullid2} {
7523 set cmd [list | git ls-files --stage -t]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007524 } else {
Paul Mackerras8f489362007-07-13 19:49:37 +10007525 set cmd [list | git ls-tree -r $id]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007526 }
7527 if {[catch {set gtf [open $cmd r]}]} {
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007528 return
7529 }
7530 set treepending $id
7531 set treefilelist($id) {}
7532 set treeidlist($id) {}
Alexander Gavrilov09c70292008-10-13 12:12:31 +04007533 fconfigure $gtf -blocking 0 -encoding binary
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007534 filerun $gtf [list gettreeline $gtf $id]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007535 }
7536 } else {
7537 setfilelist $id
7538 }
7539}
7540
7541proc gettreeline {gtf id} {
Paul Mackerras8f489362007-07-13 19:49:37 +10007542 global treefilelist treeidlist treepending cmitmode diffids nullid nullid2
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007543
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007544 set nl 0
7545 while {[incr nl] <= 1000 && [gets $gtf line] >= 0} {
Paul Mackerras8f489362007-07-13 19:49:37 +10007546 if {$diffids eq $nullid} {
7547 set fname $line
7548 } else {
Paul Mackerras9396cd32007-06-23 20:28:15 +10007549 set i [string first "\t" $line]
7550 if {$i < 0} continue
Paul Mackerras9396cd32007-06-23 20:28:15 +10007551 set fname [string range $line [expr {$i+1}] end]
Paul Mackerrasf31fa2c2008-04-28 09:40:50 +10007552 set line [string range $line 0 [expr {$i-1}]]
7553 if {$diffids ne $nullid2 && [lindex $line 1] ne "blob"} continue
7554 set sha1 [lindex $line 2]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007555 lappend treeidlist($id) $sha1
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007556 }
Alexander Gavrilov09c70292008-10-13 12:12:31 +04007557 if {[string index $fname 0] eq "\""} {
7558 set fname [lindex $fname 0]
7559 }
7560 set fname [encoding convertfrom $fname]
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007561 lappend treefilelist($id) $fname
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007562 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007563 if {![eof $gtf]} {
7564 return [expr {$nl >= 1000? 2: 1}]
7565 }
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007566 close $gtf
7567 unset treepending
7568 if {$cmitmode ne "tree"} {
7569 if {![info exists diffmergeid]} {
7570 gettreediffs $diffids
7571 }
7572 } elseif {$id ne $diffids} {
7573 gettree $diffids
7574 } else {
7575 setfilelist $id
7576 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007577 return 0
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007578}
7579
7580proc showfile {f} {
Paul Mackerras8f489362007-07-13 19:49:37 +10007581 global treefilelist treeidlist diffids nullid nullid2
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04007582 global ctext_file_names ctext_file_lines
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007583 global ctext commentend
7584
7585 set i [lsearch -exact $treefilelist($diffids) $f]
7586 if {$i < 0} {
7587 puts "oops, $f not in list for id $diffids"
7588 return
7589 }
Paul Mackerras8f489362007-07-13 19:49:37 +10007590 if {$diffids eq $nullid} {
7591 if {[catch {set bf [open $f r]} err]} {
7592 puts "oops, can't read $f: $err"
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007593 return
7594 }
7595 } else {
Paul Mackerras8f489362007-07-13 19:49:37 +10007596 set blob [lindex $treeidlist($diffids) $i]
7597 if {[catch {set bf [open [concat | git cat-file blob $blob] r]} err]} {
7598 puts "oops, error reading blob $blob: $err"
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007599 return
7600 }
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007601 }
Alexander Gavrilov09c70292008-10-13 12:12:31 +04007602 fconfigure $bf -blocking 0 -encoding [get_path_encoding $f]
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007603 filerun $bf [list getblobline $bf $diffids]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007604 $ctext config -state normal
Paul Mackerras3ea06f92006-05-24 10:16:03 +10007605 clear_ctext $commentend
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04007606 lappend ctext_file_names $f
7607 lappend ctext_file_lines [lindex [split $commentend "."] 0]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007608 $ctext insert end "\n"
7609 $ctext insert end "$f\n" filesep
7610 $ctext config -state disabled
7611 $ctext yview $commentend
Paul Mackerras32f1b3e2007-09-28 21:27:39 +10007612 settabs 0
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007613}
7614
7615proc getblobline {bf id} {
7616 global diffids cmitmode ctext
7617
7618 if {$id ne $diffids || $cmitmode ne "tree"} {
7619 catch {close $bf}
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007620 return 0
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007621 }
7622 $ctext config -state normal
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007623 set nl 0
7624 while {[incr nl] <= 1000 && [gets $bf line] >= 0} {
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007625 $ctext insert end "$line\n"
7626 }
7627 if {[eof $bf]} {
Paul Mackerras8a897742008-10-27 21:36:25 +11007628 global jump_to_here ctext_file_names commentend
7629
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007630 # delete last newline
7631 $ctext delete "end - 2c" "end - 1c"
7632 close $bf
Paul Mackerras8a897742008-10-27 21:36:25 +11007633 if {$jump_to_here ne {} &&
7634 [lindex $jump_to_here 0] eq [lindex $ctext_file_names 0]} {
7635 set lnum [expr {[lindex $jump_to_here 1] +
7636 [lindex [split $commentend .] 0]}]
7637 mark_ctext_line $lnum
7638 }
Stefan Haller120ea892010-11-14 13:21:50 +01007639 $ctext config -state disabled
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007640 return 0
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007641 }
7642 $ctext config -state disabled
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007643 return [expr {$nl >= 1000? 2: 1}]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007644}
7645
Paul Mackerras8a897742008-10-27 21:36:25 +11007646proc mark_ctext_line {lnum} {
Paul Mackerrase3e901b2008-10-27 22:37:21 +11007647 global ctext markbgcolor
Paul Mackerras8a897742008-10-27 21:36:25 +11007648
7649 $ctext tag delete omark
7650 $ctext tag add omark $lnum.0 "$lnum.0 + 1 line"
Paul Mackerrase3e901b2008-10-27 22:37:21 +11007651 $ctext tag conf omark -background $markbgcolor
Paul Mackerras8a897742008-10-27 21:36:25 +11007652 $ctext see $lnum.0
7653}
7654
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11007655proc mergediff {id} {
Paul Mackerras8b07dca2008-11-02 22:34:47 +11007656 global diffmergeid
Alexander Gavrilov2df64422008-10-08 11:05:37 +04007657 global diffids treediffs
Paul Mackerras8b07dca2008-11-02 22:34:47 +11007658 global parents curview
Paul Mackerrase2ed4322005-07-17 03:39:44 -04007659
Paul Mackerras3c461ff2005-07-20 09:13:46 -04007660 set diffmergeid $id
Paul Mackerras7a1d9d12006-03-22 10:21:45 +11007661 set diffids $id
Alexander Gavrilov2df64422008-10-08 11:05:37 +04007662 set treediffs($id) {}
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11007663 set np [llength $parents($curview,$id)]
Paul Mackerras32f1b3e2007-09-28 21:27:39 +10007664 settabs $np
Paul Mackerras8b07dca2008-11-02 22:34:47 +11007665 getblobdiffs $id
Paul Mackerrasc8a4acb2005-07-29 09:23:03 -05007666}
7667
Paul Mackerras3c461ff2005-07-20 09:13:46 -04007668proc startdiff {ids} {
Paul Mackerras8f489362007-07-13 19:49:37 +10007669 global treediffs diffids treepending diffmergeid nullid nullid2
Paul Mackerras3c461ff2005-07-20 09:13:46 -04007670
Paul Mackerras32f1b3e2007-09-28 21:27:39 +10007671 settabs 1
Paul Mackerras3c461ff2005-07-20 09:13:46 -04007672 set diffids $ids
7673 catch {unset diffmergeid}
Paul Mackerras8f489362007-07-13 19:49:37 +10007674 if {![info exists treediffs($ids)] ||
7675 [lsearch -exact $ids $nullid] >= 0 ||
7676 [lsearch -exact $ids $nullid2] >= 0} {
Paul Mackerras3c461ff2005-07-20 09:13:46 -04007677 if {![info exists treepending]} {
7678 gettreediffs $ids
7679 }
7680 } else {
7681 addtocflist $ids
7682 }
7683}
7684
Thomas Rast9403bd02013-11-16 18:37:43 +01007685proc showinlinediff {ids} {
7686 global commitinfo commitdata ctext
7687 global treediffs
7688
7689 set info $commitinfo($ids)
7690 set diff [lindex $info 7]
7691 set difflines [split $diff "\n"]
7692
7693 initblobdiffvars
7694 set treediff {}
7695
7696 set inhdr 0
7697 foreach line $difflines {
7698 if {![string compare -length 5 "diff " $line]} {
7699 set inhdr 1
7700 } elseif {$inhdr && ![string compare -length 4 "+++ " $line]} {
7701 # offset also accounts for the b/ prefix
7702 lappend treediff [string range $line 6 end]
7703 set inhdr 0
7704 }
7705 }
7706
7707 set treediffs($ids) $treediff
7708 add_flist $treediff
7709
7710 $ctext conf -state normal
7711 foreach line $difflines {
7712 parseblobdiffline $ids $line
7713 }
7714 maybe_scroll_ctext 1
7715 $ctext conf -state disabled
7716}
7717
Pat Thoyts65bb0bd2011-12-13 16:50:50 +00007718# If the filename (name) is under any of the passed filter paths
7719# then return true to include the file in the listing.
Paul Mackerras7a39a172007-10-23 10:15:11 +10007720proc path_filter {filter name} {
Pat Thoyts65bb0bd2011-12-13 16:50:50 +00007721 set worktree [gitworktree]
Paul Mackerras7a39a172007-10-23 10:15:11 +10007722 foreach p $filter {
Pat Thoyts65bb0bd2011-12-13 16:50:50 +00007723 set fq_p [file normalize $p]
7724 set fq_n [file normalize [file join $worktree $name]]
7725 if {[string match [file normalize $fq_p]* $fq_n]} {
7726 return 1
Paul Mackerras7a39a172007-10-23 10:15:11 +10007727 }
7728 }
7729 return 0
7730}
7731
Paul Mackerras3c461ff2005-07-20 09:13:46 -04007732proc addtocflist {ids} {
Paul Mackerras74a40c72007-10-24 10:16:56 +10007733 global treediffs
Paul Mackerras7a39a172007-10-23 10:15:11 +10007734
Paul Mackerras74a40c72007-10-24 10:16:56 +10007735 add_flist $treediffs($ids)
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10007736 getblobdiffs $ids
Paul Mackerrasd2610d12005-05-11 00:45:38 +00007737}
7738
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007739proc diffcmd {ids flags} {
Jens Lehmann17f98362014-04-08 21:36:08 +02007740 global log_showroot nullid nullid2 git_version
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007741
7742 set i [lsearch -exact $ids $nullid]
Paul Mackerras8f489362007-07-13 19:49:37 +10007743 set j [lsearch -exact $ids $nullid2]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007744 if {$i >= 0} {
Paul Mackerras8f489362007-07-13 19:49:37 +10007745 if {[llength $ids] > 1 && $j < 0} {
7746 # comparing working directory with some specific revision
7747 set cmd [concat | git diff-index $flags]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007748 if {$i == 0} {
7749 lappend cmd -R [lindex $ids 1]
7750 } else {
7751 lappend cmd [lindex $ids 0]
7752 }
7753 } else {
Paul Mackerras8f489362007-07-13 19:49:37 +10007754 # comparing working directory with index
7755 set cmd [concat | git diff-files $flags]
7756 if {$j == 1} {
7757 lappend cmd -R
7758 }
7759 }
7760 } elseif {$j >= 0} {
Jens Lehmann17f98362014-04-08 21:36:08 +02007761 if {[package vcompare $git_version "1.7.2"] >= 0} {
7762 set flags "$flags --ignore-submodules=dirty"
7763 }
Paul Mackerras8f489362007-07-13 19:49:37 +10007764 set cmd [concat | git diff-index --cached $flags]
7765 if {[llength $ids] > 1} {
7766 # comparing index with specific revision
Jens Lehmann90a77922009-10-27 18:13:42 +01007767 if {$j == 0} {
Paul Mackerras8f489362007-07-13 19:49:37 +10007768 lappend cmd -R [lindex $ids 1]
7769 } else {
7770 lappend cmd [lindex $ids 0]
7771 }
7772 } else {
7773 # comparing index with HEAD
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007774 lappend cmd HEAD
7775 }
7776 } else {
Marcus Karlssonb2b76d12011-10-04 22:08:13 +02007777 if {$log_showroot} {
7778 lappend flags --root
7779 }
Paul Mackerras8f489362007-07-13 19:49:37 +10007780 set cmd [concat | git diff-tree -r $flags $ids]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007781 }
7782 return $cmd
7783}
7784
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10007785proc gettreediffs {ids} {
Felipe Contreras2c8cd902013-04-27 17:01:39 -05007786 global treediff treepending limitdiffs vfilelimit curview
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007787
Felipe Contreras2c8cd902013-04-27 17:01:39 -05007788 set cmd [diffcmd $ids {--no-commit-id}]
7789 if {$limitdiffs && $vfilelimit($curview) ne {}} {
7790 set cmd [concat $cmd -- $vfilelimit($curview)]
7791 }
7792 if {[catch {set gdtf [open $cmd r]}]} return
Alexander Gavrilov72721312008-07-26 18:48:41 +04007793
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10007794 set treepending $ids
Paul Mackerras3c461ff2005-07-20 09:13:46 -04007795 set treediff {}
Alexander Gavrilov09c70292008-10-13 12:12:31 +04007796 fconfigure $gdtf -blocking 0 -encoding binary
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007797 filerun $gdtf [list gettreediffline $gdtf $ids]
Paul Mackerrasd2610d12005-05-11 00:45:38 +00007798}
7799
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10007800proc gettreediffline {gdtf ids} {
Paul Mackerras3c461ff2005-07-20 09:13:46 -04007801 global treediff treediffs treepending diffids diffmergeid
Paul Mackerras39ee47e2008-10-15 22:23:03 +11007802 global cmitmode vfilelimit curview limitdiffs perfile_attrs
Paul Mackerras3c461ff2005-07-20 09:13:46 -04007803
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007804 set nr 0
Alexander Gavrilov4db09302008-10-13 12:12:33 +04007805 set sublist {}
Paul Mackerras39ee47e2008-10-15 22:23:03 +11007806 set max 1000
7807 if {$perfile_attrs} {
7808 # cache_gitattr is slow, and even slower on win32 where we
7809 # have to invoke it for only about 30 paths at a time
7810 set max 500
7811 if {[tk windowingsystem] == "win32"} {
7812 set max 120
7813 }
7814 }
7815 while {[incr nr] <= $max && [gets $gdtf line] >= 0} {
Paul Mackerras9396cd32007-06-23 20:28:15 +10007816 set i [string first "\t" $line]
7817 if {$i >= 0} {
7818 set file [string range $line [expr {$i+1}] end]
7819 if {[string index $file 0] eq "\""} {
7820 set file [lindex $file 0]
7821 }
Alexander Gavrilov09c70292008-10-13 12:12:31 +04007822 set file [encoding convertfrom $file]
Paul Mackerras48a81b72008-11-04 21:09:00 +11007823 if {$file ne [lindex $treediff end]} {
7824 lappend treediff $file
7825 lappend sublist $file
7826 }
Paul Mackerras9396cd32007-06-23 20:28:15 +10007827 }
Paul Mackerrasd2610d12005-05-11 00:45:38 +00007828 }
Paul Mackerras39ee47e2008-10-15 22:23:03 +11007829 if {$perfile_attrs} {
7830 cache_gitattr encoding $sublist
7831 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007832 if {![eof $gdtf]} {
Paul Mackerras39ee47e2008-10-15 22:23:03 +11007833 return [expr {$nr >= $max? 2: 1}]
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007834 }
7835 close $gdtf
Felipe Contreras2c8cd902013-04-27 17:01:39 -05007836 set treediffs($ids) $treediff
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007837 unset treepending
Paul Mackerrase1160132008-11-18 21:40:32 +11007838 if {$cmitmode eq "tree" && [llength $diffids] == 1} {
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007839 gettree $diffids
7840 } elseif {$ids != $diffids} {
7841 if {![info exists diffmergeid]} {
7842 gettreediffs $diffids
7843 }
7844 } else {
7845 addtocflist $ids
7846 }
7847 return 0
Paul Mackerrasd2610d12005-05-11 00:45:38 +00007848}
7849
Steffen Prohaska890fae72007-08-12 12:05:46 +02007850# empty string or positive integer
7851proc diffcontextvalidate {v} {
7852 return [regexp {^(|[1-9][0-9]*)$} $v]
7853}
7854
7855proc diffcontextchange {n1 n2 op} {
7856 global diffcontextstring diffcontext
7857
7858 if {[string is integer -strict $diffcontextstring]} {
Markus Heidelberga41ddbb2009-05-23 19:31:37 +02007859 if {$diffcontextstring >= 0} {
Steffen Prohaska890fae72007-08-12 12:05:46 +02007860 set diffcontext $diffcontextstring
7861 reselectline
7862 }
7863 }
7864}
7865
Steffen Prohaskab9b86002008-01-17 23:42:55 +01007866proc changeignorespace {} {
7867 reselectline
7868}
7869
Thomas Rastae4e3ff2010-10-16 12:15:10 +02007870proc changeworddiff {name ix op} {
7871 reselectline
7872}
7873
Thomas Rast5de460a2013-11-16 18:37:41 +01007874proc initblobdiffvars {} {
7875 global diffencoding targetline diffnparents
7876 global diffinhdr currdiffsubmod diffseehere
7877 set targetline {}
7878 set diffnparents 0
7879 set diffinhdr 0
7880 set diffencoding [get_path_encoding {}]
7881 set currdiffsubmod ""
7882 set diffseehere -1
7883}
7884
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10007885proc getblobdiffs {ids} {
Paul Mackerras8d73b242007-10-06 20:22:00 +10007886 global blobdifffd diffids env
Thomas Rast5de460a2013-11-16 18:37:41 +01007887 global treediffs
Steffen Prohaska890fae72007-08-12 12:05:46 +02007888 global diffcontext
Steffen Prohaskab9b86002008-01-17 23:42:55 +01007889 global ignorespace
Thomas Rastae4e3ff2010-10-16 12:15:10 +02007890 global worddiff
Paul Mackerras3ed31a82008-04-26 16:00:00 +10007891 global limitdiffs vfilelimit curview
Thomas Rast5de460a2013-11-16 18:37:41 +01007892 global git_version
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10007893
Paul Mackerrasa8138732009-05-16 21:06:01 +10007894 set textconv {}
7895 if {[package vcompare $git_version "1.6.1"] >= 0} {
7896 set textconv "--textconv"
7897 }
Jens Lehmann5c838d22009-10-28 12:40:45 +01007898 set submodule {}
7899 if {[package vcompare $git_version "1.6.6"] >= 0} {
7900 set submodule "--submodule"
7901 }
7902 set cmd [diffcmd $ids "-p $textconv $submodule -C --cc --no-commit-id -U$diffcontext"]
Steffen Prohaskab9b86002008-01-17 23:42:55 +01007903 if {$ignorespace} {
7904 append cmd " -w"
7905 }
Thomas Rastae4e3ff2010-10-16 12:15:10 +02007906 if {$worddiff ne [mc "Line diff"]} {
7907 append cmd " --word-diff=porcelain"
7908 }
Paul Mackerras3ed31a82008-04-26 16:00:00 +10007909 if {$limitdiffs && $vfilelimit($curview) ne {}} {
7910 set cmd [concat $cmd -- $vfilelimit($curview)]
Paul Mackerras7a39a172007-10-23 10:15:11 +10007911 }
7912 if {[catch {set bdf [open $cmd r]} err]} {
Paul Mackerras8b07dca2008-11-02 22:34:47 +11007913 error_popup [mc "Error getting diffs: %s" $err]
Paul Mackerrase5c2d852005-05-11 23:44:54 +00007914 return
7915 }
Pat Thoyts681c3292009-03-16 10:24:40 +00007916 fconfigure $bdf -blocking 0 -encoding binary -eofchar {}
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10007917 set blobdifffd($ids) $bdf
Thomas Rast5de460a2013-11-16 18:37:41 +01007918 initblobdiffvars
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007919 filerun $bdf [list getblobdiffline $bdf $diffids]
Paul Mackerrase5c2d852005-05-11 23:44:54 +00007920}
7921
Paul Mackerras354af6b2008-11-23 13:14:23 +11007922proc savecmitpos {} {
7923 global ctext cmitmode
7924
7925 if {$cmitmode eq "tree"} {
7926 return {}
7927 }
7928 return [list target_scrollpos [$ctext index @0,0]]
7929}
7930
7931proc savectextpos {} {
7932 global ctext
7933
7934 return [list target_scrollpos [$ctext index @0,0]]
7935}
7936
7937proc maybe_scroll_ctext {ateof} {
7938 global ctext target_scrollpos
7939
7940 if {![info exists target_scrollpos]} return
7941 if {!$ateof} {
7942 set nlines [expr {[winfo height $ctext]
7943 / [font metrics textfont -linespace]}]
7944 if {[$ctext compare "$target_scrollpos + $nlines lines" <= end]} return
7945 }
7946 $ctext yview $target_scrollpos
7947 unset target_scrollpos
7948}
7949
Paul Mackerras89b11d32006-05-02 19:55:31 +10007950proc setinlist {var i val} {
7951 global $var
7952
7953 while {[llength [set $var]] < $i} {
7954 lappend $var {}
7955 }
7956 if {[llength [set $var]] == $i} {
7957 lappend $var $val
7958 } else {
7959 lset $var $i $val
7960 }
7961}
7962
Paul Mackerras9396cd32007-06-23 20:28:15 +10007963proc makediffhdr {fname ids} {
Paul Mackerras8b07dca2008-11-02 22:34:47 +11007964 global ctext curdiffstart treediffs diffencoding
Paul Mackerras8a897742008-10-27 21:36:25 +11007965 global ctext_file_names jump_to_here targetline diffline
Paul Mackerras9396cd32007-06-23 20:28:15 +10007966
Paul Mackerras8b07dca2008-11-02 22:34:47 +11007967 set fname [encoding convertfrom $fname]
7968 set diffencoding [get_path_encoding $fname]
Paul Mackerras9396cd32007-06-23 20:28:15 +10007969 set i [lsearch -exact $treediffs($ids) $fname]
7970 if {$i >= 0} {
7971 setinlist difffilestart $i $curdiffstart
7972 }
Paul Mackerras48a81b72008-11-04 21:09:00 +11007973 lset ctext_file_names end $fname
Paul Mackerras9396cd32007-06-23 20:28:15 +10007974 set l [expr {(78 - [string length $fname]) / 2}]
7975 set pad [string range "----------------------------------------" 1 $l]
7976 $ctext insert $curdiffstart "$pad $fname $pad" filesep
Paul Mackerras8a897742008-10-27 21:36:25 +11007977 set targetline {}
7978 if {$jump_to_here ne {} && [lindex $jump_to_here 0] eq $fname} {
7979 set targetline [lindex $jump_to_here 1]
7980 }
7981 set diffline 0
Paul Mackerras9396cd32007-06-23 20:28:15 +10007982}
7983
Thomas Rast5de460a2013-11-16 18:37:41 +01007984proc blobdiffmaybeseehere {ateof} {
7985 global diffseehere
7986 if {$diffseehere >= 0} {
7987 mark_ctext_line [lindex [split $diffseehere .] 0]
7988 }
Max Kirillov1f3c8722014-01-18 14:58:51 +02007989 maybe_scroll_ctext $ateof
Thomas Rast5de460a2013-11-16 18:37:41 +01007990}
7991
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10007992proc getblobdiffline {bdf ids} {
Thomas Rast5de460a2013-11-16 18:37:41 +01007993 global diffids blobdifffd
7994 global ctext
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10007995
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007996 set nr 0
Paul Mackerrase5c2d852005-05-11 23:44:54 +00007997 $ctext conf -state normal
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007998 while {[incr nr] <= 1000 && [gets $bdf line] >= 0} {
7999 if {$ids != $diffids || $bdf != $blobdifffd($ids)} {
Paul Mackerrasc21398b2009-09-07 10:08:21 +10008000 catch {close $bdf}
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10008001 return 0
Paul Mackerras89b11d32006-05-02 19:55:31 +10008002 }
Thomas Rast5de460a2013-11-16 18:37:41 +01008003 parseblobdiffline $ids $line
Paul Mackerrase5c2d852005-05-11 23:44:54 +00008004 }
8005 $ctext conf -state disabled
Thomas Rast5de460a2013-11-16 18:37:41 +01008006 blobdiffmaybeseehere [eof $bdf]
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10008007 if {[eof $bdf]} {
Paul Mackerrasc21398b2009-09-07 10:08:21 +10008008 catch {close $bdf}
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10008009 return 0
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008010 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10008011 return [expr {$nr >= 1000? 2: 1}]
Paul Mackerrase5c2d852005-05-11 23:44:54 +00008012}
8013
Thomas Rast5de460a2013-11-16 18:37:41 +01008014proc parseblobdiffline {ids line} {
8015 global ctext curdiffstart
8016 global diffnexthead diffnextnote difffilestart
8017 global ctext_file_names ctext_file_lines
8018 global diffinhdr treediffs mergemax diffnparents
8019 global diffencoding jump_to_here targetline diffline currdiffsubmod
8020 global worddiff diffseehere
8021
8022 if {![string compare -length 5 "diff " $line]} {
8023 if {![regexp {^diff (--cc|--git) } $line m type]} {
8024 set line [encoding convertfrom $line]
8025 $ctext insert end "$line\n" hunksep
8026 continue
8027 }
8028 # start of a new file
8029 set diffinhdr 1
8030 $ctext insert end "\n"
8031 set curdiffstart [$ctext index "end - 1c"]
8032 lappend ctext_file_names ""
8033 lappend ctext_file_lines [lindex [split $curdiffstart "."] 0]
8034 $ctext insert end "\n" filesep
8035
8036 if {$type eq "--cc"} {
8037 # start of a new file in a merge diff
8038 set fname [string range $line 10 end]
8039 if {[lsearch -exact $treediffs($ids) $fname] < 0} {
8040 lappend treediffs($ids) $fname
8041 add_flist [list $fname]
8042 }
8043
8044 } else {
8045 set line [string range $line 11 end]
8046 # If the name hasn't changed the length will be odd,
8047 # the middle char will be a space, and the two bits either
8048 # side will be a/name and b/name, or "a/name" and "b/name".
8049 # If the name has changed we'll get "rename from" and
8050 # "rename to" or "copy from" and "copy to" lines following
8051 # this, and we'll use them to get the filenames.
8052 # This complexity is necessary because spaces in the
8053 # filename(s) don't get escaped.
8054 set l [string length $line]
8055 set i [expr {$l / 2}]
8056 if {!(($l & 1) && [string index $line $i] eq " " &&
8057 [string range $line 2 [expr {$i - 1}]] eq \
8058 [string range $line [expr {$i + 3}] end])} {
8059 return
8060 }
8061 # unescape if quoted and chop off the a/ from the front
8062 if {[string index $line 0] eq "\""} {
8063 set fname [string range [lindex $line 0] 2 end]
8064 } else {
8065 set fname [string range $line 2 [expr {$i - 1}]]
8066 }
8067 }
8068 makediffhdr $fname $ids
8069
8070 } elseif {![string compare -length 16 "* Unmerged path " $line]} {
8071 set fname [encoding convertfrom [string range $line 16 end]]
8072 $ctext insert end "\n"
8073 set curdiffstart [$ctext index "end - 1c"]
8074 lappend ctext_file_names $fname
8075 lappend ctext_file_lines [lindex [split $curdiffstart "."] 0]
8076 $ctext insert end "$line\n" filesep
8077 set i [lsearch -exact $treediffs($ids) $fname]
8078 if {$i >= 0} {
8079 setinlist difffilestart $i $curdiffstart
8080 }
8081
8082 } elseif {![string compare -length 2 "@@" $line]} {
8083 regexp {^@@+} $line ats
8084 set line [encoding convertfrom $diffencoding $line]
8085 $ctext insert end "$line\n" hunksep
8086 if {[regexp { \+(\d+),\d+ @@} $line m nl]} {
8087 set diffline $nl
8088 }
8089 set diffnparents [expr {[string length $ats] - 1}]
8090 set diffinhdr 0
8091
8092 } elseif {![string compare -length 10 "Submodule " $line]} {
8093 # start of a new submodule
8094 if {[regexp -indices "\[0-9a-f\]+\\.\\." $line nameend]} {
8095 set fname [string range $line 10 [expr [lindex $nameend 0] - 2]]
8096 } else {
8097 set fname [string range $line 10 [expr [string first "contains " $line] - 2]]
8098 }
8099 if {$currdiffsubmod != $fname} {
8100 $ctext insert end "\n"; # Add newline after commit message
8101 }
8102 set curdiffstart [$ctext index "end - 1c"]
8103 lappend ctext_file_names ""
8104 if {$currdiffsubmod != $fname} {
8105 lappend ctext_file_lines $fname
8106 makediffhdr $fname $ids
8107 set currdiffsubmod $fname
8108 $ctext insert end "\n$line\n" filesep
8109 } else {
8110 $ctext insert end "$line\n" filesep
8111 }
8112 } elseif {![string compare -length 3 " >" $line]} {
8113 set $currdiffsubmod ""
8114 set line [encoding convertfrom $diffencoding $line]
8115 $ctext insert end "$line\n" dresult
8116 } elseif {![string compare -length 3 " <" $line]} {
8117 set $currdiffsubmod ""
8118 set line [encoding convertfrom $diffencoding $line]
8119 $ctext insert end "$line\n" d0
8120 } elseif {$diffinhdr} {
8121 if {![string compare -length 12 "rename from " $line]} {
8122 set fname [string range $line [expr 6 + [string first " from " $line] ] end]
8123 if {[string index $fname 0] eq "\""} {
8124 set fname [lindex $fname 0]
8125 }
8126 set fname [encoding convertfrom $fname]
8127 set i [lsearch -exact $treediffs($ids) $fname]
8128 if {$i >= 0} {
8129 setinlist difffilestart $i $curdiffstart
8130 }
8131 } elseif {![string compare -length 10 $line "rename to "] ||
8132 ![string compare -length 8 $line "copy to "]} {
8133 set fname [string range $line [expr 4 + [string first " to " $line] ] end]
8134 if {[string index $fname 0] eq "\""} {
8135 set fname [lindex $fname 0]
8136 }
8137 makediffhdr $fname $ids
8138 } elseif {[string compare -length 3 $line "---"] == 0} {
8139 # do nothing
8140 return
8141 } elseif {[string compare -length 3 $line "+++"] == 0} {
8142 set diffinhdr 0
8143 return
8144 }
8145 $ctext insert end "$line\n" filesep
8146
8147 } else {
8148 set line [string map {\x1A ^Z} \
8149 [encoding convertfrom $diffencoding $line]]
8150 # parse the prefix - one ' ', '-' or '+' for each parent
8151 set prefix [string range $line 0 [expr {$diffnparents - 1}]]
8152 set tag [expr {$diffnparents > 1? "m": "d"}]
8153 set dowords [expr {$worddiff ne [mc "Line diff"] && $diffnparents == 1}]
8154 set words_pre_markup ""
8155 set words_post_markup ""
8156 if {[string trim $prefix " -+"] eq {}} {
8157 # prefix only has " ", "-" and "+" in it: normal diff line
8158 set num [string first "-" $prefix]
8159 if {$dowords} {
8160 set line [string range $line 1 end]
8161 }
8162 if {$num >= 0} {
8163 # removed line, first parent with line is $num
8164 if {$num >= $mergemax} {
8165 set num "max"
8166 }
8167 if {$dowords && $worddiff eq [mc "Markup words"]} {
8168 $ctext insert end "\[-$line-\]" $tag$num
8169 } else {
8170 $ctext insert end "$line" $tag$num
8171 }
8172 if {!$dowords} {
8173 $ctext insert end "\n" $tag$num
8174 }
8175 } else {
8176 set tags {}
8177 if {[string first "+" $prefix] >= 0} {
8178 # added line
8179 lappend tags ${tag}result
8180 if {$diffnparents > 1} {
8181 set num [string first " " $prefix]
8182 if {$num >= 0} {
8183 if {$num >= $mergemax} {
8184 set num "max"
8185 }
8186 lappend tags m$num
8187 }
8188 }
8189 set words_pre_markup "{+"
8190 set words_post_markup "+}"
8191 }
8192 if {$targetline ne {}} {
8193 if {$diffline == $targetline} {
8194 set diffseehere [$ctext index "end - 1 chars"]
8195 set targetline {}
8196 } else {
8197 incr diffline
8198 }
8199 }
8200 if {$dowords && $worddiff eq [mc "Markup words"]} {
8201 $ctext insert end "$words_pre_markup$line$words_post_markup" $tags
8202 } else {
8203 $ctext insert end "$line" $tags
8204 }
8205 if {!$dowords} {
8206 $ctext insert end "\n" $tags
8207 }
8208 }
8209 } elseif {$dowords && $prefix eq "~"} {
8210 $ctext insert end "\n" {}
8211 } else {
8212 # "\ No newline at end of file",
8213 # or something else we don't recognize
8214 $ctext insert end "$line\n" hunksep
8215 }
8216 }
8217}
8218
Paul Mackerrasa8d610a2007-04-19 11:39:12 +10008219proc changediffdisp {} {
8220 global ctext diffelide
8221
8222 $ctext tag conf d0 -elide [lindex $diffelide 0]
Paul Mackerras8b07dca2008-11-02 22:34:47 +11008223 $ctext tag conf dresult -elide [lindex $diffelide 1]
Paul Mackerrasa8d610a2007-04-19 11:39:12 +10008224}
8225
Stefan Hallerb9671352012-09-19 20:17:27 +02008226proc highlightfile {cline} {
8227 global cflist cflist_top
Paul Mackerrasf4c54b32008-05-10 13:15:36 +10008228
Stefan Hallerce837c92012-10-04 22:50:16 +02008229 if {![info exists cflist_top]} return
8230
Paul Mackerrasf4c54b32008-05-10 13:15:36 +10008231 $cflist tag remove highlight $cflist_top.0 "$cflist_top.0 lineend"
8232 $cflist tag add highlight $cline.0 "$cline.0 lineend"
8233 $cflist see $cline.0
8234 set cflist_top $cline
8235}
8236
Stefan Hallerb9671352012-09-19 20:17:27 +02008237proc highlightfile_for_scrollpos {topidx} {
Stefan Haller978904b2012-10-04 22:50:17 +02008238 global cmitmode difffilestart
Stefan Hallerb9671352012-09-19 20:17:27 +02008239
Stefan Haller978904b2012-10-04 22:50:17 +02008240 if {$cmitmode eq "tree"} return
Stefan Hallerb9671352012-09-19 20:17:27 +02008241 if {![info exists difffilestart]} return
8242
8243 set top [lindex [split $topidx .] 0]
8244 if {$difffilestart eq {} || $top < [lindex $difffilestart 0]} {
8245 highlightfile 0
8246 } else {
8247 highlightfile [expr {[bsearch $difffilestart $top] + 2}]
8248 }
8249}
8250
OGAWA Hirofumi67c22872006-09-27 12:32:19 +09008251proc prevfile {} {
Paul Mackerrasf4c54b32008-05-10 13:15:36 +10008252 global difffilestart ctext cmitmode
8253
8254 if {$cmitmode eq "tree"} return
8255 set prev 0.0
OGAWA Hirofumi67c22872006-09-27 12:32:19 +09008256 set here [$ctext index @0,0]
8257 foreach loc $difffilestart {
8258 if {[$ctext compare $loc >= $here]} {
Stefan Hallerb9671352012-09-19 20:17:27 +02008259 $ctext yview $prev
OGAWA Hirofumi67c22872006-09-27 12:32:19 +09008260 return
8261 }
8262 set prev $loc
8263 }
Stefan Hallerb9671352012-09-19 20:17:27 +02008264 $ctext yview $prev
OGAWA Hirofumi67c22872006-09-27 12:32:19 +09008265}
8266
Paul Mackerras39ad8572005-05-19 12:35:53 +00008267proc nextfile {} {
Paul Mackerrasf4c54b32008-05-10 13:15:36 +10008268 global difffilestart ctext cmitmode
8269
8270 if {$cmitmode eq "tree"} return
Paul Mackerras39ad8572005-05-19 12:35:53 +00008271 set here [$ctext index @0,0]
Paul Mackerras7fcceed2006-04-27 19:21:49 +10008272 foreach loc $difffilestart {
8273 if {[$ctext compare $loc > $here]} {
Stefan Hallerb9671352012-09-19 20:17:27 +02008274 $ctext yview $loc
OGAWA Hirofumi67c22872006-09-27 12:32:19 +09008275 return
Paul Mackerras39ad8572005-05-19 12:35:53 +00008276 }
8277 }
Paul Mackerras1db95b02005-05-09 04:08:39 +00008278}
8279
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008280proc clear_ctext {{first 1.0}} {
8281 global ctext smarktop smarkbot
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04008282 global ctext_file_names ctext_file_lines
Paul Mackerras97645682007-08-23 22:24:38 +10008283 global pendinglinks
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008284
Paul Mackerras1902c272006-05-25 21:25:13 +10008285 set l [lindex [split $first .] 0]
8286 if {![info exists smarktop] || [$ctext compare $first < $smarktop.0]} {
8287 set smarktop $l
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008288 }
Paul Mackerras1902c272006-05-25 21:25:13 +10008289 if {![info exists smarkbot] || [$ctext compare $first < $smarkbot.0]} {
8290 set smarkbot $l
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008291 }
8292 $ctext delete $first end
Paul Mackerras97645682007-08-23 22:24:38 +10008293 if {$first eq "1.0"} {
8294 catch {unset pendinglinks}
8295 }
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04008296 set ctext_file_names {}
8297 set ctext_file_lines {}
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008298}
8299
Paul Mackerras32f1b3e2007-09-28 21:27:39 +10008300proc settabs {{firstab {}}} {
Paul Mackerras9c311b32007-10-04 22:27:13 +10008301 global firsttabstop tabstop ctext have_tk85
Paul Mackerras32f1b3e2007-09-28 21:27:39 +10008302
8303 if {$firstab ne {} && $have_tk85} {
8304 set firsttabstop $firstab
8305 }
Paul Mackerras9c311b32007-10-04 22:27:13 +10008306 set w [font measure textfont "0"]
Paul Mackerras32f1b3e2007-09-28 21:27:39 +10008307 if {$firsttabstop != 0} {
Paul Mackerras64b5f142007-10-04 22:19:24 +10008308 $ctext conf -tabs [list [expr {($firsttabstop + $tabstop) * $w}] \
8309 [expr {($firsttabstop + 2 * $tabstop) * $w}]]
Paul Mackerras32f1b3e2007-09-28 21:27:39 +10008310 } elseif {$have_tk85 || $tabstop != 8} {
8311 $ctext conf -tabs [expr {$tabstop * $w}]
8312 } else {
8313 $ctext conf -tabs {}
8314 }
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008315}
8316
8317proc incrsearch {name ix op} {
Paul Mackerras1902c272006-05-25 21:25:13 +10008318 global ctext searchstring searchdirn
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008319
Paul Mackerras1902c272006-05-25 21:25:13 +10008320 if {[catch {$ctext index anchor}]} {
8321 # no anchor set, use start of selection, or of visible area
8322 set sel [$ctext tag ranges sel]
8323 if {$sel ne {}} {
8324 $ctext mark set anchor [lindex $sel 0]
8325 } elseif {$searchdirn eq "-forwards"} {
8326 $ctext mark set anchor @0,0
8327 } else {
8328 $ctext mark set anchor @0,[winfo height $ctext]
8329 }
8330 }
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008331 if {$searchstring ne {}} {
Stefan Haller30441a62012-09-22 09:40:25 +02008332 set here [$ctext search -count mlen $searchdirn -- $searchstring anchor]
Paul Mackerras1902c272006-05-25 21:25:13 +10008333 if {$here ne {}} {
8334 $ctext see $here
Stefan Haller30441a62012-09-22 09:40:25 +02008335 set mend "$here + $mlen c"
8336 $ctext tag remove sel 1.0 end
8337 $ctext tag add sel $here $mend
Stefan Hallerb9671352012-09-19 20:17:27 +02008338 suppress_highlighting_file_for_current_scrollpos
8339 highlightfile_for_scrollpos $here
Paul Mackerras1902c272006-05-25 21:25:13 +10008340 }
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008341 }
Stefan Hallerc4614992012-09-22 09:40:24 +02008342 rehighlight_search_results
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008343}
8344
8345proc dosearch {} {
Paul Mackerras1902c272006-05-25 21:25:13 +10008346 global sstring ctext searchstring searchdirn
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008347
8348 focus $sstring
8349 $sstring icursor end
Paul Mackerras1902c272006-05-25 21:25:13 +10008350 set searchdirn -forwards
8351 if {$searchstring ne {}} {
8352 set sel [$ctext tag ranges sel]
8353 if {$sel ne {}} {
8354 set start "[lindex $sel 0] + 1c"
8355 } elseif {[catch {set start [$ctext index anchor]}]} {
8356 set start "@0,0"
8357 }
8358 set match [$ctext search -count mlen -- $searchstring $start]
8359 $ctext tag remove sel 1.0 end
8360 if {$match eq {}} {
8361 bell
8362 return
8363 }
8364 $ctext see $match
Stefan Hallerb9671352012-09-19 20:17:27 +02008365 suppress_highlighting_file_for_current_scrollpos
8366 highlightfile_for_scrollpos $match
Paul Mackerras1902c272006-05-25 21:25:13 +10008367 set mend "$match + $mlen c"
8368 $ctext tag add sel $match $mend
8369 $ctext mark unset anchor
Stefan Hallerc4614992012-09-22 09:40:24 +02008370 rehighlight_search_results
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008371 }
Paul Mackerras1902c272006-05-25 21:25:13 +10008372}
8373
8374proc dosearchback {} {
8375 global sstring ctext searchstring searchdirn
8376
8377 focus $sstring
8378 $sstring icursor end
8379 set searchdirn -backwards
8380 if {$searchstring ne {}} {
8381 set sel [$ctext tag ranges sel]
8382 if {$sel ne {}} {
8383 set start [lindex $sel 0]
8384 } elseif {[catch {set start [$ctext index anchor]}]} {
8385 set start @0,[winfo height $ctext]
8386 }
8387 set match [$ctext search -backwards -count ml -- $searchstring $start]
8388 $ctext tag remove sel 1.0 end
8389 if {$match eq {}} {
8390 bell
8391 return
8392 }
8393 $ctext see $match
Stefan Hallerb9671352012-09-19 20:17:27 +02008394 suppress_highlighting_file_for_current_scrollpos
8395 highlightfile_for_scrollpos $match
Paul Mackerras1902c272006-05-25 21:25:13 +10008396 set mend "$match + $ml c"
8397 $ctext tag add sel $match $mend
8398 $ctext mark unset anchor
Stefan Hallerc4614992012-09-22 09:40:24 +02008399 rehighlight_search_results
8400 }
8401}
8402
8403proc rehighlight_search_results {} {
8404 global ctext searchstring
8405
8406 $ctext tag remove found 1.0 end
8407 $ctext tag remove currentsearchhit 1.0 end
8408
8409 if {$searchstring ne {}} {
8410 searchmarkvisible 1
Paul Mackerras1902c272006-05-25 21:25:13 +10008411 }
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008412}
8413
8414proc searchmark {first last} {
8415 global ctext searchstring
8416
Stefan Hallerc4614992012-09-22 09:40:24 +02008417 set sel [$ctext tag ranges sel]
8418
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008419 set mend $first.0
8420 while {1} {
8421 set match [$ctext search -count mlen -- $searchstring $mend $last.end]
8422 if {$match eq {}} break
8423 set mend "$match + $mlen c"
Stefan Hallerc4614992012-09-22 09:40:24 +02008424 if {$sel ne {} && [$ctext compare $match == [lindex $sel 0]]} {
8425 $ctext tag add currentsearchhit $match $mend
8426 } else {
8427 $ctext tag add found $match $mend
8428 }
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008429 }
8430}
8431
8432proc searchmarkvisible {doall} {
8433 global ctext smarktop smarkbot
8434
8435 set topline [lindex [split [$ctext index @0,0] .] 0]
8436 set botline [lindex [split [$ctext index @0,[winfo height $ctext]] .] 0]
8437 if {$doall || $botline < $smarktop || $topline > $smarkbot} {
8438 # no overlap with previous
8439 searchmark $topline $botline
8440 set smarktop $topline
8441 set smarkbot $botline
8442 } else {
8443 if {$topline < $smarktop} {
8444 searchmark $topline [expr {$smarktop-1}]
8445 set smarktop $topline
8446 }
8447 if {$botline > $smarkbot} {
8448 searchmark [expr {$smarkbot+1}] $botline
8449 set smarkbot $botline
8450 }
8451 }
8452}
8453
Stefan Hallerb9671352012-09-19 20:17:27 +02008454proc suppress_highlighting_file_for_current_scrollpos {} {
8455 global ctext suppress_highlighting_file_for_this_scrollpos
8456
8457 set suppress_highlighting_file_for_this_scrollpos [$ctext index @0,0]
8458}
8459
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008460proc scrolltext {f0 f1} {
Stefan Hallerb9671352012-09-19 20:17:27 +02008461 global searchstring cmitmode ctext
8462 global suppress_highlighting_file_for_this_scrollpos
8463
Stefan Haller978904b2012-10-04 22:50:17 +02008464 set topidx [$ctext index @0,0]
8465 if {![info exists suppress_highlighting_file_for_this_scrollpos]
8466 || $topidx ne $suppress_highlighting_file_for_this_scrollpos} {
8467 highlightfile_for_scrollpos $topidx
Stefan Hallerb9671352012-09-19 20:17:27 +02008468 }
8469
8470 catch {unset suppress_highlighting_file_for_this_scrollpos}
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008471
Pekka Kaitaniemi8809d692008-03-08 14:27:23 +02008472 .bleft.bottom.sb set $f0 $f1
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008473 if {$searchstring ne {}} {
8474 searchmarkvisible 0
8475 }
8476}
8477
Paul Mackerras1d10f362005-05-15 12:55:47 +00008478proc setcoords {} {
Paul Mackerras9c311b32007-10-04 22:27:13 +10008479 global linespc charspc canvx0 canvy0
Paul Mackerrasf6075eb2005-08-18 09:30:10 +10008480 global xspc1 xspc2 lthickness
Paul Mackerras8d858d12005-08-05 09:52:16 +10008481
Paul Mackerras9c311b32007-10-04 22:27:13 +10008482 set linespc [font metrics mainfont -linespace]
8483 set charspc [font measure mainfont "m"]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11008484 set canvy0 [expr {int(3 + 0.5 * $linespc)}]
8485 set canvx0 [expr {int(3 + 0.5 * $linespc)}]
Paul Mackerrasf6075eb2005-08-18 09:30:10 +10008486 set lthickness [expr {int($linespc / 9) + 1}]
Paul Mackerras8d858d12005-08-05 09:52:16 +10008487 set xspc1(0) $linespc
8488 set xspc2 $linespc
Paul Mackerras9a40c502005-05-12 23:46:16 +00008489}
Paul Mackerras1db95b02005-05-09 04:08:39 +00008490
Paul Mackerras1d10f362005-05-15 12:55:47 +00008491proc redisplay {} {
Paul Mackerrasbe0cd092006-03-31 09:55:11 +11008492 global canv
Paul Mackerras9f1afe02006-02-19 22:44:47 +11008493 global selectedline
8494
8495 set ymax [lindex [$canv cget -scrollregion] 3]
8496 if {$ymax eq {} || $ymax == 0} return
8497 set span [$canv yview]
8498 clear_display
Paul Mackerrasbe0cd092006-03-31 09:55:11 +11008499 setcanvscroll
Paul Mackerras9f1afe02006-02-19 22:44:47 +11008500 allcanvs yview moveto [lindex $span 0]
8501 drawvisible
Paul Mackerras94b4a692008-05-20 20:51:06 +10008502 if {$selectedline ne {}} {
Paul Mackerras9f1afe02006-02-19 22:44:47 +11008503 selectline $selectedline 0
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10008504 allcanvs yview moveto [lindex $span 0]
Paul Mackerras1db95b02005-05-09 04:08:39 +00008505 }
8506}
Paul Mackerras1d10f362005-05-15 12:55:47 +00008507
Paul Mackerras0ed1dd32007-10-06 18:27:37 +10008508proc parsefont {f n} {
8509 global fontattr
8510
8511 set fontattr($f,family) [lindex $n 0]
8512 set s [lindex $n 1]
8513 if {$s eq {} || $s == 0} {
8514 set s 10
8515 } elseif {$s < 0} {
8516 set s [expr {int(-$s / [winfo fpixels . 1p] + 0.5)}]
Paul Mackerras9c311b32007-10-04 22:27:13 +10008517 }
Paul Mackerras0ed1dd32007-10-06 18:27:37 +10008518 set fontattr($f,size) $s
8519 set fontattr($f,weight) normal
8520 set fontattr($f,slant) roman
8521 foreach style [lrange $n 2 end] {
8522 switch -- $style {
8523 "normal" -
8524 "bold" {set fontattr($f,weight) $style}
8525 "roman" -
8526 "italic" {set fontattr($f,slant) $style}
8527 }
Paul Mackerras9c311b32007-10-04 22:27:13 +10008528 }
Paul Mackerras0ed1dd32007-10-06 18:27:37 +10008529}
8530
8531proc fontflags {f {isbold 0}} {
8532 global fontattr
8533
8534 return [list -family $fontattr($f,family) -size $fontattr($f,size) \
8535 -weight [expr {$isbold? "bold": $fontattr($f,weight)}] \
8536 -slant $fontattr($f,slant)]
8537}
8538
8539proc fontname {f} {
8540 global fontattr
8541
8542 set n [list $fontattr($f,family) $fontattr($f,size)]
8543 if {$fontattr($f,weight) eq "bold"} {
8544 lappend n "bold"
Paul Mackerras9c311b32007-10-04 22:27:13 +10008545 }
Paul Mackerras0ed1dd32007-10-06 18:27:37 +10008546 if {$fontattr($f,slant) eq "italic"} {
8547 lappend n "italic"
Paul Mackerras9c311b32007-10-04 22:27:13 +10008548 }
Paul Mackerras0ed1dd32007-10-06 18:27:37 +10008549 return $n
Paul Mackerras9c311b32007-10-04 22:27:13 +10008550}
8551
Paul Mackerras1d10f362005-05-15 12:55:47 +00008552proc incrfont {inc} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11008553 global mainfont textfont ctext canv cflist showrefstop
Paul Mackerras0ed1dd32007-10-06 18:27:37 +10008554 global stopped entries fontattr
8555
Paul Mackerras1d10f362005-05-15 12:55:47 +00008556 unmarkmatches
Paul Mackerras0ed1dd32007-10-06 18:27:37 +10008557 set s $fontattr(mainfont,size)
Paul Mackerras9c311b32007-10-04 22:27:13 +10008558 incr s $inc
8559 if {$s < 1} {
8560 set s 1
8561 }
Paul Mackerras0ed1dd32007-10-06 18:27:37 +10008562 set fontattr(mainfont,size) $s
Paul Mackerras9c311b32007-10-04 22:27:13 +10008563 font config mainfont -size $s
8564 font config mainfontbold -size $s
Paul Mackerras0ed1dd32007-10-06 18:27:37 +10008565 set mainfont [fontname mainfont]
8566 set s $fontattr(textfont,size)
Paul Mackerras9c311b32007-10-04 22:27:13 +10008567 incr s $inc
8568 if {$s < 1} {
8569 set s 1
8570 }
Paul Mackerras0ed1dd32007-10-06 18:27:37 +10008571 set fontattr(textfont,size) $s
Paul Mackerras9c311b32007-10-04 22:27:13 +10008572 font config textfont -size $s
8573 font config textfontbold -size $s
Paul Mackerras0ed1dd32007-10-06 18:27:37 +10008574 set textfont [fontname textfont]
Paul Mackerras1d10f362005-05-15 12:55:47 +00008575 setcoords
Paul Mackerras32f1b3e2007-09-28 21:27:39 +10008576 settabs
Paul Mackerras1d10f362005-05-15 12:55:47 +00008577 redisplay
Paul Mackerras1db95b02005-05-09 04:08:39 +00008578}
Paul Mackerras1d10f362005-05-15 12:55:47 +00008579
Paul Mackerrasee3dc722005-06-25 16:37:13 +10008580proc clearsha1 {} {
8581 global sha1entry sha1string
8582 if {[string length $sha1string] == 40} {
8583 $sha1entry delete 0 end
8584 }
8585}
8586
Paul Mackerras887fe3c2005-05-21 07:35:37 +00008587proc sha1change {n1 n2 op} {
8588 global sha1string currentid sha1but
8589 if {$sha1string == {}
8590 || ([info exists currentid] && $sha1string == $currentid)} {
8591 set state disabled
8592 } else {
8593 set state normal
8594 }
8595 if {[$sha1but cget -state] == $state} return
8596 if {$state == "normal"} {
Christian Stimmingd990ced2007-11-07 18:42:55 +01008597 $sha1but conf -state normal -relief raised -text "[mc "Goto:"] "
Paul Mackerras887fe3c2005-05-21 07:35:37 +00008598 } else {
Christian Stimmingd990ced2007-11-07 18:42:55 +01008599 $sha1but conf -state disabled -relief flat -text "[mc "SHA1 ID:"] "
Paul Mackerras887fe3c2005-05-21 07:35:37 +00008600 }
8601}
8602
8603proc gotocommit {} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11008604 global sha1string tagids headids curview varcid
Paul Mackerrasf3b8b3c2005-07-18 12:16:35 -04008605
Paul Mackerras887fe3c2005-05-21 07:35:37 +00008606 if {$sha1string == {}
8607 || ([info exists currentid] && $sha1string == $currentid)} return
8608 if {[info exists tagids($sha1string)]} {
8609 set id $tagids($sha1string)
Stephen Rothwelle1007122006-03-30 16:13:12 +11008610 } elseif {[info exists headids($sha1string)]} {
8611 set id $headids($sha1string)
Paul Mackerras887fe3c2005-05-21 07:35:37 +00008612 } else {
8613 set id [string tolower $sha1string]
Paul Mackerrasf3b8b3c2005-07-18 12:16:35 -04008614 if {[regexp {^[0-9a-f]{4,39}$} $id]} {
Paul Mackerrasd375ef92008-10-21 10:18:12 +11008615 set matches [longid $id]
Paul Mackerrasf3b8b3c2005-07-18 12:16:35 -04008616 if {$matches ne {}} {
8617 if {[llength $matches] > 1} {
Christian Stimmingd990ced2007-11-07 18:42:55 +01008618 error_popup [mc "Short SHA1 id %s is ambiguous" $id]
Paul Mackerrasf3b8b3c2005-07-18 12:16:35 -04008619 return
8620 }
Paul Mackerrasd375ef92008-10-21 10:18:12 +11008621 set id [lindex $matches 0]
Paul Mackerrasf3b8b3c2005-07-18 12:16:35 -04008622 }
Thomas Rast9bf3acf2009-08-13 09:25:03 +02008623 } else {
8624 if {[catch {set id [exec git rev-parse --verify $sha1string]}]} {
8625 error_popup [mc "Revision %s is not known" $sha1string]
8626 return
8627 }
Paul Mackerrasf3b8b3c2005-07-18 12:16:35 -04008628 }
Paul Mackerras887fe3c2005-05-21 07:35:37 +00008629 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11008630 if {[commitinview $id $curview]} {
8631 selectline [rowofcommit $id] 1
Paul Mackerras887fe3c2005-05-21 07:35:37 +00008632 return
8633 }
Paul Mackerrasf3b8b3c2005-07-18 12:16:35 -04008634 if {[regexp {^[0-9a-fA-F]{4,}$} $sha1string]} {
Christian Stimmingd990ced2007-11-07 18:42:55 +01008635 set msg [mc "SHA1 id %s is not known" $sha1string]
Paul Mackerras887fe3c2005-05-21 07:35:37 +00008636 } else {
Thomas Rast9bf3acf2009-08-13 09:25:03 +02008637 set msg [mc "Revision %s is not in the current view" $sha1string]
Paul Mackerras887fe3c2005-05-21 07:35:37 +00008638 }
Christian Stimmingd990ced2007-11-07 18:42:55 +01008639 error_popup $msg
Paul Mackerras887fe3c2005-05-21 07:35:37 +00008640}
8641
Paul Mackerras84ba7342005-06-17 00:12:26 +00008642proc lineenter {x y id} {
8643 global hoverx hovery hoverid hovertimer
8644 global commitinfo canv
8645
Paul Mackerras8ed16482006-03-02 22:56:44 +11008646 if {![info exists commitinfo($id)] && ![getcommit $id]} return
Paul Mackerras84ba7342005-06-17 00:12:26 +00008647 set hoverx $x
8648 set hovery $y
8649 set hoverid $id
8650 if {[info exists hovertimer]} {
8651 after cancel $hovertimer
8652 }
8653 set hovertimer [after 500 linehover]
8654 $canv delete hover
8655}
8656
8657proc linemotion {x y id} {
8658 global hoverx hovery hoverid hovertimer
8659
8660 if {[info exists hoverid] && $id == $hoverid} {
8661 set hoverx $x
8662 set hovery $y
8663 if {[info exists hovertimer]} {
8664 after cancel $hovertimer
8665 }
8666 set hovertimer [after 500 linehover]
8667 }
8668}
8669
8670proc lineleave {id} {
8671 global hoverid hovertimer canv
8672
8673 if {[info exists hoverid] && $id == $hoverid} {
8674 $canv delete hover
8675 if {[info exists hovertimer]} {
8676 after cancel $hovertimer
8677 unset hovertimer
8678 }
8679 unset hoverid
8680 }
8681}
8682
8683proc linehover {} {
8684 global hoverx hovery hoverid hovertimer
8685 global canv linespc lthickness
Gauthier Östervall252c52d2013-03-27 14:40:51 +01008686 global linehoverbgcolor linehoverfgcolor linehoveroutlinecolor
8687
Paul Mackerras9c311b32007-10-04 22:27:13 +10008688 global commitinfo
Paul Mackerras84ba7342005-06-17 00:12:26 +00008689
8690 set text [lindex $commitinfo($hoverid) 0]
8691 set ymax [lindex [$canv cget -scrollregion] 3]
8692 if {$ymax == {}} return
8693 set yfrac [lindex [$canv yview] 0]
8694 set x [expr {$hoverx + 2 * $linespc}]
8695 set y [expr {$hovery + $yfrac * $ymax - $linespc / 2}]
8696 set x0 [expr {$x - 2 * $lthickness}]
8697 set y0 [expr {$y - 2 * $lthickness}]
Paul Mackerras9c311b32007-10-04 22:27:13 +10008698 set x1 [expr {$x + [font measure mainfont $text] + 2 * $lthickness}]
Paul Mackerras84ba7342005-06-17 00:12:26 +00008699 set y1 [expr {$y + $linespc + 2 * $lthickness}]
8700 set t [$canv create rectangle $x0 $y0 $x1 $y1 \
Gauthier Östervall252c52d2013-03-27 14:40:51 +01008701 -fill $linehoverbgcolor -outline $linehoveroutlinecolor \
8702 -width 1 -tags hover]
Paul Mackerras84ba7342005-06-17 00:12:26 +00008703 $canv raise $t
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10008704 set t [$canv create text $x $y -anchor nw -text $text -tags hover \
Gauthier Östervall252c52d2013-03-27 14:40:51 +01008705 -font mainfont -fill $linehoverfgcolor]
Paul Mackerras84ba7342005-06-17 00:12:26 +00008706 $canv raise $t
8707}
8708
Paul Mackerras9843c302005-08-30 10:57:11 +10008709proc clickisonarrow {id y} {
Paul Mackerras50b44ec2006-04-04 10:16:22 +10008710 global lthickness
Paul Mackerras9843c302005-08-30 10:57:11 +10008711
Paul Mackerras50b44ec2006-04-04 10:16:22 +10008712 set ranges [rowranges $id]
Paul Mackerras9843c302005-08-30 10:57:11 +10008713 set thresh [expr {2 * $lthickness + 6}]
Paul Mackerras50b44ec2006-04-04 10:16:22 +10008714 set n [expr {[llength $ranges] - 1}]
Paul Mackerrasf6342482006-02-28 10:02:03 +11008715 for {set i 1} {$i < $n} {incr i} {
Paul Mackerras50b44ec2006-04-04 10:16:22 +10008716 set row [lindex $ranges $i]
Paul Mackerrasf6342482006-02-28 10:02:03 +11008717 if {abs([yc $row] - $y) < $thresh} {
8718 return $i
Paul Mackerras9843c302005-08-30 10:57:11 +10008719 }
8720 }
8721 return {}
8722}
8723
Paul Mackerrasf6342482006-02-28 10:02:03 +11008724proc arrowjump {id n y} {
Paul Mackerras50b44ec2006-04-04 10:16:22 +10008725 global canv
Paul Mackerras9843c302005-08-30 10:57:11 +10008726
Paul Mackerrasf6342482006-02-28 10:02:03 +11008727 # 1 <-> 2, 3 <-> 4, etc...
8728 set n [expr {(($n - 1) ^ 1) + 1}]
Paul Mackerras50b44ec2006-04-04 10:16:22 +10008729 set row [lindex [rowranges $id] $n]
Paul Mackerrasf6342482006-02-28 10:02:03 +11008730 set yt [yc $row]
Paul Mackerras9843c302005-08-30 10:57:11 +10008731 set ymax [lindex [$canv cget -scrollregion] 3]
8732 if {$ymax eq {} || $ymax <= 0} return
8733 set view [$canv yview]
8734 set yspan [expr {[lindex $view 1] - [lindex $view 0]}]
8735 set yfrac [expr {$yt / $ymax - $yspan / 2}]
8736 if {$yfrac < 0} {
8737 set yfrac 0
8738 }
Paul Mackerrasf6342482006-02-28 10:02:03 +11008739 allcanvs yview moveto $yfrac
Paul Mackerras9843c302005-08-30 10:57:11 +10008740}
8741
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10008742proc lineclick {x y id isnew} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11008743 global ctext commitinfo children canv thickerline curview
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008744
Paul Mackerras8ed16482006-03-02 22:56:44 +11008745 if {![info exists commitinfo($id)] && ![getcommit $id]} return
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008746 unmarkmatches
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10008747 unselectline
Paul Mackerras9843c302005-08-30 10:57:11 +10008748 normalline
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008749 $canv delete hover
Paul Mackerras9843c302005-08-30 10:57:11 +10008750 # draw this line thicker than normal
Paul Mackerras9843c302005-08-30 10:57:11 +10008751 set thickerline $id
Paul Mackerrasc934a8a2006-03-02 23:00:44 +11008752 drawlines $id
Paul Mackerras9843c302005-08-30 10:57:11 +10008753 if {$isnew} {
8754 set ymax [lindex [$canv cget -scrollregion] 3]
8755 if {$ymax eq {}} return
8756 set yfrac [lindex [$canv yview] 0]
8757 set y [expr {$y + $yfrac * $ymax}]
8758 }
8759 set dirn [clickisonarrow $id $y]
8760 if {$dirn ne {}} {
8761 arrowjump $id $dirn $y
8762 return
8763 }
8764
8765 if {$isnew} {
Paul Mackerras354af6b2008-11-23 13:14:23 +11008766 addtohistory [list lineclick $x $y $id 0] savectextpos
Paul Mackerras9843c302005-08-30 10:57:11 +10008767 }
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008768 # fill the details pane with info about this line
8769 $ctext conf -state normal
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008770 clear_ctext
Paul Mackerras32f1b3e2007-09-28 21:27:39 +10008771 settabs 0
Christian Stimmingd990ced2007-11-07 18:42:55 +01008772 $ctext insert end "[mc "Parent"]:\t"
Paul Mackerras97645682007-08-23 22:24:38 +10008773 $ctext insert end $id link0
8774 setlink $id link0
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008775 set info $commitinfo($id)
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10008776 $ctext insert end "\n\t[lindex $info 0]\n"
Christian Stimmingd990ced2007-11-07 18:42:55 +01008777 $ctext insert end "\t[mc "Author"]:\t[lindex $info 1]\n"
Paul Mackerras232475d2005-11-15 10:34:03 +11008778 set date [formatdate [lindex $info 2]]
Christian Stimmingd990ced2007-11-07 18:42:55 +01008779 $ctext insert end "\t[mc "Date"]:\t$date\n"
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10008780 set kids $children($curview,$id)
Paul Mackerras79b2c752006-04-02 20:47:40 +10008781 if {$kids ne {}} {
Christian Stimmingd990ced2007-11-07 18:42:55 +01008782 $ctext insert end "\n[mc "Children"]:"
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10008783 set i 0
Paul Mackerras79b2c752006-04-02 20:47:40 +10008784 foreach child $kids {
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10008785 incr i
Paul Mackerras8ed16482006-03-02 22:56:44 +11008786 if {![info exists commitinfo($child)] && ![getcommit $child]} continue
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008787 set info $commitinfo($child)
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10008788 $ctext insert end "\n\t"
Paul Mackerras97645682007-08-23 22:24:38 +10008789 $ctext insert end $child link$i
8790 setlink $child link$i
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10008791 $ctext insert end "\n\t[lindex $info 0]"
Christian Stimmingd990ced2007-11-07 18:42:55 +01008792 $ctext insert end "\n\t[mc "Author"]:\t[lindex $info 1]"
Paul Mackerras232475d2005-11-15 10:34:03 +11008793 set date [formatdate [lindex $info 2]]
Christian Stimmingd990ced2007-11-07 18:42:55 +01008794 $ctext insert end "\n\t[mc "Date"]:\t$date\n"
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008795 }
8796 }
Paul Mackerras354af6b2008-11-23 13:14:23 +11008797 maybe_scroll_ctext 1
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008798 $ctext conf -state disabled
Paul Mackerras7fcceed2006-04-27 19:21:49 +10008799 init_flist {}
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008800}
8801
Paul Mackerras9843c302005-08-30 10:57:11 +10008802proc normalline {} {
8803 global thickerline
8804 if {[info exists thickerline]} {
Paul Mackerrasc934a8a2006-03-02 23:00:44 +11008805 set id $thickerline
Paul Mackerras9843c302005-08-30 10:57:11 +10008806 unset thickerline
Paul Mackerrasc934a8a2006-03-02 23:00:44 +11008807 drawlines $id
Paul Mackerras9843c302005-08-30 10:57:11 +10008808 }
8809}
8810
Paul Mackerras354af6b2008-11-23 13:14:23 +11008811proc selbyid {id {isnew 1}} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11008812 global curview
8813 if {[commitinview $id $curview]} {
Paul Mackerras354af6b2008-11-23 13:14:23 +11008814 selectline [rowofcommit $id] $isnew
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008815 }
8816}
8817
8818proc mstime {} {
8819 global startmstime
8820 if {![info exists startmstime]} {
8821 set startmstime [clock clicks -milliseconds]
8822 }
8823 return [format "%.3f" [expr {([clock click -milliseconds] - $startmstime) / 1000.0}]]
8824}
8825
8826proc rowmenu {x y id} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11008827 global rowctxmenu selectedline rowmenuid curview
Paul Mackerrasb9fdba72009-04-09 09:34:46 +10008828 global nullid nullid2 fakerowmenu mainhead markedid
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008829
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10008830 stopfinding
Paul Mackerras219ea3a2006-09-07 10:21:39 +10008831 set rowmenuid $id
Paul Mackerras94b4a692008-05-20 20:51:06 +10008832 if {$selectedline eq {} || [rowofcommit $id] eq $selectedline} {
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008833 set state disabled
8834 } else {
8835 set state normal
8836 }
Paul Mackerras6febded2012-03-23 22:07:27 +11008837 if {[info exists markedid] && $markedid ne $id} {
8838 set mstate normal
8839 } else {
8840 set mstate disabled
8841 }
Paul Mackerras8f489362007-07-13 19:49:37 +10008842 if {$id ne $nullid && $id ne $nullid2} {
Paul Mackerras219ea3a2006-09-07 10:21:39 +10008843 set menu $rowctxmenu
Michele Ballabio5e3502d2008-05-02 17:46:20 +02008844 if {$mainhead ne {}} {
Johannes Sixtda12e592008-12-03 13:43:20 +01008845 $menu entryconfigure 7 -label [mc "Reset %s branch to here" $mainhead] -state normal
Michele Ballabio5e3502d2008-05-02 17:46:20 +02008846 } else {
8847 $menu entryconfigure 7 -label [mc "Detached head: can't reset" $mainhead] -state disabled
8848 }
Paul Mackerras6febded2012-03-23 22:07:27 +11008849 $menu entryconfigure 9 -state $mstate
8850 $menu entryconfigure 10 -state $mstate
8851 $menu entryconfigure 11 -state $mstate
Paul Mackerras219ea3a2006-09-07 10:21:39 +10008852 } else {
8853 set menu $fakerowmenu
8854 }
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11008855 $menu entryconfigure [mca "Diff this -> selected"] -state $state
8856 $menu entryconfigure [mca "Diff selected -> this"] -state $state
8857 $menu entryconfigure [mca "Make patch"] -state $state
Paul Mackerras6febded2012-03-23 22:07:27 +11008858 $menu entryconfigure [mca "Diff this -> marked commit"] -state $mstate
8859 $menu entryconfigure [mca "Diff marked commit -> this"] -state $mstate
Paul Mackerras219ea3a2006-09-07 10:21:39 +10008860 tk_popup $menu $x $y
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008861}
8862
Paul Mackerrasb9fdba72009-04-09 09:34:46 +10008863proc markhere {} {
8864 global rowmenuid markedid canv
8865
8866 set markedid $rowmenuid
8867 make_idmark $markedid
8868}
8869
8870proc gotomark {} {
8871 global markedid
8872
8873 if {[info exists markedid]} {
8874 selbyid $markedid
8875 }
8876}
8877
8878proc replace_by_kids {l r} {
8879 global curview children
8880
8881 set id [commitonrow $r]
8882 set l [lreplace $l 0 0]
8883 foreach kid $children($curview,$id) {
8884 lappend l [rowofcommit $kid]
8885 }
8886 return [lsort -integer -decreasing -unique $l]
8887}
8888
8889proc find_common_desc {} {
8890 global markedid rowmenuid curview children
8891
8892 if {![info exists markedid]} return
8893 if {![commitinview $markedid $curview] ||
8894 ![commitinview $rowmenuid $curview]} return
8895 #set t1 [clock clicks -milliseconds]
8896 set l1 [list [rowofcommit $markedid]]
8897 set l2 [list [rowofcommit $rowmenuid]]
8898 while 1 {
8899 set r1 [lindex $l1 0]
8900 set r2 [lindex $l2 0]
8901 if {$r1 eq {} || $r2 eq {}} break
8902 if {$r1 == $r2} {
8903 selectline $r1 1
8904 break
8905 }
8906 if {$r1 > $r2} {
8907 set l1 [replace_by_kids $l1 $r1]
8908 } else {
8909 set l2 [replace_by_kids $l2 $r2]
8910 }
8911 }
8912 #set t2 [clock clicks -milliseconds]
8913 #puts "took [expr {$t2-$t1}]ms"
8914}
8915
Paul Mackerras010509f2009-04-09 22:10:20 +10008916proc compare_commits {} {
8917 global markedid rowmenuid curview children
8918
8919 if {![info exists markedid]} return
8920 if {![commitinview $markedid $curview]} return
8921 addtohistory [list do_cmp_commits $markedid $rowmenuid]
8922 do_cmp_commits $markedid $rowmenuid
8923}
8924
8925proc getpatchid {id} {
8926 global patchids
8927
8928 if {![info exists patchids($id)]} {
Paul Mackerras6f63fc12009-04-21 22:22:31 +10008929 set cmd [diffcmd [list $id] {-p --root}]
8930 # trim off the initial "|"
8931 set cmd [lrange $cmd 1 end]
8932 if {[catch {
8933 set x [eval exec $cmd | git patch-id]
8934 set patchids($id) [lindex $x 0]
8935 }]} {
8936 set patchids($id) "error"
8937 }
Paul Mackerras010509f2009-04-09 22:10:20 +10008938 }
8939 return $patchids($id)
8940}
8941
8942proc do_cmp_commits {a b} {
8943 global ctext curview parents children patchids commitinfo
8944
8945 $ctext conf -state normal
8946 clear_ctext
8947 init_flist {}
8948 for {set i 0} {$i < 100} {incr i} {
Paul Mackerras010509f2009-04-09 22:10:20 +10008949 set skipa 0
8950 set skipb 0
8951 if {[llength $parents($curview,$a)] > 1} {
Paul Mackerras6f63fc12009-04-21 22:22:31 +10008952 appendshortlink $a [mc "Skipping merge commit "] "\n"
Paul Mackerras010509f2009-04-09 22:10:20 +10008953 set skipa 1
8954 } else {
8955 set patcha [getpatchid $a]
8956 }
8957 if {[llength $parents($curview,$b)] > 1} {
Paul Mackerras6f63fc12009-04-21 22:22:31 +10008958 appendshortlink $b [mc "Skipping merge commit "] "\n"
Paul Mackerras010509f2009-04-09 22:10:20 +10008959 set skipb 1
8960 } else {
8961 set patchb [getpatchid $b]
8962 }
8963 if {!$skipa && !$skipb} {
8964 set heada [lindex $commitinfo($a) 0]
8965 set headb [lindex $commitinfo($b) 0]
Paul Mackerras6f63fc12009-04-21 22:22:31 +10008966 if {$patcha eq "error"} {
8967 appendshortlink $a [mc "Error getting patch ID for "] \
8968 [mc " - stopping\n"]
8969 break
8970 }
8971 if {$patchb eq "error"} {
8972 appendshortlink $b [mc "Error getting patch ID for "] \
8973 [mc " - stopping\n"]
8974 break
8975 }
Paul Mackerras010509f2009-04-09 22:10:20 +10008976 if {$patcha eq $patchb} {
8977 if {$heada eq $headb} {
Paul Mackerras6f63fc12009-04-21 22:22:31 +10008978 appendshortlink $a [mc "Commit "]
8979 appendshortlink $b " == " " $heada\n"
Paul Mackerras010509f2009-04-09 22:10:20 +10008980 } else {
Paul Mackerras6f63fc12009-04-21 22:22:31 +10008981 appendshortlink $a [mc "Commit "] " $heada\n"
8982 appendshortlink $b [mc " is the same patch as\n "] \
8983 " $headb\n"
Paul Mackerras010509f2009-04-09 22:10:20 +10008984 }
8985 set skipa 1
8986 set skipb 1
8987 } else {
8988 $ctext insert end "\n"
Paul Mackerras6f63fc12009-04-21 22:22:31 +10008989 appendshortlink $a [mc "Commit "] " $heada\n"
8990 appendshortlink $b [mc " differs from\n "] \
8991 " $headb\n"
Paul Mackerrasc21398b2009-09-07 10:08:21 +10008992 $ctext insert end [mc "Diff of commits:\n\n"]
8993 $ctext conf -state disabled
8994 update
8995 diffcommits $a $b
8996 return
Paul Mackerras010509f2009-04-09 22:10:20 +10008997 }
8998 }
8999 if {$skipa} {
Paul Mackerrasaa435612009-09-10 21:58:40 +10009000 set kids [real_children $curview,$a]
9001 if {[llength $kids] != 1} {
Paul Mackerras010509f2009-04-09 22:10:20 +10009002 $ctext insert end "\n"
Paul Mackerras6f63fc12009-04-21 22:22:31 +10009003 appendshortlink $a [mc "Commit "] \
Paul Mackerrasaa435612009-09-10 21:58:40 +10009004 [mc " has %s children - stopping\n" [llength $kids]]
Paul Mackerras010509f2009-04-09 22:10:20 +10009005 break
9006 }
Paul Mackerrasaa435612009-09-10 21:58:40 +10009007 set a [lindex $kids 0]
Paul Mackerras010509f2009-04-09 22:10:20 +10009008 }
9009 if {$skipb} {
Paul Mackerrasaa435612009-09-10 21:58:40 +10009010 set kids [real_children $curview,$b]
9011 if {[llength $kids] != 1} {
Paul Mackerras6f63fc12009-04-21 22:22:31 +10009012 appendshortlink $b [mc "Commit "] \
Paul Mackerrasaa435612009-09-10 21:58:40 +10009013 [mc " has %s children - stopping\n" [llength $kids]]
Paul Mackerras010509f2009-04-09 22:10:20 +10009014 break
9015 }
Paul Mackerrasaa435612009-09-10 21:58:40 +10009016 set b [lindex $kids 0]
Paul Mackerras010509f2009-04-09 22:10:20 +10009017 }
9018 }
9019 $ctext conf -state disabled
9020}
9021
Paul Mackerrasc21398b2009-09-07 10:08:21 +10009022proc diffcommits {a b} {
Jens Lehmanna1d383c2010-04-09 22:16:42 +02009023 global diffcontext diffids blobdifffd diffinhdr currdiffsubmod
Paul Mackerrasc21398b2009-09-07 10:08:21 +10009024
9025 set tmpdir [gitknewtmpdir]
9026 set fna [file join $tmpdir "commit-[string range $a 0 7]"]
9027 set fnb [file join $tmpdir "commit-[string range $b 0 7]"]
9028 if {[catch {
9029 exec git diff-tree -p --pretty $a >$fna
9030 exec git diff-tree -p --pretty $b >$fnb
9031 } err]} {
9032 error_popup [mc "Error writing commit to file: %s" $err]
9033 return
9034 }
9035 if {[catch {
9036 set fd [open "| diff -U$diffcontext $fna $fnb" r]
9037 } err]} {
9038 error_popup [mc "Error diffing commits: %s" $err]
9039 return
9040 }
9041 set diffids [list commits $a $b]
9042 set blobdifffd($diffids) $fd
9043 set diffinhdr 0
Jens Lehmanna1d383c2010-04-09 22:16:42 +02009044 set currdiffsubmod ""
Paul Mackerrasc21398b2009-09-07 10:08:21 +10009045 filerun $fd [list getblobdiffline $fd $diffids]
9046}
9047
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10009048proc diffvssel {dirn} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11009049 global rowmenuid selectedline
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10009050
Paul Mackerras94b4a692008-05-20 20:51:06 +10009051 if {$selectedline eq {}} return
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10009052 if {$dirn} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11009053 set oldid [commitonrow $selectedline]
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10009054 set newid $rowmenuid
9055 } else {
9056 set oldid $rowmenuid
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11009057 set newid [commitonrow $selectedline]
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10009058 }
Paul Mackerras354af6b2008-11-23 13:14:23 +11009059 addtohistory [list doseldiff $oldid $newid] savectextpos
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10009060 doseldiff $oldid $newid
9061}
9062
Paul Mackerras6febded2012-03-23 22:07:27 +11009063proc diffvsmark {dirn} {
9064 global rowmenuid markedid
9065
9066 if {![info exists markedid]} return
9067 if {$dirn} {
9068 set oldid $markedid
9069 set newid $rowmenuid
9070 } else {
9071 set oldid $rowmenuid
9072 set newid $markedid
9073 }
9074 addtohistory [list doseldiff $oldid $newid] savectextpos
9075 doseldiff $oldid $newid
9076}
9077
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10009078proc doseldiff {oldid newid} {
Paul Mackerras7fcceed2006-04-27 19:21:49 +10009079 global ctext
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10009080 global commitinfo
9081
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10009082 $ctext conf -state normal
Paul Mackerras3ea06f92006-05-24 10:16:03 +10009083 clear_ctext
Christian Stimmingd990ced2007-11-07 18:42:55 +01009084 init_flist [mc "Top"]
9085 $ctext insert end "[mc "From"] "
Paul Mackerras97645682007-08-23 22:24:38 +10009086 $ctext insert end $oldid link0
9087 setlink $oldid link0
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10009088 $ctext insert end "\n "
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10009089 $ctext insert end [lindex $commitinfo($oldid) 0]
Christian Stimmingd990ced2007-11-07 18:42:55 +01009090 $ctext insert end "\n\n[mc "To"] "
Paul Mackerras97645682007-08-23 22:24:38 +10009091 $ctext insert end $newid link1
9092 setlink $newid link1
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10009093 $ctext insert end "\n "
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10009094 $ctext insert end [lindex $commitinfo($newid) 0]
9095 $ctext insert end "\n"
9096 $ctext conf -state disabled
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10009097 $ctext tag remove found 1.0 end
Paul Mackerrasd3272442005-11-28 20:41:56 +11009098 startdiff [list $oldid $newid]
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10009099}
9100
Paul Mackerras74daedb2005-06-27 19:27:32 +10009101proc mkpatch {} {
Pat Thoytsd93f1712009-04-17 01:24:35 +01009102 global rowmenuid currentid commitinfo patchtop patchnum NS
Paul Mackerras74daedb2005-06-27 19:27:32 +10009103
9104 if {![info exists currentid]} return
9105 set oldid $currentid
9106 set oldhead [lindex $commitinfo($oldid) 0]
9107 set newid $rowmenuid
9108 set newhead [lindex $commitinfo($newid) 0]
9109 set top .patch
9110 set patchtop $top
9111 catch {destroy $top}
Pat Thoytsd93f1712009-04-17 01:24:35 +01009112 ttk_toplevel $top
Alexander Gavrilove7d64002008-11-11 23:55:42 +03009113 make_transient $top .
Pat Thoytsd93f1712009-04-17 01:24:35 +01009114 ${NS}::label $top.title -text [mc "Generate patch"]
Paul Mackerras4a2139f2005-06-29 09:47:48 +10009115 grid $top.title - -pady 10
Pat Thoytsd93f1712009-04-17 01:24:35 +01009116 ${NS}::label $top.from -text [mc "From:"]
9117 ${NS}::entry $top.fromsha1 -width 40
Paul Mackerras74daedb2005-06-27 19:27:32 +10009118 $top.fromsha1 insert 0 $oldid
9119 $top.fromsha1 conf -state readonly
9120 grid $top.from $top.fromsha1 -sticky w
Pat Thoytsd93f1712009-04-17 01:24:35 +01009121 ${NS}::entry $top.fromhead -width 60
Paul Mackerras74daedb2005-06-27 19:27:32 +10009122 $top.fromhead insert 0 $oldhead
9123 $top.fromhead conf -state readonly
9124 grid x $top.fromhead -sticky w
Pat Thoytsd93f1712009-04-17 01:24:35 +01009125 ${NS}::label $top.to -text [mc "To:"]
9126 ${NS}::entry $top.tosha1 -width 40
Paul Mackerras74daedb2005-06-27 19:27:32 +10009127 $top.tosha1 insert 0 $newid
9128 $top.tosha1 conf -state readonly
9129 grid $top.to $top.tosha1 -sticky w
Pat Thoytsd93f1712009-04-17 01:24:35 +01009130 ${NS}::entry $top.tohead -width 60
Paul Mackerras74daedb2005-06-27 19:27:32 +10009131 $top.tohead insert 0 $newhead
9132 $top.tohead conf -state readonly
9133 grid x $top.tohead -sticky w
Pat Thoytsd93f1712009-04-17 01:24:35 +01009134 ${NS}::button $top.rev -text [mc "Reverse"] -command mkpatchrev
9135 grid $top.rev x -pady 10 -padx 5
9136 ${NS}::label $top.flab -text [mc "Output file:"]
9137 ${NS}::entry $top.fname -width 60
Paul Mackerras74daedb2005-06-27 19:27:32 +10009138 $top.fname insert 0 [file normalize "patch$patchnum.patch"]
9139 incr patchnum
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10009140 grid $top.flab $top.fname -sticky w
Pat Thoytsd93f1712009-04-17 01:24:35 +01009141 ${NS}::frame $top.buts
9142 ${NS}::button $top.buts.gen -text [mc "Generate"] -command mkpatchgo
9143 ${NS}::button $top.buts.can -text [mc "Cancel"] -command mkpatchcan
Alexander Gavrilov76f15942008-11-02 21:59:44 +03009144 bind $top <Key-Return> mkpatchgo
9145 bind $top <Key-Escape> mkpatchcan
Paul Mackerras74daedb2005-06-27 19:27:32 +10009146 grid $top.buts.gen $top.buts.can
9147 grid columnconfigure $top.buts 0 -weight 1 -uniform a
9148 grid columnconfigure $top.buts 1 -weight 1 -uniform a
9149 grid $top.buts - -pady 10 -sticky ew
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10009150 focus $top.fname
Paul Mackerras74daedb2005-06-27 19:27:32 +10009151}
9152
9153proc mkpatchrev {} {
9154 global patchtop
9155
9156 set oldid [$patchtop.fromsha1 get]
9157 set oldhead [$patchtop.fromhead get]
9158 set newid [$patchtop.tosha1 get]
9159 set newhead [$patchtop.tohead get]
9160 foreach e [list fromsha1 fromhead tosha1 tohead] \
9161 v [list $newid $newhead $oldid $oldhead] {
9162 $patchtop.$e conf -state normal
9163 $patchtop.$e delete 0 end
9164 $patchtop.$e insert 0 $v
9165 $patchtop.$e conf -state readonly
9166 }
9167}
9168
9169proc mkpatchgo {} {
Paul Mackerras8f489362007-07-13 19:49:37 +10009170 global patchtop nullid nullid2
Paul Mackerras74daedb2005-06-27 19:27:32 +10009171
9172 set oldid [$patchtop.fromsha1 get]
9173 set newid [$patchtop.tosha1 get]
9174 set fname [$patchtop.fname get]
Paul Mackerras8f489362007-07-13 19:49:37 +10009175 set cmd [diffcmd [list $oldid $newid] -p]
Paul Mackerrasd372e212007-09-15 12:08:38 +10009176 # trim off the initial "|"
9177 set cmd [lrange $cmd 1 end]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10009178 lappend cmd >$fname &
9179 if {[catch {eval exec $cmd} err]} {
Alexander Gavrilov84a76f12008-11-02 21:59:45 +03009180 error_popup "[mc "Error creating patch:"] $err" $patchtop
Paul Mackerras74daedb2005-06-27 19:27:32 +10009181 }
9182 catch {destroy $patchtop}
9183 unset patchtop
9184}
9185
9186proc mkpatchcan {} {
9187 global patchtop
9188
9189 catch {destroy $patchtop}
9190 unset patchtop
9191}
9192
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10009193proc mktag {} {
Pat Thoytsd93f1712009-04-17 01:24:35 +01009194 global rowmenuid mktagtop commitinfo NS
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10009195
9196 set top .maketag
9197 set mktagtop $top
9198 catch {destroy $top}
Pat Thoytsd93f1712009-04-17 01:24:35 +01009199 ttk_toplevel $top
Alexander Gavrilove7d64002008-11-11 23:55:42 +03009200 make_transient $top .
Pat Thoytsd93f1712009-04-17 01:24:35 +01009201 ${NS}::label $top.title -text [mc "Create tag"]
Paul Mackerras4a2139f2005-06-29 09:47:48 +10009202 grid $top.title - -pady 10
Pat Thoytsd93f1712009-04-17 01:24:35 +01009203 ${NS}::label $top.id -text [mc "ID:"]
9204 ${NS}::entry $top.sha1 -width 40
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10009205 $top.sha1 insert 0 $rowmenuid
9206 $top.sha1 conf -state readonly
9207 grid $top.id $top.sha1 -sticky w
Pat Thoytsd93f1712009-04-17 01:24:35 +01009208 ${NS}::entry $top.head -width 60
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10009209 $top.head insert 0 [lindex $commitinfo($rowmenuid) 0]
9210 $top.head conf -state readonly
9211 grid x $top.head -sticky w
Pat Thoytsd93f1712009-04-17 01:24:35 +01009212 ${NS}::label $top.tlab -text [mc "Tag name:"]
9213 ${NS}::entry $top.tag -width 60
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10009214 grid $top.tlab $top.tag -sticky w
Dave Dulsondfb891e2010-01-03 14:55:52 +00009215 ${NS}::label $top.op -text [mc "Tag message is optional"]
9216 grid $top.op -columnspan 2 -sticky we
9217 ${NS}::label $top.mlab -text [mc "Tag message:"]
9218 ${NS}::entry $top.msg -width 60
9219 grid $top.mlab $top.msg -sticky w
Pat Thoytsd93f1712009-04-17 01:24:35 +01009220 ${NS}::frame $top.buts
9221 ${NS}::button $top.buts.gen -text [mc "Create"] -command mktaggo
9222 ${NS}::button $top.buts.can -text [mc "Cancel"] -command mktagcan
Alexander Gavrilov76f15942008-11-02 21:59:44 +03009223 bind $top <Key-Return> mktaggo
9224 bind $top <Key-Escape> mktagcan
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10009225 grid $top.buts.gen $top.buts.can
9226 grid columnconfigure $top.buts 0 -weight 1 -uniform a
9227 grid columnconfigure $top.buts 1 -weight 1 -uniform a
9228 grid $top.buts - -pady 10 -sticky ew
9229 focus $top.tag
9230}
9231
9232proc domktag {} {
9233 global mktagtop env tagids idtags
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10009234
9235 set id [$mktagtop.sha1 get]
9236 set tag [$mktagtop.tag get]
Dave Dulsondfb891e2010-01-03 14:55:52 +00009237 set msg [$mktagtop.msg get]
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10009238 if {$tag == {}} {
Alexander Gavrilov84a76f12008-11-02 21:59:45 +03009239 error_popup [mc "No tag name specified"] $mktagtop
9240 return 0
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10009241 }
9242 if {[info exists tagids($tag)]} {
Alexander Gavrilov84a76f12008-11-02 21:59:45 +03009243 error_popup [mc "Tag \"%s\" already exists" $tag] $mktagtop
9244 return 0
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10009245 }
9246 if {[catch {
Dave Dulsondfb891e2010-01-03 14:55:52 +00009247 if {$msg != {}} {
9248 exec git tag -a -m $msg $tag $id
9249 } else {
9250 exec git tag $tag $id
9251 }
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10009252 } err]} {
Alexander Gavrilov84a76f12008-11-02 21:59:45 +03009253 error_popup "[mc "Error creating tag:"] $err" $mktagtop
9254 return 0
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10009255 }
9256
9257 set tagids($tag) $id
9258 lappend idtags($id) $tag
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10009259 redrawtags $id
Paul Mackerrasceadfe92006-08-08 20:55:36 +10009260 addedtag $id
Paul Mackerras887c9962007-08-20 19:36:20 +10009261 dispneartags 0
9262 run refill_reflist
Alexander Gavrilov84a76f12008-11-02 21:59:45 +03009263 return 1
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10009264}
9265
9266proc redrawtags {id} {
Paul Mackerrasb9fdba72009-04-09 09:34:46 +10009267 global canv linehtag idpos currentid curview cmitlisted markedid
Paul Mackerrasc11ff122008-05-26 10:11:33 +10009268 global canvxmax iddrawn circleitem mainheadid circlecolors
Gauthier Östervall252c52d2013-03-27 14:40:51 +01009269 global mainheadcirclecolor
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10009270
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11009271 if {![commitinview $id $curview]} return
Paul Mackerras322a8cc2006-10-15 18:03:46 +10009272 if {![info exists iddrawn($id)]} return
Paul Mackerrasfc2a2562007-12-26 23:03:43 +11009273 set row [rowofcommit $id]
Paul Mackerrasc11ff122008-05-26 10:11:33 +10009274 if {$id eq $mainheadid} {
Gauthier Östervall252c52d2013-03-27 14:40:51 +01009275 set ofill $mainheadcirclecolor
Paul Mackerrasc11ff122008-05-26 10:11:33 +10009276 } else {
9277 set ofill [lindex $circlecolors $cmitlisted($curview,$id)]
9278 }
9279 $canv itemconf $circleitem($row) -fill $ofill
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10009280 $canv delete tag.$id
9281 set xt [eval drawtags $id $idpos($id)]
Paul Mackerras28593d32008-11-13 23:01:46 +11009282 $canv coords $linehtag($id) $xt [lindex $idpos($id) 2]
9283 set text [$canv itemcget $linehtag($id) -text]
9284 set font [$canv itemcget $linehtag($id) -font]
Paul Mackerrasfc2a2562007-12-26 23:03:43 +11009285 set xr [expr {$xt + [font measure $font $text]}]
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10009286 if {$xr > $canvxmax} {
9287 set canvxmax $xr
9288 setcanvscroll
9289 }
Paul Mackerrasfc2a2562007-12-26 23:03:43 +11009290 if {[info exists currentid] && $currentid == $id} {
Paul Mackerras28593d32008-11-13 23:01:46 +11009291 make_secsel $id
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10009292 }
Paul Mackerrasb9fdba72009-04-09 09:34:46 +10009293 if {[info exists markedid] && $markedid eq $id} {
9294 make_idmark $id
9295 }
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10009296}
9297
9298proc mktagcan {} {
9299 global mktagtop
9300
9301 catch {destroy $mktagtop}
9302 unset mktagtop
9303}
9304
9305proc mktaggo {} {
Alexander Gavrilov84a76f12008-11-02 21:59:45 +03009306 if {![domktag]} return
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10009307 mktagcan
9308}
9309
Paul Mackerras4a2139f2005-06-29 09:47:48 +10009310proc writecommit {} {
Pat Thoytsd93f1712009-04-17 01:24:35 +01009311 global rowmenuid wrcomtop commitinfo wrcomcmd NS
Paul Mackerras4a2139f2005-06-29 09:47:48 +10009312
9313 set top .writecommit
9314 set wrcomtop $top
9315 catch {destroy $top}
Pat Thoytsd93f1712009-04-17 01:24:35 +01009316 ttk_toplevel $top
Alexander Gavrilove7d64002008-11-11 23:55:42 +03009317 make_transient $top .
Pat Thoytsd93f1712009-04-17 01:24:35 +01009318 ${NS}::label $top.title -text [mc "Write commit to file"]
Paul Mackerras4a2139f2005-06-29 09:47:48 +10009319 grid $top.title - -pady 10
Pat Thoytsd93f1712009-04-17 01:24:35 +01009320 ${NS}::label $top.id -text [mc "ID:"]
9321 ${NS}::entry $top.sha1 -width 40
Paul Mackerras4a2139f2005-06-29 09:47:48 +10009322 $top.sha1 insert 0 $rowmenuid
9323 $top.sha1 conf -state readonly
9324 grid $top.id $top.sha1 -sticky w
Pat Thoytsd93f1712009-04-17 01:24:35 +01009325 ${NS}::entry $top.head -width 60
Paul Mackerras4a2139f2005-06-29 09:47:48 +10009326 $top.head insert 0 [lindex $commitinfo($rowmenuid) 0]
9327 $top.head conf -state readonly
9328 grid x $top.head -sticky w
Pat Thoytsd93f1712009-04-17 01:24:35 +01009329 ${NS}::label $top.clab -text [mc "Command:"]
9330 ${NS}::entry $top.cmd -width 60 -textvariable wrcomcmd
Paul Mackerras4a2139f2005-06-29 09:47:48 +10009331 grid $top.clab $top.cmd -sticky w -pady 10
Pat Thoytsd93f1712009-04-17 01:24:35 +01009332 ${NS}::label $top.flab -text [mc "Output file:"]
9333 ${NS}::entry $top.fname -width 60
Paul Mackerras4a2139f2005-06-29 09:47:48 +10009334 $top.fname insert 0 [file normalize "commit-[string range $rowmenuid 0 6]"]
9335 grid $top.flab $top.fname -sticky w
Pat Thoytsd93f1712009-04-17 01:24:35 +01009336 ${NS}::frame $top.buts
9337 ${NS}::button $top.buts.gen -text [mc "Write"] -command wrcomgo
9338 ${NS}::button $top.buts.can -text [mc "Cancel"] -command wrcomcan
Alexander Gavrilov76f15942008-11-02 21:59:44 +03009339 bind $top <Key-Return> wrcomgo
9340 bind $top <Key-Escape> wrcomcan
Paul Mackerras4a2139f2005-06-29 09:47:48 +10009341 grid $top.buts.gen $top.buts.can
9342 grid columnconfigure $top.buts 0 -weight 1 -uniform a
9343 grid columnconfigure $top.buts 1 -weight 1 -uniform a
9344 grid $top.buts - -pady 10 -sticky ew
9345 focus $top.fname
9346}
9347
9348proc wrcomgo {} {
9349 global wrcomtop
9350
9351 set id [$wrcomtop.sha1 get]
9352 set cmd "echo $id | [$wrcomtop.cmd get]"
9353 set fname [$wrcomtop.fname get]
9354 if {[catch {exec sh -c $cmd >$fname &} err]} {
Alexander Gavrilov84a76f12008-11-02 21:59:45 +03009355 error_popup "[mc "Error writing commit:"] $err" $wrcomtop
Paul Mackerras4a2139f2005-06-29 09:47:48 +10009356 }
9357 catch {destroy $wrcomtop}
9358 unset wrcomtop
9359}
9360
9361proc wrcomcan {} {
9362 global wrcomtop
9363
9364 catch {destroy $wrcomtop}
9365 unset wrcomtop
9366}
9367
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10009368proc mkbranch {} {
Pat Thoytsd93f1712009-04-17 01:24:35 +01009369 global rowmenuid mkbrtop NS
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10009370
9371 set top .makebranch
9372 catch {destroy $top}
Pat Thoytsd93f1712009-04-17 01:24:35 +01009373 ttk_toplevel $top
Alexander Gavrilove7d64002008-11-11 23:55:42 +03009374 make_transient $top .
Pat Thoytsd93f1712009-04-17 01:24:35 +01009375 ${NS}::label $top.title -text [mc "Create new branch"]
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10009376 grid $top.title - -pady 10
Pat Thoytsd93f1712009-04-17 01:24:35 +01009377 ${NS}::label $top.id -text [mc "ID:"]
9378 ${NS}::entry $top.sha1 -width 40
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10009379 $top.sha1 insert 0 $rowmenuid
9380 $top.sha1 conf -state readonly
9381 grid $top.id $top.sha1 -sticky w
Pat Thoytsd93f1712009-04-17 01:24:35 +01009382 ${NS}::label $top.nlab -text [mc "Name:"]
9383 ${NS}::entry $top.name -width 40
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10009384 grid $top.nlab $top.name -sticky w
Pat Thoytsd93f1712009-04-17 01:24:35 +01009385 ${NS}::frame $top.buts
9386 ${NS}::button $top.buts.go -text [mc "Create"] -command [list mkbrgo $top]
9387 ${NS}::button $top.buts.can -text [mc "Cancel"] -command "catch {destroy $top}"
Alexander Gavrilov76f15942008-11-02 21:59:44 +03009388 bind $top <Key-Return> [list mkbrgo $top]
9389 bind $top <Key-Escape> "catch {destroy $top}"
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10009390 grid $top.buts.go $top.buts.can
9391 grid columnconfigure $top.buts 0 -weight 1 -uniform a
9392 grid columnconfigure $top.buts 1 -weight 1 -uniform a
9393 grid $top.buts - -pady 10 -sticky ew
9394 focus $top.name
9395}
9396
9397proc mkbrgo {top} {
9398 global headids idheads
9399
9400 set name [$top.name get]
9401 set id [$top.sha1 get]
Alexander Gavrilovbee866f2008-10-08 11:05:35 +04009402 set cmdargs {}
9403 set old_id {}
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10009404 if {$name eq {}} {
Alexander Gavrilov84a76f12008-11-02 21:59:45 +03009405 error_popup [mc "Please specify a name for the new branch"] $top
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10009406 return
9407 }
Alexander Gavrilovbee866f2008-10-08 11:05:35 +04009408 if {[info exists headids($name)]} {
9409 if {![confirm_popup [mc \
Alexander Gavrilov84a76f12008-11-02 21:59:45 +03009410 "Branch '%s' already exists. Overwrite?" $name] $top]} {
Alexander Gavrilovbee866f2008-10-08 11:05:35 +04009411 return
9412 }
9413 set old_id $headids($name)
9414 lappend cmdargs -f
9415 }
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10009416 catch {destroy $top}
Alexander Gavrilovbee866f2008-10-08 11:05:35 +04009417 lappend cmdargs $name $id
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10009418 nowbusy newbranch
9419 update
9420 if {[catch {
Alexander Gavrilovbee866f2008-10-08 11:05:35 +04009421 eval exec git branch $cmdargs
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10009422 } err]} {
9423 notbusy newbranch
9424 error_popup $err
9425 } else {
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10009426 notbusy newbranch
Alexander Gavrilovbee866f2008-10-08 11:05:35 +04009427 if {$old_id ne {}} {
9428 movehead $id $name
9429 movedhead $id $name
9430 redrawtags $old_id
9431 redrawtags $id
9432 } else {
9433 set headids($name) $id
9434 lappend idheads($id) $name
9435 addedhead $id $name
9436 redrawtags $id
9437 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10009438 dispneartags 0
Paul Mackerras887c9962007-08-20 19:36:20 +10009439 run refill_reflist
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10009440 }
9441}
9442
Alexander Gavrilov15e35052008-11-02 21:59:47 +03009443proc exec_citool {tool_args {baseid {}}} {
9444 global commitinfo env
9445
9446 set save_env [array get env GIT_AUTHOR_*]
9447
9448 if {$baseid ne {}} {
9449 if {![info exists commitinfo($baseid)]} {
9450 getcommit $baseid
9451 }
9452 set author [lindex $commitinfo($baseid) 1]
9453 set date [lindex $commitinfo($baseid) 2]
9454 if {[regexp {^\s*(\S.*\S|\S)\s*<(.*)>\s*$} \
9455 $author author name email]
9456 && $date ne {}} {
9457 set env(GIT_AUTHOR_NAME) $name
9458 set env(GIT_AUTHOR_EMAIL) $email
9459 set env(GIT_AUTHOR_DATE) $date
9460 }
9461 }
9462
9463 eval exec git citool $tool_args &
9464
9465 array unset env GIT_AUTHOR_*
9466 array set env $save_env
9467}
9468
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10009469proc cherrypick {} {
Paul Mackerras468bcae2008-03-03 10:19:35 +11009470 global rowmenuid curview
Paul Mackerrasb8a938c2008-02-13 22:12:31 +11009471 global mainhead mainheadid
Martin von Zweigbergkda616db2011-04-04 22:14:17 -04009472 global gitdir
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10009473
Paul Mackerrase11f1232007-06-16 20:29:25 +10009474 set oldhead [exec git rev-parse HEAD]
9475 set dheads [descheads $rowmenuid]
9476 if {$dheads ne {} && [lsearch -exact $dheads $oldhead] >= 0} {
Christian Stimmingd990ced2007-11-07 18:42:55 +01009477 set ok [confirm_popup [mc "Commit %s is already\
9478 included in branch %s -- really re-apply it?" \
9479 [string range $rowmenuid 0 7] $mainhead]]
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10009480 if {!$ok} return
9481 }
Christian Stimmingd990ced2007-11-07 18:42:55 +01009482 nowbusy cherrypick [mc "Cherry-picking"]
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10009483 update
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10009484 # Unfortunately git-cherry-pick writes stuff to stderr even when
9485 # no error occurs, and exec takes that as an indication of error...
9486 if {[catch {exec sh -c "git cherry-pick -r $rowmenuid 2>&1"} err]} {
9487 notbusy cherrypick
Alexander Gavrilov15e35052008-11-02 21:59:47 +03009488 if {[regexp -line \
Paul Mackerras887a7912008-11-08 21:37:09 +11009489 {Entry '(.*)' (would be overwritten by merge|not uptodate)} \
9490 $err msg fname]} {
9491 error_popup [mc "Cherry-pick failed because of local changes\
9492 to file '%s'.\nPlease commit, reset or stash\
9493 your changes and try again." $fname]
9494 } elseif {[regexp -line \
Anders Kaseorgb74307f2011-01-19 14:45:00 -05009495 {^(CONFLICT \(.*\):|Automatic cherry-pick failed|error: could not apply)} \
Paul Mackerras887a7912008-11-08 21:37:09 +11009496 $err]} {
9497 if {[confirm_popup [mc "Cherry-pick failed because of merge\
9498 conflict.\nDo you wish to run git citool to\
9499 resolve it?"]]} {
9500 # Force citool to read MERGE_MSG
Martin von Zweigbergkda616db2011-04-04 22:14:17 -04009501 file delete [file join $gitdir "GITGUI_MSG"]
Paul Mackerras887a7912008-11-08 21:37:09 +11009502 exec_citool {} $rowmenuid
9503 }
Alexander Gavrilov15e35052008-11-02 21:59:47 +03009504 } else {
9505 error_popup $err
9506 }
Paul Mackerras887a7912008-11-08 21:37:09 +11009507 run updatecommits
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10009508 return
9509 }
9510 set newhead [exec git rev-parse HEAD]
9511 if {$newhead eq $oldhead} {
9512 notbusy cherrypick
Christian Stimmingd990ced2007-11-07 18:42:55 +01009513 error_popup [mc "No changes committed"]
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10009514 return
9515 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10009516 addnewchild $newhead $oldhead
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11009517 if {[commitinview $oldhead $curview]} {
Paul Mackerrascdc84292008-11-18 19:54:14 +11009518 # XXX this isn't right if we have a path limit...
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11009519 insertrow $newhead $oldhead $curview
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10009520 if {$mainhead ne {}} {
Paul Mackerrase11f1232007-06-16 20:29:25 +10009521 movehead $newhead $mainhead
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10009522 movedhead $newhead $mainhead
9523 }
Paul Mackerrasc11ff122008-05-26 10:11:33 +10009524 set mainheadid $newhead
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10009525 redrawtags $oldhead
9526 redrawtags $newhead
Paul Mackerras46308ea2008-01-15 22:16:32 +11009527 selbyid $newhead
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10009528 }
9529 notbusy cherrypick
9530}
9531
Knut Franke8f3ff932013-04-27 16:36:13 +02009532proc revert {} {
9533 global rowmenuid curview
9534 global mainhead mainheadid
9535 global gitdir
9536
9537 set oldhead [exec git rev-parse HEAD]
9538 set dheads [descheads $rowmenuid]
9539 if { $dheads eq {} || [lsearch -exact $dheads $oldhead] == -1 } {
9540 set ok [confirm_popup [mc "Commit %s is not\
9541 included in branch %s -- really revert it?" \
9542 [string range $rowmenuid 0 7] $mainhead]]
9543 if {!$ok} return
9544 }
9545 nowbusy revert [mc "Reverting"]
9546 update
9547
9548 if [catch {exec git revert --no-edit $rowmenuid} err] {
9549 notbusy revert
9550 if [regexp {files would be overwritten by merge:(\n(( |\t)+[^\n]+\n)+)}\
9551 $err match files] {
9552 regsub {\n( |\t)+} $files "\n" files
9553 error_popup [mc "Revert failed because of local changes to\
9554 the following files:%s Please commit, reset or stash \
9555 your changes and try again." $files]
9556 } elseif [regexp {error: could not revert} $err] {
9557 if [confirm_popup [mc "Revert failed because of merge conflict.\n\
9558 Do you wish to run git citool to resolve it?"]] {
9559 # Force citool to read MERGE_MSG
9560 file delete [file join $gitdir "GITGUI_MSG"]
9561 exec_citool {} $rowmenuid
9562 }
9563 } else { error_popup $err }
9564 run updatecommits
9565 return
9566 }
9567
9568 set newhead [exec git rev-parse HEAD]
9569 if { $newhead eq $oldhead } {
9570 notbusy revert
9571 error_popup [mc "No changes committed"]
9572 return
9573 }
9574
9575 addnewchild $newhead $oldhead
9576
9577 if [commitinview $oldhead $curview] {
9578 # XXX this isn't right if we have a path limit...
9579 insertrow $newhead $oldhead $curview
9580 if {$mainhead ne {}} {
9581 movehead $newhead $mainhead
9582 movedhead $newhead $mainhead
9583 }
9584 set mainheadid $newhead
9585 redrawtags $oldhead
9586 redrawtags $newhead
9587 selbyid $newhead
9588 }
9589
9590 notbusy revert
9591}
9592
Paul Mackerras6fb735a2006-10-19 10:09:06 +10009593proc resethead {} {
Pat Thoytsd93f1712009-04-17 01:24:35 +01009594 global mainhead rowmenuid confirm_ok resettype NS
Paul Mackerras6fb735a2006-10-19 10:09:06 +10009595
9596 set confirm_ok 0
9597 set w ".confirmreset"
Pat Thoytsd93f1712009-04-17 01:24:35 +01009598 ttk_toplevel $w
Alexander Gavrilove7d64002008-11-11 23:55:42 +03009599 make_transient $w .
Christian Stimmingd990ced2007-11-07 18:42:55 +01009600 wm title $w [mc "Confirm reset"]
Pat Thoytsd93f1712009-04-17 01:24:35 +01009601 ${NS}::label $w.m -text \
9602 [mc "Reset branch %s to %s?" $mainhead [string range $rowmenuid 0 7]]
Paul Mackerras6fb735a2006-10-19 10:09:06 +10009603 pack $w.m -side top -fill x -padx 20 -pady 20
Pat Thoytsd93f1712009-04-17 01:24:35 +01009604 ${NS}::labelframe $w.f -text [mc "Reset type:"]
Paul Mackerras6fb735a2006-10-19 10:09:06 +10009605 set resettype mixed
Pat Thoytsd93f1712009-04-17 01:24:35 +01009606 ${NS}::radiobutton $w.f.soft -value soft -variable resettype \
Christian Stimmingd990ced2007-11-07 18:42:55 +01009607 -text [mc "Soft: Leave working tree and index untouched"]
Paul Mackerras6fb735a2006-10-19 10:09:06 +10009608 grid $w.f.soft -sticky w
Pat Thoytsd93f1712009-04-17 01:24:35 +01009609 ${NS}::radiobutton $w.f.mixed -value mixed -variable resettype \
Christian Stimmingd990ced2007-11-07 18:42:55 +01009610 -text [mc "Mixed: Leave working tree untouched, reset index"]
Paul Mackerras6fb735a2006-10-19 10:09:06 +10009611 grid $w.f.mixed -sticky w
Pat Thoytsd93f1712009-04-17 01:24:35 +01009612 ${NS}::radiobutton $w.f.hard -value hard -variable resettype \
Christian Stimmingd990ced2007-11-07 18:42:55 +01009613 -text [mc "Hard: Reset working tree and index\n(discard ALL local changes)"]
Paul Mackerras6fb735a2006-10-19 10:09:06 +10009614 grid $w.f.hard -sticky w
Pat Thoytsd93f1712009-04-17 01:24:35 +01009615 pack $w.f -side top -fill x -padx 4
9616 ${NS}::button $w.ok -text [mc OK] -command "set confirm_ok 1; destroy $w"
Paul Mackerras6fb735a2006-10-19 10:09:06 +10009617 pack $w.ok -side left -fill x -padx 20 -pady 20
Pat Thoytsd93f1712009-04-17 01:24:35 +01009618 ${NS}::button $w.cancel -text [mc Cancel] -command "destroy $w"
Alexander Gavrilov76f15942008-11-02 21:59:44 +03009619 bind $w <Key-Escape> [list destroy $w]
Paul Mackerras6fb735a2006-10-19 10:09:06 +10009620 pack $w.cancel -side right -fill x -padx 20 -pady 20
9621 bind $w <Visibility> "grab $w; focus $w"
9622 tkwait window $w
9623 if {!$confirm_ok} return
Paul Mackerras706d6c32007-06-26 11:09:49 +10009624 if {[catch {set fd [open \
Paul Mackerras08ba8202008-05-12 10:18:38 +10009625 [list | git reset --$resettype $rowmenuid 2>@1] r]} err]} {
Paul Mackerras6fb735a2006-10-19 10:09:06 +10009626 error_popup $err
9627 } else {
Paul Mackerras706d6c32007-06-26 11:09:49 +10009628 dohidelocalchanges
Paul Mackerrasa137a902007-10-23 21:12:49 +10009629 filerun $fd [list readresetstat $fd]
Christian Stimmingd990ced2007-11-07 18:42:55 +01009630 nowbusy reset [mc "Resetting"]
Paul Mackerras46308ea2008-01-15 22:16:32 +11009631 selbyid $rowmenuid
Paul Mackerras706d6c32007-06-26 11:09:49 +10009632 }
9633}
9634
Paul Mackerrasa137a902007-10-23 21:12:49 +10009635proc readresetstat {fd} {
9636 global mainhead mainheadid showlocalchanges rprogcoord
Paul Mackerras706d6c32007-06-26 11:09:49 +10009637
9638 if {[gets $fd line] >= 0} {
9639 if {[regexp {([0-9]+)% \(([0-9]+)/([0-9]+)\)} $line match p m n]} {
Paul Mackerrasa137a902007-10-23 21:12:49 +10009640 set rprogcoord [expr {1.0 * $m / $n}]
9641 adjustprogress
Paul Mackerras706d6c32007-06-26 11:09:49 +10009642 }
9643 return 1
9644 }
Paul Mackerrasa137a902007-10-23 21:12:49 +10009645 set rprogcoord 0
9646 adjustprogress
Paul Mackerras706d6c32007-06-26 11:09:49 +10009647 notbusy reset
9648 if {[catch {close $fd} err]} {
9649 error_popup $err
9650 }
9651 set oldhead $mainheadid
9652 set newhead [exec git rev-parse HEAD]
9653 if {$newhead ne $oldhead} {
9654 movehead $newhead $mainhead
9655 movedhead $newhead $mainhead
9656 set mainheadid $newhead
Paul Mackerras6fb735a2006-10-19 10:09:06 +10009657 redrawtags $oldhead
Paul Mackerras706d6c32007-06-26 11:09:49 +10009658 redrawtags $newhead
Paul Mackerras6fb735a2006-10-19 10:09:06 +10009659 }
9660 if {$showlocalchanges} {
9661 doshowlocalchanges
9662 }
Paul Mackerras706d6c32007-06-26 11:09:49 +10009663 return 0
Paul Mackerras6fb735a2006-10-19 10:09:06 +10009664}
9665
Paul Mackerras10299152006-08-02 09:52:01 +10009666# context menu for a head
9667proc headmenu {x y id head} {
Paul Mackerras00609462007-06-17 17:08:35 +10009668 global headmenuid headmenuhead headctxmenu mainhead
Paul Mackerras10299152006-08-02 09:52:01 +10009669
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10009670 stopfinding
Paul Mackerras10299152006-08-02 09:52:01 +10009671 set headmenuid $id
9672 set headmenuhead $head
Paul Mackerras00609462007-06-17 17:08:35 +10009673 set state normal
Sitaram Chamarty70a5fc42009-11-03 21:30:12 +05309674 if {[string match "remotes/*" $head]} {
9675 set state disabled
9676 }
Paul Mackerras00609462007-06-17 17:08:35 +10009677 if {$head eq $mainhead} {
9678 set state disabled
9679 }
9680 $headctxmenu entryconfigure 0 -state $state
9681 $headctxmenu entryconfigure 1 -state $state
Paul Mackerras10299152006-08-02 09:52:01 +10009682 tk_popup $headctxmenu $x $y
9683}
9684
9685proc cobranch {} {
Paul Mackerrasc11ff122008-05-26 10:11:33 +10009686 global headmenuid headmenuhead headids
Paul Mackerrascdc84292008-11-18 19:54:14 +11009687 global showlocalchanges
Paul Mackerras10299152006-08-02 09:52:01 +10009688
9689 # check the tree is clean first??
Christian Stimmingd990ced2007-11-07 18:42:55 +01009690 nowbusy checkout [mc "Checking out"]
Paul Mackerras10299152006-08-02 09:52:01 +10009691 update
Paul Mackerras219ea3a2006-09-07 10:21:39 +10009692 dohidelocalchanges
Paul Mackerras10299152006-08-02 09:52:01 +10009693 if {[catch {
Paul Mackerras08ba8202008-05-12 10:18:38 +10009694 set fd [open [list | git checkout $headmenuhead 2>@1] r]
Paul Mackerras10299152006-08-02 09:52:01 +10009695 } err]} {
9696 notbusy checkout
9697 error_popup $err
Paul Mackerras08ba8202008-05-12 10:18:38 +10009698 if {$showlocalchanges} {
9699 dodiffindex
Paul Mackerras10299152006-08-02 09:52:01 +10009700 }
Paul Mackerras08ba8202008-05-12 10:18:38 +10009701 } else {
9702 filerun $fd [list readcheckoutstat $fd $headmenuhead $headmenuid]
Paul Mackerras6fb735a2006-10-19 10:09:06 +10009703 }
Paul Mackerras08ba8202008-05-12 10:18:38 +10009704}
9705
9706proc readcheckoutstat {fd newhead newheadid} {
9707 global mainhead mainheadid headids showlocalchanges progresscoords
Paul Mackerrascdc84292008-11-18 19:54:14 +11009708 global viewmainheadid curview
Paul Mackerras08ba8202008-05-12 10:18:38 +10009709
9710 if {[gets $fd line] >= 0} {
9711 if {[regexp {([0-9]+)% \(([0-9]+)/([0-9]+)\)} $line match p m n]} {
9712 set progresscoords [list 0 [expr {1.0 * $m / $n}]]
9713 adjustprogress
9714 }
9715 return 1
9716 }
9717 set progresscoords {0 0}
9718 adjustprogress
9719 notbusy checkout
9720 if {[catch {close $fd} err]} {
9721 error_popup $err
9722 }
Paul Mackerrasc11ff122008-05-26 10:11:33 +10009723 set oldmainid $mainheadid
Paul Mackerras08ba8202008-05-12 10:18:38 +10009724 set mainhead $newhead
9725 set mainheadid $newheadid
Paul Mackerrascdc84292008-11-18 19:54:14 +11009726 set viewmainheadid($curview) $newheadid
Paul Mackerrasc11ff122008-05-26 10:11:33 +10009727 redrawtags $oldmainid
Paul Mackerras08ba8202008-05-12 10:18:38 +10009728 redrawtags $newheadid
9729 selbyid $newheadid
Paul Mackerras6fb735a2006-10-19 10:09:06 +10009730 if {$showlocalchanges} {
9731 dodiffindex
Paul Mackerras10299152006-08-02 09:52:01 +10009732 }
9733}
9734
9735proc rmbranch {} {
Paul Mackerrase11f1232007-06-16 20:29:25 +10009736 global headmenuid headmenuhead mainhead
Paul Mackerrasb1054ac2007-08-15 10:09:47 +10009737 global idheads
Paul Mackerras10299152006-08-02 09:52:01 +10009738
9739 set head $headmenuhead
9740 set id $headmenuid
Paul Mackerras00609462007-06-17 17:08:35 +10009741 # this check shouldn't be needed any more...
Paul Mackerras10299152006-08-02 09:52:01 +10009742 if {$head eq $mainhead} {
Christian Stimmingd990ced2007-11-07 18:42:55 +01009743 error_popup [mc "Cannot delete the currently checked-out branch"]
Paul Mackerras10299152006-08-02 09:52:01 +10009744 return
9745 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10009746 set dheads [descheads $id]
Paul Mackerrasd7b16112007-08-17 17:57:31 +10009747 if {[llength $dheads] == 1 && $idheads($dheads) eq $head} {
Paul Mackerras10299152006-08-02 09:52:01 +10009748 # the stuff on this branch isn't on any other branch
Christian Stimmingd990ced2007-11-07 18:42:55 +01009749 if {![confirm_popup [mc "The commits on branch %s aren't on any other\
9750 branch.\nReally delete branch %s?" $head $head]]} return
Paul Mackerras10299152006-08-02 09:52:01 +10009751 }
9752 nowbusy rmbranch
9753 update
9754 if {[catch {exec git branch -D $head} err]} {
9755 notbusy rmbranch
9756 error_popup $err
9757 return
9758 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10009759 removehead $id $head
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10009760 removedhead $id $head
Paul Mackerras10299152006-08-02 09:52:01 +10009761 redrawtags $id
9762 notbusy rmbranch
Paul Mackerrase11f1232007-06-16 20:29:25 +10009763 dispneartags 0
Paul Mackerras887c9962007-08-20 19:36:20 +10009764 run refill_reflist
9765}
9766
9767# Display a list of tags and heads
9768proc showrefs {} {
Pat Thoytsd93f1712009-04-17 01:24:35 +01009769 global showrefstop bgcolor fgcolor selectbgcolor NS
Paul Mackerras9c311b32007-10-04 22:27:13 +10009770 global bglist fglist reflistfilter reflist maincursor
Paul Mackerras887c9962007-08-20 19:36:20 +10009771
9772 set top .showrefs
9773 set showrefstop $top
9774 if {[winfo exists $top]} {
9775 raise $top
9776 refill_reflist
9777 return
9778 }
Pat Thoytsd93f1712009-04-17 01:24:35 +01009779 ttk_toplevel $top
Christian Stimmingd990ced2007-11-07 18:42:55 +01009780 wm title $top [mc "Tags and heads: %s" [file tail [pwd]]]
Alexander Gavrilove7d64002008-11-11 23:55:42 +03009781 make_transient $top .
Paul Mackerras887c9962007-08-20 19:36:20 +10009782 text $top.list -background $bgcolor -foreground $fgcolor \
Paul Mackerras9c311b32007-10-04 22:27:13 +10009783 -selectbackground $selectbgcolor -font mainfont \
Paul Mackerras887c9962007-08-20 19:36:20 +10009784 -xscrollcommand "$top.xsb set" -yscrollcommand "$top.ysb set" \
9785 -width 30 -height 20 -cursor $maincursor \
9786 -spacing1 1 -spacing3 1 -state disabled
9787 $top.list tag configure highlight -background $selectbgcolor
9788 lappend bglist $top.list
9789 lappend fglist $top.list
Pat Thoytsd93f1712009-04-17 01:24:35 +01009790 ${NS}::scrollbar $top.ysb -command "$top.list yview" -orient vertical
9791 ${NS}::scrollbar $top.xsb -command "$top.list xview" -orient horizontal
Paul Mackerras887c9962007-08-20 19:36:20 +10009792 grid $top.list $top.ysb -sticky nsew
9793 grid $top.xsb x -sticky ew
Pat Thoytsd93f1712009-04-17 01:24:35 +01009794 ${NS}::frame $top.f
9795 ${NS}::label $top.f.l -text "[mc "Filter"]: "
9796 ${NS}::entry $top.f.e -width 20 -textvariable reflistfilter
Paul Mackerras887c9962007-08-20 19:36:20 +10009797 set reflistfilter "*"
9798 trace add variable reflistfilter write reflistfilter_change
9799 pack $top.f.e -side right -fill x -expand 1
9800 pack $top.f.l -side left
9801 grid $top.f - -sticky ew -pady 2
Pat Thoytsd93f1712009-04-17 01:24:35 +01009802 ${NS}::button $top.close -command [list destroy $top] -text [mc "Close"]
Alexander Gavrilov76f15942008-11-02 21:59:44 +03009803 bind $top <Key-Escape> [list destroy $top]
Paul Mackerras887c9962007-08-20 19:36:20 +10009804 grid $top.close -
9805 grid columnconfigure $top 0 -weight 1
9806 grid rowconfigure $top 0 -weight 1
9807 bind $top.list <1> {break}
9808 bind $top.list <B1-Motion> {break}
9809 bind $top.list <ButtonRelease-1> {sel_reflist %W %x %y; break}
9810 set reflist {}
9811 refill_reflist
9812}
9813
9814proc sel_reflist {w x y} {
9815 global showrefstop reflist headids tagids otherrefids
9816
9817 if {![winfo exists $showrefstop]} return
9818 set l [lindex [split [$w index "@$x,$y"] "."] 0]
9819 set ref [lindex $reflist [expr {$l-1}]]
9820 set n [lindex $ref 0]
9821 switch -- [lindex $ref 1] {
9822 "H" {selbyid $headids($n)}
9823 "T" {selbyid $tagids($n)}
9824 "o" {selbyid $otherrefids($n)}
9825 }
9826 $showrefstop.list tag add highlight $l.0 "$l.0 lineend"
9827}
9828
9829proc unsel_reflist {} {
9830 global showrefstop
9831
9832 if {![info exists showrefstop] || ![winfo exists $showrefstop]} return
9833 $showrefstop.list tag remove highlight 0.0 end
9834}
9835
9836proc reflistfilter_change {n1 n2 op} {
9837 global reflistfilter
9838
9839 after cancel refill_reflist
9840 after 200 refill_reflist
9841}
9842
9843proc refill_reflist {} {
9844 global reflist reflistfilter showrefstop headids tagids otherrefids
Paul Mackerrasd375ef92008-10-21 10:18:12 +11009845 global curview
Paul Mackerras887c9962007-08-20 19:36:20 +10009846
9847 if {![info exists showrefstop] || ![winfo exists $showrefstop]} return
9848 set refs {}
9849 foreach n [array names headids] {
9850 if {[string match $reflistfilter $n]} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11009851 if {[commitinview $headids($n) $curview]} {
Paul Mackerras887c9962007-08-20 19:36:20 +10009852 lappend refs [list $n H]
9853 } else {
Paul Mackerrasd375ef92008-10-21 10:18:12 +11009854 interestedin $headids($n) {run refill_reflist}
Paul Mackerras887c9962007-08-20 19:36:20 +10009855 }
9856 }
9857 }
9858 foreach n [array names tagids] {
9859 if {[string match $reflistfilter $n]} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11009860 if {[commitinview $tagids($n) $curview]} {
Paul Mackerras887c9962007-08-20 19:36:20 +10009861 lappend refs [list $n T]
9862 } else {
Paul Mackerrasd375ef92008-10-21 10:18:12 +11009863 interestedin $tagids($n) {run refill_reflist}
Paul Mackerras887c9962007-08-20 19:36:20 +10009864 }
9865 }
9866 }
9867 foreach n [array names otherrefids] {
9868 if {[string match $reflistfilter $n]} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11009869 if {[commitinview $otherrefids($n) $curview]} {
Paul Mackerras887c9962007-08-20 19:36:20 +10009870 lappend refs [list $n o]
9871 } else {
Paul Mackerrasd375ef92008-10-21 10:18:12 +11009872 interestedin $otherrefids($n) {run refill_reflist}
Paul Mackerras887c9962007-08-20 19:36:20 +10009873 }
9874 }
9875 }
9876 set refs [lsort -index 0 $refs]
9877 if {$refs eq $reflist} return
9878
9879 # Update the contents of $showrefstop.list according to the
9880 # differences between $reflist (old) and $refs (new)
9881 $showrefstop.list conf -state normal
9882 $showrefstop.list insert end "\n"
9883 set i 0
9884 set j 0
9885 while {$i < [llength $reflist] || $j < [llength $refs]} {
9886 if {$i < [llength $reflist]} {
9887 if {$j < [llength $refs]} {
9888 set cmp [string compare [lindex $reflist $i 0] \
9889 [lindex $refs $j 0]]
9890 if {$cmp == 0} {
9891 set cmp [string compare [lindex $reflist $i 1] \
9892 [lindex $refs $j 1]]
9893 }
9894 } else {
9895 set cmp -1
9896 }
9897 } else {
9898 set cmp 1
9899 }
9900 switch -- $cmp {
9901 -1 {
9902 $showrefstop.list delete "[expr {$j+1}].0" "[expr {$j+2}].0"
9903 incr i
9904 }
9905 0 {
9906 incr i
9907 incr j
9908 }
9909 1 {
9910 set l [expr {$j + 1}]
9911 $showrefstop.list image create $l.0 -align baseline \
9912 -image reficon-[lindex $refs $j 1] -padx 2
9913 $showrefstop.list insert $l.1 "[lindex $refs $j 0]\n"
9914 incr j
9915 }
9916 }
9917 }
9918 set reflist $refs
9919 # delete last newline
9920 $showrefstop.list delete end-2c end-1c
9921 $showrefstop.list conf -state disabled
Paul Mackerras10299152006-08-02 09:52:01 +10009922}
9923
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10009924# Stuff for finding nearby tags
9925proc getallcommits {} {
Paul Mackerras5cd15b62007-08-30 21:54:17 +10009926 global allcommits nextarc seeds allccache allcwait cachedarcs allcupdate
9927 global idheads idtags idotherrefs allparents tagobjid
Martin von Zweigbergkda616db2011-04-04 22:14:17 -04009928 global gitdir
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10009929
Paul Mackerrasa69b2d12007-08-13 15:02:02 +10009930 if {![info exists allcommits]} {
Paul Mackerrasa69b2d12007-08-13 15:02:02 +10009931 set nextarc 0
9932 set allcommits 0
9933 set seeds {}
Paul Mackerras5cd15b62007-08-30 21:54:17 +10009934 set allcwait 0
9935 set cachedarcs 0
Martin von Zweigbergkda616db2011-04-04 22:14:17 -04009936 set allccache [file join $gitdir "gitk.cache"]
Paul Mackerras5cd15b62007-08-30 21:54:17 +10009937 if {![catch {
9938 set f [open $allccache r]
9939 set allcwait 1
9940 getcache $f
9941 }]} return
Paul Mackerrasa69b2d12007-08-13 15:02:02 +10009942 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10009943
Paul Mackerras5cd15b62007-08-30 21:54:17 +10009944 if {$allcwait} {
9945 return
Paul Mackerrase11f1232007-06-16 20:29:25 +10009946 }
Paul Mackerras5cd15b62007-08-30 21:54:17 +10009947 set cmd [list | git rev-list --parents]
9948 set allcupdate [expr {$seeds ne {}}]
9949 if {!$allcupdate} {
9950 set ids "--all"
9951 } else {
9952 set refs [concat [array names idheads] [array names idtags] \
9953 [array names idotherrefs]]
9954 set ids {}
9955 set tagobjs {}
9956 foreach name [array names tagobjid] {
9957 lappend tagobjs $tagobjid($name)
9958 }
9959 foreach id [lsort -unique $refs] {
9960 if {![info exists allparents($id)] &&
9961 [lsearch -exact $tagobjs $id] < 0} {
9962 lappend ids $id
9963 }
9964 }
9965 if {$ids ne {}} {
9966 foreach id $seeds {
9967 lappend ids "^$id"
9968 }
9969 }
9970 }
9971 if {$ids ne {}} {
9972 set fd [open [concat $cmd $ids] r]
9973 fconfigure $fd -blocking 0
9974 incr allcommits
9975 nowbusy allcommits
9976 filerun $fd [list getallclines $fd]
9977 } else {
9978 dispneartags 0
9979 }
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10009980}
9981
Paul Mackerrase11f1232007-06-16 20:29:25 +10009982# Since most commits have 1 parent and 1 child, we group strings of
9983# such commits into "arcs" joining branch/merge points (BMPs), which
9984# are commits that either don't have 1 parent or don't have 1 child.
9985#
9986# arcnos(id) - incoming arcs for BMP, arc we're on for other nodes
9987# arcout(id) - outgoing arcs for BMP
9988# arcids(a) - list of IDs on arc including end but not start
9989# arcstart(a) - BMP ID at start of arc
9990# arcend(a) - BMP ID at end of arc
9991# growing(a) - arc a is still growing
9992# arctags(a) - IDs out of arcids (excluding end) that have tags
9993# archeads(a) - IDs out of arcids (excluding end) that have heads
9994# The start of an arc is at the descendent end, so "incoming" means
9995# coming from descendents, and "outgoing" means going towards ancestors.
Paul Mackerrascec7bec2006-08-02 09:38:10 +10009996
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10009997proc getallclines {fd} {
Paul Mackerras5cd15b62007-08-30 21:54:17 +10009998 global allparents allchildren idtags idheads nextarc
Paul Mackerrase11f1232007-06-16 20:29:25 +10009999 global arcnos arcids arctags arcout arcend arcstart archeads growing
Paul Mackerras5cd15b62007-08-30 21:54:17 +100010000 global seeds allcommits cachedarcs allcupdate
Pat Thoytsd93f1712009-04-17 01:24:35 +010010001
Paul Mackerrase11f1232007-06-16 20:29:25 +100010002 set nid 0
Paul Mackerras7eb3cb92007-06-17 14:45:00 +100010003 while {[incr nid] <= 1000 && [gets $fd line] >= 0} {
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +100010004 set id [lindex $line 0]
Paul Mackerrase11f1232007-06-16 20:29:25 +100010005 if {[info exists allparents($id)]} {
10006 # seen it already
10007 continue
10008 }
Paul Mackerras5cd15b62007-08-30 21:54:17 +100010009 set cachedarcs 0
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +100010010 set olds [lrange $line 1 end]
10011 set allparents($id) $olds
10012 if {![info exists allchildren($id)]} {
10013 set allchildren($id) {}
Paul Mackerrase11f1232007-06-16 20:29:25 +100010014 set arcnos($id) {}
10015 lappend seeds $id
10016 } else {
10017 set a $arcnos($id)
10018 if {[llength $olds] == 1 && [llength $a] == 1} {
10019 lappend arcids($a) $id
10020 if {[info exists idtags($id)]} {
10021 lappend arctags($a) $id
10022 }
10023 if {[info exists idheads($id)]} {
10024 lappend archeads($a) $id
10025 }
10026 if {[info exists allparents($olds)]} {
10027 # seen parent already
10028 if {![info exists arcout($olds)]} {
10029 splitarc $olds
10030 }
10031 lappend arcids($a) $olds
10032 set arcend($a) $olds
10033 unset growing($a)
10034 }
10035 lappend allchildren($olds) $id
10036 lappend arcnos($olds) $a
10037 continue
10038 }
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +100010039 }
Paul Mackerrase11f1232007-06-16 20:29:25 +100010040 foreach a $arcnos($id) {
10041 lappend arcids($a) $id
10042 set arcend($a) $id
10043 unset growing($a)
10044 }
10045
10046 set ao {}
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +100010047 foreach p $olds {
10048 lappend allchildren($p) $id
Paul Mackerrase11f1232007-06-16 20:29:25 +100010049 set a [incr nextarc]
10050 set arcstart($a) $id
10051 set archeads($a) {}
10052 set arctags($a) {}
10053 set archeads($a) {}
10054 set arcids($a) {}
10055 lappend ao $a
10056 set growing($a) 1
10057 if {[info exists allparents($p)]} {
10058 # seen it already, may need to make a new branch
10059 if {![info exists arcout($p)]} {
10060 splitarc $p
10061 }
10062 lappend arcids($a) $p
10063 set arcend($a) $p
10064 unset growing($a)
10065 }
10066 lappend arcnos($p) $a
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +100010067 }
Paul Mackerrase11f1232007-06-16 20:29:25 +100010068 set arcout($id) $ao
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +100010069 }
Paul Mackerrasf3326b62007-06-18 22:39:21 +100010070 if {$nid > 0} {
10071 global cached_dheads cached_dtags cached_atags
10072 catch {unset cached_dheads}
10073 catch {unset cached_dtags}
10074 catch {unset cached_atags}
10075 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +100010076 if {![eof $fd]} {
10077 return [expr {$nid >= 1000? 2: 1}]
10078 }
Paul Mackerras5cd15b62007-08-30 21:54:17 +100010079 set cacheok 1
10080 if {[catch {
10081 fconfigure $fd -blocking 1
10082 close $fd
10083 } err]} {
10084 # got an error reading the list of commits
10085 # if we were updating, try rereading the whole thing again
10086 if {$allcupdate} {
10087 incr allcommits -1
10088 dropcache $err
10089 return
10090 }
Christian Stimmingd990ced2007-11-07 18:42:55 +010010091 error_popup "[mc "Error reading commit topology information;\
Paul Mackerras5cd15b62007-08-30 21:54:17 +100010092 branch and preceding/following tag information\
Christian Stimmingd990ced2007-11-07 18:42:55 +010010093 will be incomplete."]\n($err)"
Paul Mackerras5cd15b62007-08-30 21:54:17 +100010094 set cacheok 0
10095 }
Paul Mackerrase11f1232007-06-16 20:29:25 +100010096 if {[incr allcommits -1] == 0} {
10097 notbusy allcommits
Paul Mackerras5cd15b62007-08-30 21:54:17 +100010098 if {$cacheok} {
10099 run savecache
10100 }
Paul Mackerrase11f1232007-06-16 20:29:25 +100010101 }
10102 dispneartags 0
Paul Mackerras7eb3cb92007-06-17 14:45:00 +100010103 return 0
Paul Mackerrase11f1232007-06-16 20:29:25 +100010104}
10105
10106proc recalcarc {a} {
10107 global arctags archeads arcids idtags idheads
10108
10109 set at {}
10110 set ah {}
10111 foreach id [lrange $arcids($a) 0 end-1] {
10112 if {[info exists idtags($id)]} {
10113 lappend at $id
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +100010114 }
Paul Mackerrase11f1232007-06-16 20:29:25 +100010115 if {[info exists idheads($id)]} {
10116 lappend ah $id
10117 }
10118 }
10119 set arctags($a) $at
10120 set archeads($a) $ah
10121}
10122
10123proc splitarc {p} {
Paul Mackerras5cd15b62007-08-30 21:54:17 +100010124 global arcnos arcids nextarc arctags archeads idtags idheads
Paul Mackerrase11f1232007-06-16 20:29:25 +100010125 global arcstart arcend arcout allparents growing
10126
10127 set a $arcnos($p)
10128 if {[llength $a] != 1} {
10129 puts "oops splitarc called but [llength $a] arcs already"
10130 return
10131 }
10132 set a [lindex $a 0]
10133 set i [lsearch -exact $arcids($a) $p]
10134 if {$i < 0} {
10135 puts "oops splitarc $p not in arc $a"
10136 return
10137 }
10138 set na [incr nextarc]
10139 if {[info exists arcend($a)]} {
10140 set arcend($na) $arcend($a)
10141 } else {
10142 set l [lindex $allparents([lindex $arcids($a) end]) 0]
10143 set j [lsearch -exact $arcnos($l) $a]
10144 set arcnos($l) [lreplace $arcnos($l) $j $j $na]
10145 }
10146 set tail [lrange $arcids($a) [expr {$i+1}] end]
10147 set arcids($a) [lrange $arcids($a) 0 $i]
10148 set arcend($a) $p
10149 set arcstart($na) $p
10150 set arcout($p) $na
10151 set arcids($na) $tail
10152 if {[info exists growing($a)]} {
10153 set growing($na) 1
10154 unset growing($a)
10155 }
Paul Mackerrase11f1232007-06-16 20:29:25 +100010156
10157 foreach id $tail {
10158 if {[llength $arcnos($id)] == 1} {
10159 set arcnos($id) $na
10160 } else {
10161 set j [lsearch -exact $arcnos($id) $a]
10162 set arcnos($id) [lreplace $arcnos($id) $j $j $na]
10163 }
10164 }
10165
10166 # reconstruct tags and heads lists
10167 if {$arctags($a) ne {} || $archeads($a) ne {}} {
10168 recalcarc $a
10169 recalcarc $na
10170 } else {
10171 set arctags($na) {}
10172 set archeads($na) {}
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +100010173 }
10174}
10175
Paul Mackerrase11f1232007-06-16 20:29:25 +100010176# Update things for a new commit added that is a child of one
10177# existing commit. Used when cherry-picking.
10178proc addnewchild {id p} {
Paul Mackerras5cd15b62007-08-30 21:54:17 +100010179 global allparents allchildren idtags nextarc
Paul Mackerrase11f1232007-06-16 20:29:25 +100010180 global arcnos arcids arctags arcout arcend arcstart archeads growing
Paul Mackerras719c2b92007-08-29 22:41:34 +100010181 global seeds allcommits
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +100010182
Paul Mackerras3ebba3c2007-10-20 22:10:52 +100010183 if {![info exists allcommits] || ![info exists arcnos($p)]} return
Paul Mackerrase11f1232007-06-16 20:29:25 +100010184 set allparents($id) [list $p]
10185 set allchildren($id) {}
10186 set arcnos($id) {}
10187 lappend seeds $id
Paul Mackerrase11f1232007-06-16 20:29:25 +100010188 lappend allchildren($p) $id
10189 set a [incr nextarc]
10190 set arcstart($a) $id
10191 set archeads($a) {}
10192 set arctags($a) {}
10193 set arcids($a) [list $p]
10194 set arcend($a) $p
10195 if {![info exists arcout($p)]} {
10196 splitarc $p
10197 }
10198 lappend arcnos($p) $a
10199 set arcout($id) [list $a]
10200}
10201
Paul Mackerras5cd15b62007-08-30 21:54:17 +100010202# This implements a cache for the topology information.
10203# The cache saves, for each arc, the start and end of the arc,
10204# the ids on the arc, and the outgoing arcs from the end.
10205proc readcache {f} {
10206 global arcnos arcids arcout arcstart arcend arctags archeads nextarc
10207 global idtags idheads allparents cachedarcs possible_seeds seeds growing
10208 global allcwait
10209
10210 set a $nextarc
10211 set lim $cachedarcs
10212 if {$lim - $a > 500} {
10213 set lim [expr {$a + 500}]
10214 }
10215 if {[catch {
10216 if {$a == $lim} {
10217 # finish reading the cache and setting up arctags, etc.
10218 set line [gets $f]
10219 if {$line ne "1"} {error "bad final version"}
10220 close $f
10221 foreach id [array names idtags] {
10222 if {[info exists arcnos($id)] && [llength $arcnos($id)] == 1 &&
10223 [llength $allparents($id)] == 1} {
10224 set a [lindex $arcnos($id) 0]
10225 if {$arctags($a) eq {}} {
10226 recalcarc $a
10227 }
10228 }
10229 }
10230 foreach id [array names idheads] {
10231 if {[info exists arcnos($id)] && [llength $arcnos($id)] == 1 &&
10232 [llength $allparents($id)] == 1} {
10233 set a [lindex $arcnos($id) 0]
10234 if {$archeads($a) eq {}} {
10235 recalcarc $a
10236 }
10237 }
10238 }
10239 foreach id [lsort -unique $possible_seeds] {
10240 if {$arcnos($id) eq {}} {
10241 lappend seeds $id
10242 }
10243 }
10244 set allcwait 0
10245 } else {
10246 while {[incr a] <= $lim} {
10247 set line [gets $f]
10248 if {[llength $line] != 3} {error "bad line"}
10249 set s [lindex $line 0]
10250 set arcstart($a) $s
10251 lappend arcout($s) $a
10252 if {![info exists arcnos($s)]} {
10253 lappend possible_seeds $s
10254 set arcnos($s) {}
10255 }
10256 set e [lindex $line 1]
10257 if {$e eq {}} {
10258 set growing($a) 1
10259 } else {
10260 set arcend($a) $e
10261 if {![info exists arcout($e)]} {
10262 set arcout($e) {}
10263 }
10264 }
10265 set arcids($a) [lindex $line 2]
10266 foreach id $arcids($a) {
10267 lappend allparents($s) $id
10268 set s $id
10269 lappend arcnos($id) $a
10270 }
10271 if {![info exists allparents($s)]} {
10272 set allparents($s) {}
10273 }
10274 set arctags($a) {}
10275 set archeads($a) {}
10276 }
10277 set nextarc [expr {$a - 1}]
10278 }
10279 } err]} {
10280 dropcache $err
10281 return 0
10282 }
10283 if {!$allcwait} {
10284 getallcommits
10285 }
10286 return $allcwait
10287}
10288
10289proc getcache {f} {
10290 global nextarc cachedarcs possible_seeds
10291
10292 if {[catch {
10293 set line [gets $f]
10294 if {[llength $line] != 2 || [lindex $line 0] ne "1"} {error "bad version"}
10295 # make sure it's an integer
10296 set cachedarcs [expr {int([lindex $line 1])}]
10297 if {$cachedarcs < 0} {error "bad number of arcs"}
10298 set nextarc 0
10299 set possible_seeds {}
10300 run readcache $f
10301 } err]} {
10302 dropcache $err
10303 }
10304 return 0
10305}
10306
10307proc dropcache {err} {
10308 global allcwait nextarc cachedarcs seeds
10309
10310 #puts "dropping cache ($err)"
10311 foreach v {arcnos arcout arcids arcstart arcend growing \
10312 arctags archeads allparents allchildren} {
10313 global $v
10314 catch {unset $v}
10315 }
10316 set allcwait 0
10317 set nextarc 0
10318 set cachedarcs 0
10319 set seeds {}
10320 getallcommits
10321}
10322
10323proc writecache {f} {
10324 global cachearc cachedarcs allccache
10325 global arcstart arcend arcnos arcids arcout
10326
10327 set a $cachearc
10328 set lim $cachedarcs
10329 if {$lim - $a > 1000} {
10330 set lim [expr {$a + 1000}]
10331 }
10332 if {[catch {
10333 while {[incr a] <= $lim} {
10334 if {[info exists arcend($a)]} {
10335 puts $f [list $arcstart($a) $arcend($a) $arcids($a)]
10336 } else {
10337 puts $f [list $arcstart($a) {} $arcids($a)]
10338 }
10339 }
10340 } err]} {
10341 catch {close $f}
10342 catch {file delete $allccache}
10343 #puts "writing cache failed ($err)"
10344 return 0
10345 }
10346 set cachearc [expr {$a - 1}]
10347 if {$a > $cachedarcs} {
10348 puts $f "1"
10349 close $f
10350 return 0
10351 }
10352 return 1
10353}
10354
10355proc savecache {} {
10356 global nextarc cachedarcs cachearc allccache
10357
10358 if {$nextarc == $cachedarcs} return
10359 set cachearc 0
10360 set cachedarcs $nextarc
10361 catch {
10362 set f [open $allccache w]
10363 puts $f [list 1 $cachedarcs]
10364 run writecache $f
10365 }
10366}
10367
Paul Mackerrase11f1232007-06-16 20:29:25 +100010368# Returns 1 if a is an ancestor of b, -1 if b is an ancestor of a,
10369# or 0 if neither is true.
10370proc anc_or_desc {a b} {
10371 global arcout arcstart arcend arcnos cached_isanc
10372
10373 if {$arcnos($a) eq $arcnos($b)} {
10374 # Both are on the same arc(s); either both are the same BMP,
10375 # or if one is not a BMP, the other is also not a BMP or is
10376 # the BMP at end of the arc (and it only has 1 incoming arc).
Paul Mackerras69c0b5d2007-07-04 21:57:04 +100010377 # Or both can be BMPs with no incoming arcs.
10378 if {$a eq $b || $arcnos($a) eq {}} {
Paul Mackerrase11f1232007-06-16 20:29:25 +100010379 return 0
10380 }
10381 # assert {[llength $arcnos($a)] == 1}
10382 set arc [lindex $arcnos($a) 0]
10383 set i [lsearch -exact $arcids($arc) $a]
10384 set j [lsearch -exact $arcids($arc) $b]
10385 if {$i < 0 || $i > $j} {
10386 return 1
10387 } else {
10388 return -1
10389 }
10390 }
10391
10392 if {![info exists arcout($a)]} {
10393 set arc [lindex $arcnos($a) 0]
10394 if {[info exists arcend($arc)]} {
10395 set aend $arcend($arc)
10396 } else {
10397 set aend {}
10398 }
10399 set a $arcstart($arc)
10400 } else {
10401 set aend $a
10402 }
10403 if {![info exists arcout($b)]} {
10404 set arc [lindex $arcnos($b) 0]
10405 if {[info exists arcend($arc)]} {
10406 set bend $arcend($arc)
10407 } else {
10408 set bend {}
10409 }
10410 set b $arcstart($arc)
10411 } else {
10412 set bend $b
10413 }
10414 if {$a eq $bend} {
10415 return 1
10416 }
10417 if {$b eq $aend} {
10418 return -1
10419 }
10420 if {[info exists cached_isanc($a,$bend)]} {
10421 if {$cached_isanc($a,$bend)} {
10422 return 1
10423 }
10424 }
10425 if {[info exists cached_isanc($b,$aend)]} {
10426 if {$cached_isanc($b,$aend)} {
10427 return -1
10428 }
10429 if {[info exists cached_isanc($a,$bend)]} {
10430 return 0
10431 }
10432 }
10433
10434 set todo [list $a $b]
10435 set anc($a) a
10436 set anc($b) b
10437 for {set i 0} {$i < [llength $todo]} {incr i} {
10438 set x [lindex $todo $i]
10439 if {$anc($x) eq {}} {
10440 continue
10441 }
10442 foreach arc $arcnos($x) {
10443 set xd $arcstart($arc)
10444 if {$xd eq $bend} {
10445 set cached_isanc($a,$bend) 1
10446 set cached_isanc($b,$aend) 0
10447 return 1
10448 } elseif {$xd eq $aend} {
10449 set cached_isanc($b,$aend) 1
10450 set cached_isanc($a,$bend) 0
10451 return -1
10452 }
10453 if {![info exists anc($xd)]} {
10454 set anc($xd) $anc($x)
10455 lappend todo $xd
10456 } elseif {$anc($xd) ne $anc($x)} {
10457 set anc($xd) {}
10458 }
10459 }
10460 }
10461 set cached_isanc($a,$bend) 0
10462 set cached_isanc($b,$aend) 0
10463 return 0
10464}
10465
10466# This identifies whether $desc has an ancestor that is
10467# a growing tip of the graph and which is not an ancestor of $anc
10468# and returns 0 if so and 1 if not.
10469# If we subsequently discover a tag on such a growing tip, and that
10470# turns out to be a descendent of $anc (which it could, since we
10471# don't necessarily see children before parents), then $desc
10472# isn't a good choice to display as a descendent tag of
10473# $anc (since it is the descendent of another tag which is
10474# a descendent of $anc). Similarly, $anc isn't a good choice to
10475# display as a ancestor tag of $desc.
10476#
10477proc is_certain {desc anc} {
10478 global arcnos arcout arcstart arcend growing problems
10479
10480 set certain {}
10481 if {[llength $arcnos($anc)] == 1} {
10482 # tags on the same arc are certain
10483 if {$arcnos($desc) eq $arcnos($anc)} {
10484 return 1
10485 }
10486 if {![info exists arcout($anc)]} {
10487 # if $anc is partway along an arc, use the start of the arc instead
10488 set a [lindex $arcnos($anc) 0]
10489 set anc $arcstart($a)
10490 }
10491 }
10492 if {[llength $arcnos($desc)] > 1 || [info exists arcout($desc)]} {
10493 set x $desc
10494 } else {
10495 set a [lindex $arcnos($desc) 0]
10496 set x $arcend($a)
10497 }
10498 if {$x == $anc} {
10499 return 1
10500 }
10501 set anclist [list $x]
10502 set dl($x) 1
10503 set nnh 1
10504 set ngrowanc 0
10505 for {set i 0} {$i < [llength $anclist] && ($nnh > 0 || $ngrowanc > 0)} {incr i} {
10506 set x [lindex $anclist $i]
10507 if {$dl($x)} {
10508 incr nnh -1
10509 }
10510 set done($x) 1
10511 foreach a $arcout($x) {
10512 if {[info exists growing($a)]} {
10513 if {![info exists growanc($x)] && $dl($x)} {
10514 set growanc($x) 1
10515 incr ngrowanc
10516 }
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +100010517 } else {
Paul Mackerrase11f1232007-06-16 20:29:25 +100010518 set y $arcend($a)
10519 if {[info exists dl($y)]} {
10520 if {$dl($y)} {
10521 if {!$dl($x)} {
10522 set dl($y) 0
10523 if {![info exists done($y)]} {
10524 incr nnh -1
10525 }
10526 if {[info exists growanc($x)]} {
10527 incr ngrowanc -1
10528 }
10529 set xl [list $y]
10530 for {set k 0} {$k < [llength $xl]} {incr k} {
10531 set z [lindex $xl $k]
10532 foreach c $arcout($z) {
10533 if {[info exists arcend($c)]} {
10534 set v $arcend($c)
10535 if {[info exists dl($v)] && $dl($v)} {
10536 set dl($v) 0
10537 if {![info exists done($v)]} {
10538 incr nnh -1
10539 }
10540 if {[info exists growanc($v)]} {
10541 incr ngrowanc -1
10542 }
10543 lappend xl $v
10544 }
10545 }
10546 }
10547 }
10548 }
10549 }
10550 } elseif {$y eq $anc || !$dl($x)} {
10551 set dl($y) 0
10552 lappend anclist $y
10553 } else {
10554 set dl($y) 1
10555 lappend anclist $y
10556 incr nnh
10557 }
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +100010558 }
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +100010559 }
10560 }
Paul Mackerrase11f1232007-06-16 20:29:25 +100010561 foreach x [array names growanc] {
10562 if {$dl($x)} {
10563 return 0
10564 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +100010565 return 0
Paul Mackerrase11f1232007-06-16 20:29:25 +100010566 }
10567 return 1
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +100010568}
10569
Paul Mackerrase11f1232007-06-16 20:29:25 +100010570proc validate_arctags {a} {
10571 global arctags idtags
10572
10573 set i -1
10574 set na $arctags($a)
10575 foreach id $arctags($a) {
10576 incr i
10577 if {![info exists idtags($id)]} {
10578 set na [lreplace $na $i $i]
10579 incr i -1
10580 }
10581 }
10582 set arctags($a) $na
10583}
10584
10585proc validate_archeads {a} {
10586 global archeads idheads
10587
10588 set i -1
10589 set na $archeads($a)
10590 foreach id $archeads($a) {
10591 incr i
10592 if {![info exists idheads($id)]} {
10593 set na [lreplace $na $i $i]
10594 incr i -1
10595 }
10596 }
10597 set archeads($a) $na
10598}
10599
10600# Return the list of IDs that have tags that are descendents of id,
10601# ignoring IDs that are descendents of IDs already reported.
10602proc desctags {id} {
10603 global arcnos arcstart arcids arctags idtags allparents
10604 global growing cached_dtags
10605
10606 if {![info exists allparents($id)]} {
10607 return {}
10608 }
10609 set t1 [clock clicks -milliseconds]
10610 set argid $id
10611 if {[llength $arcnos($id)] == 1 && [llength $allparents($id)] == 1} {
10612 # part-way along an arc; check that arc first
10613 set a [lindex $arcnos($id) 0]
10614 if {$arctags($a) ne {}} {
10615 validate_arctags $a
10616 set i [lsearch -exact $arcids($a) $id]
10617 set tid {}
10618 foreach t $arctags($a) {
10619 set j [lsearch -exact $arcids($a) $t]
10620 if {$j >= $i} break
10621 set tid $t
10622 }
10623 if {$tid ne {}} {
10624 return $tid
10625 }
10626 }
10627 set id $arcstart($a)
10628 if {[info exists idtags($id)]} {
10629 return $id
10630 }
10631 }
10632 if {[info exists cached_dtags($id)]} {
10633 return $cached_dtags($id)
10634 }
10635
10636 set origid $id
10637 set todo [list $id]
10638 set queued($id) 1
10639 set nc 1
10640 for {set i 0} {$i < [llength $todo] && $nc > 0} {incr i} {
10641 set id [lindex $todo $i]
10642 set done($id) 1
10643 set ta [info exists hastaggedancestor($id)]
10644 if {!$ta} {
10645 incr nc -1
10646 }
10647 # ignore tags on starting node
10648 if {!$ta && $i > 0} {
10649 if {[info exists idtags($id)]} {
10650 set tagloc($id) $id
10651 set ta 1
10652 } elseif {[info exists cached_dtags($id)]} {
10653 set tagloc($id) $cached_dtags($id)
10654 set ta 1
10655 }
10656 }
10657 foreach a $arcnos($id) {
10658 set d $arcstart($a)
10659 if {!$ta && $arctags($a) ne {}} {
10660 validate_arctags $a
10661 if {$arctags($a) ne {}} {
10662 lappend tagloc($id) [lindex $arctags($a) end]
10663 }
10664 }
10665 if {$ta || $arctags($a) ne {}} {
10666 set tomark [list $d]
10667 for {set j 0} {$j < [llength $tomark]} {incr j} {
10668 set dd [lindex $tomark $j]
10669 if {![info exists hastaggedancestor($dd)]} {
10670 if {[info exists done($dd)]} {
10671 foreach b $arcnos($dd) {
10672 lappend tomark $arcstart($b)
10673 }
10674 if {[info exists tagloc($dd)]} {
10675 unset tagloc($dd)
10676 }
10677 } elseif {[info exists queued($dd)]} {
10678 incr nc -1
10679 }
10680 set hastaggedancestor($dd) 1
10681 }
10682 }
10683 }
10684 if {![info exists queued($d)]} {
10685 lappend todo $d
10686 set queued($d) 1
10687 if {![info exists hastaggedancestor($d)]} {
10688 incr nc
10689 }
10690 }
10691 }
10692 }
10693 set tags {}
10694 foreach id [array names tagloc] {
10695 if {![info exists hastaggedancestor($id)]} {
10696 foreach t $tagloc($id) {
10697 if {[lsearch -exact $tags $t] < 0} {
10698 lappend tags $t
10699 }
10700 }
10701 }
10702 }
10703 set t2 [clock clicks -milliseconds]
10704 set loopix $i
10705
10706 # remove tags that are descendents of other tags
10707 for {set i 0} {$i < [llength $tags]} {incr i} {
10708 set a [lindex $tags $i]
10709 for {set j 0} {$j < $i} {incr j} {
10710 set b [lindex $tags $j]
10711 set r [anc_or_desc $a $b]
10712 if {$r == 1} {
10713 set tags [lreplace $tags $j $j]
10714 incr j -1
10715 incr i -1
10716 } elseif {$r == -1} {
10717 set tags [lreplace $tags $i $i]
10718 incr i -1
10719 break
10720 }
10721 }
10722 }
10723
10724 if {[array names growing] ne {}} {
10725 # graph isn't finished, need to check if any tag could get
10726 # eclipsed by another tag coming later. Simply ignore any
10727 # tags that could later get eclipsed.
10728 set ctags {}
10729 foreach t $tags {
10730 if {[is_certain $t $origid]} {
10731 lappend ctags $t
10732 }
10733 }
10734 if {$tags eq $ctags} {
10735 set cached_dtags($origid) $tags
10736 } else {
10737 set tags $ctags
10738 }
10739 } else {
10740 set cached_dtags($origid) $tags
10741 }
10742 set t3 [clock clicks -milliseconds]
10743 if {0 && $t3 - $t1 >= 100} {
10744 puts "iterating descendents ($loopix/[llength $todo] nodes) took\
10745 [expr {$t2-$t1}]+[expr {$t3-$t2}]ms, $nc candidates left"
10746 }
10747 return $tags
10748}
10749
10750proc anctags {id} {
10751 global arcnos arcids arcout arcend arctags idtags allparents
10752 global growing cached_atags
10753
10754 if {![info exists allparents($id)]} {
10755 return {}
10756 }
10757 set t1 [clock clicks -milliseconds]
10758 set argid $id
10759 if {[llength $arcnos($id)] == 1 && [llength $allparents($id)] == 1} {
10760 # part-way along an arc; check that arc first
10761 set a [lindex $arcnos($id) 0]
10762 if {$arctags($a) ne {}} {
10763 validate_arctags $a
10764 set i [lsearch -exact $arcids($a) $id]
10765 foreach t $arctags($a) {
10766 set j [lsearch -exact $arcids($a) $t]
10767 if {$j > $i} {
10768 return $t
10769 }
10770 }
10771 }
10772 if {![info exists arcend($a)]} {
10773 return {}
10774 }
10775 set id $arcend($a)
10776 if {[info exists idtags($id)]} {
10777 return $id
10778 }
10779 }
10780 if {[info exists cached_atags($id)]} {
10781 return $cached_atags($id)
10782 }
10783
10784 set origid $id
10785 set todo [list $id]
10786 set queued($id) 1
10787 set taglist {}
10788 set nc 1
10789 for {set i 0} {$i < [llength $todo] && $nc > 0} {incr i} {
10790 set id [lindex $todo $i]
10791 set done($id) 1
10792 set td [info exists hastaggeddescendent($id)]
10793 if {!$td} {
10794 incr nc -1
10795 }
10796 # ignore tags on starting node
10797 if {!$td && $i > 0} {
10798 if {[info exists idtags($id)]} {
10799 set tagloc($id) $id
10800 set td 1
10801 } elseif {[info exists cached_atags($id)]} {
10802 set tagloc($id) $cached_atags($id)
10803 set td 1
10804 }
10805 }
10806 foreach a $arcout($id) {
10807 if {!$td && $arctags($a) ne {}} {
10808 validate_arctags $a
10809 if {$arctags($a) ne {}} {
10810 lappend tagloc($id) [lindex $arctags($a) 0]
10811 }
10812 }
10813 if {![info exists arcend($a)]} continue
10814 set d $arcend($a)
10815 if {$td || $arctags($a) ne {}} {
10816 set tomark [list $d]
10817 for {set j 0} {$j < [llength $tomark]} {incr j} {
10818 set dd [lindex $tomark $j]
10819 if {![info exists hastaggeddescendent($dd)]} {
10820 if {[info exists done($dd)]} {
10821 foreach b $arcout($dd) {
10822 if {[info exists arcend($b)]} {
10823 lappend tomark $arcend($b)
10824 }
10825 }
10826 if {[info exists tagloc($dd)]} {
10827 unset tagloc($dd)
10828 }
10829 } elseif {[info exists queued($dd)]} {
10830 incr nc -1
10831 }
10832 set hastaggeddescendent($dd) 1
10833 }
10834 }
10835 }
10836 if {![info exists queued($d)]} {
10837 lappend todo $d
10838 set queued($d) 1
10839 if {![info exists hastaggeddescendent($d)]} {
10840 incr nc
10841 }
10842 }
10843 }
10844 }
10845 set t2 [clock clicks -milliseconds]
10846 set loopix $i
10847 set tags {}
10848 foreach id [array names tagloc] {
10849 if {![info exists hastaggeddescendent($id)]} {
10850 foreach t $tagloc($id) {
10851 if {[lsearch -exact $tags $t] < 0} {
10852 lappend tags $t
10853 }
10854 }
10855 }
10856 }
10857
10858 # remove tags that are ancestors of other tags
10859 for {set i 0} {$i < [llength $tags]} {incr i} {
10860 set a [lindex $tags $i]
10861 for {set j 0} {$j < $i} {incr j} {
10862 set b [lindex $tags $j]
10863 set r [anc_or_desc $a $b]
10864 if {$r == -1} {
10865 set tags [lreplace $tags $j $j]
10866 incr j -1
10867 incr i -1
10868 } elseif {$r == 1} {
10869 set tags [lreplace $tags $i $i]
10870 incr i -1
10871 break
10872 }
10873 }
10874 }
10875
10876 if {[array names growing] ne {}} {
10877 # graph isn't finished, need to check if any tag could get
10878 # eclipsed by another tag coming later. Simply ignore any
10879 # tags that could later get eclipsed.
10880 set ctags {}
10881 foreach t $tags {
10882 if {[is_certain $origid $t]} {
10883 lappend ctags $t
10884 }
10885 }
10886 if {$tags eq $ctags} {
10887 set cached_atags($origid) $tags
10888 } else {
10889 set tags $ctags
10890 }
10891 } else {
10892 set cached_atags($origid) $tags
10893 }
10894 set t3 [clock clicks -milliseconds]
10895 if {0 && $t3 - $t1 >= 100} {
10896 puts "iterating ancestors ($loopix/[llength $todo] nodes) took\
10897 [expr {$t2-$t1}]+[expr {$t3-$t2}]ms, $nc candidates left"
10898 }
10899 return $tags
10900}
10901
10902# Return the list of IDs that have heads that are descendents of id,
10903# including id itself if it has a head.
10904proc descheads {id} {
10905 global arcnos arcstart arcids archeads idheads cached_dheads
Paul Mackerrasd809fb12013-01-01 16:51:03 +110010906 global allparents arcout
Paul Mackerrase11f1232007-06-16 20:29:25 +100010907
10908 if {![info exists allparents($id)]} {
10909 return {}
10910 }
Paul Mackerrasf3326b62007-06-18 22:39:21 +100010911 set aret {}
Paul Mackerrasd809fb12013-01-01 16:51:03 +110010912 if {![info exists arcout($id)]} {
Paul Mackerrase11f1232007-06-16 20:29:25 +100010913 # part-way along an arc; check it first
10914 set a [lindex $arcnos($id) 0]
10915 if {$archeads($a) ne {}} {
10916 validate_archeads $a
10917 set i [lsearch -exact $arcids($a) $id]
10918 foreach t $archeads($a) {
10919 set j [lsearch -exact $arcids($a) $t]
10920 if {$j > $i} break
Paul Mackerrasf3326b62007-06-18 22:39:21 +100010921 lappend aret $t
Paul Mackerrase11f1232007-06-16 20:29:25 +100010922 }
10923 }
10924 set id $arcstart($a)
10925 }
10926 set origid $id
10927 set todo [list $id]
10928 set seen($id) 1
Paul Mackerrasf3326b62007-06-18 22:39:21 +100010929 set ret {}
Paul Mackerrase11f1232007-06-16 20:29:25 +100010930 for {set i 0} {$i < [llength $todo]} {incr i} {
10931 set id [lindex $todo $i]
10932 if {[info exists cached_dheads($id)]} {
10933 set ret [concat $ret $cached_dheads($id)]
10934 } else {
10935 if {[info exists idheads($id)]} {
10936 lappend ret $id
10937 }
10938 foreach a $arcnos($id) {
10939 if {$archeads($a) ne {}} {
Paul Mackerras706d6c32007-06-26 11:09:49 +100010940 validate_archeads $a
10941 if {$archeads($a) ne {}} {
10942 set ret [concat $ret $archeads($a)]
10943 }
Paul Mackerrase11f1232007-06-16 20:29:25 +100010944 }
10945 set d $arcstart($a)
10946 if {![info exists seen($d)]} {
10947 lappend todo $d
10948 set seen($d) 1
10949 }
10950 }
10951 }
10952 }
10953 set ret [lsort -unique $ret]
10954 set cached_dheads($origid) $ret
Paul Mackerrasf3326b62007-06-18 22:39:21 +100010955 return [concat $ret $aret]
Paul Mackerrase11f1232007-06-16 20:29:25 +100010956}
10957
Paul Mackerrasceadfe92006-08-08 20:55:36 +100010958proc addedtag {id} {
Paul Mackerrase11f1232007-06-16 20:29:25 +100010959 global arcnos arcout cached_dtags cached_atags
Paul Mackerrasceadfe92006-08-08 20:55:36 +100010960
Paul Mackerrase11f1232007-06-16 20:29:25 +100010961 if {![info exists arcnos($id)]} return
10962 if {![info exists arcout($id)]} {
10963 recalcarc [lindex $arcnos($id) 0]
Paul Mackerrasceadfe92006-08-08 20:55:36 +100010964 }
Paul Mackerrase11f1232007-06-16 20:29:25 +100010965 catch {unset cached_dtags}
10966 catch {unset cached_atags}
Paul Mackerrasceadfe92006-08-08 20:55:36 +100010967}
10968
Paul Mackerrasca6d8f52006-08-06 21:08:05 +100010969proc addedhead {hid head} {
Paul Mackerrase11f1232007-06-16 20:29:25 +100010970 global arcnos arcout cached_dheads
Paul Mackerrasca6d8f52006-08-06 21:08:05 +100010971
Paul Mackerrase11f1232007-06-16 20:29:25 +100010972 if {![info exists arcnos($hid)]} return
10973 if {![info exists arcout($hid)]} {
10974 recalcarc [lindex $arcnos($hid) 0]
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +100010975 }
Paul Mackerrase11f1232007-06-16 20:29:25 +100010976 catch {unset cached_dheads}
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +100010977}
10978
Paul Mackerrasca6d8f52006-08-06 21:08:05 +100010979proc removedhead {hid head} {
Paul Mackerrase11f1232007-06-16 20:29:25 +100010980 global cached_dheads
Paul Mackerrasca6d8f52006-08-06 21:08:05 +100010981
Paul Mackerrase11f1232007-06-16 20:29:25 +100010982 catch {unset cached_dheads}
Paul Mackerras10299152006-08-02 09:52:01 +100010983}
10984
Paul Mackerrase11f1232007-06-16 20:29:25 +100010985proc movedhead {hid head} {
10986 global arcnos arcout cached_dheads
Paul Mackerrasca6d8f52006-08-06 21:08:05 +100010987
Paul Mackerrase11f1232007-06-16 20:29:25 +100010988 if {![info exists arcnos($hid)]} return
10989 if {![info exists arcout($hid)]} {
10990 recalcarc [lindex $arcnos($hid) 0]
Paul Mackerrasca6d8f52006-08-06 21:08:05 +100010991 }
Paul Mackerrase11f1232007-06-16 20:29:25 +100010992 catch {unset cached_dheads}
Paul Mackerrasca6d8f52006-08-06 21:08:05 +100010993}
10994
Paul Mackerrascec7bec2006-08-02 09:38:10 +100010995proc changedrefs {} {
David Aguilar587277f2012-09-08 12:53:16 -070010996 global cached_dheads cached_dtags cached_atags cached_tagcontent
Paul Mackerrase11f1232007-06-16 20:29:25 +100010997 global arctags archeads arcnos arcout idheads idtags
Paul Mackerrascec7bec2006-08-02 09:38:10 +100010998
Paul Mackerrase11f1232007-06-16 20:29:25 +100010999 foreach id [concat [array names idheads] [array names idtags]] {
11000 if {[info exists arcnos($id)] && ![info exists arcout($id)]} {
11001 set a [lindex $arcnos($id) 0]
11002 if {![info exists donearc($a)]} {
11003 recalcarc $a
11004 set donearc($a) 1
11005 }
Paul Mackerrascec7bec2006-08-02 09:38:10 +100011006 }
11007 }
David Aguilar587277f2012-09-08 12:53:16 -070011008 catch {unset cached_tagcontent}
Paul Mackerrase11f1232007-06-16 20:29:25 +100011009 catch {unset cached_dtags}
11010 catch {unset cached_atags}
11011 catch {unset cached_dheads}
Paul Mackerrascec7bec2006-08-02 09:38:10 +100011012}
11013
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +100011014proc rereadrefs {} {
Paul Mackerrasfc2a2562007-12-26 23:03:43 +110011015 global idtags idheads idotherrefs mainheadid
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +100011016
11017 set refids [concat [array names idtags] \
11018 [array names idheads] [array names idotherrefs]]
11019 foreach id $refids {
11020 if {![info exists ref($id)]} {
11021 set ref($id) [listrefs $id]
11022 }
11023 }
Paul Mackerrasfc2a2562007-12-26 23:03:43 +110011024 set oldmainhead $mainheadid
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +100011025 readrefs
Paul Mackerrascec7bec2006-08-02 09:38:10 +100011026 changedrefs
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +100011027 set refids [lsort -unique [concat $refids [array names idtags] \
11028 [array names idheads] [array names idotherrefs]]]
11029 foreach id $refids {
11030 set v [listrefs $id]
Paul Mackerrasc11ff122008-05-26 10:11:33 +100011031 if {![info exists ref($id)] || $ref($id) != $v} {
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +100011032 redrawtags $id
11033 }
11034 }
Paul Mackerrasc11ff122008-05-26 10:11:33 +100011035 if {$oldmainhead ne $mainheadid} {
11036 redrawtags $oldmainhead
11037 redrawtags $mainheadid
11038 }
Paul Mackerras887c9962007-08-20 19:36:20 +100011039 run refill_reflist
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +100011040}
11041
Junio C Hamano2e1ded42006-06-11 09:50:47 -070011042proc listrefs {id} {
11043 global idtags idheads idotherrefs
11044
11045 set x {}
11046 if {[info exists idtags($id)]} {
11047 set x $idtags($id)
11048 }
11049 set y {}
11050 if {[info exists idheads($id)]} {
11051 set y $idheads($id)
11052 }
11053 set z {}
11054 if {[info exists idotherrefs($id)]} {
11055 set z $idotherrefs($id)
11056 }
11057 return [list $x $y $z]
11058}
11059
Paul Mackerras4399fe32013-01-03 10:10:31 +110011060proc add_tag_ctext {tag} {
11061 global ctext cached_tagcontent tagids
11062
11063 if {![info exists cached_tagcontent($tag)]} {
11064 catch {
11065 set cached_tagcontent($tag) [exec git cat-file -p $tag]
11066 }
11067 }
11068 $ctext insert end "[mc "Tag"]: $tag\n" bold
11069 if {[info exists cached_tagcontent($tag)]} {
11070 set text $cached_tagcontent($tag)
11071 } else {
11072 set text "[mc "Id"]: $tagids($tag)"
11073 }
11074 appendwithlinks $text {}
11075}
11076
Paul Mackerras106288c2005-08-19 23:11:39 +100011077proc showtag {tag isnew} {
David Aguilar587277f2012-09-08 12:53:16 -070011078 global ctext cached_tagcontent tagids linknum tagobjid
Paul Mackerras106288c2005-08-19 23:11:39 +100011079
11080 if {$isnew} {
Paul Mackerras354af6b2008-11-23 13:14:23 +110011081 addtohistory [list showtag $tag 0] savectextpos
Paul Mackerras106288c2005-08-19 23:11:39 +100011082 }
11083 $ctext conf -state normal
Paul Mackerras3ea06f92006-05-24 10:16:03 +100011084 clear_ctext
Paul Mackerras32f1b3e2007-09-28 21:27:39 +100011085 settabs 0
Paul Mackerras106288c2005-08-19 23:11:39 +100011086 set linknum 0
Paul Mackerras4399fe32013-01-03 10:10:31 +110011087 add_tag_ctext $tag
11088 maybe_scroll_ctext 1
11089 $ctext conf -state disabled
11090 init_flist {}
11091}
11092
11093proc showtags {id isnew} {
11094 global idtags ctext linknum
11095
11096 if {$isnew} {
11097 addtohistory [list showtags $id 0] savectextpos
Paul Mackerras62d3ea62006-09-11 10:36:53 +100011098 }
Paul Mackerras4399fe32013-01-03 10:10:31 +110011099 $ctext conf -state normal
11100 clear_ctext
11101 settabs 0
11102 set linknum 0
11103 set sep {}
11104 foreach tag $idtags($id) {
11105 $ctext insert end $sep
11106 add_tag_ctext $tag
11107 set sep "\n\n"
Paul Mackerras106288c2005-08-19 23:11:39 +100011108 }
Pat Thoytsa80e82f2009-11-14 13:21:09 +000011109 maybe_scroll_ctext 1
Paul Mackerras106288c2005-08-19 23:11:39 +100011110 $ctext conf -state disabled
Paul Mackerras7fcceed2006-04-27 19:21:49 +100011111 init_flist {}
Paul Mackerras106288c2005-08-19 23:11:39 +100011112}
11113
Paul Mackerras1d10f362005-05-15 12:55:47 +000011114proc doquit {} {
11115 global stopped
Thomas Arcila314f5de2008-03-24 12:55:36 +010011116 global gitktmpdir
11117
Paul Mackerras1d10f362005-05-15 12:55:47 +000011118 set stopped 100
Mark Levedahlb6047c52007-02-08 22:22:24 -050011119 savestuff .
Paul Mackerras1d10f362005-05-15 12:55:47 +000011120 destroy .
Thomas Arcila314f5de2008-03-24 12:55:36 +010011121
11122 if {[info exists gitktmpdir]} {
11123 catch {file delete -force $gitktmpdir}
11124 }
Paul Mackerras1d10f362005-05-15 12:55:47 +000011125}
11126
Paul Mackerras9a7558f2007-10-06 20:16:06 +100011127proc mkfontdisp {font top which} {
Pat Thoytsd93f1712009-04-17 01:24:35 +010011128 global fontattr fontpref $font NS use_ttk
Paul Mackerras9a7558f2007-10-06 20:16:06 +100011129
11130 set fontpref($font) [set $font]
Pat Thoytsd93f1712009-04-17 01:24:35 +010011131 ${NS}::button $top.${font}but -text $which \
Paul Mackerras9a7558f2007-10-06 20:16:06 +100011132 -command [list choosefont $font $which]
Pat Thoytsd93f1712009-04-17 01:24:35 +010011133 ${NS}::label $top.$font -relief flat -font $font \
Paul Mackerras9a7558f2007-10-06 20:16:06 +100011134 -text $fontattr($font,family) -justify left
11135 grid x $top.${font}but $top.$font -sticky w
11136}
11137
11138proc choosefont {font which} {
11139 global fontparam fontlist fonttop fontattr
Pat Thoytsd93f1712009-04-17 01:24:35 +010011140 global prefstop NS
Paul Mackerras9a7558f2007-10-06 20:16:06 +100011141
11142 set fontparam(which) $which
11143 set fontparam(font) $font
11144 set fontparam(family) [font actual $font -family]
11145 set fontparam(size) $fontattr($font,size)
11146 set fontparam(weight) $fontattr($font,weight)
11147 set fontparam(slant) $fontattr($font,slant)
11148 set top .gitkfont
11149 set fonttop $top
11150 if {![winfo exists $top]} {
11151 font create sample
11152 eval font config sample [font actual $font]
Pat Thoytsd93f1712009-04-17 01:24:35 +010011153 ttk_toplevel $top
Alexander Gavrilove7d64002008-11-11 23:55:42 +030011154 make_transient $top $prefstop
Christian Stimmingd990ced2007-11-07 18:42:55 +010011155 wm title $top [mc "Gitk font chooser"]
Pat Thoytsd93f1712009-04-17 01:24:35 +010011156 ${NS}::label $top.l -textvariable fontparam(which)
Paul Mackerras9a7558f2007-10-06 20:16:06 +100011157 pack $top.l -side top
11158 set fontlist [lsort [font families]]
Pat Thoytsd93f1712009-04-17 01:24:35 +010011159 ${NS}::frame $top.f
Paul Mackerras9a7558f2007-10-06 20:16:06 +100011160 listbox $top.f.fam -listvariable fontlist \
11161 -yscrollcommand [list $top.f.sb set]
11162 bind $top.f.fam <<ListboxSelect>> selfontfam
Pat Thoytsd93f1712009-04-17 01:24:35 +010011163 ${NS}::scrollbar $top.f.sb -command [list $top.f.fam yview]
Paul Mackerras9a7558f2007-10-06 20:16:06 +100011164 pack $top.f.sb -side right -fill y
11165 pack $top.f.fam -side left -fill both -expand 1
11166 pack $top.f -side top -fill both -expand 1
Pat Thoytsd93f1712009-04-17 01:24:35 +010011167 ${NS}::frame $top.g
Paul Mackerras9a7558f2007-10-06 20:16:06 +100011168 spinbox $top.g.size -from 4 -to 40 -width 4 \
11169 -textvariable fontparam(size) \
11170 -validatecommand {string is integer -strict %s}
11171 checkbutton $top.g.bold -padx 5 \
Christian Stimmingd990ced2007-11-07 18:42:55 +010011172 -font {{Times New Roman} 12 bold} -text [mc "B"] -indicatoron 0 \
Paul Mackerras9a7558f2007-10-06 20:16:06 +100011173 -variable fontparam(weight) -onvalue bold -offvalue normal
11174 checkbutton $top.g.ital -padx 5 \
Christian Stimmingd990ced2007-11-07 18:42:55 +010011175 -font {{Times New Roman} 12 italic} -text [mc "I"] -indicatoron 0 \
Paul Mackerras9a7558f2007-10-06 20:16:06 +100011176 -variable fontparam(slant) -onvalue italic -offvalue roman
11177 pack $top.g.size $top.g.bold $top.g.ital -side left
11178 pack $top.g -side top
11179 canvas $top.c -width 150 -height 50 -border 2 -relief sunk \
11180 -background white
11181 $top.c create text 100 25 -anchor center -text $which -font sample \
11182 -fill black -tags text
11183 bind $top.c <Configure> [list centertext $top.c]
11184 pack $top.c -side top -fill x
Pat Thoytsd93f1712009-04-17 01:24:35 +010011185 ${NS}::frame $top.buts
11186 ${NS}::button $top.buts.ok -text [mc "OK"] -command fontok -default active
11187 ${NS}::button $top.buts.can -text [mc "Cancel"] -command fontcan -default normal
Alexander Gavrilov76f15942008-11-02 21:59:44 +030011188 bind $top <Key-Return> fontok
11189 bind $top <Key-Escape> fontcan
Paul Mackerras9a7558f2007-10-06 20:16:06 +100011190 grid $top.buts.ok $top.buts.can
11191 grid columnconfigure $top.buts 0 -weight 1 -uniform a
11192 grid columnconfigure $top.buts 1 -weight 1 -uniform a
11193 pack $top.buts -side bottom -fill x
11194 trace add variable fontparam write chg_fontparam
11195 } else {
11196 raise $top
11197 $top.c itemconf text -text $which
11198 }
11199 set i [lsearch -exact $fontlist $fontparam(family)]
11200 if {$i >= 0} {
11201 $top.f.fam selection set $i
11202 $top.f.fam see $i
11203 }
11204}
11205
11206proc centertext {w} {
11207 $w coords text [expr {[winfo width $w] / 2}] [expr {[winfo height $w] / 2}]
11208}
11209
11210proc fontok {} {
11211 global fontparam fontpref prefstop
11212
11213 set f $fontparam(font)
11214 set fontpref($f) [list $fontparam(family) $fontparam(size)]
11215 if {$fontparam(weight) eq "bold"} {
11216 lappend fontpref($f) "bold"
11217 }
11218 if {$fontparam(slant) eq "italic"} {
11219 lappend fontpref($f) "italic"
11220 }
Pat Thoyts39ddf992012-04-01 23:00:52 +010011221 set w $prefstop.notebook.fonts.$f
Paul Mackerras9a7558f2007-10-06 20:16:06 +100011222 $w conf -text $fontparam(family) -font $fontpref($f)
Pat Thoytsd93f1712009-04-17 01:24:35 +010011223
Paul Mackerras9a7558f2007-10-06 20:16:06 +100011224 fontcan
11225}
11226
11227proc fontcan {} {
11228 global fonttop fontparam
11229
11230 if {[info exists fonttop]} {
11231 catch {destroy $fonttop}
11232 catch {font delete sample}
11233 unset fonttop
11234 unset fontparam
11235 }
11236}
11237
Pat Thoytsd93f1712009-04-17 01:24:35 +010011238if {[package vsatisfies [package provide Tk] 8.6]} {
11239 # In Tk 8.6 we have a native font chooser dialog. Overwrite the above
11240 # function to make use of it.
11241 proc choosefont {font which} {
11242 tk fontchooser configure -title $which -font $font \
11243 -command [list on_choosefont $font $which]
11244 tk fontchooser show
11245 }
11246 proc on_choosefont {font which newfont} {
11247 global fontparam
11248 puts stderr "$font $newfont"
11249 array set f [font actual $newfont]
11250 set fontparam(which) $which
11251 set fontparam(font) $font
11252 set fontparam(family) $f(-family)
11253 set fontparam(size) $f(-size)
11254 set fontparam(weight) $f(-weight)
11255 set fontparam(slant) $f(-slant)
11256 fontok
11257 }
11258}
11259
Paul Mackerras9a7558f2007-10-06 20:16:06 +100011260proc selfontfam {} {
11261 global fonttop fontparam
11262
11263 set i [$fonttop.f.fam curselection]
11264 if {$i ne {}} {
11265 set fontparam(family) [$fonttop.f.fam get $i]
11266 }
11267}
11268
11269proc chg_fontparam {v sub op} {
11270 global fontparam
11271
11272 font config sample -$sub $fontparam($sub)
11273}
11274
Pat Thoyts44acce02011-12-13 14:56:49 +000011275# Create a property sheet tab page
11276proc create_prefs_page {w} {
11277 global NS
11278 set parent [join [lrange [split $w .] 0 end-1] .]
11279 if {[winfo class $parent] eq "TNotebook"} {
11280 ${NS}::frame $w
11281 } else {
11282 ${NS}::labelframe $w
11283 }
11284}
11285
11286proc prefspage_general {notebook} {
11287 global NS maxwidth maxgraphpct showneartags showlocalchanges
11288 global tabstop limitdiffs autoselect autosellen extdifftool perfile_attrs
Paul Mackerrasd34835c2013-01-01 23:08:12 +110011289 global hideremotes want_ttk have_ttk maxrefs
Pat Thoyts44acce02011-12-13 14:56:49 +000011290
11291 set page [create_prefs_page $notebook.general]
11292
11293 ${NS}::label $page.ldisp -text [mc "Commit list display options"]
11294 grid $page.ldisp - -sticky w -pady 10
11295 ${NS}::label $page.spacer -text " "
11296 ${NS}::label $page.maxwidthl -text [mc "Maximum graph width (lines)"]
11297 spinbox $page.maxwidth -from 0 -to 100 -width 4 -textvariable maxwidth
11298 grid $page.spacer $page.maxwidthl $page.maxwidth -sticky w
11299 ${NS}::label $page.maxpctl -text [mc "Maximum graph width (% of pane)"]
11300 spinbox $page.maxpct -from 1 -to 100 -width 4 -textvariable maxgraphpct
11301 grid x $page.maxpctl $page.maxpct -sticky w
11302 ${NS}::checkbutton $page.showlocal -text [mc "Show local changes"] \
11303 -variable showlocalchanges
11304 grid x $page.showlocal -sticky w
11305 ${NS}::checkbutton $page.autoselect -text [mc "Auto-select SHA1 (length)"] \
11306 -variable autoselect
11307 spinbox $page.autosellen -from 1 -to 40 -width 4 -textvariable autosellen
11308 grid x $page.autoselect $page.autosellen -sticky w
11309 ${NS}::checkbutton $page.hideremotes -text [mc "Hide remote refs"] \
11310 -variable hideremotes
11311 grid x $page.hideremotes -sticky w
11312
11313 ${NS}::label $page.ddisp -text [mc "Diff display options"]
11314 grid $page.ddisp - -sticky w -pady 10
11315 ${NS}::label $page.tabstopl -text [mc "Tab spacing"]
11316 spinbox $page.tabstop -from 1 -to 20 -width 4 -textvariable tabstop
11317 grid x $page.tabstopl $page.tabstop -sticky w
Paul Mackerrasd34835c2013-01-01 23:08:12 +110011318 ${NS}::checkbutton $page.ntag -text [mc "Display nearby tags/heads"] \
Pat Thoyts44acce02011-12-13 14:56:49 +000011319 -variable showneartags
11320 grid x $page.ntag -sticky w
Paul Mackerrasd34835c2013-01-01 23:08:12 +110011321 ${NS}::label $page.maxrefsl -text [mc "Maximum # tags/heads to show"]
11322 spinbox $page.maxrefs -from 1 -to 1000 -width 4 -textvariable maxrefs
11323 grid x $page.maxrefsl $page.maxrefs -sticky w
Pat Thoyts44acce02011-12-13 14:56:49 +000011324 ${NS}::checkbutton $page.ldiff -text [mc "Limit diffs to listed paths"] \
11325 -variable limitdiffs
11326 grid x $page.ldiff -sticky w
11327 ${NS}::checkbutton $page.lattr -text [mc "Support per-file encodings"] \
11328 -variable perfile_attrs
11329 grid x $page.lattr -sticky w
11330
11331 ${NS}::entry $page.extdifft -textvariable extdifftool
11332 ${NS}::frame $page.extdifff
11333 ${NS}::label $page.extdifff.l -text [mc "External diff tool" ]
11334 ${NS}::button $page.extdifff.b -text [mc "Choose..."] -command choose_extdiff
11335 pack $page.extdifff.l $page.extdifff.b -side left
11336 pack configure $page.extdifff.l -padx 10
11337 grid x $page.extdifff $page.extdifft -sticky ew
11338
11339 ${NS}::label $page.lgen -text [mc "General options"]
11340 grid $page.lgen - -sticky w -pady 10
11341 ${NS}::checkbutton $page.want_ttk -variable want_ttk \
11342 -text [mc "Use themed widgets"]
11343 if {$have_ttk} {
11344 ${NS}::label $page.ttk_note -text [mc "(change requires restart)"]
11345 } else {
11346 ${NS}::label $page.ttk_note -text [mc "(currently unavailable)"]
11347 }
11348 grid x $page.want_ttk $page.ttk_note -sticky w
11349 return $page
11350}
11351
11352proc prefspage_colors {notebook} {
11353 global NS uicolor bgcolor fgcolor ctext diffcolors selectbgcolor markbgcolor
11354
11355 set page [create_prefs_page $notebook.colors]
11356
11357 ${NS}::label $page.cdisp -text [mc "Colors: press to choose"]
11358 grid $page.cdisp - -sticky w -pady 10
11359 label $page.ui -padx 40 -relief sunk -background $uicolor
11360 ${NS}::button $page.uibut -text [mc "Interface"] \
11361 -command [list choosecolor uicolor {} $page.ui [mc "interface"] setui]
11362 grid x $page.uibut $page.ui -sticky w
11363 label $page.bg -padx 40 -relief sunk -background $bgcolor
11364 ${NS}::button $page.bgbut -text [mc "Background"] \
11365 -command [list choosecolor bgcolor {} $page.bg [mc "background"] setbg]
11366 grid x $page.bgbut $page.bg -sticky w
11367 label $page.fg -padx 40 -relief sunk -background $fgcolor
11368 ${NS}::button $page.fgbut -text [mc "Foreground"] \
11369 -command [list choosecolor fgcolor {} $page.fg [mc "foreground"] setfg]
11370 grid x $page.fgbut $page.fg -sticky w
11371 label $page.diffold -padx 40 -relief sunk -background [lindex $diffcolors 0]
11372 ${NS}::button $page.diffoldbut -text [mc "Diff: old lines"] \
11373 -command [list choosecolor diffcolors 0 $page.diffold [mc "diff old lines"] \
11374 [list $ctext tag conf d0 -foreground]]
11375 grid x $page.diffoldbut $page.diffold -sticky w
11376 label $page.diffnew -padx 40 -relief sunk -background [lindex $diffcolors 1]
11377 ${NS}::button $page.diffnewbut -text [mc "Diff: new lines"] \
11378 -command [list choosecolor diffcolors 1 $page.diffnew [mc "diff new lines"] \
11379 [list $ctext tag conf dresult -foreground]]
11380 grid x $page.diffnewbut $page.diffnew -sticky w
11381 label $page.hunksep -padx 40 -relief sunk -background [lindex $diffcolors 2]
11382 ${NS}::button $page.hunksepbut -text [mc "Diff: hunk header"] \
11383 -command [list choosecolor diffcolors 2 $page.hunksep \
11384 [mc "diff hunk header"] \
11385 [list $ctext tag conf hunksep -foreground]]
11386 grid x $page.hunksepbut $page.hunksep -sticky w
11387 label $page.markbgsep -padx 40 -relief sunk -background $markbgcolor
11388 ${NS}::button $page.markbgbut -text [mc "Marked line bg"] \
11389 -command [list choosecolor markbgcolor {} $page.markbgsep \
11390 [mc "marked line background"] \
11391 [list $ctext tag conf omark -background]]
11392 grid x $page.markbgbut $page.markbgsep -sticky w
11393 label $page.selbgsep -padx 40 -relief sunk -background $selectbgcolor
11394 ${NS}::button $page.selbgbut -text [mc "Select bg"] \
11395 -command [list choosecolor selectbgcolor {} $page.selbgsep [mc "background"] setselbg]
11396 grid x $page.selbgbut $page.selbgsep -sticky w
11397 return $page
11398}
11399
11400proc prefspage_fonts {notebook} {
11401 global NS
11402 set page [create_prefs_page $notebook.fonts]
11403 ${NS}::label $page.cfont -text [mc "Fonts: press to choose"]
11404 grid $page.cfont - -sticky w -pady 10
11405 mkfontdisp mainfont $page [mc "Main font"]
11406 mkfontdisp textfont $page [mc "Diff display font"]
11407 mkfontdisp uifont $page [mc "User interface font"]
11408 return $page
11409}
11410
Paul Mackerras712fcc02005-11-30 09:28:16 +110011411proc doprefs {} {
Pat Thoytsd93f1712009-04-17 01:24:35 +010011412 global maxwidth maxgraphpct use_ttk NS
Paul Mackerras219ea3a2006-09-07 10:21:39 +100011413 global oldprefs prefstop showneartags showlocalchanges
Guillermo S. Romero5497f7a2009-10-15 18:51:49 +020011414 global uicolor bgcolor fgcolor ctext diffcolors selectbgcolor markbgcolor
Paul Mackerras21ac8a82011-03-09 20:52:38 +110011415 global tabstop limitdiffs autoselect autosellen extdifftool perfile_attrs
Paul Mackerras0cc08ff2009-09-05 22:06:46 +100011416 global hideremotes want_ttk have_ttk
Paul Mackerras232475d2005-11-15 10:34:03 +110011417
Paul Mackerras712fcc02005-11-30 09:28:16 +110011418 set top .gitkprefs
11419 set prefstop $top
11420 if {[winfo exists $top]} {
11421 raise $top
11422 return
Paul Mackerras757f17b2005-11-21 09:56:07 +110011423 }
Paul Mackerras3de07112007-10-23 22:40:50 +100011424 foreach v {maxwidth maxgraphpct showneartags showlocalchanges \
Paul Mackerras0cc08ff2009-09-05 22:06:46 +100011425 limitdiffs tabstop perfile_attrs hideremotes want_ttk} {
Paul Mackerras712fcc02005-11-30 09:28:16 +110011426 set oldprefs($v) [set $v]
Paul Mackerras232475d2005-11-15 10:34:03 +110011427 }
Pat Thoytsd93f1712009-04-17 01:24:35 +010011428 ttk_toplevel $top
Christian Stimmingd990ced2007-11-07 18:42:55 +010011429 wm title $top [mc "Gitk preferences"]
Alexander Gavrilove7d64002008-11-11 23:55:42 +030011430 make_transient $top .
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +100011431
Pat Thoyts44acce02011-12-13 14:56:49 +000011432 if {[set use_notebook [expr {$use_ttk && [info command ::ttk::notebook] ne ""}]]} {
11433 set notebook [ttk::notebook $top.notebook]
Paul Mackerras0cc08ff2009-09-05 22:06:46 +100011434 } else {
Pat Thoyts44acce02011-12-13 14:56:49 +000011435 set notebook [${NS}::frame $top.notebook -borderwidth 0 -relief flat]
Paul Mackerras0cc08ff2009-09-05 22:06:46 +100011436 }
Paul Mackerras0cc08ff2009-09-05 22:06:46 +100011437
Pat Thoyts44acce02011-12-13 14:56:49 +000011438 lappend pages [prefspage_general $notebook] [mc "General"]
11439 lappend pages [prefspage_colors $notebook] [mc "Colors"]
11440 lappend pages [prefspage_fonts $notebook] [mc "Fonts"]
Pat Thoyts28cb7072012-04-01 23:00:51 +010011441 set col 0
Pat Thoyts44acce02011-12-13 14:56:49 +000011442 foreach {page title} $pages {
11443 if {$use_notebook} {
11444 $notebook add $page -text $title
11445 } else {
11446 set btn [${NS}::button $notebook.b_[string map {. X} $page] \
11447 -text $title -command [list raise $page]]
11448 $page configure -text $title
11449 grid $btn -row 0 -column [incr col] -sticky w
11450 grid $page -row 1 -column 0 -sticky news -columnspan 100
11451 }
11452 }
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +100011453
Pat Thoyts44acce02011-12-13 14:56:49 +000011454 if {!$use_notebook} {
11455 grid columnconfigure $notebook 0 -weight 1
11456 grid rowconfigure $notebook 1 -weight 1
11457 raise [lindex $pages 0]
11458 }
11459
11460 grid $notebook -sticky news -padx 2 -pady 2
11461 grid rowconfigure $top 0 -weight 1
11462 grid columnconfigure $top 0 -weight 1
Paul Mackerras9a7558f2007-10-06 20:16:06 +100011463
Pat Thoytsd93f1712009-04-17 01:24:35 +010011464 ${NS}::frame $top.buts
11465 ${NS}::button $top.buts.ok -text [mc "OK"] -command prefsok -default active
11466 ${NS}::button $top.buts.can -text [mc "Cancel"] -command prefscan -default normal
Alexander Gavrilov76f15942008-11-02 21:59:44 +030011467 bind $top <Key-Return> prefsok
11468 bind $top <Key-Escape> prefscan
Paul Mackerras712fcc02005-11-30 09:28:16 +110011469 grid $top.buts.ok $top.buts.can
11470 grid columnconfigure $top.buts 0 -weight 1 -uniform a
11471 grid columnconfigure $top.buts 1 -weight 1 -uniform a
11472 grid $top.buts - - -pady 10 -sticky ew
Pat Thoytsd93f1712009-04-17 01:24:35 +010011473 grid columnconfigure $top 2 -weight 1
Pat Thoyts44acce02011-12-13 14:56:49 +000011474 bind $top <Visibility> [list focus $top.buts.ok]
Paul Mackerras712fcc02005-11-30 09:28:16 +110011475}
11476
Thomas Arcila314f5de2008-03-24 12:55:36 +010011477proc choose_extdiff {} {
11478 global extdifftool
11479
Michele Ballabiob56e0a92009-03-30 21:17:25 +020011480 set prog [tk_getOpenFile -title [mc "External diff tool"] -multiple false]
Thomas Arcila314f5de2008-03-24 12:55:36 +010011481 if {$prog ne {}} {
11482 set extdifftool $prog
11483 }
11484}
11485
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +100011486proc choosecolor {v vi w x cmd} {
11487 global $v
11488
11489 set c [tk_chooseColor -initialcolor [lindex [set $v] $vi] \
Christian Stimmingd990ced2007-11-07 18:42:55 +010011490 -title [mc "Gitk: choose color for %s" $x]]
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +100011491 if {$c eq {}} return
11492 $w conf -background $c
11493 lset $v $vi $c
11494 eval $cmd $c
11495}
11496
Mark Levedahl60378c02007-05-20 12:12:48 -040011497proc setselbg {c} {
11498 global bglist cflist
11499 foreach w $bglist {
11500 $w configure -selectbackground $c
11501 }
11502 $cflist tag configure highlight \
11503 -background [$cflist cget -selectbackground]
11504 allcanvs itemconf secsel -fill $c
11505}
11506
Paul Mackerras51a7e8b2009-11-14 21:15:01 +110011507# This sets the background color and the color scheme for the whole UI.
11508# For some reason, tk_setPalette chooses a nasty dark red for selectColor
11509# if we don't specify one ourselves, which makes the checkbuttons and
11510# radiobuttons look bad. This chooses white for selectColor if the
11511# background color is light, or black if it is dark.
Guillermo S. Romero5497f7a2009-10-15 18:51:49 +020011512proc setui {c} {
Pat Thoyts2e58c942010-03-12 18:31:47 +000011513 if {[tk windowingsystem] eq "win32"} { return }
Paul Mackerras51a7e8b2009-11-14 21:15:01 +110011514 set bg [winfo rgb . $c]
11515 set selc black
11516 if {[lindex $bg 0] + 1.5 * [lindex $bg 1] + 0.5 * [lindex $bg 2] > 100000} {
11517 set selc white
11518 }
11519 tk_setPalette background $c selectColor $selc
Guillermo S. Romero5497f7a2009-10-15 18:51:49 +020011520}
11521
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +100011522proc setbg {c} {
11523 global bglist
11524
11525 foreach w $bglist {
11526 $w conf -background $c
11527 }
11528}
11529
11530proc setfg {c} {
11531 global fglist canv
11532
11533 foreach w $fglist {
11534 $w conf -foreground $c
11535 }
11536 allcanvs itemconf text -fill $c
11537 $canv itemconf circle -outline $c
Paul Mackerrasb9fdba72009-04-09 09:34:46 +100011538 $canv itemconf markid -outline $c
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +100011539}
11540
Paul Mackerras712fcc02005-11-30 09:28:16 +110011541proc prefscan {} {
Paul Mackerras94503912007-10-23 10:33:38 +100011542 global oldprefs prefstop
Paul Mackerras712fcc02005-11-30 09:28:16 +110011543
Paul Mackerras3de07112007-10-23 22:40:50 +100011544 foreach v {maxwidth maxgraphpct showneartags showlocalchanges \
Paul Mackerras0cc08ff2009-09-05 22:06:46 +100011545 limitdiffs tabstop perfile_attrs hideremotes want_ttk} {
Paul Mackerras94503912007-10-23 10:33:38 +100011546 global $v
Paul Mackerras712fcc02005-11-30 09:28:16 +110011547 set $v $oldprefs($v)
11548 }
11549 catch {destroy $prefstop}
11550 unset prefstop
Paul Mackerras9a7558f2007-10-06 20:16:06 +100011551 fontcan
Paul Mackerras712fcc02005-11-30 09:28:16 +110011552}
11553
11554proc prefsok {} {
11555 global maxwidth maxgraphpct
Paul Mackerras219ea3a2006-09-07 10:21:39 +100011556 global oldprefs prefstop showneartags showlocalchanges
Paul Mackerras9a7558f2007-10-06 20:16:06 +100011557 global fontpref mainfont textfont uifont
Paul Mackerras39ee47e2008-10-15 22:23:03 +110011558 global limitdiffs treediffs perfile_attrs
Thomas Rastffe15292009-08-03 23:53:36 +020011559 global hideremotes
Paul Mackerras712fcc02005-11-30 09:28:16 +110011560
11561 catch {destroy $prefstop}
11562 unset prefstop
Paul Mackerras9a7558f2007-10-06 20:16:06 +100011563 fontcan
11564 set fontchanged 0
11565 if {$mainfont ne $fontpref(mainfont)} {
11566 set mainfont $fontpref(mainfont)
11567 parsefont mainfont $mainfont
11568 eval font configure mainfont [fontflags mainfont]
11569 eval font configure mainfontbold [fontflags mainfont 1]
11570 setcoords
11571 set fontchanged 1
11572 }
11573 if {$textfont ne $fontpref(textfont)} {
11574 set textfont $fontpref(textfont)
11575 parsefont textfont $textfont
11576 eval font configure textfont [fontflags textfont]
11577 eval font configure textfontbold [fontflags textfont 1]
11578 }
11579 if {$uifont ne $fontpref(uifont)} {
11580 set uifont $fontpref(uifont)
11581 parsefont uifont $uifont
11582 eval font configure uifont [fontflags uifont]
11583 }
Paul Mackerras32f1b3e2007-09-28 21:27:39 +100011584 settabs
Paul Mackerras219ea3a2006-09-07 10:21:39 +100011585 if {$showlocalchanges != $oldprefs(showlocalchanges)} {
11586 if {$showlocalchanges} {
11587 doshowlocalchanges
11588 } else {
11589 dohidelocalchanges
11590 }
11591 }
Paul Mackerras39ee47e2008-10-15 22:23:03 +110011592 if {$limitdiffs != $oldprefs(limitdiffs) ||
11593 ($perfile_attrs && !$oldprefs(perfile_attrs))} {
11594 # treediffs elements are limited by path;
11595 # won't have encodings cached if perfile_attrs was just turned on
Paul Mackerras74a40c72007-10-24 10:16:56 +100011596 catch {unset treediffs}
11597 }
Paul Mackerras9a7558f2007-10-06 20:16:06 +100011598 if {$fontchanged || $maxwidth != $oldprefs(maxwidth)
Paul Mackerras712fcc02005-11-30 09:28:16 +110011599 || $maxgraphpct != $oldprefs(maxgraphpct)} {
11600 redisplay
Paul Mackerras7a39a172007-10-23 10:15:11 +100011601 } elseif {$showneartags != $oldprefs(showneartags) ||
11602 $limitdiffs != $oldprefs(limitdiffs)} {
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +100011603 reselectline
Paul Mackerras712fcc02005-11-30 09:28:16 +110011604 }
Thomas Rastffe15292009-08-03 23:53:36 +020011605 if {$hideremotes != $oldprefs(hideremotes)} {
11606 rereadrefs
11607 }
Paul Mackerras712fcc02005-11-30 09:28:16 +110011608}
11609
11610proc formatdate {d} {
Arjen Laarhovene8b5f4b2007-08-14 22:02:04 +020011611 global datetimeformat
Paul Mackerras219ea3a2006-09-07 10:21:39 +100011612 if {$d ne {}} {
Anders Kaseorg019e1632014-05-12 07:25:58 -040011613 # If $datetimeformat includes a timezone, display in the
11614 # timezone of the argument. Otherwise, display in local time.
11615 if {[string match {*%[zZ]*} $datetimeformat]} {
11616 if {[catch {set d [clock format [lindex $d 0] -timezone [lindex $d 1] -format $datetimeformat]}]} {
11617 # Tcl < 8.5 does not support -timezone. Emulate it by
11618 # setting TZ (e.g. TZ=<-0430>+04:30).
11619 global env
11620 if {[info exists env(TZ)]} {
11621 set savedTZ $env(TZ)
11622 }
11623 set zone [lindex $d 1]
11624 set sign [string map {+ - - +} [string index $zone 0]]
11625 set env(TZ) <$zone>$sign[string range $zone 1 2]:[string range $zone 3 4]
11626 set d [clock format [lindex $d 0] -format $datetimeformat]
11627 if {[info exists savedTZ]} {
11628 set env(TZ) $savedTZ
11629 } else {
11630 unset env(TZ)
11631 }
11632 }
11633 } else {
11634 set d [clock format [lindex $d 0] -format $datetimeformat]
11635 }
Paul Mackerras219ea3a2006-09-07 10:21:39 +100011636 }
11637 return $d
Paul Mackerras232475d2005-11-15 10:34:03 +110011638}
11639
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +110011640# This list of encoding names and aliases is distilled from
11641# http://www.iana.org/assignments/character-sets.
11642# Not all of them are supported by Tcl.
11643set encoding_aliases {
11644 { ANSI_X3.4-1968 iso-ir-6 ANSI_X3.4-1986 ISO_646.irv:1991 ASCII
11645 ISO646-US US-ASCII us IBM367 cp367 csASCII }
11646 { ISO-10646-UTF-1 csISO10646UTF1 }
11647 { ISO_646.basic:1983 ref csISO646basic1983 }
11648 { INVARIANT csINVARIANT }
11649 { ISO_646.irv:1983 iso-ir-2 irv csISO2IntlRefVersion }
11650 { BS_4730 iso-ir-4 ISO646-GB gb uk csISO4UnitedKingdom }
11651 { NATS-SEFI iso-ir-8-1 csNATSSEFI }
11652 { NATS-SEFI-ADD iso-ir-8-2 csNATSSEFIADD }
11653 { NATS-DANO iso-ir-9-1 csNATSDANO }
11654 { NATS-DANO-ADD iso-ir-9-2 csNATSDANOADD }
11655 { SEN_850200_B iso-ir-10 FI ISO646-FI ISO646-SE se csISO10Swedish }
11656 { SEN_850200_C iso-ir-11 ISO646-SE2 se2 csISO11SwedishForNames }
11657 { KS_C_5601-1987 iso-ir-149 KS_C_5601-1989 KSC_5601 korean csKSC56011987 }
11658 { ISO-2022-KR csISO2022KR }
11659 { EUC-KR csEUCKR }
11660 { ISO-2022-JP csISO2022JP }
11661 { ISO-2022-JP-2 csISO2022JP2 }
11662 { JIS_C6220-1969-jp JIS_C6220-1969 iso-ir-13 katakana x0201-7
11663 csISO13JISC6220jp }
11664 { JIS_C6220-1969-ro iso-ir-14 jp ISO646-JP csISO14JISC6220ro }
11665 { IT iso-ir-15 ISO646-IT csISO15Italian }
11666 { PT iso-ir-16 ISO646-PT csISO16Portuguese }
11667 { ES iso-ir-17 ISO646-ES csISO17Spanish }
11668 { greek7-old iso-ir-18 csISO18Greek7Old }
11669 { latin-greek iso-ir-19 csISO19LatinGreek }
11670 { DIN_66003 iso-ir-21 de ISO646-DE csISO21German }
11671 { NF_Z_62-010_(1973) iso-ir-25 ISO646-FR1 csISO25French }
11672 { Latin-greek-1 iso-ir-27 csISO27LatinGreek1 }
11673 { ISO_5427 iso-ir-37 csISO5427Cyrillic }
11674 { JIS_C6226-1978 iso-ir-42 csISO42JISC62261978 }
11675 { BS_viewdata iso-ir-47 csISO47BSViewdata }
11676 { INIS iso-ir-49 csISO49INIS }
11677 { INIS-8 iso-ir-50 csISO50INIS8 }
11678 { INIS-cyrillic iso-ir-51 csISO51INISCyrillic }
11679 { ISO_5427:1981 iso-ir-54 ISO5427Cyrillic1981 }
11680 { ISO_5428:1980 iso-ir-55 csISO5428Greek }
11681 { GB_1988-80 iso-ir-57 cn ISO646-CN csISO57GB1988 }
11682 { GB_2312-80 iso-ir-58 chinese csISO58GB231280 }
11683 { NS_4551-1 iso-ir-60 ISO646-NO no csISO60DanishNorwegian
11684 csISO60Norwegian1 }
11685 { NS_4551-2 ISO646-NO2 iso-ir-61 no2 csISO61Norwegian2 }
11686 { NF_Z_62-010 iso-ir-69 ISO646-FR fr csISO69French }
11687 { videotex-suppl iso-ir-70 csISO70VideotexSupp1 }
11688 { PT2 iso-ir-84 ISO646-PT2 csISO84Portuguese2 }
11689 { ES2 iso-ir-85 ISO646-ES2 csISO85Spanish2 }
11690 { MSZ_7795.3 iso-ir-86 ISO646-HU hu csISO86Hungarian }
11691 { JIS_C6226-1983 iso-ir-87 x0208 JIS_X0208-1983 csISO87JISX0208 }
11692 { greek7 iso-ir-88 csISO88Greek7 }
11693 { ASMO_449 ISO_9036 arabic7 iso-ir-89 csISO89ASMO449 }
11694 { iso-ir-90 csISO90 }
11695 { JIS_C6229-1984-a iso-ir-91 jp-ocr-a csISO91JISC62291984a }
11696 { JIS_C6229-1984-b iso-ir-92 ISO646-JP-OCR-B jp-ocr-b
11697 csISO92JISC62991984b }
11698 { JIS_C6229-1984-b-add iso-ir-93 jp-ocr-b-add csISO93JIS62291984badd }
11699 { JIS_C6229-1984-hand iso-ir-94 jp-ocr-hand csISO94JIS62291984hand }
11700 { JIS_C6229-1984-hand-add iso-ir-95 jp-ocr-hand-add
11701 csISO95JIS62291984handadd }
11702 { JIS_C6229-1984-kana iso-ir-96 csISO96JISC62291984kana }
11703 { ISO_2033-1983 iso-ir-98 e13b csISO2033 }
11704 { ANSI_X3.110-1983 iso-ir-99 CSA_T500-1983 NAPLPS csISO99NAPLPS }
11705 { ISO_8859-1:1987 iso-ir-100 ISO_8859-1 ISO-8859-1 latin1 l1 IBM819
11706 CP819 csISOLatin1 }
11707 { ISO_8859-2:1987 iso-ir-101 ISO_8859-2 ISO-8859-2 latin2 l2 csISOLatin2 }
11708 { T.61-7bit iso-ir-102 csISO102T617bit }
11709 { T.61-8bit T.61 iso-ir-103 csISO103T618bit }
11710 { ISO_8859-3:1988 iso-ir-109 ISO_8859-3 ISO-8859-3 latin3 l3 csISOLatin3 }
11711 { ISO_8859-4:1988 iso-ir-110 ISO_8859-4 ISO-8859-4 latin4 l4 csISOLatin4 }
11712 { ECMA-cyrillic iso-ir-111 KOI8-E csISO111ECMACyrillic }
11713 { CSA_Z243.4-1985-1 iso-ir-121 ISO646-CA csa7-1 ca csISO121Canadian1 }
11714 { CSA_Z243.4-1985-2 iso-ir-122 ISO646-CA2 csa7-2 csISO122Canadian2 }
11715 { CSA_Z243.4-1985-gr iso-ir-123 csISO123CSAZ24341985gr }
11716 { ISO_8859-6:1987 iso-ir-127 ISO_8859-6 ISO-8859-6 ECMA-114 ASMO-708
11717 arabic csISOLatinArabic }
11718 { ISO_8859-6-E csISO88596E ISO-8859-6-E }
11719 { ISO_8859-6-I csISO88596I ISO-8859-6-I }
11720 { ISO_8859-7:1987 iso-ir-126 ISO_8859-7 ISO-8859-7 ELOT_928 ECMA-118
11721 greek greek8 csISOLatinGreek }
11722 { T.101-G2 iso-ir-128 csISO128T101G2 }
11723 { ISO_8859-8:1988 iso-ir-138 ISO_8859-8 ISO-8859-8 hebrew
11724 csISOLatinHebrew }
11725 { ISO_8859-8-E csISO88598E ISO-8859-8-E }
11726 { ISO_8859-8-I csISO88598I ISO-8859-8-I }
11727 { CSN_369103 iso-ir-139 csISO139CSN369103 }
11728 { JUS_I.B1.002 iso-ir-141 ISO646-YU js yu csISO141JUSIB1002 }
11729 { ISO_6937-2-add iso-ir-142 csISOTextComm }
11730 { IEC_P27-1 iso-ir-143 csISO143IECP271 }
11731 { ISO_8859-5:1988 iso-ir-144 ISO_8859-5 ISO-8859-5 cyrillic
11732 csISOLatinCyrillic }
11733 { JUS_I.B1.003-serb iso-ir-146 serbian csISO146Serbian }
11734 { JUS_I.B1.003-mac macedonian iso-ir-147 csISO147Macedonian }
11735 { ISO_8859-9:1989 iso-ir-148 ISO_8859-9 ISO-8859-9 latin5 l5 csISOLatin5 }
11736 { greek-ccitt iso-ir-150 csISO150 csISO150GreekCCITT }
11737 { NC_NC00-10:81 cuba iso-ir-151 ISO646-CU csISO151Cuba }
11738 { ISO_6937-2-25 iso-ir-152 csISO6937Add }
11739 { GOST_19768-74 ST_SEV_358-88 iso-ir-153 csISO153GOST1976874 }
11740 { ISO_8859-supp iso-ir-154 latin1-2-5 csISO8859Supp }
11741 { ISO_10367-box iso-ir-155 csISO10367Box }
11742 { ISO-8859-10 iso-ir-157 l6 ISO_8859-10:1992 csISOLatin6 latin6 }
11743 { latin-lap lap iso-ir-158 csISO158Lap }
11744 { JIS_X0212-1990 x0212 iso-ir-159 csISO159JISX02121990 }
11745 { DS_2089 DS2089 ISO646-DK dk csISO646Danish }
11746 { us-dk csUSDK }
11747 { dk-us csDKUS }
11748 { JIS_X0201 X0201 csHalfWidthKatakana }
11749 { KSC5636 ISO646-KR csKSC5636 }
11750 { ISO-10646-UCS-2 csUnicode }
11751 { ISO-10646-UCS-4 csUCS4 }
11752 { DEC-MCS dec csDECMCS }
11753 { hp-roman8 roman8 r8 csHPRoman8 }
11754 { macintosh mac csMacintosh }
11755 { IBM037 cp037 ebcdic-cp-us ebcdic-cp-ca ebcdic-cp-wt ebcdic-cp-nl
11756 csIBM037 }
11757 { IBM038 EBCDIC-INT cp038 csIBM038 }
11758 { IBM273 CP273 csIBM273 }
11759 { IBM274 EBCDIC-BE CP274 csIBM274 }
11760 { IBM275 EBCDIC-BR cp275 csIBM275 }
11761 { IBM277 EBCDIC-CP-DK EBCDIC-CP-NO csIBM277 }
11762 { IBM278 CP278 ebcdic-cp-fi ebcdic-cp-se csIBM278 }
11763 { IBM280 CP280 ebcdic-cp-it csIBM280 }
11764 { IBM281 EBCDIC-JP-E cp281 csIBM281 }
11765 { IBM284 CP284 ebcdic-cp-es csIBM284 }
11766 { IBM285 CP285 ebcdic-cp-gb csIBM285 }
11767 { IBM290 cp290 EBCDIC-JP-kana csIBM290 }
11768 { IBM297 cp297 ebcdic-cp-fr csIBM297 }
11769 { IBM420 cp420 ebcdic-cp-ar1 csIBM420 }
11770 { IBM423 cp423 ebcdic-cp-gr csIBM423 }
11771 { IBM424 cp424 ebcdic-cp-he csIBM424 }
11772 { IBM437 cp437 437 csPC8CodePage437 }
11773 { IBM500 CP500 ebcdic-cp-be ebcdic-cp-ch csIBM500 }
11774 { IBM775 cp775 csPC775Baltic }
11775 { IBM850 cp850 850 csPC850Multilingual }
11776 { IBM851 cp851 851 csIBM851 }
11777 { IBM852 cp852 852 csPCp852 }
11778 { IBM855 cp855 855 csIBM855 }
11779 { IBM857 cp857 857 csIBM857 }
11780 { IBM860 cp860 860 csIBM860 }
11781 { IBM861 cp861 861 cp-is csIBM861 }
11782 { IBM862 cp862 862 csPC862LatinHebrew }
11783 { IBM863 cp863 863 csIBM863 }
11784 { IBM864 cp864 csIBM864 }
11785 { IBM865 cp865 865 csIBM865 }
11786 { IBM866 cp866 866 csIBM866 }
11787 { IBM868 CP868 cp-ar csIBM868 }
11788 { IBM869 cp869 869 cp-gr csIBM869 }
11789 { IBM870 CP870 ebcdic-cp-roece ebcdic-cp-yu csIBM870 }
11790 { IBM871 CP871 ebcdic-cp-is csIBM871 }
11791 { IBM880 cp880 EBCDIC-Cyrillic csIBM880 }
11792 { IBM891 cp891 csIBM891 }
11793 { IBM903 cp903 csIBM903 }
11794 { IBM904 cp904 904 csIBBM904 }
11795 { IBM905 CP905 ebcdic-cp-tr csIBM905 }
11796 { IBM918 CP918 ebcdic-cp-ar2 csIBM918 }
11797 { IBM1026 CP1026 csIBM1026 }
11798 { EBCDIC-AT-DE csIBMEBCDICATDE }
11799 { EBCDIC-AT-DE-A csEBCDICATDEA }
11800 { EBCDIC-CA-FR csEBCDICCAFR }
11801 { EBCDIC-DK-NO csEBCDICDKNO }
11802 { EBCDIC-DK-NO-A csEBCDICDKNOA }
11803 { EBCDIC-FI-SE csEBCDICFISE }
11804 { EBCDIC-FI-SE-A csEBCDICFISEA }
11805 { EBCDIC-FR csEBCDICFR }
11806 { EBCDIC-IT csEBCDICIT }
11807 { EBCDIC-PT csEBCDICPT }
11808 { EBCDIC-ES csEBCDICES }
11809 { EBCDIC-ES-A csEBCDICESA }
11810 { EBCDIC-ES-S csEBCDICESS }
11811 { EBCDIC-UK csEBCDICUK }
11812 { EBCDIC-US csEBCDICUS }
11813 { UNKNOWN-8BIT csUnknown8BiT }
11814 { MNEMONIC csMnemonic }
11815 { MNEM csMnem }
11816 { VISCII csVISCII }
11817 { VIQR csVIQR }
11818 { KOI8-R csKOI8R }
11819 { IBM00858 CCSID00858 CP00858 PC-Multilingual-850+euro }
11820 { IBM00924 CCSID00924 CP00924 ebcdic-Latin9--euro }
11821 { IBM01140 CCSID01140 CP01140 ebcdic-us-37+euro }
11822 { IBM01141 CCSID01141 CP01141 ebcdic-de-273+euro }
11823 { IBM01142 CCSID01142 CP01142 ebcdic-dk-277+euro ebcdic-no-277+euro }
11824 { IBM01143 CCSID01143 CP01143 ebcdic-fi-278+euro ebcdic-se-278+euro }
11825 { IBM01144 CCSID01144 CP01144 ebcdic-it-280+euro }
11826 { IBM01145 CCSID01145 CP01145 ebcdic-es-284+euro }
11827 { IBM01146 CCSID01146 CP01146 ebcdic-gb-285+euro }
11828 { IBM01147 CCSID01147 CP01147 ebcdic-fr-297+euro }
11829 { IBM01148 CCSID01148 CP01148 ebcdic-international-500+euro }
11830 { IBM01149 CCSID01149 CP01149 ebcdic-is-871+euro }
11831 { IBM1047 IBM-1047 }
11832 { PTCP154 csPTCP154 PT154 CP154 Cyrillic-Asian }
11833 { Amiga-1251 Ami1251 Amiga1251 Ami-1251 }
11834 { UNICODE-1-1 csUnicode11 }
11835 { CESU-8 csCESU-8 }
11836 { BOCU-1 csBOCU-1 }
11837 { UNICODE-1-1-UTF-7 csUnicode11UTF7 }
11838 { ISO-8859-14 iso-ir-199 ISO_8859-14:1998 ISO_8859-14 latin8 iso-celtic
11839 l8 }
11840 { ISO-8859-15 ISO_8859-15 Latin-9 }
11841 { ISO-8859-16 iso-ir-226 ISO_8859-16:2001 ISO_8859-16 latin10 l10 }
11842 { GBK CP936 MS936 windows-936 }
11843 { JIS_Encoding csJISEncoding }
Alexander Gavrilov09c70292008-10-13 12:12:31 +040011844 { Shift_JIS MS_Kanji csShiftJIS ShiftJIS Shift-JIS }
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +110011845 { Extended_UNIX_Code_Packed_Format_for_Japanese csEUCPkdFmtJapanese
11846 EUC-JP }
11847 { Extended_UNIX_Code_Fixed_Width_for_Japanese csEUCFixWidJapanese }
11848 { ISO-10646-UCS-Basic csUnicodeASCII }
11849 { ISO-10646-Unicode-Latin1 csUnicodeLatin1 ISO-10646 }
11850 { ISO-Unicode-IBM-1261 csUnicodeIBM1261 }
11851 { ISO-Unicode-IBM-1268 csUnicodeIBM1268 }
11852 { ISO-Unicode-IBM-1276 csUnicodeIBM1276 }
11853 { ISO-Unicode-IBM-1264 csUnicodeIBM1264 }
11854 { ISO-Unicode-IBM-1265 csUnicodeIBM1265 }
11855 { ISO-8859-1-Windows-3.0-Latin-1 csWindows30Latin1 }
11856 { ISO-8859-1-Windows-3.1-Latin-1 csWindows31Latin1 }
11857 { ISO-8859-2-Windows-Latin-2 csWindows31Latin2 }
11858 { ISO-8859-9-Windows-Latin-5 csWindows31Latin5 }
11859 { Adobe-Standard-Encoding csAdobeStandardEncoding }
11860 { Ventura-US csVenturaUS }
11861 { Ventura-International csVenturaInternational }
11862 { PC8-Danish-Norwegian csPC8DanishNorwegian }
11863 { PC8-Turkish csPC8Turkish }
11864 { IBM-Symbols csIBMSymbols }
11865 { IBM-Thai csIBMThai }
11866 { HP-Legal csHPLegal }
11867 { HP-Pi-font csHPPiFont }
11868 { HP-Math8 csHPMath8 }
11869 { Adobe-Symbol-Encoding csHPPSMath }
11870 { HP-DeskTop csHPDesktop }
11871 { Ventura-Math csVenturaMath }
11872 { Microsoft-Publishing csMicrosoftPublishing }
11873 { Windows-31J csWindows31J }
11874 { GB2312 csGB2312 }
11875 { Big5 csBig5 }
11876}
11877
11878proc tcl_encoding {enc} {
Paul Mackerras39ee47e2008-10-15 22:23:03 +110011879 global encoding_aliases tcl_encoding_cache
11880 if {[info exists tcl_encoding_cache($enc)]} {
11881 return $tcl_encoding_cache($enc)
11882 }
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +110011883 set names [encoding names]
11884 set lcnames [string tolower $names]
11885 set enc [string tolower $enc]
11886 set i [lsearch -exact $lcnames $enc]
11887 if {$i < 0} {
11888 # look for "isonnn" instead of "iso-nnn" or "iso_nnn"
Alexander Gavrilov09c70292008-10-13 12:12:31 +040011889 if {[regsub {^(iso|cp|ibm|jis)[-_]} $enc {\1} encx]} {
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +110011890 set i [lsearch -exact $lcnames $encx]
11891 }
11892 }
11893 if {$i < 0} {
11894 foreach l $encoding_aliases {
11895 set ll [string tolower $l]
11896 if {[lsearch -exact $ll $enc] < 0} continue
11897 # look through the aliases for one that tcl knows about
11898 foreach e $ll {
11899 set i [lsearch -exact $lcnames $e]
11900 if {$i < 0} {
Alexander Gavrilov09c70292008-10-13 12:12:31 +040011901 if {[regsub {^(iso|cp|ibm|jis)[-_]} $e {\1} ex]} {
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +110011902 set i [lsearch -exact $lcnames $ex]
11903 }
11904 }
11905 if {$i >= 0} break
11906 }
11907 break
11908 }
11909 }
Paul Mackerras39ee47e2008-10-15 22:23:03 +110011910 set tclenc {}
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +110011911 if {$i >= 0} {
Paul Mackerras39ee47e2008-10-15 22:23:03 +110011912 set tclenc [lindex $names $i]
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +110011913 }
Paul Mackerras39ee47e2008-10-15 22:23:03 +110011914 set tcl_encoding_cache($enc) $tclenc
11915 return $tclenc
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +110011916}
11917
Alexander Gavrilov09c70292008-10-13 12:12:31 +040011918proc gitattr {path attr default} {
Paul Mackerras39ee47e2008-10-15 22:23:03 +110011919 global path_attr_cache
11920 if {[info exists path_attr_cache($attr,$path)]} {
11921 set r $path_attr_cache($attr,$path)
11922 } else {
11923 set r "unspecified"
11924 if {![catch {set line [exec git check-attr $attr -- $path]}]} {
Johannes Sixt097e1112009-07-21 10:09:48 +020011925 regexp "(.*): $attr: (.*)" $line m f r
Alexander Gavrilov09c70292008-10-13 12:12:31 +040011926 }
Alexander Gavrilov4db09302008-10-13 12:12:33 +040011927 set path_attr_cache($attr,$path) $r
Paul Mackerras39ee47e2008-10-15 22:23:03 +110011928 }
11929 if {$r eq "unspecified"} {
11930 return $default
11931 }
11932 return $r
Alexander Gavrilov09c70292008-10-13 12:12:31 +040011933}
11934
Alexander Gavrilov4db09302008-10-13 12:12:33 +040011935proc cache_gitattr {attr pathlist} {
Paul Mackerras39ee47e2008-10-15 22:23:03 +110011936 global path_attr_cache
11937 set newlist {}
11938 foreach path $pathlist {
11939 if {![info exists path_attr_cache($attr,$path)]} {
11940 lappend newlist $path
Alexander Gavrilov4db09302008-10-13 12:12:33 +040011941 }
Paul Mackerras39ee47e2008-10-15 22:23:03 +110011942 }
11943 set lim 1000
11944 if {[tk windowingsystem] == "win32"} {
11945 # windows has a 32k limit on the arguments to a command...
11946 set lim 30
11947 }
11948 while {$newlist ne {}} {
11949 set head [lrange $newlist 0 [expr {$lim - 1}]]
11950 set newlist [lrange $newlist $lim end]
11951 if {![catch {set rlist [eval exec git check-attr $attr -- $head]}]} {
11952 foreach row [split $rlist "\n"] {
Johannes Sixt097e1112009-07-21 10:09:48 +020011953 if {[regexp "(.*): $attr: (.*)" $row m path value]} {
Paul Mackerras39ee47e2008-10-15 22:23:03 +110011954 if {[string index $path 0] eq "\""} {
11955 set path [encoding convertfrom [lindex $path 0]]
11956 }
11957 set path_attr_cache($attr,$path) $value
Alexander Gavrilov4db09302008-10-13 12:12:33 +040011958 }
Paul Mackerras39ee47e2008-10-15 22:23:03 +110011959 }
Alexander Gavrilov4db09302008-10-13 12:12:33 +040011960 }
Paul Mackerras39ee47e2008-10-15 22:23:03 +110011961 }
Alexander Gavrilov4db09302008-10-13 12:12:33 +040011962}
11963
Alexander Gavrilov09c70292008-10-13 12:12:31 +040011964proc get_path_encoding {path} {
Paul Mackerras39ee47e2008-10-15 22:23:03 +110011965 global gui_encoding perfile_attrs
11966 set tcl_enc $gui_encoding
11967 if {$path ne {} && $perfile_attrs} {
11968 set enc2 [tcl_encoding [gitattr $path encoding $tcl_enc]]
11969 if {$enc2 ne {}} {
11970 set tcl_enc $enc2
Alexander Gavrilov09c70292008-10-13 12:12:31 +040011971 }
Paul Mackerras39ee47e2008-10-15 22:23:03 +110011972 }
11973 return $tcl_enc
Alexander Gavrilov09c70292008-10-13 12:12:31 +040011974}
11975
Paul Mackerras5d7589d2007-10-20 21:21:03 +100011976# First check that Tcl/Tk is recent enough
11977if {[catch {package require Tk 8.4} err]} {
Bernt Hansen8d849952009-11-02 07:41:00 -050011978 show_error {} . "Sorry, gitk cannot run with this version of Tcl/Tk.\n\
11979 Gitk requires at least Tcl/Tk 8.4." list
Paul Mackerras5d7589d2007-10-20 21:21:03 +100011980 exit 1
11981}
11982
Tair Sabirgaliev76bf6ff2013-04-24 15:48:27 +060011983# on OSX bring the current Wish process window to front
11984if {[tk windowingsystem] eq "aqua"} {
11985 exec osascript -e [format {
11986 tell application "System Events"
11987 set frontmost of processes whose unix id is %d to true
11988 end tell
11989 } [pid] ]
11990}
11991
Aske Olsson0ae10352012-05-10 12:13:43 +020011992# Unset GIT_TRACE var if set
11993if { [info exists ::env(GIT_TRACE)] } {
11994 unset ::env(GIT_TRACE)
11995}
11996
Paul Mackerras1d10f362005-05-15 12:55:47 +000011997# defaults...
Timo Hirvonen8974c6f2006-05-24 10:57:40 +030011998set wrcomcmd "git diff-tree --stdin -p --pretty"
Junio C Hamano671bc152005-11-27 16:12:51 -080011999
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +110012000set gitencoding {}
Junio C Hamano671bc152005-11-27 16:12:51 -080012001catch {
Paul Mackerras27cb61c2007-02-15 08:54:34 +110012002 set gitencoding [exec git config --get i18n.commitencoding]
Junio C Hamano671bc152005-11-27 16:12:51 -080012003}
Alexander Gavrilov590915d2008-11-09 18:06:07 +030012004catch {
12005 set gitencoding [exec git config --get i18n.logoutputencoding]
12006}
Junio C Hamano671bc152005-11-27 16:12:51 -080012007if {$gitencoding == ""} {
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +110012008 set gitencoding "utf-8"
12009}
12010set tclencoding [tcl_encoding $gitencoding]
12011if {$tclencoding == {}} {
12012 puts stderr "Warning: encoding $gitencoding is not supported by Tcl/Tk"
Junio C Hamano671bc152005-11-27 16:12:51 -080012013}
Paul Mackerras1d10f362005-05-15 12:55:47 +000012014
Alexander Gavrilov09c70292008-10-13 12:12:31 +040012015set gui_encoding [encoding system]
12016catch {
Paul Mackerras39ee47e2008-10-15 22:23:03 +110012017 set enc [exec git config --get gui.encoding]
12018 if {$enc ne {}} {
12019 set tclenc [tcl_encoding $enc]
12020 if {$tclenc ne {}} {
12021 set gui_encoding $tclenc
12022 } else {
12023 puts stderr "Warning: encoding $enc is not supported by Tcl/Tk"
12024 }
12025 }
Alexander Gavrilov09c70292008-10-13 12:12:31 +040012026}
12027
Marcus Karlssonb2b76d12011-10-04 22:08:13 +020012028set log_showroot true
12029catch {
12030 set log_showroot [exec git config --bool --get log.showroot]
12031}
12032
Daniel A. Steffen5fdcbb12009-03-23 12:17:38 +010012033if {[tk windowingsystem] eq "aqua"} {
12034 set mainfont {{Lucida Grande} 9}
12035 set textfont {Monaco 9}
12036 set uifont {{Lucida Grande} 9 bold}
Jonathan Nieder5c9096f2012-03-08 06:30:11 -060012037} elseif {![catch {::tk::pkgconfig get fontsystem} xft] && $xft eq "xft"} {
12038 # fontconfig!
12039 set mainfont {sans 9}
12040 set textfont {monospace 9}
12041 set uifont {sans 9 bold}
Daniel A. Steffen5fdcbb12009-03-23 12:17:38 +010012042} else {
12043 set mainfont {Helvetica 9}
12044 set textfont {Courier 9}
12045 set uifont {Helvetica 9 bold}
12046}
Mark Levedahl7e12f1a2007-05-20 11:45:50 -040012047set tabstop 8
Paul Mackerrasb74fd572005-07-16 07:46:13 -040012048set findmergefiles 0
Paul Mackerras8d858d12005-08-05 09:52:16 +100012049set maxgraphpct 50
Paul Mackerrasf6075eb2005-08-18 09:30:10 +100012050set maxwidth 16
Paul Mackerras232475d2005-11-15 10:34:03 +110012051set revlistorder 0
Paul Mackerras757f17b2005-11-21 09:56:07 +110012052set fastdate 0
Paul Mackerras6e8c8702007-07-31 21:03:06 +100012053set uparrowlen 5
12054set downarrowlen 5
12055set mingaplen 100
Paul Mackerrasf8b28a42006-05-01 09:50:57 +100012056set cmitmode "patch"
Sergey Vlasovf1b86292006-05-15 19:13:14 +040012057set wrapcomment "none"
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +100012058set showneartags 1
Thomas Rastffe15292009-08-03 23:53:36 +020012059set hideremotes 0
Paul Mackerras0a4dd8b2007-06-16 21:21:57 +100012060set maxrefs 20
Max Kirillovbde4a0f2014-06-24 08:19:44 +030012061set visiblerefs {"master"}
Paul Mackerras322a8cc2006-10-15 18:03:46 +100012062set maxlinelen 200
Paul Mackerras219ea3a2006-09-07 10:21:39 +100012063set showlocalchanges 1
Paul Mackerras7a39a172007-10-23 10:15:11 +100012064set limitdiffs 1
Arjen Laarhovene8b5f4b2007-08-14 22:02:04 +020012065set datetimeformat "%Y-%m-%d %H:%M:%S"
Jeff King95293b52008-03-06 06:49:25 -050012066set autoselect 1
Paul Mackerras21ac8a82011-03-09 20:52:38 +110012067set autosellen 40
Paul Mackerras39ee47e2008-10-15 22:23:03 +110012068set perfile_attrs 0
Paul Mackerras0cc08ff2009-09-05 22:06:46 +100012069set want_ttk 1
Paul Mackerras1d10f362005-05-15 12:55:47 +000012070
Daniel A. Steffen5fdcbb12009-03-23 12:17:38 +010012071if {[tk windowingsystem] eq "aqua"} {
12072 set extdifftool "opendiff"
12073} else {
12074 set extdifftool "meld"
12075}
Thomas Arcila314f5de2008-03-24 12:55:36 +010012076
Paul Mackerras1d10f362005-05-15 12:55:47 +000012077set colors {green red blue magenta darkgrey brown orange}
Pat Thoyts1924d1b2009-11-06 23:28:01 +000012078if {[tk windowingsystem] eq "win32"} {
12079 set uicolor SystemButtonFace
Gauthier Östervall252c52d2013-03-27 14:40:51 +010012080 set uifgcolor SystemButtonText
12081 set uifgdisabledcolor SystemDisabledText
Pat Thoyts1924d1b2009-11-06 23:28:01 +000012082 set bgcolor SystemWindow
Gauthier Östervall252c52d2013-03-27 14:40:51 +010012083 set fgcolor SystemWindowText
Pat Thoyts1924d1b2009-11-06 23:28:01 +000012084 set selectbgcolor SystemHighlight
12085} else {
12086 set uicolor grey85
Gauthier Östervall252c52d2013-03-27 14:40:51 +010012087 set uifgcolor black
12088 set uifgdisabledcolor "#999"
Pat Thoyts1924d1b2009-11-06 23:28:01 +000012089 set bgcolor white
12090 set fgcolor black
12091 set selectbgcolor gray85
12092}
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +100012093set diffcolors {red "#00a000" blue}
Steffen Prohaska890fae72007-08-12 12:05:46 +020012094set diffcontext 3
Gauthier Östervall252c52d2013-03-27 14:40:51 +010012095set mergecolors {red blue green purple brown "#009090" magenta "#808000" "#009000" "#ff0080" cyan "#b07070" "#70b0f0" "#70f0b0" "#f0b070" "#ff70b0"}
Steffen Prohaskab9b86002008-01-17 23:42:55 +010012096set ignorespace 0
Thomas Rastae4e3ff2010-10-16 12:15:10 +020012097set worddiff ""
Paul Mackerrase3e901b2008-10-27 22:37:21 +110012098set markbgcolor "#e0e0ff"
Paul Mackerras1d10f362005-05-15 12:55:47 +000012099
Gauthier Östervall252c52d2013-03-27 14:40:51 +010012100set headbgcolor green
12101set headfgcolor black
12102set headoutlinecolor black
12103set remotebgcolor #ffddaa
12104set tagbgcolor yellow
12105set tagfgcolor black
12106set tagoutlinecolor black
12107set reflinecolor black
12108set filesepbgcolor #aaaaaa
12109set filesepfgcolor black
12110set linehoverbgcolor #ffff80
12111set linehoverfgcolor black
12112set linehoveroutlinecolor black
12113set mainheadcirclecolor yellow
12114set workingfilescirclecolor red
12115set indexcirclecolor green
Paul Mackerrasc11ff122008-05-26 10:11:33 +100012116set circlecolors {white blue gray blue blue}
Gauthier Östervall252c52d2013-03-27 14:40:51 +010012117set linkfgcolor blue
12118set circleoutlinecolor $fgcolor
12119set foundbgcolor yellow
12120set currentsearchhitbgcolor orange
Paul Mackerrasc11ff122008-05-26 10:11:33 +100012121
Paul Mackerrasd277e892008-09-21 18:11:37 -050012122# button for popping up context menus
12123if {[tk windowingsystem] eq "aqua"} {
12124 set ctxbut <Button-2>
12125} else {
12126 set ctxbut <Button-3>
12127}
12128
Christian Stimming663c3aa2007-11-07 18:40:59 +010012129## For msgcat loading, first locate the installation location.
12130if { [info exists ::env(GITK_MSGSDIR)] } {
12131 ## Msgsdir was manually set in the environment.
12132 set gitk_msgsdir $::env(GITK_MSGSDIR)
12133} else {
12134 ## Let's guess the prefix from argv0.
12135 set gitk_prefix [file dirname [file dirname [file normalize $argv0]]]
12136 set gitk_libdir [file join $gitk_prefix share gitk lib]
12137 set gitk_msgsdir [file join $gitk_libdir msgs]
12138 unset gitk_prefix
12139}
12140
12141## Internationalization (i18n) through msgcat and gettext. See
12142## http://www.gnu.org/software/gettext/manual/html_node/Tcl.html
12143package require msgcat
12144namespace import ::msgcat::mc
12145## And eventually load the actual message catalog
12146::msgcat::mcload $gitk_msgsdir
12147
Astril Hayato8f863392014-01-21 19:10:16 +000012148catch {
12149 # follow the XDG base directory specification by default. See
12150 # http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html
12151 if {[info exists env(XDG_CONFIG_HOME)] && $env(XDG_CONFIG_HOME) ne ""} {
12152 # XDG_CONFIG_HOME environment variable is set
12153 set config_file [file join $env(XDG_CONFIG_HOME) git gitk]
12154 set config_file_tmp [file join $env(XDG_CONFIG_HOME) git gitk-tmp]
12155 } else {
12156 # default XDG_CONFIG_HOME
12157 set config_file "~/.config/git/gitk"
12158 set config_file_tmp "~/.config/git/gitk-tmp"
12159 }
12160 if {![file exists $config_file]} {
12161 # for backward compatibility use the old config file if it exists
12162 if {[file exists "~/.gitk"]} {
12163 set config_file "~/.gitk"
12164 set config_file_tmp "~/.gitk-tmp"
12165 } elseif {![file exists [file dirname $config_file]]} {
12166 file mkdir [file dirname $config_file]
12167 }
12168 }
12169 source $config_file
12170}
Paul Mackerras1d10f362005-05-15 12:55:47 +000012171
Paul Mackerras0ed1dd32007-10-06 18:27:37 +100012172parsefont mainfont $mainfont
12173eval font create mainfont [fontflags mainfont]
12174eval font create mainfontbold [fontflags mainfont 1]
12175
12176parsefont textfont $textfont
12177eval font create textfont [fontflags textfont]
12178eval font create textfontbold [fontflags textfont 1]
12179
12180parsefont uifont $uifont
12181eval font create uifont [fontflags uifont]
Paul Mackerras17386062005-05-18 22:51:00 +000012182
Paul Mackerras51a7e8b2009-11-14 21:15:01 +110012183setui $uicolor
Guillermo S. Romero5497f7a2009-10-15 18:51:49 +020012184
Paul Mackerrasb039f0a2008-01-06 15:54:46 +110012185setoptions
12186
Paul Mackerrasaa81d972006-02-28 11:27:12 +110012187# check that we can find a .git directory somewhere...
Martin von Zweigbergk86e847b2011-04-04 22:14:18 -040012188if {[catch {set gitdir [exec git rev-parse --git-dir]}]} {
Christian Stimmingd990ced2007-11-07 18:42:55 +010012189 show_error {} . [mc "Cannot find a git repository here."]
Alex Riesen6c87d602007-07-29 22:29:45 +020012190 exit 1
12191}
Paul Mackerrasaa81d972006-02-28 11:27:12 +110012192
Alexander Gavrilov39816d62008-08-23 12:27:44 +040012193set selecthead {}
12194set selectheadid {}
12195
Paul Mackerrascdaee5d2007-07-12 22:29:49 +100012196set revtreeargs {}
Paul Mackerras098dd8a2006-05-03 09:32:53 +100012197set cmdline_files {}
Paul Mackerrascdaee5d2007-07-12 22:29:49 +100012198set i 0
Yann Dirson2d480852008-02-21 21:23:31 +010012199set revtreeargscmd {}
Paul Mackerrascdaee5d2007-07-12 22:29:49 +100012200foreach arg $argv {
Yann Dirson2d480852008-02-21 21:23:31 +010012201 switch -glob -- $arg {
Paul Mackerras6ebedab2007-07-13 13:45:55 +100012202 "" { }
Paul Mackerrascdaee5d2007-07-12 22:29:49 +100012203 "--" {
12204 set cmdline_files [lrange $argv [expr {$i + 1}] end]
12205 break
12206 }
Alexander Gavrilov39816d62008-08-23 12:27:44 +040012207 "--select-commit=*" {
12208 set selecthead [string range $arg 16 end]
12209 }
Yann Dirson2d480852008-02-21 21:23:31 +010012210 "--argscmd=*" {
12211 set revtreeargscmd [string range $arg 10 end]
12212 }
Paul Mackerrascdaee5d2007-07-12 22:29:49 +100012213 default {
12214 lappend revtreeargs $arg
12215 }
12216 }
12217 incr i
12218}
12219
Alexander Gavrilov39816d62008-08-23 12:27:44 +040012220if {$selecthead eq "HEAD"} {
12221 set selecthead {}
12222}
12223
Paul Mackerrascdaee5d2007-07-12 22:29:49 +100012224if {$i >= [llength $argv] && $revtreeargs ne {}} {
Paul Mackerras3ed31a82008-04-26 16:00:00 +100012225 # no -- on command line, but some arguments (other than --argscmd)
Paul Mackerras098dd8a2006-05-03 09:32:53 +100012226 if {[catch {
Timo Hirvonen8974c6f2006-05-24 10:57:40 +030012227 set f [eval exec git rev-parse --no-revs --no-flags $revtreeargs]
Paul Mackerras098dd8a2006-05-03 09:32:53 +100012228 set cmdline_files [split $f "\n"]
12229 set n [llength $cmdline_files]
12230 set revtreeargs [lrange $revtreeargs 0 end-$n]
Paul Mackerrascdaee5d2007-07-12 22:29:49 +100012231 # Unfortunately git rev-parse doesn't produce an error when
12232 # something is both a revision and a filename. To be consistent
12233 # with git log and git rev-list, check revtreeargs for filenames.
12234 foreach arg $revtreeargs {
12235 if {[file exists $arg]} {
Christian Stimmingd990ced2007-11-07 18:42:55 +010012236 show_error {} . [mc "Ambiguous argument '%s': both revision\
12237 and filename" $arg]
Paul Mackerrascdaee5d2007-07-12 22:29:49 +100012238 exit 1
12239 }
12240 }
Paul Mackerras098dd8a2006-05-03 09:32:53 +100012241 } err]} {
12242 # unfortunately we get both stdout and stderr in $err,
12243 # so look for "fatal:".
12244 set i [string first "fatal:" $err]
12245 if {$i > 0} {
Junio C Hamanob5e09632006-05-26 00:07:15 -070012246 set err [string range $err [expr {$i + 6}] end]
Paul Mackerras098dd8a2006-05-03 09:32:53 +100012247 }
Christian Stimmingd990ced2007-11-07 18:42:55 +010012248 show_error {} . "[mc "Bad arguments to gitk:"]\n$err"
Paul Mackerras098dd8a2006-05-03 09:32:53 +100012249 exit 1
12250 }
12251}
12252
Paul Mackerras219ea3a2006-09-07 10:21:39 +100012253set nullid "0000000000000000000000000000000000000000"
Paul Mackerras8f489362007-07-13 19:49:37 +100012254set nullid2 "0000000000000000000000000000000000000001"
Thomas Arcila314f5de2008-03-24 12:55:36 +010012255set nullfile "/dev/null"
Paul Mackerras8f489362007-07-13 19:49:37 +100012256
Paul Mackerras32f1b3e2007-09-28 21:27:39 +100012257set have_tk85 [expr {[package vcompare $tk_version "8.5"] >= 0}]
Paul Mackerras0cc08ff2009-09-05 22:06:46 +100012258if {![info exists have_ttk]} {
12259 set have_ttk [llength [info commands ::ttk::style]]
Pat Thoytsd93f1712009-04-17 01:24:35 +010012260}
Paul Mackerras0cc08ff2009-09-05 22:06:46 +100012261set use_ttk [expr {$have_ttk && $want_ttk}]
Pat Thoytsd93f1712009-04-17 01:24:35 +010012262set NS [expr {$use_ttk ? "ttk" : ""}]
Paul Mackerras0cc08ff2009-09-05 22:06:46 +100012263
Anders Kaseorg7add5af2011-01-06 17:42:33 -070012264regexp {^git version ([\d.]*\d)} [exec git version] _ git_version
Paul Mackerras219ea3a2006-09-07 10:21:39 +100012265
Kirill Smelkov7defefb2010-05-20 13:50:41 +040012266set show_notes {}
12267if {[package vcompare $git_version "1.6.6.2"] >= 0} {
12268 set show_notes "--show-notes"
12269}
12270
Zbigniew Jędrzejewski-Szmek3878e632011-11-09 17:28:28 +010012271set appname "gitk"
12272
Paul Mackerras7eb3cb92007-06-17 14:45:00 +100012273set runq {}
Paul Mackerrasd6982062005-08-06 22:06:06 +100012274set history {}
12275set historyindex 0
Paul Mackerras908c3582006-05-20 09:38:11 +100012276set fh_serial 0
Paul Mackerras908c3582006-05-20 09:38:11 +100012277set nhl_names {}
Paul Mackerras63b79192006-05-20 21:31:52 +100012278set highlight_paths {}
Paul Mackerras687c8762007-09-22 12:49:33 +100012279set findpattern {}
Paul Mackerras1902c272006-05-25 21:25:13 +100012280set searchdirn -forwards
Paul Mackerras28593d32008-11-13 23:01:46 +110012281set boldids {}
12282set boldnameids {}
Paul Mackerrasa8d610a2007-04-19 11:39:12 +100012283set diffelide {0 0}
Paul Mackerras4fb0fa12007-07-04 19:43:51 +100012284set markingmatches 0
Paul Mackerras97645682007-08-23 22:24:38 +100012285set linkentercount 0
Paul Mackerras03800812007-08-29 21:45:21 +100012286set need_redisplay 0
12287set nrows_drawn 0
Paul Mackerras32f1b3e2007-09-28 21:27:39 +100012288set firsttabstop 0
Paul Mackerras9f1afe02006-02-19 22:44:47 +110012289
Paul Mackerras50b44ec2006-04-04 10:16:22 +100012290set nextviewnum 1
12291set curview 0
Paul Mackerrasa90a6d22006-04-25 17:12:46 +100012292set selectedview 0
Christian Stimmingb007ee22007-11-07 18:44:35 +010012293set selectedhlview [mc "None"]
12294set highlight_related [mc "None"]
Paul Mackerras687c8762007-09-22 12:49:33 +100012295set highlight_files {}
Paul Mackerras50b44ec2006-04-04 10:16:22 +100012296set viewfiles(0) {}
Paul Mackerrasa90a6d22006-04-25 17:12:46 +100012297set viewperm(0) 0
Paul Mackerras098dd8a2006-05-03 09:32:53 +100012298set viewargs(0) {}
Yann Dirson2d480852008-02-21 21:23:31 +010012299set viewargscmd(0) {}
Paul Mackerras50b44ec2006-04-04 10:16:22 +100012300
Paul Mackerras94b4a692008-05-20 20:51:06 +100012301set selectedline {}
Paul Mackerras6df74032008-05-11 22:13:02 +100012302set numcommits 0
Paul Mackerras7fcc92b2007-12-03 10:33:01 +110012303set loginstance 0
Paul Mackerras098dd8a2006-05-03 09:32:53 +100012304set cmdlineok 0
Paul Mackerras1d10f362005-05-15 12:55:47 +000012305set stopped 0
Paul Mackerras0fba86b2005-05-16 23:54:58 +000012306set stuffsaved 0
Paul Mackerras74daedb2005-06-27 19:27:32 +100012307set patchnum 0
Paul Mackerras219ea3a2006-09-07 10:21:39 +100012308set lserial 0
Martin von Zweigbergk74cb8842011-05-23 22:44:08 -040012309set hasworktree [hasworktree]
Martin von Zweigbergkc332f442011-04-04 22:14:12 -040012310set cdup {}
Martin von Zweigbergk74cb8842011-05-23 22:44:08 -040012311if {[expr {[exec git rev-parse --is-inside-work-tree] == "true"}]} {
Martin von Zweigbergkc332f442011-04-04 22:14:12 -040012312 set cdup [exec git rev-parse --show-cdup]
12313}
Martin von Zweigbergk784b7e22011-04-04 22:14:15 -040012314set worktree [exec git rev-parse --show-toplevel]
Paul Mackerras1d10f362005-05-15 12:55:47 +000012315setcoords
Paul Mackerrasd94f8cd2006-04-06 10:18:23 +100012316makewindow
Giuseppe Bilotta37871b72009-03-19 01:54:17 -070012317catch {
12318 image create photo gitlogo -width 16 -height 16
12319
12320 image create photo gitlogominus -width 4 -height 2
12321 gitlogominus put #C00000 -to 0 0 4 2
12322 gitlogo copy gitlogominus -to 1 5
12323 gitlogo copy gitlogominus -to 6 5
12324 gitlogo copy gitlogominus -to 11 5
12325 image delete gitlogominus
12326
12327 image create photo gitlogoplus -width 4 -height 4
12328 gitlogoplus put #008000 -to 1 0 3 4
12329 gitlogoplus put #008000 -to 0 1 4 3
12330 gitlogo copy gitlogoplus -to 1 9
12331 gitlogo copy gitlogoplus -to 6 9
12332 gitlogo copy gitlogoplus -to 11 9
12333 image delete gitlogoplus
12334
Stephen Boydd38d7d42009-03-19 01:54:18 -070012335 image create photo gitlogo32 -width 32 -height 32
12336 gitlogo32 copy gitlogo -zoom 2 2
12337
12338 wm iconphoto . -default gitlogo gitlogo32
Giuseppe Bilotta37871b72009-03-19 01:54:17 -070012339}
Paul Mackerras0eafba12007-07-23 21:35:03 +100012340# wait for the window to become visible
12341tkwait visibility .
Zbigniew Jędrzejewski-Szmek3878e632011-11-09 17:28:28 +010012342wm title . "$appname: [reponame]"
Pat Thoyts478afad2009-04-15 17:14:03 +010012343update
Paul Mackerras887fe3c2005-05-21 07:35:37 +000012344readrefs
Paul Mackerrasa8aaf192006-04-23 22:45:55 +100012345
Yann Dirson2d480852008-02-21 21:23:31 +010012346if {$cmdline_files ne {} || $revtreeargs ne {} || $revtreeargscmd ne {}} {
Paul Mackerras50b44ec2006-04-04 10:16:22 +100012347 # create a view for the files/dirs specified on the command line
12348 set curview 1
Paul Mackerrasa90a6d22006-04-25 17:12:46 +100012349 set selectedview 1
Paul Mackerras50b44ec2006-04-04 10:16:22 +100012350 set nextviewnum 2
Christian Stimmingd990ced2007-11-07 18:42:55 +010012351 set viewname(1) [mc "Command line"]
Paul Mackerras50b44ec2006-04-04 10:16:22 +100012352 set viewfiles(1) $cmdline_files
Paul Mackerras098dd8a2006-05-03 09:32:53 +100012353 set viewargs(1) $revtreeargs
Yann Dirson2d480852008-02-21 21:23:31 +010012354 set viewargscmd(1) $revtreeargscmd
Paul Mackerrasa90a6d22006-04-25 17:12:46 +100012355 set viewperm(1) 0
Paul Mackerras3ed31a82008-04-26 16:00:00 +100012356 set vdatemode(1) 0
Paul Mackerrasda7c24d2006-05-02 11:15:29 +100012357 addviewmenu 1
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +110012358 .bar.view entryconf [mca "Edit view..."] -state normal
12359 .bar.view entryconf [mca "Delete view"] -state normal
Paul Mackerras50b44ec2006-04-04 10:16:22 +100012360}
Paul Mackerrasa90a6d22006-04-25 17:12:46 +100012361
12362if {[info exists permviews]} {
12363 foreach v $permviews {
12364 set n $nextviewnum
12365 incr nextviewnum
12366 set viewname($n) [lindex $v 0]
12367 set viewfiles($n) [lindex $v 1]
Paul Mackerras098dd8a2006-05-03 09:32:53 +100012368 set viewargs($n) [lindex $v 2]
Yann Dirson2d480852008-02-21 21:23:31 +010012369 set viewargscmd($n) [lindex $v 3]
Paul Mackerrasa90a6d22006-04-25 17:12:46 +100012370 set viewperm($n) 1
Paul Mackerrasda7c24d2006-05-02 11:15:29 +100012371 addviewmenu $n
Paul Mackerrasa90a6d22006-04-25 17:12:46 +100012372 }
12373}
Johannes Sixte4df5192008-12-18 08:30:49 +010012374
12375if {[tk windowingsystem] eq "win32"} {
12376 focus -force .
12377}
12378
Alexander Gavrilov567c34e2008-07-26 20:13:45 +040012379getcommits {}
Pat Thoytsadab0da2010-03-12 18:31:48 +000012380
12381# Local variables:
12382# mode: tcl
12383# indent-tabs-mode: t
12384# tab-width: 8
12385# End: