blob: abe4805adedb3c3559bf0048ae49df2e2ac37337 [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 Mackerrasfbf42642016-12-12 20:46:42 +11005# Copyright © 2005-2016 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
Max Kirillov4d5e1b12014-09-09 10:29:16 +0300297 } elseif {[lsearch -exact $revs --all] >= 0} {
298 lappend revs HEAD
Paul Mackerrasee66e082008-05-09 10:14:07 +1000299 }
300 if {[catch {set ids [eval exec git rev-parse $revs]} err]} {
301 # we get stdout followed by stderr in $err
302 # for an unknown rev, git rev-parse echoes it and then errors out
303 set errlines [split $err "\n"]
304 set badrev {}
305 for {set l 0} {$l < [llength $errlines]} {incr l} {
306 set line [lindex $errlines $l]
307 if {!([string length $line] == 40 && [string is xdigit $line])} {
308 if {[string match "fatal:*" $line]} {
309 if {[string match "fatal: ambiguous argument*" $line]
310 && $badrev ne {}} {
311 if {[llength $badrev] == 1} {
312 set err "unknown revision $badrev"
313 } else {
314 set err "unknown revisions: [join $badrev ", "]"
315 }
316 } else {
317 set err [join [lrange $errlines $l end] "\n"]
318 }
319 break
320 }
321 lappend badrev $line
322 }
Pat Thoytsd93f1712009-04-17 01:24:35 +0100323 }
Christian Stimming3945d2c2008-09-12 11:39:43 +0200324 error_popup "[mc "Error parsing revisions:"] $err"
Paul Mackerrasee66e082008-05-09 10:14:07 +1000325 return {}
326 }
327 set ret {}
328 set pos {}
329 set neg {}
330 set sdm 0
331 foreach id [split $ids "\n"] {
332 if {$id eq "--gitk-symmetric-diff-marker"} {
333 set sdm 4
334 } elseif {[string match "^*" $id]} {
335 if {$sdm != 1} {
336 lappend ret $id
337 if {$sdm == 3} {
338 set sdm 0
339 }
340 }
341 lappend neg [string range $id 1 end]
342 } else {
343 if {$sdm != 2} {
344 lappend ret $id
345 } else {
Thomas Rast2b1fbf92009-08-05 23:15:36 +0200346 lset ret end $id...[lindex $ret end]
Paul Mackerrasee66e082008-05-09 10:14:07 +1000347 }
348 lappend pos $id
349 }
350 incr sdm -1
351 }
352 set vposids($view) $pos
353 set vnegids($view) $neg
354 return $ret
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000355}
356
Paul Mackerrasf9e0b6f2008-03-04 21:14:17 +1100357# Start off a git log process and arrange to read its output
Paul Mackerrasda7c24d2006-05-02 11:15:29 +1000358proc start_rev_list {view} {
Paul Mackerras6df74032008-05-11 22:13:02 +1000359 global startmsecs commitidx viewcomplete curview
Alexander Gavrilove439e092008-07-13 16:40:47 +0400360 global tclencoding
Paul Mackerrasee66e082008-05-09 10:14:07 +1000361 global viewargs viewargscmd viewfiles vfilelimit
Paul Mackerrasd375ef92008-10-21 10:18:12 +1100362 global showlocalchanges
Alexander Gavrilove439e092008-07-13 16:40:47 +0400363 global viewactive viewinstances vmergeonly
Paul Mackerrascdc84292008-11-18 19:54:14 +1100364 global mainheadid viewmainheadid viewmainheadid_orig
Paul Mackerrasee66e082008-05-09 10:14:07 +1000365 global vcanopt vflags vrevs vorigargs
Kirill Smelkov7defefb2010-05-20 13:50:41 +0400366 global show_notes
Paul Mackerras38ad0912005-12-01 22:42:46 +1100367
368 set startmsecs [clock clicks -milliseconds]
Paul Mackerrasda7c24d2006-05-02 11:15:29 +1000369 set commitidx($view) 0
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000370 # these are set this way for the error exits
371 set viewcomplete($view) 1
372 set viewactive($view) 0
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100373 varcinit $view
374
Yann Dirson2d480852008-02-21 21:23:31 +0100375 set args $viewargs($view)
376 if {$viewargscmd($view) ne {}} {
377 if {[catch {
378 set str [exec sh -c $viewargscmd($view)]
379 } err]} {
Christian Stimming3945d2c2008-09-12 11:39:43 +0200380 error_popup "[mc "Error executing --argscmd command:"] $err"
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000381 return 0
Yann Dirson2d480852008-02-21 21:23:31 +0100382 }
383 set args [concat $args [split $str "\n"]]
384 }
Paul Mackerrasee66e082008-05-09 10:14:07 +1000385 set vcanopt($view) [parseviewargs $view $args]
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000386
387 set files $viewfiles($view)
388 if {$vmergeonly($view)} {
389 set files [unmerged_files $files]
390 if {$files eq {}} {
391 global nr_unmerged
392 if {$nr_unmerged == 0} {
393 error_popup [mc "No files selected: --merge specified but\
394 no files are unmerged."]
395 } else {
396 error_popup [mc "No files selected: --merge specified but\
397 no unmerged files are within file limit."]
398 }
399 return 0
400 }
401 }
402 set vfilelimit($view) $files
403
Paul Mackerrasee66e082008-05-09 10:14:07 +1000404 if {$vcanopt($view)} {
405 set revs [parseviewrevs $view $vrevs($view)]
406 if {$revs eq {}} {
407 return 0
408 }
409 set args [concat $vflags($view) $revs]
410 } else {
411 set args $vorigargs($view)
412 }
413
Paul Mackerras418c4c72006-02-07 09:10:18 +1100414 if {[catch {
Kirill Smelkov7defefb2010-05-20 13:50:41 +0400415 set fd [open [concat | git log --no-color -z --pretty=raw $show_notes \
416 --parents --boundary $args "--" $files] r]
Paul Mackerras418c4c72006-02-07 09:10:18 +1100417 } err]} {
Paul Mackerras00abadb2007-12-20 10:25:50 +1100418 error_popup "[mc "Error executing git log:"] $err"
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000419 return 0
Paul Mackerras38ad0912005-12-01 22:42:46 +1100420 }
Alexander Gavrilove439e092008-07-13 16:40:47 +0400421 set i [reg_instance $fd]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100422 set viewinstances($view) [list $i]
Paul Mackerrascdc84292008-11-18 19:54:14 +1100423 set viewmainheadid($view) $mainheadid
424 set viewmainheadid_orig($view) $mainheadid
425 if {$files ne {} && $mainheadid ne {}} {
426 get_viewmainhead $view
427 }
428 if {$showlocalchanges && $viewmainheadid($view) ne {}} {
429 interestedin $viewmainheadid($view) dodiffindex
Paul Mackerras3e6b8932007-09-15 09:33:39 +1000430 }
Mark Levedahl86da5b62007-07-17 18:42:04 -0400431 fconfigure $fd -blocking 0 -translation lf -eofchar {}
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +1100432 if {$tclencoding != {}} {
Paul Mackerrasda7c24d2006-05-02 11:15:29 +1000433 fconfigure $fd -encoding $tclencoding
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +1100434 }
Paul Mackerrasf806f0f2008-02-24 12:16:56 +1100435 filerun $fd [list getcommitlines $fd $i $view 0]
Christian Stimmingd990ced2007-11-07 18:42:55 +0100436 nowbusy $view [mc "Reading"]
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000437 set viewcomplete($view) 0
438 set viewactive($view) 1
439 return 1
Paul Mackerras38ad0912005-12-01 22:42:46 +1100440}
441
Alexander Gavrilove2f90ee2008-07-12 16:09:28 +0400442proc stop_instance {inst} {
443 global commfd leftover
444
445 set fd $commfd($inst)
446 catch {
447 set pid [pid $fd]
Alexander Gavrilovb6326e92008-07-15 00:35:42 +0400448
449 if {$::tcl_platform(platform) eq {windows}} {
Sebastian Schuberth7b68b0ee2014-10-23 21:30:54 +0200450 exec taskkill /pid $pid
Alexander Gavrilovb6326e92008-07-15 00:35:42 +0400451 } else {
452 exec kill $pid
453 }
Alexander Gavrilove2f90ee2008-07-12 16:09:28 +0400454 }
455 catch {close $fd}
456 nukefile $fd
457 unset commfd($inst)
458 unset leftover($inst)
459}
460
461proc stop_backends {} {
462 global commfd
463
464 foreach inst [array names commfd] {
465 stop_instance $inst
466 }
467}
468
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100469proc stop_rev_list {view} {
Alexander Gavrilove2f90ee2008-07-12 16:09:28 +0400470 global viewinstances
Paul Mackerras22626ef2006-04-17 09:56:02 +1000471
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100472 foreach inst $viewinstances($view) {
Alexander Gavrilove2f90ee2008-07-12 16:09:28 +0400473 stop_instance $inst
Paul Mackerras22626ef2006-04-17 09:56:02 +1000474 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100475 set viewinstances($view) {}
Paul Mackerras22626ef2006-04-17 09:56:02 +1000476}
477
Alexander Gavrilov567c34e2008-07-26 20:13:45 +0400478proc reset_pending_select {selid} {
Alexander Gavrilov39816d62008-08-23 12:27:44 +0400479 global pending_select mainheadid selectheadid
Alexander Gavrilov567c34e2008-07-26 20:13:45 +0400480
481 if {$selid ne {}} {
482 set pending_select $selid
Alexander Gavrilov39816d62008-08-23 12:27:44 +0400483 } elseif {$selectheadid ne {}} {
484 set pending_select $selectheadid
Alexander Gavrilov567c34e2008-07-26 20:13:45 +0400485 } else {
486 set pending_select $mainheadid
487 }
488}
489
490proc getcommits {selid} {
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000491 global canv curview need_redisplay viewactive
Sven Verdoolaegeb5c2f302005-11-29 22:15:51 +0100492
Paul Mackerrasda7c24d2006-05-02 11:15:29 +1000493 initlayout
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000494 if {[start_rev_list $curview]} {
Alexander Gavrilov567c34e2008-07-26 20:13:45 +0400495 reset_pending_select $selid
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000496 show_status [mc "Reading commits..."]
497 set need_redisplay 1
498 } else {
499 show_status [mc "No commits selected"]
500 }
Paul Mackerras1d10f362005-05-15 12:55:47 +0000501}
502
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100503proc updatecommits {} {
Paul Mackerrasee66e082008-05-09 10:14:07 +1000504 global curview vcanopt vorigargs vfilelimit viewinstances
Alexander Gavrilove439e092008-07-13 16:40:47 +0400505 global viewactive viewcomplete tclencoding
506 global startmsecs showneartags showlocalchanges
Paul Mackerrascdc84292008-11-18 19:54:14 +1100507 global mainheadid viewmainheadid viewmainheadid_orig pending_select
Martin von Zweigbergk74cb8842011-05-23 22:44:08 -0400508 global hasworktree
Paul Mackerrasee66e082008-05-09 10:14:07 +1000509 global varcid vposids vnegids vflags vrevs
Kirill Smelkov7defefb2010-05-20 13:50:41 +0400510 global show_notes
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100511
Martin von Zweigbergk74cb8842011-05-23 22:44:08 -0400512 set hasworktree [hasworktree]
Paul Mackerrasfc2a2562007-12-26 23:03:43 +1100513 rereadrefs
Paul Mackerrascdc84292008-11-18 19:54:14 +1100514 set view $curview
515 if {$mainheadid ne $viewmainheadid_orig($view)} {
516 if {$showlocalchanges} {
Paul Mackerraseb5f8c92007-12-29 21:13:34 +1100517 dohidelocalchanges
518 }
Paul Mackerrascdc84292008-11-18 19:54:14 +1100519 set viewmainheadid($view) $mainheadid
520 set viewmainheadid_orig($view) $mainheadid
521 if {$vfilelimit($view) ne {}} {
522 get_viewmainhead $view
Paul Mackerraseb5f8c92007-12-29 21:13:34 +1100523 }
524 }
Paul Mackerrascdc84292008-11-18 19:54:14 +1100525 if {$showlocalchanges} {
526 doshowlocalchanges
527 }
Paul Mackerrasee66e082008-05-09 10:14:07 +1000528 if {$vcanopt($view)} {
529 set oldpos $vposids($view)
530 set oldneg $vnegids($view)
531 set revs [parseviewrevs $view $vrevs($view)]
532 if {$revs eq {}} {
533 return
534 }
535 # note: getting the delta when negative refs change is hard,
536 # and could require multiple git log invocations, so in that
537 # case we ask git log for all the commits (not just the delta)
538 if {$oldneg eq $vnegids($view)} {
539 set newrevs {}
540 set npos 0
541 # take out positive refs that we asked for before or
542 # that we have already seen
543 foreach rev $revs {
544 if {[string length $rev] == 40} {
545 if {[lsearch -exact $oldpos $rev] < 0
546 && ![info exists varcid($view,$rev)]} {
547 lappend newrevs $rev
548 incr npos
549 }
550 } else {
551 lappend $newrevs $rev
552 }
553 }
554 if {$npos == 0} return
555 set revs $newrevs
556 set vposids($view) [lsort -unique [concat $oldpos $vposids($view)]]
557 }
558 set args [concat $vflags($view) $revs --not $oldpos]
559 } else {
560 set args $vorigargs($view)
561 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100562 if {[catch {
Kirill Smelkov7defefb2010-05-20 13:50:41 +0400563 set fd [open [concat | git log --no-color -z --pretty=raw $show_notes \
564 --parents --boundary $args "--" $vfilelimit($view)] r]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100565 } err]} {
Christian Stimming3945d2c2008-09-12 11:39:43 +0200566 error_popup "[mc "Error executing git log:"] $err"
Paul Mackerrasee66e082008-05-09 10:14:07 +1000567 return
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100568 }
569 if {$viewactive($view) == 0} {
570 set startmsecs [clock clicks -milliseconds]
571 }
Alexander Gavrilove439e092008-07-13 16:40:47 +0400572 set i [reg_instance $fd]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100573 lappend viewinstances($view) $i
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100574 fconfigure $fd -blocking 0 -translation lf -eofchar {}
575 if {$tclencoding != {}} {
576 fconfigure $fd -encoding $tclencoding
577 }
Paul Mackerrasf806f0f2008-02-24 12:16:56 +1100578 filerun $fd [list getcommitlines $fd $i $view 1]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100579 incr viewactive($view)
580 set viewcomplete($view) 0
Alexander Gavrilov567c34e2008-07-26 20:13:45 +0400581 reset_pending_select {}
Michele Ballabiob56e0a92009-03-30 21:17:25 +0200582 nowbusy $view [mc "Reading"]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100583 if {$showneartags} {
584 getallcommits
585 }
586}
587
588proc reloadcommits {} {
589 global curview viewcomplete selectedline currentid thickerline
590 global showneartags treediffs commitinterest cached_commitrow
Markus Hitter18ae9122016-11-07 19:02:51 +0100591 global targetid commitinfo
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100592
Alexander Gavrilov567c34e2008-07-26 20:13:45 +0400593 set selid {}
594 if {$selectedline ne {}} {
595 set selid $currentid
596 }
597
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100598 if {!$viewcomplete($curview)} {
599 stop_rev_list $curview
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100600 }
601 resetvarcs $curview
Paul Mackerras94b4a692008-05-20 20:51:06 +1000602 set selectedline {}
Paul Mackerras009409f2015-05-02 20:53:36 +1000603 unset -nocomplain currentid
604 unset -nocomplain thickerline
605 unset -nocomplain treediffs
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100606 readrefs
607 changedrefs
608 if {$showneartags} {
609 getallcommits
610 }
611 clear_display
Markus Hitter18ae9122016-11-07 19:02:51 +0100612 unset -nocomplain commitinfo
Paul Mackerras009409f2015-05-02 20:53:36 +1000613 unset -nocomplain commitinterest
614 unset -nocomplain cached_commitrow
615 unset -nocomplain targetid
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100616 setcanvscroll
Alexander Gavrilov567c34e2008-07-26 20:13:45 +0400617 getcommits $selid
Paul Mackerrase7297a12008-01-15 22:30:40 +1100618 return 0
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100619}
620
Paul Mackerras6e8c8702007-07-31 21:03:06 +1000621# This makes a string representation of a positive integer which
622# sorts as a string in numerical order
623proc strrep {n} {
624 if {$n < 16} {
625 return [format "%x" $n]
626 } elseif {$n < 256} {
627 return [format "x%.2x" $n]
628 } elseif {$n < 65536} {
629 return [format "y%.4x" $n]
630 }
631 return [format "z%.8x" $n]
632}
633
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100634# Procedures used in reordering commits from git log (without
635# --topo-order) into the order for display.
636
637proc varcinit {view} {
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100638 global varcstart vupptr vdownptr vleftptr vbackptr varctok varcrow
639 global vtokmod varcmod vrowmod varcix vlastins
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100640
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100641 set varcstart($view) {{}}
642 set vupptr($view) {0}
643 set vdownptr($view) {0}
644 set vleftptr($view) {0}
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100645 set vbackptr($view) {0}
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100646 set varctok($view) {{}}
647 set varcrow($view) {{}}
648 set vtokmod($view) {}
649 set varcmod($view) 0
Paul Mackerrase5b37ac2007-12-12 18:13:51 +1100650 set vrowmod($view) 0
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100651 set varcix($view) {{}}
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100652 set vlastins($view) {0}
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100653}
654
655proc resetvarcs {view} {
656 global varcid varccommits parents children vseedcount ordertok
Paul Mackerras22387f22012-03-19 11:21:08 +1100657 global vshortids
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100658
659 foreach vid [array names varcid $view,*] {
660 unset varcid($vid)
661 unset children($vid)
662 unset parents($vid)
663 }
Paul Mackerras22387f22012-03-19 11:21:08 +1100664 foreach vid [array names vshortids $view,*] {
665 unset vshortids($vid)
666 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100667 # some commits might have children but haven't been seen yet
668 foreach vid [array names children $view,*] {
669 unset children($vid)
670 }
671 foreach va [array names varccommits $view,*] {
672 unset varccommits($va)
673 }
674 foreach vd [array names vseedcount $view,*] {
675 unset vseedcount($vd)
676 }
Paul Mackerras009409f2015-05-02 20:53:36 +1000677 unset -nocomplain ordertok
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100678}
679
Paul Mackerras468bcae2008-03-03 10:19:35 +1100680# returns a list of the commits with no children
681proc seeds {v} {
682 global vdownptr vleftptr varcstart
683
684 set ret {}
685 set a [lindex $vdownptr($v) 0]
686 while {$a != 0} {
687 lappend ret [lindex $varcstart($v) $a]
688 set a [lindex $vleftptr($v) $a]
689 }
690 return $ret
691}
692
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100693proc newvarc {view id} {
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000694 global varcid varctok parents children vdatemode
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100695 global vupptr vdownptr vleftptr vbackptr varcrow varcix varcstart
696 global commitdata commitinfo vseedcount varccommits vlastins
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100697
698 set a [llength $varctok($view)]
699 set vid $view,$id
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000700 if {[llength $children($vid)] == 0 || $vdatemode($view)} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100701 if {![info exists commitinfo($id)]} {
702 parsecommit $id $commitdata($id) 1
703 }
Anders Kaseorgf5974d92011-01-19 14:47:25 -0500704 set cdate [lindex [lindex $commitinfo($id) 4] 0]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100705 if {![string is integer -strict $cdate]} {
706 set cdate 0
707 }
708 if {![info exists vseedcount($view,$cdate)]} {
709 set vseedcount($view,$cdate) -1
710 }
711 set c [incr vseedcount($view,$cdate)]
712 set cdate [expr {$cdate ^ 0xffffffff}]
713 set tok "s[strrep $cdate][strrep $c]"
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100714 } else {
715 set tok {}
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100716 }
717 set ka 0
718 if {[llength $children($vid)] > 0} {
719 set kid [lindex $children($vid) end]
720 set k $varcid($view,$kid)
721 if {[string compare [lindex $varctok($view) $k] $tok] > 0} {
722 set ki $kid
723 set ka $k
724 set tok [lindex $varctok($view) $k]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100725 }
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100726 }
727 if {$ka != 0} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100728 set i [lsearch -exact $parents($view,$ki) $id]
729 set j [expr {[llength $parents($view,$ki)] - 1 - $i}]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100730 append tok [strrep $j]
731 }
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100732 set c [lindex $vlastins($view) $ka]
733 if {$c == 0 || [string compare $tok [lindex $varctok($view) $c]] < 0} {
734 set c $ka
735 set b [lindex $vdownptr($view) $ka]
736 } else {
737 set b [lindex $vleftptr($view) $c]
738 }
739 while {$b != 0 && [string compare $tok [lindex $varctok($view) $b]] >= 0} {
740 set c $b
741 set b [lindex $vleftptr($view) $c]
742 }
743 if {$c == $ka} {
744 lset vdownptr($view) $ka $a
745 lappend vbackptr($view) 0
746 } else {
747 lset vleftptr($view) $c $a
748 lappend vbackptr($view) $c
749 }
750 lset vlastins($view) $ka $a
751 lappend vupptr($view) $ka
752 lappend vleftptr($view) $b
753 if {$b != 0} {
754 lset vbackptr($view) $b $a
755 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100756 lappend varctok($view) $tok
757 lappend varcstart($view) $id
758 lappend vdownptr($view) 0
759 lappend varcrow($view) {}
760 lappend varcix($view) {}
Paul Mackerrase5b37ac2007-12-12 18:13:51 +1100761 set varccommits($view,$a) {}
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100762 lappend vlastins($view) 0
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100763 return $a
764}
765
766proc splitvarc {p v} {
Paul Mackerras52b8ea92009-03-02 09:38:17 +1100767 global varcid varcstart varccommits varctok vtokmod
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100768 global vupptr vdownptr vleftptr vbackptr varcix varcrow vlastins
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100769
770 set oa $varcid($v,$p)
Paul Mackerras52b8ea92009-03-02 09:38:17 +1100771 set otok [lindex $varctok($v) $oa]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100772 set ac $varccommits($v,$oa)
773 set i [lsearch -exact $varccommits($v,$oa) $p]
774 if {$i <= 0} return
775 set na [llength $varctok($v)]
776 # "%" sorts before "0"...
Paul Mackerras52b8ea92009-03-02 09:38:17 +1100777 set tok "$otok%[strrep $i]"
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100778 lappend varctok($v) $tok
779 lappend varcrow($v) {}
780 lappend varcix($v) {}
781 set varccommits($v,$oa) [lrange $ac 0 [expr {$i - 1}]]
782 set varccommits($v,$na) [lrange $ac $i end]
783 lappend varcstart($v) $p
784 foreach id $varccommits($v,$na) {
785 set varcid($v,$id) $na
786 }
787 lappend vdownptr($v) [lindex $vdownptr($v) $oa]
Paul Mackerras841ea822008-02-18 10:44:33 +1100788 lappend vlastins($v) [lindex $vlastins($v) $oa]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100789 lset vdownptr($v) $oa $na
Paul Mackerras841ea822008-02-18 10:44:33 +1100790 lset vlastins($v) $oa 0
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100791 lappend vupptr($v) $oa
792 lappend vleftptr($v) 0
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100793 lappend vbackptr($v) 0
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100794 for {set b [lindex $vdownptr($v) $na]} {$b != 0} {set b [lindex $vleftptr($v) $b]} {
795 lset vupptr($v) $b $na
796 }
Paul Mackerras52b8ea92009-03-02 09:38:17 +1100797 if {[string compare $otok $vtokmod($v)] <= 0} {
798 modify_arc $v $oa
799 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100800}
801
802proc renumbervarc {a v} {
803 global parents children varctok varcstart varccommits
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000804 global vupptr vdownptr vleftptr vbackptr vlastins varcid vtokmod vdatemode
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100805
806 set t1 [clock clicks -milliseconds]
807 set todo {}
808 set isrelated($a) 1
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100809 set kidchanged($a) 1
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100810 set ntot 0
811 while {$a != 0} {
812 if {[info exists isrelated($a)]} {
813 lappend todo $a
814 set id [lindex $varccommits($v,$a) end]
815 foreach p $parents($v,$id) {
816 if {[info exists varcid($v,$p)]} {
817 set isrelated($varcid($v,$p)) 1
818 }
819 }
820 }
821 incr ntot
822 set b [lindex $vdownptr($v) $a]
823 if {$b == 0} {
824 while {$a != 0} {
825 set b [lindex $vleftptr($v) $a]
826 if {$b != 0} break
827 set a [lindex $vupptr($v) $a]
828 }
829 }
830 set a $b
831 }
832 foreach a $todo {
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100833 if {![info exists kidchanged($a)]} continue
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100834 set id [lindex $varcstart($v) $a]
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100835 if {[llength $children($v,$id)] > 1} {
836 set children($v,$id) [lsort -command [list vtokcmp $v] \
837 $children($v,$id)]
838 }
839 set oldtok [lindex $varctok($v) $a]
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000840 if {!$vdatemode($v)} {
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100841 set tok {}
842 } else {
843 set tok $oldtok
844 }
845 set ka 0
Paul Mackerrasc8c9f3d2008-01-06 13:54:58 +1100846 set kid [last_real_child $v,$id]
847 if {$kid ne {}} {
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100848 set k $varcid($v,$kid)
849 if {[string compare [lindex $varctok($v) $k] $tok] > 0} {
850 set ki $kid
851 set ka $k
852 set tok [lindex $varctok($v) $k]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100853 }
854 }
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100855 if {$ka != 0} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100856 set i [lsearch -exact $parents($v,$ki) $id]
857 set j [expr {[llength $parents($v,$ki)] - 1 - $i}]
858 append tok [strrep $j]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100859 }
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100860 if {$tok eq $oldtok} {
861 continue
862 }
863 set id [lindex $varccommits($v,$a) end]
864 foreach p $parents($v,$id) {
865 if {[info exists varcid($v,$p)]} {
866 set kidchanged($varcid($v,$p)) 1
867 } else {
868 set sortkids($p) 1
869 }
870 }
871 lset varctok($v) $a $tok
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100872 set b [lindex $vupptr($v) $a]
873 if {$b != $ka} {
Paul Mackerras9257d8f2007-12-11 10:45:38 +1100874 if {[string compare [lindex $varctok($v) $ka] $vtokmod($v)] < 0} {
875 modify_arc $v $ka
Paul Mackerras38dfe932007-12-06 20:50:31 +1100876 }
Paul Mackerras9257d8f2007-12-11 10:45:38 +1100877 if {[string compare [lindex $varctok($v) $b] $vtokmod($v)] < 0} {
878 modify_arc $v $b
Paul Mackerras38dfe932007-12-06 20:50:31 +1100879 }
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100880 set c [lindex $vbackptr($v) $a]
881 set d [lindex $vleftptr($v) $a]
882 if {$c == 0} {
883 lset vdownptr($v) $b $d
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100884 } else {
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100885 lset vleftptr($v) $c $d
886 }
887 if {$d != 0} {
888 lset vbackptr($v) $d $c
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100889 }
Paul Mackerras841ea822008-02-18 10:44:33 +1100890 if {[lindex $vlastins($v) $b] == $a} {
891 lset vlastins($v) $b $c
892 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100893 lset vupptr($v) $a $ka
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100894 set c [lindex $vlastins($v) $ka]
895 if {$c == 0 || \
896 [string compare $tok [lindex $varctok($v) $c]] < 0} {
897 set c $ka
898 set b [lindex $vdownptr($v) $ka]
899 } else {
900 set b [lindex $vleftptr($v) $c]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100901 }
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100902 while {$b != 0 && \
903 [string compare $tok [lindex $varctok($v) $b]] >= 0} {
904 set c $b
905 set b [lindex $vleftptr($v) $c]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100906 }
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100907 if {$c == $ka} {
908 lset vdownptr($v) $ka $a
909 lset vbackptr($v) $a 0
910 } else {
911 lset vleftptr($v) $c $a
912 lset vbackptr($v) $a $c
913 }
914 lset vleftptr($v) $a $b
915 if {$b != 0} {
916 lset vbackptr($v) $b $a
917 }
918 lset vlastins($v) $ka $a
919 }
920 }
921 foreach id [array names sortkids] {
922 if {[llength $children($v,$id)] > 1} {
923 set children($v,$id) [lsort -command [list vtokcmp $v] \
924 $children($v,$id)]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100925 }
926 }
927 set t2 [clock clicks -milliseconds]
928 #puts "renumbervarc did [llength $todo] of $ntot arcs in [expr {$t2-$t1}]ms"
929}
930
Paul Mackerrasf806f0f2008-02-24 12:16:56 +1100931# Fix up the graph after we have found out that in view $v,
932# $p (a commit that we have already seen) is actually the parent
933# of the last commit in arc $a.
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100934proc fix_reversal {p a v} {
Paul Mackerras24f7a662007-12-19 09:35:33 +1100935 global varcid varcstart varctok vupptr
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100936
937 set pa $varcid($v,$p)
938 if {$p ne [lindex $varcstart($v) $pa]} {
939 splitvarc $p $v
940 set pa $varcid($v,$p)
941 }
Paul Mackerras24f7a662007-12-19 09:35:33 +1100942 # seeds always need to be renumbered
943 if {[lindex $vupptr($v) $pa] == 0 ||
944 [string compare [lindex $varctok($v) $a] \
945 [lindex $varctok($v) $pa]] > 0} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100946 renumbervarc $pa $v
947 }
948}
949
950proc insertrow {id p v} {
Paul Mackerrasb8a938c2008-02-13 22:12:31 +1100951 global cmitlisted children parents varcid varctok vtokmod
952 global varccommits ordertok commitidx numcommits curview
Paul Mackerras22387f22012-03-19 11:21:08 +1100953 global targetid targetrow vshortids
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100954
Paul Mackerrasb8a938c2008-02-13 22:12:31 +1100955 readcommit $id
956 set vid $v,$id
957 set cmitlisted($vid) 1
958 set children($vid) {}
959 set parents($vid) [list $p]
960 set a [newvarc $v $id]
961 set varcid($vid) $a
Paul Mackerras22387f22012-03-19 11:21:08 +1100962 lappend vshortids($v,[string range $id 0 3]) $id
Paul Mackerrasb8a938c2008-02-13 22:12:31 +1100963 if {[string compare [lindex $varctok($v) $a] $vtokmod($v)] < 0} {
964 modify_arc $v $a
965 }
966 lappend varccommits($v,$a) $id
967 set vp $v,$p
968 if {[llength [lappend children($vp) $id]] > 1} {
969 set children($vp) [lsort -command [list vtokcmp $v] $children($vp)]
Paul Mackerras009409f2015-05-02 20:53:36 +1000970 unset -nocomplain ordertok
Paul Mackerrasb8a938c2008-02-13 22:12:31 +1100971 }
972 fix_reversal $p $a $v
973 incr commitidx($v)
974 if {$v == $curview} {
975 set numcommits $commitidx($v)
976 setcanvscroll
977 if {[info exists targetid]} {
978 if {![comes_before $targetid $p]} {
979 incr targetrow
980 }
981 }
982 }
983}
984
985proc insertfakerow {id p} {
986 global varcid varccommits parents children cmitlisted
987 global commitidx varctok vtokmod targetid targetrow curview numcommits
988
989 set v $curview
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100990 set a $varcid($v,$p)
991 set i [lsearch -exact $varccommits($v,$a) $p]
992 if {$i < 0} {
Paul Mackerrasb8a938c2008-02-13 22:12:31 +1100993 puts "oops: insertfakerow can't find [shortids $p] on arc $a"
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100994 return
995 }
996 set children($v,$id) {}
997 set parents($v,$id) [list $p]
998 set varcid($v,$id) $a
Paul Mackerras9257d8f2007-12-11 10:45:38 +1100999 lappend children($v,$p) $id
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001000 set cmitlisted($v,$id) 1
Paul Mackerrasb8a938c2008-02-13 22:12:31 +11001001 set numcommits [incr commitidx($v)]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001002 # note we deliberately don't update varcstart($v) even if $i == 0
1003 set varccommits($v,$a) [linsert $varccommits($v,$a) $i $id]
Paul Mackerrasc9cfdc92008-03-04 21:32:38 +11001004 modify_arc $v $a $i
Paul Mackerras42a671f2008-01-02 09:59:39 +11001005 if {[info exists targetid]} {
1006 if {![comes_before $targetid $p]} {
1007 incr targetrow
1008 }
1009 }
Paul Mackerrasb8a938c2008-02-13 22:12:31 +11001010 setcanvscroll
Paul Mackerras9257d8f2007-12-11 10:45:38 +11001011 drawvisible
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001012}
1013
Paul Mackerrasb8a938c2008-02-13 22:12:31 +11001014proc removefakerow {id} {
Paul Mackerras9257d8f2007-12-11 10:45:38 +11001015 global varcid varccommits parents children commitidx
Paul Mackerrasfc2a2562007-12-26 23:03:43 +11001016 global varctok vtokmod cmitlisted currentid selectedline
Paul Mackerrasb8a938c2008-02-13 22:12:31 +11001017 global targetid curview numcommits
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001018
Paul Mackerrasb8a938c2008-02-13 22:12:31 +11001019 set v $curview
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001020 if {[llength $parents($v,$id)] != 1} {
Paul Mackerrasb8a938c2008-02-13 22:12:31 +11001021 puts "oops: removefakerow [shortids $id] has [llength $parents($v,$id)] parents"
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001022 return
1023 }
1024 set p [lindex $parents($v,$id) 0]
1025 set a $varcid($v,$id)
1026 set i [lsearch -exact $varccommits($v,$a) $id]
1027 if {$i < 0} {
Paul Mackerrasb8a938c2008-02-13 22:12:31 +11001028 puts "oops: removefakerow can't find [shortids $id] on arc $a"
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001029 return
1030 }
1031 unset varcid($v,$id)
1032 set varccommits($v,$a) [lreplace $varccommits($v,$a) $i $i]
1033 unset parents($v,$id)
1034 unset children($v,$id)
1035 unset cmitlisted($v,$id)
Paul Mackerrasb8a938c2008-02-13 22:12:31 +11001036 set numcommits [incr commitidx($v) -1]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001037 set j [lsearch -exact $children($v,$p) $id]
1038 if {$j >= 0} {
1039 set children($v,$p) [lreplace $children($v,$p) $j $j]
1040 }
Paul Mackerrasc9cfdc92008-03-04 21:32:38 +11001041 modify_arc $v $a $i
Paul Mackerrasfc2a2562007-12-26 23:03:43 +11001042 if {[info exist currentid] && $id eq $currentid} {
1043 unset currentid
Paul Mackerras94b4a692008-05-20 20:51:06 +10001044 set selectedline {}
Paul Mackerrasfc2a2562007-12-26 23:03:43 +11001045 }
Paul Mackerras42a671f2008-01-02 09:59:39 +11001046 if {[info exists targetid] && $targetid eq $id} {
1047 set targetid $p
1048 }
Paul Mackerrasb8a938c2008-02-13 22:12:31 +11001049 setcanvscroll
Paul Mackerras9257d8f2007-12-11 10:45:38 +11001050 drawvisible
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001051}
1052
Paul Mackerrasaa435612009-09-10 21:58:40 +10001053proc real_children {vp} {
1054 global children nullid nullid2
1055
1056 set kids {}
1057 foreach id $children($vp) {
1058 if {$id ne $nullid && $id ne $nullid2} {
1059 lappend kids $id
1060 }
1061 }
1062 return $kids
1063}
1064
Paul Mackerrasc8c9f3d2008-01-06 13:54:58 +11001065proc first_real_child {vp} {
1066 global children nullid nullid2
1067
1068 foreach id $children($vp) {
1069 if {$id ne $nullid && $id ne $nullid2} {
1070 return $id
1071 }
1072 }
1073 return {}
1074}
1075
1076proc last_real_child {vp} {
1077 global children nullid nullid2
1078
1079 set kids $children($vp)
1080 for {set i [llength $kids]} {[incr i -1] >= 0} {} {
1081 set id [lindex $kids $i]
1082 if {$id ne $nullid && $id ne $nullid2} {
1083 return $id
1084 }
1085 }
1086 return {}
1087}
1088
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001089proc vtokcmp {v a b} {
1090 global varctok varcid
1091
1092 return [string compare [lindex $varctok($v) $varcid($v,$a)] \
1093 [lindex $varctok($v) $varcid($v,$b)]]
1094}
1095
Paul Mackerrasc9cfdc92008-03-04 21:32:38 +11001096# This assumes that if lim is not given, the caller has checked that
1097# arc a's token is less than $vtokmod($v)
Paul Mackerrase5b37ac2007-12-12 18:13:51 +11001098proc modify_arc {v a {lim {}}} {
1099 global varctok vtokmod varcmod varcrow vupptr curview vrowmod varccommits
Paul Mackerras9257d8f2007-12-11 10:45:38 +11001100
Paul Mackerrasc9cfdc92008-03-04 21:32:38 +11001101 if {$lim ne {}} {
1102 set c [string compare [lindex $varctok($v) $a] $vtokmod($v)]
1103 if {$c > 0} return
1104 if {$c == 0} {
1105 set r [lindex $varcrow($v) $a]
1106 if {$r ne {} && $vrowmod($v) <= $r + $lim} return
1107 }
1108 }
Paul Mackerras9257d8f2007-12-11 10:45:38 +11001109 set vtokmod($v) [lindex $varctok($v) $a]
1110 set varcmod($v) $a
1111 if {$v == $curview} {
1112 while {$a != 0 && [lindex $varcrow($v) $a] eq {}} {
1113 set a [lindex $vupptr($v) $a]
Paul Mackerrase5b37ac2007-12-12 18:13:51 +11001114 set lim {}
Paul Mackerras9257d8f2007-12-11 10:45:38 +11001115 }
Paul Mackerrase5b37ac2007-12-12 18:13:51 +11001116 set r 0
1117 if {$a != 0} {
1118 if {$lim eq {}} {
1119 set lim [llength $varccommits($v,$a)]
1120 }
1121 set r [expr {[lindex $varcrow($v) $a] + $lim}]
1122 }
1123 set vrowmod($v) $r
Paul Mackerras0c278862007-12-11 20:09:53 +11001124 undolayout $r
Paul Mackerras9257d8f2007-12-11 10:45:38 +11001125 }
1126}
1127
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001128proc update_arcrows {v} {
Paul Mackerrase5b37ac2007-12-12 18:13:51 +11001129 global vtokmod varcmod vrowmod varcrow commitidx currentid selectedline
Paul Mackerras24f7a662007-12-19 09:35:33 +11001130 global varcid vrownum varcorder varcix varccommits
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001131 global vupptr vdownptr vleftptr varctok
Paul Mackerras24f7a662007-12-19 09:35:33 +11001132 global displayorder parentlist curview cached_commitrow
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001133
Paul Mackerrasc9cfdc92008-03-04 21:32:38 +11001134 if {$vrowmod($v) == $commitidx($v)} return
1135 if {$v == $curview} {
1136 if {[llength $displayorder] > $vrowmod($v)} {
1137 set displayorder [lrange $displayorder 0 [expr {$vrowmod($v) - 1}]]
1138 set parentlist [lrange $parentlist 0 [expr {$vrowmod($v) - 1}]]
1139 }
Paul Mackerras009409f2015-05-02 20:53:36 +10001140 unset -nocomplain cached_commitrow
Paul Mackerrasc9cfdc92008-03-04 21:32:38 +11001141 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001142 set narctot [expr {[llength $varctok($v)] - 1}]
1143 set a $varcmod($v)
1144 while {$a != 0 && [lindex $varcix($v) $a] eq {}} {
1145 # go up the tree until we find something that has a row number,
1146 # or we get to a seed
1147 set a [lindex $vupptr($v) $a]
1148 }
1149 if {$a == 0} {
1150 set a [lindex $vdownptr($v) 0]
1151 if {$a == 0} return
1152 set vrownum($v) {0}
1153 set varcorder($v) [list $a]
1154 lset varcix($v) $a 0
1155 lset varcrow($v) $a 0
1156 set arcn 0
1157 set row 0
1158 } else {
1159 set arcn [lindex $varcix($v) $a]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001160 if {[llength $vrownum($v)] > $arcn + 1} {
1161 set vrownum($v) [lrange $vrownum($v) 0 $arcn]
1162 set varcorder($v) [lrange $varcorder($v) 0 $arcn]
1163 }
1164 set row [lindex $varcrow($v) $a]
1165 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001166 while {1} {
1167 set p $a
1168 incr row [llength $varccommits($v,$a)]
1169 # go down if possible
1170 set b [lindex $vdownptr($v) $a]
1171 if {$b == 0} {
1172 # if not, go left, or go up until we can go left
1173 while {$a != 0} {
1174 set b [lindex $vleftptr($v) $a]
1175 if {$b != 0} break
1176 set a [lindex $vupptr($v) $a]
1177 }
1178 if {$a == 0} break
1179 }
1180 set a $b
1181 incr arcn
1182 lappend vrownum($v) $row
1183 lappend varcorder($v) $a
1184 lset varcix($v) $a $arcn
1185 lset varcrow($v) $a $row
1186 }
Paul Mackerrase5b37ac2007-12-12 18:13:51 +11001187 set vtokmod($v) [lindex $varctok($v) $p]
1188 set varcmod($v) $p
1189 set vrowmod($v) $row
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001190 if {[info exists currentid]} {
1191 set selectedline [rowofcommit $currentid]
1192 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001193}
1194
1195# Test whether view $v contains commit $id
1196proc commitinview {id v} {
1197 global varcid
1198
1199 return [info exists varcid($v,$id)]
1200}
1201
1202# Return the row number for commit $id in the current view
1203proc rowofcommit {id} {
1204 global varcid varccommits varcrow curview cached_commitrow
Paul Mackerras9257d8f2007-12-11 10:45:38 +11001205 global varctok vtokmod
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001206
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001207 set v $curview
1208 if {![info exists varcid($v,$id)]} {
1209 puts "oops rowofcommit no arc for [shortids $id]"
1210 return {}
1211 }
1212 set a $varcid($v,$id)
Paul Mackerrasfc2a2562007-12-26 23:03:43 +11001213 if {[string compare [lindex $varctok($v) $a] $vtokmod($v)] >= 0} {
Paul Mackerras9257d8f2007-12-11 10:45:38 +11001214 update_arcrows $v
1215 }
Paul Mackerras31c0eaa2007-12-30 22:41:14 +11001216 if {[info exists cached_commitrow($id)]} {
1217 return $cached_commitrow($id)
1218 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001219 set i [lsearch -exact $varccommits($v,$a) $id]
1220 if {$i < 0} {
1221 puts "oops didn't find commit [shortids $id] in arc $a"
1222 return {}
1223 }
1224 incr i [lindex $varcrow($v) $a]
1225 set cached_commitrow($id) $i
1226 return $i
1227}
1228
Paul Mackerras42a671f2008-01-02 09:59:39 +11001229# Returns 1 if a is on an earlier row than b, otherwise 0
1230proc comes_before {a b} {
1231 global varcid varctok curview
1232
1233 set v $curview
1234 if {$a eq $b || ![info exists varcid($v,$a)] || \
1235 ![info exists varcid($v,$b)]} {
1236 return 0
1237 }
1238 if {$varcid($v,$a) != $varcid($v,$b)} {
1239 return [expr {[string compare [lindex $varctok($v) $varcid($v,$a)] \
1240 [lindex $varctok($v) $varcid($v,$b)]] < 0}]
1241 }
1242 return [expr {[rowofcommit $a] < [rowofcommit $b]}]
1243}
1244
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001245proc bsearch {l elt} {
1246 if {[llength $l] == 0 || $elt <= [lindex $l 0]} {
1247 return 0
1248 }
1249 set lo 0
1250 set hi [llength $l]
1251 while {$hi - $lo > 1} {
1252 set mid [expr {int(($lo + $hi) / 2)}]
1253 set t [lindex $l $mid]
1254 if {$elt < $t} {
1255 set hi $mid
1256 } elseif {$elt > $t} {
1257 set lo $mid
1258 } else {
1259 return $mid
1260 }
1261 }
1262 return $lo
1263}
1264
1265# Make sure rows $start..$end-1 are valid in displayorder and parentlist
1266proc make_disporder {start end} {
1267 global vrownum curview commitidx displayorder parentlist
Paul Mackerrase5b37ac2007-12-12 18:13:51 +11001268 global varccommits varcorder parents vrowmod varcrow
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001269 global d_valid_start d_valid_end
1270
Paul Mackerrase5b37ac2007-12-12 18:13:51 +11001271 if {$end > $vrowmod($curview)} {
Paul Mackerras9257d8f2007-12-11 10:45:38 +11001272 update_arcrows $curview
1273 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001274 set ai [bsearch $vrownum($curview) $start]
1275 set start [lindex $vrownum($curview) $ai]
1276 set narc [llength $vrownum($curview)]
1277 for {set r $start} {$ai < $narc && $r < $end} {incr ai} {
1278 set a [lindex $varcorder($curview) $ai]
1279 set l [llength $displayorder]
1280 set al [llength $varccommits($curview,$a)]
1281 if {$l < $r + $al} {
1282 if {$l < $r} {
1283 set pad [ntimes [expr {$r - $l}] {}]
1284 set displayorder [concat $displayorder $pad]
1285 set parentlist [concat $parentlist $pad]
1286 } elseif {$l > $r} {
1287 set displayorder [lrange $displayorder 0 [expr {$r - 1}]]
1288 set parentlist [lrange $parentlist 0 [expr {$r - 1}]]
1289 }
1290 foreach id $varccommits($curview,$a) {
1291 lappend displayorder $id
1292 lappend parentlist $parents($curview,$id)
1293 }
Paul Mackerras17529cf92008-01-12 21:46:31 +11001294 } elseif {[lindex $displayorder [expr {$r + $al - 1}]] eq {}} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001295 set i $r
1296 foreach id $varccommits($curview,$a) {
1297 lset displayorder $i $id
1298 lset parentlist $i $parents($curview,$id)
1299 incr i
1300 }
1301 }
1302 incr r $al
1303 }
1304}
1305
1306proc commitonrow {row} {
1307 global displayorder
1308
1309 set id [lindex $displayorder $row]
1310 if {$id eq {}} {
1311 make_disporder $row [expr {$row + 1}]
1312 set id [lindex $displayorder $row]
1313 }
1314 return $id
1315}
1316
1317proc closevarcs {v} {
1318 global varctok varccommits varcid parents children
Stefan Dotterweichd92aa572016-06-04 10:47:16 +02001319 global cmitlisted commitidx vtokmod curview numcommits
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001320
1321 set missing_parents 0
1322 set scripts {}
1323 set narcs [llength $varctok($v)]
1324 for {set a 1} {$a < $narcs} {incr a} {
1325 set id [lindex $varccommits($v,$a) end]
1326 foreach p $parents($v,$id) {
1327 if {[info exists varcid($v,$p)]} continue
1328 # add p as a new commit
1329 incr missing_parents
1330 set cmitlisted($v,$p) 0
1331 set parents($v,$p) {}
1332 if {[llength $children($v,$p)] == 1 &&
1333 [llength $parents($v,$id)] == 1} {
1334 set b $a
1335 } else {
1336 set b [newvarc $v $p]
1337 }
1338 set varcid($v,$p) $b
Paul Mackerras9257d8f2007-12-11 10:45:38 +11001339 if {[string compare [lindex $varctok($v) $b] $vtokmod($v)] < 0} {
1340 modify_arc $v $b
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001341 }
Paul Mackerrase5b37ac2007-12-12 18:13:51 +11001342 lappend varccommits($v,$b) $p
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001343 incr commitidx($v)
Stefan Dotterweichd92aa572016-06-04 10:47:16 +02001344 if {$v == $curview} {
1345 set numcommits $commitidx($v)
1346 }
Paul Mackerrasd375ef92008-10-21 10:18:12 +11001347 set scripts [check_interest $p $scripts]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001348 }
1349 }
1350 if {$missing_parents > 0} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001351 foreach s $scripts {
1352 eval $s
1353 }
1354 }
1355}
1356
Paul Mackerrasf806f0f2008-02-24 12:16:56 +11001357# Use $rwid as a substitute for $id, i.e. reparent $id's children to $rwid
1358# Assumes we already have an arc for $rwid.
1359proc rewrite_commit {v id rwid} {
1360 global children parents varcid varctok vtokmod varccommits
1361
1362 foreach ch $children($v,$id) {
1363 # make $rwid be $ch's parent in place of $id
1364 set i [lsearch -exact $parents($v,$ch) $id]
1365 if {$i < 0} {
1366 puts "oops rewrite_commit didn't find $id in parent list for $ch"
1367 }
1368 set parents($v,$ch) [lreplace $parents($v,$ch) $i $i $rwid]
1369 # add $ch to $rwid's children and sort the list if necessary
1370 if {[llength [lappend children($v,$rwid) $ch]] > 1} {
1371 set children($v,$rwid) [lsort -command [list vtokcmp $v] \
1372 $children($v,$rwid)]
1373 }
1374 # fix the graph after joining $id to $rwid
1375 set a $varcid($v,$ch)
1376 fix_reversal $rwid $a $v
Paul Mackerrasc9cfdc92008-03-04 21:32:38 +11001377 # parentlist is wrong for the last element of arc $a
1378 # even if displayorder is right, hence the 3rd arg here
1379 modify_arc $v $a [expr {[llength $varccommits($v,$a)] - 1}]
Paul Mackerrasf806f0f2008-02-24 12:16:56 +11001380 }
1381}
1382
Paul Mackerrasd375ef92008-10-21 10:18:12 +11001383# Mechanism for registering a command to be executed when we come
1384# across a particular commit. To handle the case when only the
1385# prefix of the commit is known, the commitinterest array is now
1386# indexed by the first 4 characters of the ID. Each element is a
1387# list of id, cmd pairs.
1388proc interestedin {id cmd} {
1389 global commitinterest
1390
1391 lappend commitinterest([string range $id 0 3]) $id $cmd
1392}
1393
1394proc check_interest {id scripts} {
1395 global commitinterest
1396
1397 set prefix [string range $id 0 3]
1398 if {[info exists commitinterest($prefix)]} {
1399 set newlist {}
1400 foreach {i script} $commitinterest($prefix) {
1401 if {[string match "$i*" $id]} {
1402 lappend scripts [string map [list "%I" $id "%P" $i] $script]
1403 } else {
1404 lappend newlist $i $script
1405 }
1406 }
1407 if {$newlist ne {}} {
1408 set commitinterest($prefix) $newlist
1409 } else {
1410 unset commitinterest($prefix)
1411 }
1412 }
1413 return $scripts
1414}
1415
Paul Mackerrasf806f0f2008-02-24 12:16:56 +11001416proc getcommitlines {fd inst view updating} {
Paul Mackerrasd375ef92008-10-21 10:18:12 +11001417 global cmitlisted leftover
Paul Mackerras3ed31a82008-04-26 16:00:00 +10001418 global commitidx commitdata vdatemode
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001419 global parents children curview hlview
Paul Mackerras468bcae2008-03-03 10:19:35 +11001420 global idpending ordertok
Paul Mackerras22387f22012-03-19 11:21:08 +11001421 global varccommits varcid varctok vtokmod vfilelimit vshortids
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +00001422
Paul Mackerrasd1e46752006-08-16 20:02:32 +10001423 set stuff [read $fd 500000]
Paul Mackerras005a2f42007-07-26 22:36:39 +10001424 # git log doesn't terminate the last commit with a null...
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001425 if {$stuff == {} && $leftover($inst) ne {} && [eof $fd]} {
Paul Mackerras005a2f42007-07-26 22:36:39 +10001426 set stuff "\0"
1427 }
Paul Mackerrasb490a992005-06-22 10:25:38 +10001428 if {$stuff == {}} {
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10001429 if {![eof $fd]} {
1430 return 1
1431 }
Paul Mackerras6df74032008-05-11 22:13:02 +10001432 global commfd viewcomplete viewactive viewname
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001433 global viewinstances
1434 unset commfd($inst)
1435 set i [lsearch -exact $viewinstances($view) $inst]
1436 if {$i >= 0} {
1437 set viewinstances($view) [lreplace $viewinstances($view) $i $i]
Paul Mackerrasb0cdca92007-08-23 19:35:51 +10001438 }
Paul Mackerrasf0654862005-07-18 14:29:03 -04001439 # set it blocking so we wait for the process to terminate
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10001440 fconfigure $fd -blocking 1
Paul Mackerras098dd8a2006-05-03 09:32:53 +10001441 if {[catch {close $fd} err]} {
1442 set fv {}
1443 if {$view != $curview} {
1444 set fv " for the \"$viewname($view)\" view"
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10001445 }
Paul Mackerras098dd8a2006-05-03 09:32:53 +10001446 if {[string range $err 0 4] == "usage"} {
1447 set err "Gitk: error reading commits$fv:\
Paul Mackerrasf9e0b6f2008-03-04 21:14:17 +11001448 bad arguments to git log."
Marc Branchaud5ee1c992015-04-07 11:53:37 -04001449 if {$viewname($view) eq [mc "Command line"]} {
Paul Mackerras098dd8a2006-05-03 09:32:53 +10001450 append err \
Paul Mackerrasf9e0b6f2008-03-04 21:14:17 +11001451 " (Note: arguments to gitk are passed to git log\
Paul Mackerras098dd8a2006-05-03 09:32:53 +10001452 to allow selection of commits to be displayed.)"
1453 }
1454 } else {
1455 set err "Error reading commits$fv: $err"
1456 }
1457 error_popup $err
Paul Mackerras1d10f362005-05-15 12:55:47 +00001458 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001459 if {[incr viewactive($view) -1] <= 0} {
1460 set viewcomplete($view) 1
1461 # Check if we have seen any ids listed as parents that haven't
1462 # appeared in the list
1463 closevarcs $view
1464 notbusy $view
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001465 }
Paul Mackerras098dd8a2006-05-03 09:32:53 +10001466 if {$view == $curview} {
Paul Mackerrasac1276a2008-03-03 10:11:08 +11001467 run chewcommits
Paul Mackerras9a40c502005-05-12 23:46:16 +00001468 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10001469 return 0
Paul Mackerras9a40c502005-05-12 23:46:16 +00001470 }
Paul Mackerrasb490a992005-06-22 10:25:38 +10001471 set start 0
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11001472 set gotsome 0
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001473 set scripts {}
Paul Mackerrasb490a992005-06-22 10:25:38 +10001474 while 1 {
1475 set i [string first "\0" $stuff $start]
1476 if {$i < 0} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001477 append leftover($inst) [string range $stuff $start end]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11001478 break
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +00001479 }
Paul Mackerrasb490a992005-06-22 10:25:38 +10001480 if {$start == 0} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001481 set cmit $leftover($inst)
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11001482 append cmit [string range $stuff 0 [expr {$i - 1}]]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001483 set leftover($inst) {}
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11001484 } else {
1485 set cmit [string range $stuff $start [expr {$i - 1}]]
Paul Mackerrasb490a992005-06-22 10:25:38 +10001486 }
1487 set start [expr {$i + 1}]
Paul Mackerrase5ea7012005-08-18 20:40:39 +10001488 set j [string first "\n" $cmit]
1489 set ok 0
Paul Mackerras16c1ff92006-03-30 18:43:51 +11001490 set listed 1
Paul Mackerrasc961b222007-07-09 22:45:47 +10001491 if {$j >= 0 && [string match "commit *" $cmit]} {
1492 set ids [string range $cmit 7 [expr {$j - 1}]]
Linus Torvalds1407ade2008-02-09 14:02:07 -08001493 if {[string match {[-^<>]*} $ids]} {
Paul Mackerrasc961b222007-07-09 22:45:47 +10001494 switch -- [string index $ids 0] {
1495 "-" {set listed 0}
Linus Torvalds1407ade2008-02-09 14:02:07 -08001496 "^" {set listed 2}
1497 "<" {set listed 3}
1498 ">" {set listed 4}
Paul Mackerrasc961b222007-07-09 22:45:47 +10001499 }
Paul Mackerras16c1ff92006-03-30 18:43:51 +11001500 set ids [string range $ids 1 end]
1501 }
Paul Mackerrase5ea7012005-08-18 20:40:39 +10001502 set ok 1
1503 foreach id $ids {
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11001504 if {[string length $id] != 40} {
Paul Mackerrase5ea7012005-08-18 20:40:39 +10001505 set ok 0
1506 break
1507 }
1508 }
1509 }
1510 if {!$ok} {
Paul Mackerras7e952e72005-06-27 20:04:26 +10001511 set shortcmit $cmit
1512 if {[string length $shortcmit] > 80} {
1513 set shortcmit "[string range $shortcmit 0 80]..."
1514 }
Christian Stimmingd990ced2007-11-07 18:42:55 +01001515 error_popup "[mc "Can't parse git log output:"] {$shortcmit}"
Paul Mackerrasb490a992005-06-22 10:25:38 +10001516 exit 1
1517 }
Paul Mackerrase5ea7012005-08-18 20:40:39 +10001518 set id [lindex $ids 0]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001519 set vid $view,$id
Paul Mackerrasf806f0f2008-02-24 12:16:56 +11001520
Paul Mackerras22387f22012-03-19 11:21:08 +11001521 lappend vshortids($view,[string range $id 0 3]) $id
1522
Paul Mackerrasf806f0f2008-02-24 12:16:56 +11001523 if {!$listed && $updating && ![info exists varcid($vid)] &&
Paul Mackerras3ed31a82008-04-26 16:00:00 +10001524 $vfilelimit($view) ne {}} {
Paul Mackerrasf806f0f2008-02-24 12:16:56 +11001525 # git log doesn't rewrite parents for unlisted commits
1526 # when doing path limiting, so work around that here
1527 # by working out the rewritten parent with git rev-list
1528 # and if we already know about it, using the rewritten
1529 # parent as a substitute parent for $id's children.
1530 if {![catch {
1531 set rwid [exec git rev-list --first-parent --max-count=1 \
Paul Mackerras3ed31a82008-04-26 16:00:00 +10001532 $id -- $vfilelimit($view)]
Paul Mackerrasf806f0f2008-02-24 12:16:56 +11001533 }]} {
1534 if {$rwid ne {} && [info exists varcid($view,$rwid)]} {
1535 # use $rwid in place of $id
1536 rewrite_commit $view $id $rwid
1537 continue
1538 }
1539 }
1540 }
1541
Paul Mackerrasf1bf4ee2008-02-16 17:47:31 +11001542 set a 0
1543 if {[info exists varcid($vid)]} {
1544 if {$cmitlisted($vid) || !$listed} continue
1545 set a $varcid($vid)
1546 }
Paul Mackerras16c1ff92006-03-30 18:43:51 +11001547 if {$listed} {
1548 set olds [lrange $ids 1 end]
Paul Mackerras16c1ff92006-03-30 18:43:51 +11001549 } else {
1550 set olds {}
1551 }
Paul Mackerrasf7a3e8d2006-03-18 10:04:48 +11001552 set commitdata($id) [string range $cmit [expr {$j + 1}] end]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001553 set cmitlisted($vid) $listed
1554 set parents($vid) $olds
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001555 if {![info exists children($vid)]} {
1556 set children($vid) {}
Paul Mackerrasf1bf4ee2008-02-16 17:47:31 +11001557 } elseif {$a == 0 && [llength $children($vid)] == 1} {
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +11001558 set k [lindex $children($vid) 0]
1559 if {[llength $parents($view,$k)] == 1 &&
Paul Mackerras3ed31a82008-04-26 16:00:00 +10001560 (!$vdatemode($view) ||
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +11001561 $varcid($view,$k) == [llength $varctok($view)] - 1)} {
1562 set a $varcid($view,$k)
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001563 }
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10001564 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001565 if {$a == 0} {
1566 # new arc
1567 set a [newvarc $view $id]
1568 }
Paul Mackerrase5b37ac2007-12-12 18:13:51 +11001569 if {[string compare [lindex $varctok($view) $a] $vtokmod($view)] < 0} {
1570 modify_arc $view $a
1571 }
Paul Mackerrasf1bf4ee2008-02-16 17:47:31 +11001572 if {![info exists varcid($vid)]} {
1573 set varcid($vid) $a
1574 lappend varccommits($view,$a) $id
1575 incr commitidx($view)
1576 }
Paul Mackerrase5b37ac2007-12-12 18:13:51 +11001577
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001578 set i 0
1579 foreach p $olds {
1580 if {$i == 0 || [lsearch -exact $olds $p] >= $i} {
1581 set vp $view,$p
1582 if {[llength [lappend children($vp) $id]] > 1 &&
1583 [vtokcmp $view [lindex $children($vp) end-1] $id] > 0} {
1584 set children($vp) [lsort -command [list vtokcmp $view] \
1585 $children($vp)]
Paul Mackerras009409f2015-05-02 20:53:36 +10001586 unset -nocomplain ordertok
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001587 }
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +11001588 if {[info exists varcid($view,$p)]} {
1589 fix_reversal $p $a $view
1590 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001591 }
1592 incr i
1593 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001594
Paul Mackerrasd375ef92008-10-21 10:18:12 +11001595 set scripts [check_interest $id $scripts]
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11001596 set gotsome 1
Paul Mackerras9f1afe02006-02-19 22:44:47 +11001597 }
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11001598 if {$gotsome} {
Paul Mackerrasac1276a2008-03-03 10:11:08 +11001599 global numcommits hlview
1600
1601 if {$view == $curview} {
1602 set numcommits $commitidx($view)
1603 run chewcommits
1604 }
1605 if {[info exists hlview] && $view == $hlview} {
1606 # we never actually get here...
1607 run vhighlightmore
1608 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001609 foreach s $scripts {
1610 eval $s
1611 }
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11001612 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10001613 return 2
Paul Mackerrascfb45632005-05-31 12:14:42 +00001614}
1615
Paul Mackerrasac1276a2008-03-03 10:11:08 +11001616proc chewcommits {} {
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10001617 global curview hlview viewcomplete
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001618 global pending_select
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +00001619
Paul Mackerrasac1276a2008-03-03 10:11:08 +11001620 layoutmore
1621 if {$viewcomplete($curview)} {
1622 global commitidx varctok
1623 global numcommits startmsecs
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10001624
Paul Mackerrasac1276a2008-03-03 10:11:08 +11001625 if {[info exists pending_select]} {
Alexander Gavrilov835e62a2008-07-26 20:15:54 +04001626 update
1627 reset_pending_select {}
1628
1629 if {[commitinview $pending_select $curview]} {
1630 selectline [rowofcommit $pending_select] 1
1631 } else {
1632 set row [first_real_row]
1633 selectline $row 1
1634 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10001635 }
Paul Mackerrasac1276a2008-03-03 10:11:08 +11001636 if {$commitidx($curview) > 0} {
1637 #set ms [expr {[clock clicks -milliseconds] - $startmsecs}]
1638 #puts "overall $ms ms for $numcommits commits"
1639 #puts "[llength $varctok($view)] arcs, $commitidx($view) commits"
1640 } else {
1641 show_status [mc "No commits selected"]
1642 }
1643 notbusy layout
Paul Mackerrasb6645502005-08-11 09:56:23 +10001644 }
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10001645 return 0
Paul Mackerras1db95b02005-05-09 04:08:39 +00001646}
1647
Alexander Gavrilov590915d2008-11-09 18:06:07 +03001648proc do_readcommit {id} {
1649 global tclencoding
1650
1651 # Invoke git-log to handle automatic encoding conversion
1652 set fd [open [concat | git log --no-color --pretty=raw -1 $id] r]
1653 # Read the results using i18n.logoutputencoding
1654 fconfigure $fd -translation lf -eofchar {}
1655 if {$tclencoding != {}} {
1656 fconfigure $fd -encoding $tclencoding
1657 }
1658 set contents [read $fd]
1659 close $fd
1660 # Remove the heading line
1661 regsub {^commit [0-9a-f]+\n} $contents {} contents
1662
1663 return $contents
1664}
1665
Paul Mackerras1db95b02005-05-09 04:08:39 +00001666proc readcommit {id} {
Alexander Gavrilov590915d2008-11-09 18:06:07 +03001667 if {[catch {set contents [do_readcommit $id]}]} return
1668 parsecommit $id $contents 1
Paul Mackerrasb490a992005-06-22 10:25:38 +10001669}
1670
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11001671proc parsecommit {id contents listed} {
Anders Kaseorgef738962011-01-19 14:46:59 -05001672 global commitinfo
Sven Verdoolaegeb5c2f302005-11-29 22:15:51 +01001673
1674 set inhdr 1
1675 set comment {}
1676 set headline {}
1677 set auname {}
1678 set audate {}
1679 set comname {}
1680 set comdate {}
Paul Mackerras232475d2005-11-15 10:34:03 +11001681 set hdrend [string first "\n\n" $contents]
1682 if {$hdrend < 0} {
1683 # should never happen...
1684 set hdrend [string length $contents]
1685 }
1686 set header [string range $contents 0 [expr {$hdrend - 1}]]
1687 set comment [string range $contents [expr {$hdrend + 2}] end]
1688 foreach line [split $header "\n"] {
Kevin Ballard61f57cb2008-12-18 01:26:48 -08001689 set line [split $line " "]
Paul Mackerras232475d2005-11-15 10:34:03 +11001690 set tag [lindex $line 0]
1691 if {$tag == "author"} {
Anders Kaseorgf5974d92011-01-19 14:47:25 -05001692 set audate [lrange $line end-1 end]
Kevin Ballard61f57cb2008-12-18 01:26:48 -08001693 set auname [join [lrange $line 1 end-2] " "]
Paul Mackerras232475d2005-11-15 10:34:03 +11001694 } elseif {$tag == "committer"} {
Anders Kaseorgf5974d92011-01-19 14:47:25 -05001695 set comdate [lrange $line end-1 end]
Kevin Ballard61f57cb2008-12-18 01:26:48 -08001696 set comname [join [lrange $line 1 end-2] " "]
Paul Mackerras1db95b02005-05-09 04:08:39 +00001697 }
1698 }
Paul Mackerras232475d2005-11-15 10:34:03 +11001699 set headline {}
Paul Mackerras43c25072006-09-27 10:56:02 +10001700 # take the first non-blank line of the comment as the headline
1701 set headline [string trimleft $comment]
1702 set i [string first "\n" $headline]
Paul Mackerras232475d2005-11-15 10:34:03 +11001703 if {$i >= 0} {
Paul Mackerras43c25072006-09-27 10:56:02 +10001704 set headline [string range $headline 0 $i]
1705 }
1706 set headline [string trimright $headline]
1707 set i [string first "\r" $headline]
1708 if {$i >= 0} {
1709 set headline [string trimright [string range $headline 0 $i]]
Paul Mackerras232475d2005-11-15 10:34:03 +11001710 }
1711 if {!$listed} {
Paul Mackerrasf9e0b6f2008-03-04 21:14:17 +11001712 # git log indents the comment by 4 spaces;
Timo Hirvonen8974c6f2006-05-24 10:57:40 +03001713 # if we got this via git cat-file, add the indentation
Paul Mackerras232475d2005-11-15 10:34:03 +11001714 set newcomment {}
1715 foreach line [split $comment "\n"] {
1716 append newcomment " "
1717 append newcomment $line
Paul Mackerrasf6e28692005-11-20 23:08:22 +11001718 append newcomment "\n"
Paul Mackerras232475d2005-11-15 10:34:03 +11001719 }
1720 set comment $newcomment
Paul Mackerras1db95b02005-05-09 04:08:39 +00001721 }
Raphael Zimmerer36242492011-04-19 22:37:09 +02001722 set hasnote [string first "\nNotes:\n" $contents]
Thomas Rastb449eb22013-11-16 18:37:42 +01001723 set diff ""
1724 # If there is diff output shown in the git-log stream, split it
1725 # out. But get rid of the empty line that always precedes the
1726 # diff.
1727 set i [string first "\n\ndiff" $comment]
1728 if {$i >= 0} {
1729 set diff [string range $comment $i+1 end]
1730 set comment [string range $comment 0 $i-1]
1731 }
Paul Mackerrase5c2d852005-05-11 23:44:54 +00001732 set commitinfo($id) [list $headline $auname $audate \
Thomas Rastb449eb22013-11-16 18:37:42 +01001733 $comname $comdate $comment $hasnote $diff]
Paul Mackerras1db95b02005-05-09 04:08:39 +00001734}
1735
Paul Mackerrasf7a3e8d2006-03-18 10:04:48 +11001736proc getcommit {id} {
Paul Mackerras79b2c752006-04-02 20:47:40 +10001737 global commitdata commitinfo
Paul Mackerras8ed16482006-03-02 22:56:44 +11001738
Paul Mackerrasf7a3e8d2006-03-18 10:04:48 +11001739 if {[info exists commitdata($id)]} {
1740 parsecommit $id $commitdata($id) 1
Paul Mackerras8ed16482006-03-02 22:56:44 +11001741 } else {
1742 readcommit $id
1743 if {![info exists commitinfo($id)]} {
Christian Stimmingd990ced2007-11-07 18:42:55 +01001744 set commitinfo($id) [list [mc "No commit information available"]]
Paul Mackerras8ed16482006-03-02 22:56:44 +11001745 }
1746 }
1747 return 1
1748}
1749
Paul Mackerrasd375ef92008-10-21 10:18:12 +11001750# Expand an abbreviated commit ID to a list of full 40-char IDs that match
1751# and are present in the current view.
1752# This is fairly slow...
1753proc longid {prefix} {
Paul Mackerras22387f22012-03-19 11:21:08 +11001754 global varcid curview vshortids
Paul Mackerrasd375ef92008-10-21 10:18:12 +11001755
1756 set ids {}
Paul Mackerras22387f22012-03-19 11:21:08 +11001757 if {[string length $prefix] >= 4} {
1758 set vshortid $curview,[string range $prefix 0 3]
1759 if {[info exists vshortids($vshortid)]} {
1760 foreach id $vshortids($vshortid) {
1761 if {[string match "$prefix*" $id]} {
1762 if {[lsearch -exact $ids $id] < 0} {
1763 lappend ids $id
1764 if {[llength $ids] >= 2} break
1765 }
1766 }
1767 }
1768 }
1769 } else {
1770 foreach match [array names varcid "$curview,$prefix*"] {
1771 lappend ids [lindex [split $match ","] 1]
1772 if {[llength $ids] >= 2} break
1773 }
Paul Mackerrasd375ef92008-10-21 10:18:12 +11001774 }
1775 return $ids
1776}
1777
Paul Mackerras887fe3c2005-05-21 07:35:37 +00001778proc readrefs {} {
Paul Mackerras62d3ea62006-09-11 10:36:53 +10001779 global tagids idtags headids idheads tagobjid
Paul Mackerras219ea3a2006-09-07 10:21:39 +10001780 global otherrefids idotherrefs mainhead mainheadid
Alexander Gavrilov39816d62008-08-23 12:27:44 +04001781 global selecthead selectheadid
Thomas Rastffe15292009-08-03 23:53:36 +02001782 global hideremotes
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10001783
Sven Verdoolaegeb5c2f302005-11-29 22:15:51 +01001784 foreach v {tagids idtags headids idheads otherrefids idotherrefs} {
Paul Mackerras009409f2015-05-02 20:53:36 +10001785 unset -nocomplain $v
Sven Verdoolaegeb5c2f302005-11-29 22:15:51 +01001786 }
Paul Mackerras62d3ea62006-09-11 10:36:53 +10001787 set refd [open [list | git show-ref -d] r]
1788 while {[gets $refd line] >= 0} {
1789 if {[string index $line 40] ne " "} continue
1790 set id [string range $line 0 39]
1791 set ref [string range $line 41 end]
1792 if {![string match "refs/*" $ref]} continue
1793 set name [string range $ref 5 end]
1794 if {[string match "remotes/*" $name]} {
Thomas Rastffe15292009-08-03 23:53:36 +02001795 if {![string match "*/HEAD" $name] && !$hideremotes} {
Paul Mackerras62d3ea62006-09-11 10:36:53 +10001796 set headids($name) $id
1797 lappend idheads($id) $name
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10001798 }
Paul Mackerras62d3ea62006-09-11 10:36:53 +10001799 } elseif {[string match "heads/*" $name]} {
1800 set name [string range $name 6 end]
Junio C Hamano36a7cad2005-11-18 23:54:17 -08001801 set headids($name) $id
1802 lappend idheads($id) $name
Paul Mackerras62d3ea62006-09-11 10:36:53 +10001803 } elseif {[string match "tags/*" $name]} {
1804 # this lets refs/tags/foo^{} overwrite refs/tags/foo,
1805 # which is what we want since the former is the commit ID
1806 set name [string range $name 5 end]
1807 if {[string match "*^{}" $name]} {
1808 set name [string range $name 0 end-3]
1809 } else {
1810 set tagobjid($name) $id
1811 }
1812 set tagids($name) $id
1813 lappend idtags($id) $name
Junio C Hamano36a7cad2005-11-18 23:54:17 -08001814 } else {
1815 set otherrefids($name) $id
1816 lappend idotherrefs($id) $name
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10001817 }
1818 }
Alex Riesen062d6712007-07-29 22:28:40 +02001819 catch {close $refd}
Paul Mackerras8a485712006-07-06 10:21:23 +10001820 set mainhead {}
Paul Mackerras219ea3a2006-09-07 10:21:39 +10001821 set mainheadid {}
Paul Mackerras8a485712006-07-06 10:21:23 +10001822 catch {
Paul Mackerrasc11ff122008-05-26 10:11:33 +10001823 set mainheadid [exec git rev-parse HEAD]
Paul Mackerras8a485712006-07-06 10:21:23 +10001824 set thehead [exec git symbolic-ref HEAD]
1825 if {[string match "refs/heads/*" $thehead]} {
1826 set mainhead [string range $thehead 11 end]
1827 }
1828 }
Alexander Gavrilov39816d62008-08-23 12:27:44 +04001829 set selectheadid {}
1830 if {$selecthead ne {}} {
1831 catch {
1832 set selectheadid [exec git rev-parse --verify $selecthead]
1833 }
1834 }
Paul Mackerras887fe3c2005-05-21 07:35:37 +00001835}
1836
Paul Mackerras8f489362007-07-13 19:49:37 +10001837# skip over fake commits
1838proc first_real_row {} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001839 global nullid nullid2 numcommits
Paul Mackerras8f489362007-07-13 19:49:37 +10001840
1841 for {set row 0} {$row < $numcommits} {incr row} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001842 set id [commitonrow $row]
Paul Mackerras8f489362007-07-13 19:49:37 +10001843 if {$id ne $nullid && $id ne $nullid2} {
1844 break
1845 }
1846 }
1847 return $row
1848}
1849
Paul Mackerrase11f1232007-06-16 20:29:25 +10001850# update things for a head moved to a child of its previous location
1851proc movehead {id name} {
1852 global headids idheads
1853
1854 removehead $headids($name) $name
1855 set headids($name) $id
1856 lappend idheads($id) $name
1857}
1858
1859# update things when a head has been removed
1860proc removehead {id name} {
1861 global headids idheads
1862
1863 if {$idheads($id) eq $name} {
1864 unset idheads($id)
1865 } else {
1866 set i [lsearch -exact $idheads($id) $name]
1867 if {$i >= 0} {
1868 set idheads($id) [lreplace $idheads($id) $i $i]
1869 }
1870 }
1871 unset headids($name)
1872}
1873
Pat Thoytsd93f1712009-04-17 01:24:35 +01001874proc ttk_toplevel {w args} {
1875 global use_ttk
1876 eval [linsert $args 0 ::toplevel $w]
1877 if {$use_ttk} {
1878 place [ttk::frame $w._toplevel_background] -x 0 -y 0 -relwidth 1 -relheight 1
1879 }
1880 return $w
1881}
1882
Alexander Gavrilove7d64002008-11-11 23:55:42 +03001883proc make_transient {window origin} {
1884 global have_tk85
1885
1886 # In MacOS Tk 8.4 transient appears to work by setting
1887 # overrideredirect, which is utterly useless, since the
1888 # windows get no border, and are not even kept above
1889 # the parent.
1890 if {!$have_tk85 && [tk windowingsystem] eq {aqua}} return
1891
1892 wm transient $window $origin
1893
1894 # Windows fails to place transient windows normally, so
1895 # schedule a callback to center them on the parent.
1896 if {[tk windowingsystem] eq {win32}} {
1897 after idle [list tk::PlaceWindow $window widget $origin]
1898 }
1899}
1900
Alex Henrieef87a482015-05-11 13:26:41 -06001901proc show_error {w top msg} {
Pat Thoytsd93f1712009-04-17 01:24:35 +01001902 global NS
Pat Thoyts3cb1f9c2009-05-12 15:45:06 +01001903 if {![info exists NS]} {set NS ""}
Pat Thoytsd93f1712009-04-17 01:24:35 +01001904 if {[wm state $top] eq "withdrawn"} { wm deiconify $top }
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00001905 message $w.m -text $msg -justify center -aspect 400
1906 pack $w.m -side top -fill x -padx 20 -pady 20
Alex Henrieef87a482015-05-11 13:26:41 -06001907 ${NS}::button $w.ok -default active -text [mc OK] -command "destroy $top"
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00001908 pack $w.ok -side bottom -fill x
Paul Mackerrase54be9e2006-05-26 22:34:30 +10001909 bind $top <Visibility> "grab $top; focus $top"
1910 bind $top <Key-Return> "destroy $top"
Alexander Gavrilov76f15942008-11-02 21:59:44 +03001911 bind $top <Key-space> "destroy $top"
1912 bind $top <Key-Escape> "destroy $top"
Paul Mackerrase54be9e2006-05-26 22:34:30 +10001913 tkwait window $top
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00001914}
1915
Alexander Gavrilov84a76f12008-11-02 21:59:45 +03001916proc error_popup {msg {owner .}} {
Pat Thoytsd93f1712009-04-17 01:24:35 +01001917 if {[tk windowingsystem] eq "win32"} {
1918 tk_messageBox -icon error -type ok -title [wm title .] \
1919 -parent $owner -message $msg
1920 } else {
1921 set w .error
1922 ttk_toplevel $w
1923 make_transient $w $owner
1924 show_error $w $w $msg
1925 }
Paul Mackerras098dd8a2006-05-03 09:32:53 +10001926}
1927
Alexander Gavrilov84a76f12008-11-02 21:59:45 +03001928proc confirm_popup {msg {owner .}} {
Pat Thoytsd93f1712009-04-17 01:24:35 +01001929 global confirm_ok NS
Paul Mackerras10299152006-08-02 09:52:01 +10001930 set confirm_ok 0
1931 set w .confirm
Pat Thoytsd93f1712009-04-17 01:24:35 +01001932 ttk_toplevel $w
Alexander Gavrilove7d64002008-11-11 23:55:42 +03001933 make_transient $w $owner
Paul Mackerras10299152006-08-02 09:52:01 +10001934 message $w.m -text $msg -justify center -aspect 400
1935 pack $w.m -side top -fill x -padx 20 -pady 20
Pat Thoytsd93f1712009-04-17 01:24:35 +01001936 ${NS}::button $w.ok -text [mc OK] -command "set confirm_ok 1; destroy $w"
Paul Mackerras10299152006-08-02 09:52:01 +10001937 pack $w.ok -side left -fill x
Pat Thoytsd93f1712009-04-17 01:24:35 +01001938 ${NS}::button $w.cancel -text [mc Cancel] -command "destroy $w"
Paul Mackerras10299152006-08-02 09:52:01 +10001939 pack $w.cancel -side right -fill x
1940 bind $w <Visibility> "grab $w; focus $w"
Alexander Gavrilov76f15942008-11-02 21:59:44 +03001941 bind $w <Key-Return> "set confirm_ok 1; destroy $w"
1942 bind $w <Key-space> "set confirm_ok 1; destroy $w"
1943 bind $w <Key-Escape> "destroy $w"
Pat Thoytsd93f1712009-04-17 01:24:35 +01001944 tk::PlaceWindow $w widget $owner
Paul Mackerras10299152006-08-02 09:52:01 +10001945 tkwait window $w
1946 return $confirm_ok
1947}
1948
Paul Mackerrasb039f0a2008-01-06 15:54:46 +11001949proc setoptions {} {
Giuseppe Bilotta6cb73c82015-12-08 08:05:50 +01001950 global use_ttk
1951
Pat Thoytsd93f1712009-04-17 01:24:35 +01001952 if {[tk windowingsystem] ne "win32"} {
1953 option add *Panedwindow.showHandle 1 startupFile
1954 option add *Panedwindow.sashRelief raised startupFile
1955 if {[tk windowingsystem] ne "aqua"} {
1956 option add *Menu.font uifont startupFile
1957 }
1958 } else {
1959 option add *Menu.TearOff 0 startupFile
1960 }
Paul Mackerrasb039f0a2008-01-06 15:54:46 +11001961 option add *Button.font uifont startupFile
1962 option add *Checkbutton.font uifont startupFile
1963 option add *Radiobutton.font uifont startupFile
Paul Mackerrasb039f0a2008-01-06 15:54:46 +11001964 option add *Menubutton.font uifont startupFile
1965 option add *Label.font uifont startupFile
1966 option add *Message.font uifont startupFile
Mark Hillsb9b142f2010-01-13 20:40:22 +00001967 option add *Entry.font textfont startupFile
1968 option add *Text.font textfont startupFile
Pat Thoytsd93f1712009-04-17 01:24:35 +01001969 option add *Labelframe.font uifont startupFile
Mark Hills0933b042010-01-13 20:40:19 +00001970 option add *Spinbox.font textfont startupFile
Mark Hills207ad7b2010-01-13 20:40:20 +00001971 option add *Listbox.font mainfont startupFile
Paul Mackerrasb039f0a2008-01-06 15:54:46 +11001972}
1973
Giuseppe Bilotta6cb73c82015-12-08 08:05:50 +01001974proc setttkstyle {} {
1975 eval font configure TkDefaultFont [fontflags mainfont]
1976 eval font configure TkTextFont [fontflags textfont]
1977 eval font configure TkHeadingFont [fontflags mainfont]
1978 eval font configure TkCaptionFont [fontflags mainfont] -weight bold
1979 eval font configure TkTooltipFont [fontflags uifont]
1980 eval font configure TkFixedFont [fontflags textfont]
1981 eval font configure TkIconFont [fontflags uifont]
1982 eval font configure TkMenuFont [fontflags uifont]
1983 eval font configure TkSmallCaptionFont [fontflags uifont]
1984}
1985
Paul Mackerras79056032008-10-18 16:24:46 +11001986# Make a menu and submenus.
1987# m is the window name for the menu, items is the list of menu items to add.
1988# Each item is a list {mc label type description options...}
1989# mc is ignored; it's so we can put mc there to alert xgettext
1990# label is the string that appears in the menu
1991# type is cascade, command or radiobutton (should add checkbutton)
1992# description depends on type; it's the sublist for cascade, the
1993# command to invoke for command, or {variable value} for radiobutton
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11001994proc makemenu {m items} {
1995 menu $m
Alexander Gavrilovcea07cf2008-11-09 13:00:45 +03001996 if {[tk windowingsystem] eq {aqua}} {
1997 set Meta1 Cmd
1998 } else {
1999 set Meta1 Ctrl
2000 }
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11002001 foreach i $items {
Paul Mackerras79056032008-10-18 16:24:46 +11002002 set name [mc [lindex $i 1]]
2003 set type [lindex $i 2]
2004 set thing [lindex $i 3]
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11002005 set params [list $type]
2006 if {$name ne {}} {
2007 set u [string first "&" [string map {&& x} $name]]
2008 lappend params -label [string map {&& & & {}} $name]
2009 if {$u >= 0} {
2010 lappend params -underline $u
2011 }
2012 }
2013 switch -- $type {
2014 "cascade" {
Paul Mackerras79056032008-10-18 16:24:46 +11002015 set submenu [string tolower [string map {& ""} [lindex $i 1]]]
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11002016 lappend params -menu $m.$submenu
2017 }
2018 "command" {
2019 lappend params -command $thing
2020 }
2021 "radiobutton" {
2022 lappend params -variable [lindex $thing 0] \
2023 -value [lindex $thing 1]
2024 }
2025 }
Alexander Gavrilovcea07cf2008-11-09 13:00:45 +03002026 set tail [lrange $i 4 end]
2027 regsub -all {\yMeta1\y} $tail $Meta1 tail
2028 eval $m add $params $tail
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11002029 if {$type eq "cascade"} {
2030 makemenu $m.$submenu $thing
2031 }
2032 }
2033}
2034
2035# translate string and remove ampersands
2036proc mca {str} {
2037 return [string map {&& & & {}} [mc $str]]
2038}
2039
Paul Mackerras39c12692013-05-11 17:08:41 +10002040proc cleardropsel {w} {
2041 $w selection clear
2042}
Pat Thoytsd93f1712009-04-17 01:24:35 +01002043proc makedroplist {w varname args} {
2044 global use_ttk
2045 if {$use_ttk} {
Pat Thoyts3cb1f9c2009-05-12 15:45:06 +01002046 set width 0
2047 foreach label $args {
2048 set cx [string length $label]
2049 if {$cx > $width} {set width $cx}
2050 }
2051 set gm [ttk::combobox $w -width $width -state readonly\
Paul Mackerras39c12692013-05-11 17:08:41 +10002052 -textvariable $varname -values $args \
2053 -exportselection false]
2054 bind $gm <<ComboboxSelected>> [list $gm selection clear]
Pat Thoytsd93f1712009-04-17 01:24:35 +01002055 } else {
2056 set gm [eval [linsert $args 0 tk_optionMenu $w $varname]]
2057 }
2058 return $gm
2059}
2060
Paul Mackerrasd94f8cd2006-04-06 10:18:23 +10002061proc makewindow {} {
Paul Mackerras31c0eaa2007-12-30 22:41:14 +11002062 global canv canv2 canv3 linespc charspc ctext cflist cscroll
Paul Mackerras9c311b32007-10-04 22:27:13 +10002063 global tabstop
Paul Mackerrasb74fd572005-07-16 07:46:13 -04002064 global findtype findtypemenu findloc findstring fstring geometry
Paul Mackerras887fe3c2005-05-21 07:35:37 +00002065 global entries sha1entry sha1string sha1but
Steffen Prohaska890fae72007-08-12 12:05:46 +02002066 global diffcontextstring diffcontext
Steffen Prohaskab9b86002008-01-17 23:42:55 +01002067 global ignorespace
Paul Mackerras94a2eed2005-08-07 15:27:57 +10002068 global maincursor textcursor curtextcursor
Paul Mackerras219ea3a2006-09-07 10:21:39 +10002069 global rowctxmenu fakerowmenu mergemax wrapcomment
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10002070 global highlight_files gdttype
Paul Mackerras3ea06f92006-05-24 10:16:03 +10002071 global searchstring sstring
Mark Levedahl60378c02007-05-20 12:12:48 -04002072 global bgcolor fgcolor bglist fglist diffcolors selectbgcolor
Gauthier Östervall252c52d2013-03-27 14:40:51 +01002073 global uifgcolor uifgdisabledcolor
2074 global filesepbgcolor filesepfgcolor
2075 global mergecolors foundbgcolor currentsearchhitbgcolor
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10002076 global headctxmenu progresscanv progressitem progresscoords statusw
2077 global fprogitem fprogcoord lastprogupdate progupdatepending
Paul Mackerras6df74032008-05-11 22:13:02 +10002078 global rprogitem rprogcoord rownumsel numcommits
Pat Thoytsd93f1712009-04-17 01:24:35 +01002079 global have_tk85 use_ttk NS
Thomas Rastae4e3ff2010-10-16 12:15:10 +02002080 global git_version
2081 global worddiff
Paul Mackerras9a40c502005-05-12 23:46:16 +00002082
Paul Mackerras79056032008-10-18 16:24:46 +11002083 # The "mc" arguments here are purely so that xgettext
2084 # sees the following string as needing to be translated
Daniel A. Steffen5fdcbb12009-03-23 12:17:38 +01002085 set file {
Giuseppe Bilottad99b4b02015-09-09 15:20:53 +02002086 mc "&File" cascade {
2087 {mc "&Update" command updatecommits -accelerator F5}
2088 {mc "&Reload" command reloadcommits -accelerator Shift-F5}
2089 {mc "Reread re&ferences" command rereadrefs}
2090 {mc "&List references" command showrefs -accelerator F2}
Alexander Gavrilov7fb0abb2008-11-13 23:12:42 +03002091 {xx "" separator}
Giuseppe Bilottad99b4b02015-09-09 15:20:53 +02002092 {mc "Start git &gui" command {exec git gui &}}
Alexander Gavrilov7fb0abb2008-11-13 23:12:42 +03002093 {xx "" separator}
Giuseppe Bilottad99b4b02015-09-09 15:20:53 +02002094 {mc "&Quit" command doquit -accelerator Meta1-Q}
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11002095 }}
Daniel A. Steffen5fdcbb12009-03-23 12:17:38 +01002096 set edit {
Giuseppe Bilottad99b4b02015-09-09 15:20:53 +02002097 mc "&Edit" cascade {
2098 {mc "&Preferences" command doprefs}
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11002099 }}
Daniel A. Steffen5fdcbb12009-03-23 12:17:38 +01002100 set view {
Giuseppe Bilottad99b4b02015-09-09 15:20:53 +02002101 mc "&View" cascade {
2102 {mc "&New view..." command {newview 0} -accelerator Shift-F4}
2103 {mc "&Edit view..." command editview -state disabled -accelerator F4}
2104 {mc "&Delete view" command delview -state disabled}
Paul Mackerras79056032008-10-18 16:24:46 +11002105 {xx "" separator}
Giuseppe Bilottad99b4b02015-09-09 15:20:53 +02002106 {mc "&All files" radiobutton {selectedview 0} -command {showview 0}}
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11002107 }}
Daniel A. Steffen5fdcbb12009-03-23 12:17:38 +01002108 if {[tk windowingsystem] ne "aqua"} {
2109 set help {
Giuseppe Bilottad99b4b02015-09-09 15:20:53 +02002110 mc "&Help" cascade {
2111 {mc "&About gitk" command about}
2112 {mc "&Key bindings" command keys}
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11002113 }}
Daniel A. Steffen5fdcbb12009-03-23 12:17:38 +01002114 set bar [list $file $edit $view $help]
2115 } else {
2116 proc ::tk::mac::ShowPreferences {} {doprefs}
2117 proc ::tk::mac::Quit {} {doquit}
2118 lset file end [lreplace [lindex $file end] end-1 end]
2119 set apple {
Giuseppe Bilottad99b4b02015-09-09 15:20:53 +02002120 xx "&Apple" cascade {
2121 {mc "&About gitk" command about}
Daniel A. Steffen5fdcbb12009-03-23 12:17:38 +01002122 {xx "" separator}
2123 }}
2124 set help {
Giuseppe Bilottad99b4b02015-09-09 15:20:53 +02002125 mc "&Help" cascade {
2126 {mc "&Key bindings" command keys}
Daniel A. Steffen5fdcbb12009-03-23 12:17:38 +01002127 }}
2128 set bar [list $apple $file $view $help]
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11002129 }
Daniel A. Steffen5fdcbb12009-03-23 12:17:38 +01002130 makemenu .bar $bar
Paul Mackerras9a40c502005-05-12 23:46:16 +00002131 . configure -menu .bar
2132
Pat Thoytsd93f1712009-04-17 01:24:35 +01002133 if {$use_ttk} {
2134 # cover the non-themed toplevel with a themed frame.
2135 place [ttk::frame ._main_background] -x 0 -y 0 -relwidth 1 -relheight 1
2136 }
2137
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002138 # the gui has upper and lower half, parts of a paned window.
Pat Thoytsd93f1712009-04-17 01:24:35 +01002139 ${NS}::panedwindow .ctop -orient vertical
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002140
2141 # possibly use assumed geometry
Mark Levedahl9ca72f42007-02-12 19:19:34 -05002142 if {![info exists geometry(pwsash0)]} {
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002143 set geometry(topheight) [expr {15 * $linespc}]
2144 set geometry(topwidth) [expr {80 * $charspc}]
2145 set geometry(botheight) [expr {15 * $linespc}]
2146 set geometry(botwidth) [expr {50 * $charspc}]
Pat Thoytsd93f1712009-04-17 01:24:35 +01002147 set geometry(pwsash0) [list [expr {40 * $charspc}] 2]
2148 set geometry(pwsash1) [list [expr {60 * $charspc}] 2]
Paul Mackerras0fba86b2005-05-16 23:54:58 +00002149 }
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002150
2151 # 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 +01002152 ${NS}::frame .tf -height $geometry(topheight) -width $geometry(topwidth)
2153 ${NS}::frame .tf.histframe
2154 ${NS}::panedwindow .tf.histframe.pwclist -orient horizontal
2155 if {!$use_ttk} {
2156 .tf.histframe.pwclist configure -sashpad 0 -handlesize 4
2157 }
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002158
2159 # create three canvases
2160 set cscroll .tf.histframe.csb
2161 set canv .tf.histframe.pwclist.canv
Mark Levedahl9ca72f42007-02-12 19:19:34 -05002162 canvas $canv \
Mark Levedahl60378c02007-05-20 12:12:48 -04002163 -selectbackground $selectbgcolor \
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10002164 -background $bgcolor -bd 0 \
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002165 -yscrollincr $linespc -yscrollcommand "scrollcanv $cscroll"
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002166 .tf.histframe.pwclist add $canv
2167 set canv2 .tf.histframe.pwclist.canv2
Mark Levedahl9ca72f42007-02-12 19:19:34 -05002168 canvas $canv2 \
Mark Levedahl60378c02007-05-20 12:12:48 -04002169 -selectbackground $selectbgcolor \
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10002170 -background $bgcolor -bd 0 -yscrollincr $linespc
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002171 .tf.histframe.pwclist add $canv2
2172 set canv3 .tf.histframe.pwclist.canv3
Mark Levedahl9ca72f42007-02-12 19:19:34 -05002173 canvas $canv3 \
Mark Levedahl60378c02007-05-20 12:12:48 -04002174 -selectbackground $selectbgcolor \
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10002175 -background $bgcolor -bd 0 -yscrollincr $linespc
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002176 .tf.histframe.pwclist add $canv3
Pat Thoytsd93f1712009-04-17 01:24:35 +01002177 if {$use_ttk} {
2178 bind .tf.histframe.pwclist <Map> {
2179 bind %W <Map> {}
2180 .tf.histframe.pwclist sashpos 1 [lindex $::geometry(pwsash1) 0]
2181 .tf.histframe.pwclist sashpos 0 [lindex $::geometry(pwsash0) 0]
2182 }
2183 } else {
2184 eval .tf.histframe.pwclist sash place 0 $geometry(pwsash0)
2185 eval .tf.histframe.pwclist sash place 1 $geometry(pwsash1)
2186 }
Paul Mackerras98f350e2005-05-15 05:56:51 +00002187
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002188 # a scroll bar to rule them
Pat Thoytsd93f1712009-04-17 01:24:35 +01002189 ${NS}::scrollbar $cscroll -command {allcanvs yview}
2190 if {!$use_ttk} {$cscroll configure -highlightthickness 0}
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002191 pack $cscroll -side right -fill y
2192 bind .tf.histframe.pwclist <Configure> {resizeclistpanes %W %w}
2193 lappend bglist $canv $canv2 $canv3
2194 pack .tf.histframe.pwclist -fill both -expand 1 -side left
2195
2196 # we have two button bars at bottom of top frame. Bar 1
Pat Thoytsd93f1712009-04-17 01:24:35 +01002197 ${NS}::frame .tf.bar
2198 ${NS}::frame .tf.lbar -height 15
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002199
2200 set sha1entry .tf.bar.sha1
Paul Mackerras887fe3c2005-05-21 07:35:37 +00002201 set entries $sha1entry
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002202 set sha1but .tf.bar.sha1label
Markus Heidelberg0359ba72010-01-09 23:11:12 +01002203 button $sha1but -text "[mc "SHA1 ID:"] " -state disabled -relief flat \
Paul Mackerrasb039f0a2008-01-06 15:54:46 +11002204 -command gotocommit -width 8
Paul Mackerras887fe3c2005-05-21 07:35:37 +00002205 $sha1but conf -disabledforeground [$sha1but cget -foreground]
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002206 pack .tf.bar.sha1label -side left
Pat Thoytsd93f1712009-04-17 01:24:35 +01002207 ${NS}::entry $sha1entry -width 40 -font textfont -textvariable sha1string
Paul Mackerras887fe3c2005-05-21 07:35:37 +00002208 trace add variable sha1string write sha1change
Paul Mackerras98f350e2005-05-15 05:56:51 +00002209 pack $sha1entry -side left -pady 2
Paul Mackerrasd6982062005-08-06 22:06:06 +10002210
Stefan Hallerf062e502012-09-22 09:46:48 +02002211 set bm_left_data {
Paul Mackerrasd6982062005-08-06 22:06:06 +10002212 #define left_width 16
2213 #define left_height 16
2214 static unsigned char left_bits[] = {
2215 0x00, 0x00, 0xc0, 0x01, 0xe0, 0x00, 0x70, 0x00, 0x38, 0x00, 0x1c, 0x00,
2216 0x0e, 0x00, 0xff, 0x7f, 0xff, 0x7f, 0xff, 0x7f, 0x0e, 0x00, 0x1c, 0x00,
2217 0x38, 0x00, 0x70, 0x00, 0xe0, 0x00, 0xc0, 0x01};
2218 }
Stefan Hallerf062e502012-09-22 09:46:48 +02002219 set bm_right_data {
Paul Mackerrasd6982062005-08-06 22:06:06 +10002220 #define right_width 16
2221 #define right_height 16
2222 static unsigned char right_bits[] = {
2223 0x00, 0x00, 0xc0, 0x01, 0x80, 0x03, 0x00, 0x07, 0x00, 0x0e, 0x00, 0x1c,
2224 0x00, 0x38, 0xff, 0x7f, 0xff, 0x7f, 0xff, 0x7f, 0x00, 0x38, 0x00, 0x1c,
2225 0x00, 0x0e, 0x00, 0x07, 0x80, 0x03, 0xc0, 0x01};
2226 }
Gauthier Östervall252c52d2013-03-27 14:40:51 +01002227 image create bitmap bm-left -data $bm_left_data -foreground $uifgcolor
2228 image create bitmap bm-left-gray -data $bm_left_data -foreground $uifgdisabledcolor
2229 image create bitmap bm-right -data $bm_right_data -foreground $uifgcolor
2230 image create bitmap bm-right-gray -data $bm_right_data -foreground $uifgdisabledcolor
Stefan Hallerf062e502012-09-22 09:46:48 +02002231
Marcus Karlsson62e9ac52012-10-07 23:21:14 +02002232 ${NS}::button .tf.bar.leftbut -command goback -state disabled -width 26
2233 if {$use_ttk} {
2234 .tf.bar.leftbut configure -image [list bm-left disabled bm-left-gray]
2235 } else {
2236 .tf.bar.leftbut configure -image bm-left
2237 }
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002238 pack .tf.bar.leftbut -side left -fill y
Marcus Karlsson62e9ac52012-10-07 23:21:14 +02002239 ${NS}::button .tf.bar.rightbut -command goforw -state disabled -width 26
2240 if {$use_ttk} {
2241 .tf.bar.rightbut configure -image [list bm-right disabled bm-right-gray]
2242 } else {
2243 .tf.bar.rightbut configure -image bm-right
2244 }
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002245 pack .tf.bar.rightbut -side left -fill y
Paul Mackerrasd6982062005-08-06 22:06:06 +10002246
Pat Thoytsd93f1712009-04-17 01:24:35 +01002247 ${NS}::label .tf.bar.rowlabel -text [mc "Row"]
Paul Mackerras6df74032008-05-11 22:13:02 +10002248 set rownumsel {}
Pat Thoytsd93f1712009-04-17 01:24:35 +01002249 ${NS}::label .tf.bar.rownum -width 7 -textvariable rownumsel \
Paul Mackerras6df74032008-05-11 22:13:02 +10002250 -relief sunken -anchor e
Pat Thoytsd93f1712009-04-17 01:24:35 +01002251 ${NS}::label .tf.bar.rowlabel2 -text "/"
2252 ${NS}::label .tf.bar.numcommits -width 7 -textvariable numcommits \
Paul Mackerras6df74032008-05-11 22:13:02 +10002253 -relief sunken -anchor e
2254 pack .tf.bar.rowlabel .tf.bar.rownum .tf.bar.rowlabel2 .tf.bar.numcommits \
2255 -side left
Pat Thoytsd93f1712009-04-17 01:24:35 +01002256 if {!$use_ttk} {
2257 foreach w {rownum numcommits} {.tf.bar.$w configure -font textfont}
2258 }
Paul Mackerras6df74032008-05-11 22:13:02 +10002259 global selectedline
Paul Mackerras94b4a692008-05-20 20:51:06 +10002260 trace add variable selectedline write selectedline_change
Paul Mackerras6df74032008-05-11 22:13:02 +10002261
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10002262 # Status label and progress bar
2263 set statusw .tf.bar.status
Pat Thoytsd93f1712009-04-17 01:24:35 +01002264 ${NS}::label $statusw -width 15 -relief sunken
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10002265 pack $statusw -side left -padx 5
Pat Thoytsd93f1712009-04-17 01:24:35 +01002266 if {$use_ttk} {
2267 set progresscanv [ttk::progressbar .tf.bar.progress]
2268 } else {
2269 set h [expr {[font metrics uifont -linespace] + 2}]
2270 set progresscanv .tf.bar.progress
2271 canvas $progresscanv -relief sunken -height $h -borderwidth 2
Paul Mackerras6e8fda52016-12-12 11:29:21 +11002272 set progressitem [$progresscanv create rect -1 0 0 $h -fill "#00ff00"]
Pat Thoytsd93f1712009-04-17 01:24:35 +01002273 set fprogitem [$progresscanv create rect -1 0 0 $h -fill yellow]
2274 set rprogitem [$progresscanv create rect -1 0 0 $h -fill red]
2275 }
2276 pack $progresscanv -side right -expand 1 -fill x -padx {0 2}
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10002277 set progresscoords {0 0}
2278 set fprogcoord 0
Paul Mackerrasa137a902007-10-23 21:12:49 +10002279 set rprogcoord 0
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10002280 bind $progresscanv <Configure> adjustprogress
2281 set lastprogupdate [clock clicks -milliseconds]
2282 set progupdatepending 0
Paul Mackerrasb5721c72005-05-10 12:08:22 +00002283
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002284 # build up the bottom bar of upper window
Pat Thoytsd93f1712009-04-17 01:24:35 +01002285 ${NS}::label .tf.lbar.flabel -text "[mc "Find"] "
Marc Branchaud786f15c2013-12-18 11:04:13 -05002286
2287 set bm_down_data {
2288 #define down_width 16
2289 #define down_height 16
2290 static unsigned char down_bits[] = {
2291 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01,
2292 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01,
2293 0x87, 0xe1, 0x8e, 0x71, 0x9c, 0x39, 0xb8, 0x1d,
2294 0xf0, 0x0f, 0xe0, 0x07, 0xc0, 0x03, 0x80, 0x01};
2295 }
2296 image create bitmap bm-down -data $bm_down_data -foreground $uifgcolor
2297 ${NS}::button .tf.lbar.fnext -width 26 -command {dofind 1 1}
2298 .tf.lbar.fnext configure -image bm-down
2299
2300 set bm_up_data {
2301 #define up_width 16
2302 #define up_height 16
2303 static unsigned char up_bits[] = {
2304 0x80, 0x01, 0xc0, 0x03, 0xe0, 0x07, 0xf0, 0x0f,
2305 0xb8, 0x1d, 0x9c, 0x39, 0x8e, 0x71, 0x87, 0xe1,
2306 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01,
2307 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01};
2308 }
2309 image create bitmap bm-up -data $bm_up_data -foreground $uifgcolor
2310 ${NS}::button .tf.lbar.fprev -width 26 -command {dofind -1 1}
2311 .tf.lbar.fprev configure -image bm-up
2312
Pat Thoytsd93f1712009-04-17 01:24:35 +01002313 ${NS}::label .tf.lbar.flab2 -text " [mc "commit"] "
Marc Branchaud786f15c2013-12-18 11:04:13 -05002314
Paul Mackerras687c8762007-09-22 12:49:33 +10002315 pack .tf.lbar.flabel .tf.lbar.fnext .tf.lbar.fprev .tf.lbar.flab2 \
2316 -side left -fill y
Christian Stimmingb007ee22007-11-07 18:44:35 +01002317 set gdttype [mc "containing:"]
Pat Thoyts3cb1f9c2009-05-12 15:45:06 +01002318 set gm [makedroplist .tf.lbar.gdttype gdttype \
Christian Stimmingb007ee22007-11-07 18:44:35 +01002319 [mc "containing:"] \
2320 [mc "touching paths:"] \
Martin Langhoffc33cb902012-06-14 20:34:11 +02002321 [mc "adding/removing string:"] \
2322 [mc "changing lines matching:"]]
Paul Mackerras687c8762007-09-22 12:49:33 +10002323 trace add variable gdttype write gdttype_change
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002324 pack .tf.lbar.gdttype -side left -fill y
Paul Mackerras687c8762007-09-22 12:49:33 +10002325
2326 set findstring {}
2327 set fstring .tf.lbar.findstring
2328 lappend entries $fstring
Mark Hillsb9b142f2010-01-13 20:40:22 +00002329 ${NS}::entry $fstring -width 30 -textvariable findstring
Paul Mackerras687c8762007-09-22 12:49:33 +10002330 trace add variable findstring write find_change
Christian Stimmingb007ee22007-11-07 18:44:35 +01002331 set findtype [mc "Exact"]
Pat Thoytsd93f1712009-04-17 01:24:35 +01002332 set findtypemenu [makedroplist .tf.lbar.findtype \
2333 findtype [mc "Exact"] [mc "IgnCase"] [mc "Regexp"]]
Paul Mackerras687c8762007-09-22 12:49:33 +10002334 trace add variable findtype write findcom_change
Christian Stimmingb007ee22007-11-07 18:44:35 +01002335 set findloc [mc "All fields"]
Pat Thoytsd93f1712009-04-17 01:24:35 +01002336 makedroplist .tf.lbar.findloc findloc [mc "All fields"] [mc "Headline"] \
Christian Stimmingb007ee22007-11-07 18:44:35 +01002337 [mc "Comments"] [mc "Author"] [mc "Committer"]
Paul Mackerras687c8762007-09-22 12:49:33 +10002338 trace add variable findloc write find_change
Paul Mackerras687c8762007-09-22 12:49:33 +10002339 pack .tf.lbar.findloc -side right
2340 pack .tf.lbar.findtype -side right
2341 pack $fstring -side left -expand 1 -fill x
Paul Mackerras908c3582006-05-20 09:38:11 +10002342
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002343 # Finish putting the upper half of the viewer together
2344 pack .tf.lbar -in .tf -side bottom -fill x
2345 pack .tf.bar -in .tf -side bottom -fill x
2346 pack .tf.histframe -fill both -side top -expand 1
2347 .ctop add .tf
Pat Thoytsd93f1712009-04-17 01:24:35 +01002348 if {!$use_ttk} {
2349 .ctop paneconfigure .tf -height $geometry(topheight)
2350 .ctop paneconfigure .tf -width $geometry(topwidth)
2351 }
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002352
2353 # now build up the bottom
Pat Thoytsd93f1712009-04-17 01:24:35 +01002354 ${NS}::panedwindow .pwbottom -orient horizontal
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002355
2356 # lower left, a text box over search bar, scroll bar to the right
2357 # if we know window height, then that will set the lower text height, otherwise
2358 # we set lower text height which will drive window height
2359 if {[info exists geometry(main)]} {
Pat Thoytsd93f1712009-04-17 01:24:35 +01002360 ${NS}::frame .bleft -width $geometry(botwidth)
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002361 } else {
Pat Thoytsd93f1712009-04-17 01:24:35 +01002362 ${NS}::frame .bleft -width $geometry(botwidth) -height $geometry(botheight)
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002363 }
Pat Thoytsd93f1712009-04-17 01:24:35 +01002364 ${NS}::frame .bleft.top
2365 ${NS}::frame .bleft.mid
2366 ${NS}::frame .bleft.bottom
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002367
Giuseppe Bilottacae4b602015-12-08 08:05:51 +01002368 # gap between sub-widgets
2369 set wgap [font measure uifont "i"]
2370
Pat Thoytsd93f1712009-04-17 01:24:35 +01002371 ${NS}::button .bleft.top.search -text [mc "Search"] -command dosearch
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002372 pack .bleft.top.search -side left -padx 5
2373 set sstring .bleft.top.sstring
Pat Thoytsd93f1712009-04-17 01:24:35 +01002374 set searchstring ""
Mark Hillsb9b142f2010-01-13 20:40:22 +00002375 ${NS}::entry $sstring -width 20 -textvariable searchstring
Paul Mackerras3ea06f92006-05-24 10:16:03 +10002376 lappend entries $sstring
2377 trace add variable searchstring write incrsearch
2378 pack $sstring -side left -expand 1 -fill x
Pat Thoytsd93f1712009-04-17 01:24:35 +01002379 ${NS}::radiobutton .bleft.mid.diff -text [mc "Diff"] \
Paul Mackerrasa8d610a2007-04-19 11:39:12 +10002380 -command changediffdisp -variable diffelide -value {0 0}
Pat Thoytsd93f1712009-04-17 01:24:35 +01002381 ${NS}::radiobutton .bleft.mid.old -text [mc "Old version"] \
Paul Mackerrasa8d610a2007-04-19 11:39:12 +10002382 -command changediffdisp -variable diffelide -value {0 1}
Pat Thoytsd93f1712009-04-17 01:24:35 +01002383 ${NS}::radiobutton .bleft.mid.new -text [mc "New version"] \
Paul Mackerrasa8d610a2007-04-19 11:39:12 +10002384 -command changediffdisp -variable diffelide -value {1 0}
Giuseppe Bilottacae4b602015-12-08 08:05:51 +01002385
Pat Thoytsd93f1712009-04-17 01:24:35 +01002386 ${NS}::label .bleft.mid.labeldiffcontext -text " [mc "Lines of context"]: "
Giuseppe Bilottacae4b602015-12-08 08:05:51 +01002387 pack .bleft.mid.diff .bleft.mid.old .bleft.mid.new -side left -ipadx $wgap
Mark Hills0933b042010-01-13 20:40:19 +00002388 spinbox .bleft.mid.diffcontext -width 5 \
Markus Heidelberga41ddbb2009-05-23 19:31:37 +02002389 -from 0 -increment 1 -to 10000000 \
Steffen Prohaska890fae72007-08-12 12:05:46 +02002390 -validate all -validatecommand "diffcontextvalidate %P" \
2391 -textvariable diffcontextstring
2392 .bleft.mid.diffcontext set $diffcontext
2393 trace add variable diffcontextstring write diffcontextchange
2394 lappend entries .bleft.mid.diffcontext
Giuseppe Bilottacae4b602015-12-08 08:05:51 +01002395 pack .bleft.mid.labeldiffcontext .bleft.mid.diffcontext -side left -ipadx $wgap
Pat Thoytsd93f1712009-04-17 01:24:35 +01002396 ${NS}::checkbutton .bleft.mid.ignspace -text [mc "Ignore space change"] \
Steffen Prohaskab9b86002008-01-17 23:42:55 +01002397 -command changeignorespace -variable ignorespace
2398 pack .bleft.mid.ignspace -side left -padx 5
Thomas Rastae4e3ff2010-10-16 12:15:10 +02002399
2400 set worddiff [mc "Line diff"]
2401 if {[package vcompare $git_version "1.7.2"] >= 0} {
2402 makedroplist .bleft.mid.worddiff worddiff [mc "Line diff"] \
2403 [mc "Markup words"] [mc "Color words"]
2404 trace add variable worddiff write changeworddiff
2405 pack .bleft.mid.worddiff -side left -padx 5
2406 }
2407
Pekka Kaitaniemi8809d692008-03-08 14:27:23 +02002408 set ctext .bleft.bottom.ctext
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10002409 text $ctext -background $bgcolor -foreground $fgcolor \
Markus Hitter106a6d92016-11-06 20:38:03 +01002410 -state disabled -undo 0 -font textfont \
Pekka Kaitaniemi8809d692008-03-08 14:27:23 +02002411 -yscrollcommand scrolltext -wrap none \
2412 -xscrollcommand ".bleft.bottom.sbhorizontal set"
Paul Mackerras32f1b3e2007-09-28 21:27:39 +10002413 if {$have_tk85} {
2414 $ctext conf -tabstyle wordprocessor
2415 }
Pat Thoytsd93f1712009-04-17 01:24:35 +01002416 ${NS}::scrollbar .bleft.bottom.sb -command "$ctext yview"
2417 ${NS}::scrollbar .bleft.bottom.sbhorizontal -command "$ctext xview" -orient h
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002418 pack .bleft.top -side top -fill x
Paul Mackerrasa8d610a2007-04-19 11:39:12 +10002419 pack .bleft.mid -side top -fill x
Pekka Kaitaniemi8809d692008-03-08 14:27:23 +02002420 grid $ctext .bleft.bottom.sb -sticky nsew
2421 grid .bleft.bottom.sbhorizontal -sticky ew
2422 grid columnconfigure .bleft.bottom 0 -weight 1
2423 grid rowconfigure .bleft.bottom 0 -weight 1
2424 grid rowconfigure .bleft.bottom 1 -weight 0
2425 pack .bleft.bottom -side top -fill both -expand 1
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10002426 lappend bglist $ctext
2427 lappend fglist $ctext
Paul Mackerrasd2610d12005-05-11 00:45:38 +00002428
Sergey Vlasovf1b86292006-05-15 19:13:14 +04002429 $ctext tag conf comment -wrap $wrapcomment
Gauthier Östervall252c52d2013-03-27 14:40:51 +01002430 $ctext tag conf filesep -font textfontbold -fore $filesepfgcolor -back $filesepbgcolor
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10002431 $ctext tag conf hunksep -fore [lindex $diffcolors 2]
2432 $ctext tag conf d0 -fore [lindex $diffcolors 0]
Paul Mackerras8b07dca2008-11-02 22:34:47 +11002433 $ctext tag conf dresult -fore [lindex $diffcolors 1]
Gauthier Östervall252c52d2013-03-27 14:40:51 +01002434 $ctext tag conf m0 -fore [lindex $mergecolors 0]
2435 $ctext tag conf m1 -fore [lindex $mergecolors 1]
2436 $ctext tag conf m2 -fore [lindex $mergecolors 2]
2437 $ctext tag conf m3 -fore [lindex $mergecolors 3]
2438 $ctext tag conf m4 -fore [lindex $mergecolors 4]
2439 $ctext tag conf m5 -fore [lindex $mergecolors 5]
2440 $ctext tag conf m6 -fore [lindex $mergecolors 6]
2441 $ctext tag conf m7 -fore [lindex $mergecolors 7]
2442 $ctext tag conf m8 -fore [lindex $mergecolors 8]
2443 $ctext tag conf m9 -fore [lindex $mergecolors 9]
2444 $ctext tag conf m10 -fore [lindex $mergecolors 10]
2445 $ctext tag conf m11 -fore [lindex $mergecolors 11]
2446 $ctext tag conf m12 -fore [lindex $mergecolors 12]
2447 $ctext tag conf m13 -fore [lindex $mergecolors 13]
2448 $ctext tag conf m14 -fore [lindex $mergecolors 14]
2449 $ctext tag conf m15 -fore [lindex $mergecolors 15]
Paul Mackerras712fcc02005-11-30 09:28:16 +11002450 $ctext tag conf mmax -fore darkgrey
Paul Mackerrasb77b0272006-02-07 09:13:52 +11002451 set mergemax 16
Paul Mackerras9c311b32007-10-04 22:27:13 +10002452 $ctext tag conf mresult -font textfontbold
2453 $ctext tag conf msep -font textfontbold
Gauthier Östervall252c52d2013-03-27 14:40:51 +01002454 $ctext tag conf found -back $foundbgcolor
2455 $ctext tag conf currentsearchhit -back $currentsearchhitbgcolor
Paul Mackerras76d64ca2014-01-23 22:06:22 +11002456 $ctext tag conf wwrap -wrap word -lmargin2 1c
Paul Mackerras4399fe32013-01-03 10:10:31 +11002457 $ctext tag conf bold -font textfontbold
Paul Mackerrase5c2d852005-05-11 23:44:54 +00002458
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002459 .pwbottom add .bleft
Pat Thoytsd93f1712009-04-17 01:24:35 +01002460 if {!$use_ttk} {
2461 .pwbottom paneconfigure .bleft -width $geometry(botwidth)
2462 }
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002463
2464 # lower right
Pat Thoytsd93f1712009-04-17 01:24:35 +01002465 ${NS}::frame .bright
2466 ${NS}::frame .bright.mode
2467 ${NS}::radiobutton .bright.mode.patch -text [mc "Patch"] \
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10002468 -command reselectline -variable cmitmode -value "patch"
Pat Thoytsd93f1712009-04-17 01:24:35 +01002469 ${NS}::radiobutton .bright.mode.tree -text [mc "Tree"] \
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10002470 -command reselectline -variable cmitmode -value "tree"
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002471 grid .bright.mode.patch .bright.mode.tree -sticky ew
2472 pack .bright.mode -side top -fill x
2473 set cflist .bright.cfiles
Paul Mackerras9c311b32007-10-04 22:27:13 +10002474 set indent [font measure mainfont "nn"]
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002475 text $cflist \
Mark Levedahl60378c02007-05-20 12:12:48 -04002476 -selectbackground $selectbgcolor \
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10002477 -background $bgcolor -foreground $fgcolor \
Paul Mackerras9c311b32007-10-04 22:27:13 +10002478 -font mainfont \
Paul Mackerras7fcceed2006-04-27 19:21:49 +10002479 -tabs [list $indent [expr {2 * $indent}]] \
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002480 -yscrollcommand ".bright.sb set" \
Paul Mackerras7fcceed2006-04-27 19:21:49 +10002481 -cursor [. cget -cursor] \
2482 -spacing1 1 -spacing3 1
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10002483 lappend bglist $cflist
2484 lappend fglist $cflist
Pat Thoytsd93f1712009-04-17 01:24:35 +01002485 ${NS}::scrollbar .bright.sb -command "$cflist yview"
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002486 pack .bright.sb -side right -fill y
Paul Mackerrasd2610d12005-05-11 00:45:38 +00002487 pack $cflist -side left -fill both -expand 1
Paul Mackerras89b11d32006-05-02 19:55:31 +10002488 $cflist tag configure highlight \
2489 -background [$cflist cget -selectbackground]
Paul Mackerras9c311b32007-10-04 22:27:13 +10002490 $cflist tag configure bold -font mainfontbold
Paul Mackerrasd2610d12005-05-11 00:45:38 +00002491
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002492 .pwbottom add .bright
2493 .ctop add .pwbottom
Paul Mackerras1db95b02005-05-09 04:08:39 +00002494
Paul Mackerrasb9bee112008-03-10 16:50:34 +11002495 # restore window width & height if known
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002496 if {[info exists geometry(main)]} {
Paul Mackerrasb9bee112008-03-10 16:50:34 +11002497 if {[scan $geometry(main) "%dx%d" w h] >= 2} {
2498 if {$w > [winfo screenwidth .]} {
2499 set w [winfo screenwidth .]
2500 }
2501 if {$h > [winfo screenheight .]} {
2502 set h [winfo screenheight .]
2503 }
2504 wm geometry . "${w}x$h"
2505 }
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002506 }
2507
Pat Thoytsc876dba2009-04-14 22:09:53 +01002508 if {[info exists geometry(state)] && $geometry(state) eq "zoomed"} {
2509 wm state . $geometry(state)
2510 }
2511
Shawn O. Pearced23d98d2007-07-19 00:37:58 -04002512 if {[tk windowingsystem] eq {aqua}} {
2513 set M1B M1
Daniel A. Steffen5fdcbb12009-03-23 12:17:38 +01002514 set ::BM "3"
Shawn O. Pearced23d98d2007-07-19 00:37:58 -04002515 } else {
2516 set M1B Control
Daniel A. Steffen5fdcbb12009-03-23 12:17:38 +01002517 set ::BM "2"
Shawn O. Pearced23d98d2007-07-19 00:37:58 -04002518 }
2519
Pat Thoytsd93f1712009-04-17 01:24:35 +01002520 if {$use_ttk} {
2521 bind .ctop <Map> {
2522 bind %W <Map> {}
2523 %W sashpos 0 $::geometry(topheight)
2524 }
2525 bind .pwbottom <Map> {
2526 bind %W <Map> {}
2527 %W sashpos 0 $::geometry(botwidth)
2528 }
2529 }
2530
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002531 bind .pwbottom <Configure> {resizecdetpanes %W %w}
2532 pack .ctop -fill both -expand 1
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10002533 bindall <1> {selcanvline %W %x %y}
2534 #bindall <B1-Motion> {selcanvline %W %x %y}
Mark Levedahl314c3092007-08-07 21:40:35 -04002535 if {[tk windowingsystem] == "win32"} {
2536 bind . <MouseWheel> { windows_mousewheel_redirector %W %X %Y %D }
2537 bind $ctext <MouseWheel> { windows_mousewheel_redirector %W %X %Y %D ; break }
2538 } else {
2539 bindall <ButtonRelease-4> "allcanvs yview scroll -5 units"
2540 bindall <ButtonRelease-5> "allcanvs yview scroll 5 units"
Gabriele Mazzotta122b8072014-11-15 15:05:06 +01002541 bind $ctext <Button> {
2542 if {"%b" eq 6} {
2543 $ctext xview scroll -5 units
2544 } elseif {"%b" eq 7} {
2545 $ctext xview scroll 5 units
2546 }
2547 }
Jonathan del Strother5dd57d52007-10-15 10:33:07 +01002548 if {[tk windowingsystem] eq "aqua"} {
2549 bindall <MouseWheel> {
2550 set delta [expr {- (%D)}]
2551 allcanvs yview scroll $delta units
2552 }
Daniel A. Steffen5fdcbb12009-03-23 12:17:38 +01002553 bindall <Shift-MouseWheel> {
2554 set delta [expr {- (%D)}]
2555 $canv xview scroll $delta units
2556 }
Jonathan del Strother5dd57d52007-10-15 10:33:07 +01002557 }
Mark Levedahl314c3092007-08-07 21:40:35 -04002558 }
Daniel A. Steffen5fdcbb12009-03-23 12:17:38 +01002559 bindall <$::BM> "canvscan mark %W %x %y"
2560 bindall <B$::BM-Motion> "canvscan dragto %W %x %y"
Jens Lehmanndecd0a12010-02-02 23:11:28 +01002561 bind all <$M1B-Key-w> {destroy [winfo toplevel %W]}
2562 bind . <$M1B-Key-w> doquit
Rutger Nijlunsing6e5f7202006-04-05 10:24:03 +10002563 bindkey <Home> selfirstline
2564 bindkey <End> sellastline
Paul Mackerras17386062005-05-18 22:51:00 +00002565 bind . <Key-Up> "selnextline -1"
2566 bind . <Key-Down> "selnextline 1"
Paul Mackerrascca5d942007-10-27 21:16:56 +10002567 bind . <Shift-Key-Up> "dofind -1 0"
2568 bind . <Shift-Key-Down> "dofind 1 0"
Rutger Nijlunsing6e5f7202006-04-05 10:24:03 +10002569 bindkey <Key-Right> "goforw"
2570 bindkey <Key-Left> "goback"
2571 bind . <Key-Prior> "selnextpage -1"
2572 bind . <Key-Next> "selnextpage 1"
Shawn O. Pearced23d98d2007-07-19 00:37:58 -04002573 bind . <$M1B-Home> "allcanvs yview moveto 0.0"
2574 bind . <$M1B-End> "allcanvs yview moveto 1.0"
2575 bind . <$M1B-Key-Up> "allcanvs yview scroll -1 units"
2576 bind . <$M1B-Key-Down> "allcanvs yview scroll 1 units"
2577 bind . <$M1B-Key-Prior> "allcanvs yview scroll -1 pages"
2578 bind . <$M1B-Key-Next> "allcanvs yview scroll 1 pages"
Paul Mackerrascfb45632005-05-31 12:14:42 +00002579 bindkey <Key-Delete> "$ctext yview scroll -1 pages"
2580 bindkey <Key-BackSpace> "$ctext yview scroll -1 pages"
2581 bindkey <Key-space> "$ctext yview scroll 1 pages"
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00002582 bindkey p "selnextline -1"
2583 bindkey n "selnextline 1"
Robert Suetterlin6e2dda32005-09-22 10:07:36 +10002584 bindkey z "goback"
2585 bindkey x "goforw"
Jonathan Nieder811c70f2011-09-19 11:49:50 -05002586 bindkey k "selnextline -1"
2587 bindkey j "selnextline 1"
2588 bindkey h "goback"
Robert Suetterlin6e2dda32005-09-22 10:07:36 +10002589 bindkey l "goforw"
Paul Mackerrasf4c54b32008-05-10 13:15:36 +10002590 bindkey b prevfile
Paul Mackerrascfb45632005-05-31 12:14:42 +00002591 bindkey d "$ctext yview scroll 18 units"
2592 bindkey u "$ctext yview scroll -18 units"
Ismael Luceno0deb5c92015-04-15 13:18:17 -03002593 bindkey g {$sha1entry delete 0 end; focus $sha1entry}
Giuseppe Bilotta97bed032008-12-02 02:19:22 +01002594 bindkey / {focus $fstring}
Michele Ballabiob6e192d2009-03-30 14:55:21 +02002595 bindkey <Key-KP_Divide> {focus $fstring}
Paul Mackerrascca5d942007-10-27 21:16:56 +10002596 bindkey <Key-Return> {dofind 1 1}
2597 bindkey ? {dofind -1 1}
Paul Mackerras39ad8572005-05-19 12:35:53 +00002598 bindkey f nextfile
Alexander Gavrilovcea07cf2008-11-09 13:00:45 +03002599 bind . <F5> updatecommits
Andrew Wongebb91db2012-10-02 11:04:45 -04002600 bindmodfunctionkey Shift 5 reloadcommits
Alexander Gavrilovcea07cf2008-11-09 13:00:45 +03002601 bind . <F2> showrefs
Andrew Wong69ecfcd2012-10-02 11:04:44 -04002602 bindmodfunctionkey Shift 4 {newview 0}
Alexander Gavrilovcea07cf2008-11-09 13:00:45 +03002603 bind . <F4> edit_or_newview
Shawn O. Pearced23d98d2007-07-19 00:37:58 -04002604 bind . <$M1B-q> doquit
Paul Mackerrascca5d942007-10-27 21:16:56 +10002605 bind . <$M1B-f> {dofind 1 1}
2606 bind . <$M1B-g> {dofind 1 0}
Shawn O. Pearced23d98d2007-07-19 00:37:58 -04002607 bind . <$M1B-r> dosearchback
2608 bind . <$M1B-s> dosearch
2609 bind . <$M1B-equal> {incrfont 1}
Johannes Schindelin646f3a12008-01-11 12:39:33 +00002610 bind . <$M1B-plus> {incrfont 1}
Shawn O. Pearced23d98d2007-07-19 00:37:58 -04002611 bind . <$M1B-KP_Add> {incrfont 1}
2612 bind . <$M1B-minus> {incrfont -1}
2613 bind . <$M1B-KP_Subtract> {incrfont -1}
Mark Levedahlb6047c52007-02-08 22:22:24 -05002614 wm protocol . WM_DELETE_WINDOW doquit
Alexander Gavrilove2f90ee2008-07-12 16:09:28 +04002615 bind . <Destroy> {stop_backends}
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00002616 bind . <Button-1> "click %W"
Paul Mackerrascca5d942007-10-27 21:16:56 +10002617 bind $fstring <Key-Return> {dofind 1 1}
Paul Mackerras968ce452008-10-16 09:57:02 +11002618 bind $sha1entry <Key-Return> {gotocommit; break}
Paul Mackerrasee3dc722005-06-25 16:37:13 +10002619 bind $sha1entry <<PasteSelection>> clearsha1
Ilya Bobyrada2ea12014-03-20 01:58:51 -07002620 bind $sha1entry <<Paste>> clearsha1
Paul Mackerras7fcceed2006-04-27 19:21:49 +10002621 bind $cflist <1> {sel_flist %W %x %y; break}
2622 bind $cflist <B1-Motion> {sel_flist %W %x %y; break}
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10002623 bind $cflist <ButtonRelease-1> {treeclick %W %x %y}
Paul Mackerrasd277e892008-09-21 18:11:37 -05002624 global ctxbut
2625 bind $cflist $ctxbut {pop_flist_menu %W %X %Y %x %y}
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04002626 bind $ctext $ctxbut {pop_diff_menu %W %X %Y %x %y}
Stefan Haller4adcbea2010-11-14 13:22:56 +01002627 bind $ctext <Button-1> {focus %W}
Stefan Hallerc4614992012-09-22 09:40:24 +02002628 bind $ctext <<Selection>> rehighlight_search_results
Max Kirillovd4ec30b2014-07-08 23:45:35 +03002629 for {set i 1} {$i < 10} {incr i} {
2630 bind . <$M1B-Key-$i> [list go_to_parent $i]
2631 }
Paul Mackerrasea13cba2005-06-16 10:54:04 +00002632
2633 set maincursor [. cget -cursor]
2634 set textcursor [$ctext cget -cursor]
Paul Mackerras94a2eed2005-08-07 15:27:57 +10002635 set curtextcursor $textcursor
Paul Mackerras84ba7342005-06-17 00:12:26 +00002636
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10002637 set rowctxmenu .rowctxmenu
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11002638 makemenu $rowctxmenu {
Paul Mackerras79056032008-10-18 16:24:46 +11002639 {mc "Diff this -> selected" command {diffvssel 0}}
2640 {mc "Diff selected -> this" command {diffvssel 1}}
2641 {mc "Make patch" command mkpatch}
2642 {mc "Create tag" command mktag}
Beat Bollid835dbb2015-07-18 13:15:39 +02002643 {mc "Copy commit summary" command copysummary}
Paul Mackerras79056032008-10-18 16:24:46 +11002644 {mc "Write commit to file" command writecommit}
2645 {mc "Create new branch" command mkbranch}
2646 {mc "Cherry-pick this commit" command cherrypick}
2647 {mc "Reset HEAD branch to here" command resethead}
Paul Mackerrasb9fdba72009-04-09 09:34:46 +10002648 {mc "Mark this commit" command markhere}
2649 {mc "Return to mark" command gotomark}
2650 {mc "Find descendant of this and mark" command find_common_desc}
Paul Mackerras010509f2009-04-09 22:10:20 +10002651 {mc "Compare with marked commit" command compare_commits}
Paul Mackerras6febded2012-03-23 22:07:27 +11002652 {mc "Diff this -> marked commit" command {diffvsmark 0}}
2653 {mc "Diff marked commit -> this" command {diffvsmark 1}}
Knut Franke8f3ff932013-04-27 16:36:13 +02002654 {mc "Revert this commit" command revert}
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11002655 }
2656 $rowctxmenu configure -tearoff 0
Paul Mackerras10299152006-08-02 09:52:01 +10002657
Paul Mackerras219ea3a2006-09-07 10:21:39 +10002658 set fakerowmenu .fakerowmenu
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11002659 makemenu $fakerowmenu {
Paul Mackerras79056032008-10-18 16:24:46 +11002660 {mc "Diff this -> selected" command {diffvssel 0}}
2661 {mc "Diff selected -> this" command {diffvssel 1}}
2662 {mc "Make patch" command mkpatch}
Paul Mackerras6febded2012-03-23 22:07:27 +11002663 {mc "Diff this -> marked commit" command {diffvsmark 0}}
2664 {mc "Diff marked commit -> this" command {diffvsmark 1}}
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11002665 }
2666 $fakerowmenu configure -tearoff 0
Paul Mackerras219ea3a2006-09-07 10:21:39 +10002667
Paul Mackerras10299152006-08-02 09:52:01 +10002668 set headctxmenu .headctxmenu
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11002669 makemenu $headctxmenu {
Paul Mackerras79056032008-10-18 16:24:46 +11002670 {mc "Check out this branch" command cobranch}
Rogier Goossens5a046c52016-03-19 19:32:16 +01002671 {mc "Rename this branch" command mvbranch}
Paul Mackerras79056032008-10-18 16:24:46 +11002672 {mc "Remove this branch" command rmbranch}
Michael Rappazzo427cf162015-05-07 22:29:20 -04002673 {mc "Copy branch name" command {clipboard clear; clipboard append $headmenuhead}}
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11002674 }
2675 $headctxmenu configure -tearoff 0
Paul Mackerras32447292007-07-27 22:30:15 +10002676
2677 global flist_menu
2678 set flist_menu .flistctxmenu
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11002679 makemenu $flist_menu {
Paul Mackerras79056032008-10-18 16:24:46 +11002680 {mc "Highlight this too" command {flist_hl 0}}
2681 {mc "Highlight this only" command {flist_hl 1}}
2682 {mc "External diff" command {external_diff}}
2683 {mc "Blame parent commit" command {external_blame 1}}
Michael Rappazzo427cf162015-05-07 22:29:20 -04002684 {mc "Copy path" command {clipboard clear; clipboard append $flist_menu_file}}
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11002685 }
2686 $flist_menu configure -tearoff 0
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04002687
2688 global diff_menu
2689 set diff_menu .diffctxmenu
2690 makemenu $diff_menu {
Paul Mackerras8a897742008-10-27 21:36:25 +11002691 {mc "Show origin of this line" command show_line_source}
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04002692 {mc "Run git gui blame on this line" command {external_blame_diff}}
2693 }
2694 $diff_menu configure -tearoff 0
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00002695}
2696
Mark Levedahl314c3092007-08-07 21:40:35 -04002697# Windows sends all mouse wheel events to the current focused window, not
2698# the one where the mouse hovers, so bind those events here and redirect
2699# to the correct window
2700proc windows_mousewheel_redirector {W X Y D} {
2701 global canv canv2 canv3
2702 set w [winfo containing -displayof $W $X $Y]
2703 if {$w ne ""} {
2704 set u [expr {$D < 0 ? 5 : -5}]
2705 if {$w == $canv || $w == $canv2 || $w == $canv3} {
2706 allcanvs yview scroll $u units
2707 } else {
2708 catch {
2709 $w yview scroll $u units
2710 }
2711 }
2712 }
2713}
2714
Paul Mackerras6df74032008-05-11 22:13:02 +10002715# Update row number label when selectedline changes
2716proc selectedline_change {n1 n2 op} {
2717 global selectedline rownumsel
2718
Paul Mackerras94b4a692008-05-20 20:51:06 +10002719 if {$selectedline eq {}} {
Paul Mackerras6df74032008-05-11 22:13:02 +10002720 set rownumsel {}
2721 } else {
2722 set rownumsel [expr {$selectedline + 1}]
2723 }
2724}
2725
Paul Mackerrasbe0cd092006-03-31 09:55:11 +11002726# mouse-2 makes all windows scan vertically, but only the one
2727# the cursor is in scans horizontally
2728proc canvscan {op w x y} {
2729 global canv canv2 canv3
2730 foreach c [list $canv $canv2 $canv3] {
2731 if {$c == $w} {
2732 $c scan $op $x $y
2733 } else {
2734 $c scan $op 0 $y
2735 }
2736 }
2737}
2738
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002739proc scrollcanv {cscroll f0 f1} {
2740 $cscroll set $f0 $f1
Paul Mackerras31c0eaa2007-12-30 22:41:14 +11002741 drawvisible
Paul Mackerras908c3582006-05-20 09:38:11 +10002742 flushhighlights
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002743}
2744
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00002745# when we make a key binding for the toplevel, make sure
2746# it doesn't get triggered when that key is pressed in the
2747# find string entry widget.
2748proc bindkey {ev script} {
Paul Mackerras887fe3c2005-05-21 07:35:37 +00002749 global entries
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00002750 bind . $ev $script
2751 set escript [bind Entry $ev]
2752 if {$escript == {}} {
2753 set escript [bind Entry <Key>]
2754 }
Paul Mackerras887fe3c2005-05-21 07:35:37 +00002755 foreach e $entries {
2756 bind $e $ev "$escript; break"
2757 }
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00002758}
2759
Andrew Wong69ecfcd2012-10-02 11:04:44 -04002760proc bindmodfunctionkey {mod n script} {
2761 bind . <$mod-F$n> $script
2762 catch { bind . <$mod-XF86_Switch_VT_$n> $script }
2763}
2764
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00002765# set the focus back to the toplevel for any click outside
Paul Mackerras887fe3c2005-05-21 07:35:37 +00002766# the entry widgets
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00002767proc click {w} {
Mark Levedahlbd441de2007-08-07 21:40:34 -04002768 global ctext entries
2769 foreach e [concat $entries $ctext] {
Paul Mackerras887fe3c2005-05-21 07:35:37 +00002770 if {$w == $e} return
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00002771 }
Paul Mackerras887fe3c2005-05-21 07:35:37 +00002772 focus .
Paul Mackerras0fba86b2005-05-16 23:54:58 +00002773}
2774
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10002775# Adjust the progress bar for a change in requested extent or canvas size
2776proc adjustprogress {} {
2777 global progresscanv progressitem progresscoords
2778 global fprogitem fprogcoord lastprogupdate progupdatepending
Pat Thoytsd93f1712009-04-17 01:24:35 +01002779 global rprogitem rprogcoord use_ttk
2780
2781 if {$use_ttk} {
2782 $progresscanv configure -value [expr {int($fprogcoord * 100)}]
2783 return
2784 }
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10002785
2786 set w [expr {[winfo width $progresscanv] - 4}]
2787 set x0 [expr {$w * [lindex $progresscoords 0]}]
2788 set x1 [expr {$w * [lindex $progresscoords 1]}]
2789 set h [winfo height $progresscanv]
2790 $progresscanv coords $progressitem $x0 0 $x1 $h
2791 $progresscanv coords $fprogitem 0 0 [expr {$w * $fprogcoord}] $h
Paul Mackerrasa137a902007-10-23 21:12:49 +10002792 $progresscanv coords $rprogitem 0 0 [expr {$w * $rprogcoord}] $h
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10002793 set now [clock clicks -milliseconds]
2794 if {$now >= $lastprogupdate + 100} {
2795 set progupdatepending 0
2796 update
2797 } elseif {!$progupdatepending} {
2798 set progupdatepending 1
2799 after [expr {$lastprogupdate + 100 - $now}] doprogupdate
2800 }
2801}
2802
2803proc doprogupdate {} {
2804 global lastprogupdate progupdatepending
2805
2806 if {$progupdatepending} {
2807 set progupdatepending 0
2808 set lastprogupdate [clock clicks -milliseconds]
2809 update
2810 }
2811}
2812
Max Kirilloveaf7e832015-03-04 05:58:18 +02002813proc config_check_tmp_exists {tries_left} {
2814 global config_file_tmp
2815
2816 if {[file exists $config_file_tmp]} {
2817 incr tries_left -1
2818 if {$tries_left > 0} {
2819 after 100 [list config_check_tmp_exists $tries_left]
2820 } else {
2821 error_popup "There appears to be a stale $config_file_tmp\
2822 file, which will prevent gitk from saving its configuration on exit.\
2823 Please remove it if it is not being used by any existing gitk process."
2824 }
2825 }
2826}
2827
Max Kirillov995f7922015-03-04 05:58:16 +02002828proc config_init_trace {name} {
2829 global config_variable_changed config_variable_original
2830
2831 upvar #0 $name var
2832 set config_variable_changed($name) 0
2833 set config_variable_original($name) $var
2834}
2835
2836proc config_variable_change_cb {name name2 op} {
2837 global config_variable_changed config_variable_original
2838
2839 upvar #0 $name var
2840 if {$op eq "write" &&
2841 (![info exists config_variable_original($name)] ||
2842 $config_variable_original($name) ne $var)} {
2843 set config_variable_changed($name) 1
2844 }
2845}
2846
Paul Mackerras0fba86b2005-05-16 23:54:58 +00002847proc savestuff {w} {
Max Kirillov9fabefb2014-09-14 23:35:57 +03002848 global stuffsaved
Astril Hayato8f863392014-01-21 19:10:16 +00002849 global config_file config_file_tmp
Max Kirillov995f7922015-03-04 05:58:16 +02002850 global config_variables config_variable_changed
2851 global viewchanged
2852
2853 upvar #0 viewname current_viewname
2854 upvar #0 viewfiles current_viewfiles
2855 upvar #0 viewargs current_viewargs
2856 upvar #0 viewargscmd current_viewargscmd
2857 upvar #0 viewperm current_viewperm
2858 upvar #0 nextviewnum current_nextviewnum
2859 upvar #0 use_ttk current_use_ttk
Paul Mackerras4ef17532005-07-27 22:16:51 -05002860
Paul Mackerras0fba86b2005-05-16 23:54:58 +00002861 if {$stuffsaved} return
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00002862 if {![winfo viewable .]} return
Max Kirilloveaf7e832015-03-04 05:58:18 +02002863 set remove_tmp 0
Max Kirillov1dd29602015-03-04 05:58:17 +02002864 if {[catch {
Max Kirilloveaf7e832015-03-04 05:58:18 +02002865 set try_count 0
2866 while {[catch {set f [open $config_file_tmp {WRONLY CREAT EXCL}]}]} {
2867 if {[incr try_count] > 50} {
2868 error "Unable to write config file: $config_file_tmp exists"
2869 }
2870 after 100
Astril Hayato8f863392014-01-21 19:10:16 +00002871 }
Max Kirilloveaf7e832015-03-04 05:58:18 +02002872 set remove_tmp 1
Paul Mackerras9832e4f2009-03-23 21:37:51 +11002873 if {$::tcl_platform(platform) eq {windows}} {
Astril Hayato8f863392014-01-21 19:10:16 +00002874 file attributes $config_file_tmp -hidden true
Paul Mackerras9832e4f2009-03-23 21:37:51 +11002875 }
Max Kirillov995f7922015-03-04 05:58:16 +02002876 if {[file exists $config_file]} {
2877 source $config_file
2878 }
Max Kirillov9fabefb2014-09-14 23:35:57 +03002879 foreach var_name $config_variables {
2880 upvar #0 $var_name var
Max Kirillov995f7922015-03-04 05:58:16 +02002881 upvar 0 $var_name old_var
2882 if {!$config_variable_changed($var_name) && [info exists old_var]} {
2883 puts $f [list set $var_name $old_var]
2884 } else {
2885 puts $f [list set $var_name $var]
2886 }
Max Kirillov9fabefb2014-09-14 23:35:57 +03002887 }
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002888
Mark Levedahlb6047c52007-02-08 22:22:24 -05002889 puts $f "set geometry(main) [wm geometry .]"
Pat Thoytsc876dba2009-04-14 22:09:53 +01002890 puts $f "set geometry(state) [wm state .]"
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002891 puts $f "set geometry(topwidth) [winfo width .tf]"
2892 puts $f "set geometry(topheight) [winfo height .tf]"
Max Kirillov995f7922015-03-04 05:58:16 +02002893 if {$current_use_ttk} {
Pat Thoytsd93f1712009-04-17 01:24:35 +01002894 puts $f "set geometry(pwsash0) \"[.tf.histframe.pwclist sashpos 0] 1\""
2895 puts $f "set geometry(pwsash1) \"[.tf.histframe.pwclist sashpos 1] 1\""
2896 } else {
2897 puts $f "set geometry(pwsash0) \"[.tf.histframe.pwclist sash coord 0]\""
2898 puts $f "set geometry(pwsash1) \"[.tf.histframe.pwclist sash coord 1]\""
2899 }
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002900 puts $f "set geometry(botwidth) [winfo width .bleft]"
2901 puts $f "set geometry(botheight) [winfo height .bleft]"
2902
Max Kirillov995f7922015-03-04 05:58:16 +02002903 array set view_save {}
2904 array set views {}
2905 if {![info exists permviews]} { set permviews {} }
2906 foreach view $permviews {
2907 set view_save([lindex $view 0]) 1
2908 set views([lindex $view 0]) $view
2909 }
Paul Mackerrasa90a6d22006-04-25 17:12:46 +10002910 puts -nonewline $f "set permviews {"
Max Kirillov995f7922015-03-04 05:58:16 +02002911 for {set v 1} {$v < $current_nextviewnum} {incr v} {
2912 if {$viewchanged($v)} {
2913 if {$current_viewperm($v)} {
2914 set views($current_viewname($v)) [list $current_viewname($v) $current_viewfiles($v) $current_viewargs($v) $current_viewargscmd($v)]
2915 } else {
2916 set view_save($current_viewname($v)) 0
2917 }
Paul Mackerrasa90a6d22006-04-25 17:12:46 +10002918 }
2919 }
Max Kirillov995f7922015-03-04 05:58:16 +02002920 # write old and updated view to their places and append remaining to the end
2921 foreach view $permviews {
2922 set view_name [lindex $view 0]
2923 if {$view_save($view_name)} {
2924 puts $f "{$views($view_name)}"
2925 }
2926 unset views($view_name)
2927 }
2928 foreach view_name [array names views] {
2929 puts $f "{$views($view_name)}"
2930 }
Paul Mackerrasa90a6d22006-04-25 17:12:46 +10002931 puts $f "}"
Paul Mackerras0fba86b2005-05-16 23:54:58 +00002932 close $f
Astril Hayato8f863392014-01-21 19:10:16 +00002933 file rename -force $config_file_tmp $config_file
Max Kirilloveaf7e832015-03-04 05:58:18 +02002934 set remove_tmp 0
Max Kirillov1dd29602015-03-04 05:58:17 +02002935 } err]} {
2936 puts "Error saving config: $err"
Paul Mackerras0fba86b2005-05-16 23:54:58 +00002937 }
Max Kirilloveaf7e832015-03-04 05:58:18 +02002938 if {$remove_tmp} {
2939 file delete -force $config_file_tmp
2940 }
Paul Mackerras0fba86b2005-05-16 23:54:58 +00002941 set stuffsaved 1
Paul Mackerras1db95b02005-05-09 04:08:39 +00002942}
2943
Paul Mackerras43bddeb2005-05-15 23:19:18 +00002944proc resizeclistpanes {win w} {
Pat Thoytsd93f1712009-04-17 01:24:35 +01002945 global oldwidth use_ttk
Paul Mackerras418c4c72006-02-07 09:10:18 +11002946 if {[info exists oldwidth($win)]} {
Pat Thoytsd93f1712009-04-17 01:24:35 +01002947 if {$use_ttk} {
2948 set s0 [$win sashpos 0]
2949 set s1 [$win sashpos 1]
2950 } else {
2951 set s0 [$win sash coord 0]
2952 set s1 [$win sash coord 1]
2953 }
Paul Mackerras43bddeb2005-05-15 23:19:18 +00002954 if {$w < 60} {
2955 set sash0 [expr {int($w/2 - 2)}]
2956 set sash1 [expr {int($w*5/6 - 2)}]
2957 } else {
2958 set factor [expr {1.0 * $w / $oldwidth($win)}]
2959 set sash0 [expr {int($factor * [lindex $s0 0])}]
2960 set sash1 [expr {int($factor * [lindex $s1 0])}]
2961 if {$sash0 < 30} {
2962 set sash0 30
2963 }
2964 if {$sash1 < $sash0 + 20} {
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08002965 set sash1 [expr {$sash0 + 20}]
Paul Mackerras43bddeb2005-05-15 23:19:18 +00002966 }
2967 if {$sash1 > $w - 10} {
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08002968 set sash1 [expr {$w - 10}]
Paul Mackerras43bddeb2005-05-15 23:19:18 +00002969 if {$sash0 > $sash1 - 20} {
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08002970 set sash0 [expr {$sash1 - 20}]
Paul Mackerras43bddeb2005-05-15 23:19:18 +00002971 }
2972 }
2973 }
Pat Thoytsd93f1712009-04-17 01:24:35 +01002974 if {$use_ttk} {
2975 $win sashpos 0 $sash0
2976 $win sashpos 1 $sash1
2977 } else {
2978 $win sash place 0 $sash0 [lindex $s0 1]
2979 $win sash place 1 $sash1 [lindex $s1 1]
2980 }
Paul Mackerras43bddeb2005-05-15 23:19:18 +00002981 }
2982 set oldwidth($win) $w
2983}
2984
2985proc resizecdetpanes {win w} {
Pat Thoytsd93f1712009-04-17 01:24:35 +01002986 global oldwidth use_ttk
Paul Mackerras418c4c72006-02-07 09:10:18 +11002987 if {[info exists oldwidth($win)]} {
Pat Thoytsd93f1712009-04-17 01:24:35 +01002988 if {$use_ttk} {
2989 set s0 [$win sashpos 0]
2990 } else {
2991 set s0 [$win sash coord 0]
2992 }
Paul Mackerras43bddeb2005-05-15 23:19:18 +00002993 if {$w < 60} {
2994 set sash0 [expr {int($w*3/4 - 2)}]
2995 } else {
2996 set factor [expr {1.0 * $w / $oldwidth($win)}]
2997 set sash0 [expr {int($factor * [lindex $s0 0])}]
2998 if {$sash0 < 45} {
2999 set sash0 45
3000 }
3001 if {$sash0 > $w - 15} {
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08003002 set sash0 [expr {$w - 15}]
Paul Mackerras43bddeb2005-05-15 23:19:18 +00003003 }
3004 }
Pat Thoytsd93f1712009-04-17 01:24:35 +01003005 if {$use_ttk} {
3006 $win sashpos 0 $sash0
3007 } else {
3008 $win sash place 0 $sash0 [lindex $s0 1]
3009 }
Paul Mackerras43bddeb2005-05-15 23:19:18 +00003010 }
3011 set oldwidth($win) $w
3012}
3013
Paul Mackerrasb5721c72005-05-10 12:08:22 +00003014proc allcanvs args {
3015 global canv canv2 canv3
3016 eval $canv $args
3017 eval $canv2 $args
3018 eval $canv3 $args
3019}
3020
3021proc bindall {event action} {
3022 global canv canv2 canv3
3023 bind $canv $event $action
3024 bind $canv2 $event $action
3025 bind $canv3 $event $action
3026}
3027
Paul Mackerras9a40c502005-05-12 23:46:16 +00003028proc about {} {
Guillermo S. Romero22a713c2016-02-04 03:32:19 +01003029 global bgcolor NS
Paul Mackerras9a40c502005-05-12 23:46:16 +00003030 set w .about
3031 if {[winfo exists $w]} {
3032 raise $w
3033 return
3034 }
Pat Thoytsd93f1712009-04-17 01:24:35 +01003035 ttk_toplevel $w
Christian Stimmingd990ced2007-11-07 18:42:55 +01003036 wm title $w [mc "About gitk"]
Alexander Gavrilove7d64002008-11-11 23:55:42 +03003037 make_transient $w .
Christian Stimmingd990ced2007-11-07 18:42:55 +01003038 message $w.m -text [mc "
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003039Gitk - a commit viewer for git
Paul Mackerras9a40c502005-05-12 23:46:16 +00003040
Paul Mackerrasfbf42642016-12-12 20:46:42 +11003041Copyright \u00a9 2005-2016 Paul Mackerras
Paul Mackerras9a40c502005-05-12 23:46:16 +00003042
Christian Stimmingd990ced2007-11-07 18:42:55 +01003043Use and redistribute under the terms of the GNU General Public License"] \
Guillermo S. Romero22a713c2016-02-04 03:32:19 +01003044 -justify center -aspect 400 -border 2 -bg $bgcolor -relief groove
Eygene Ryabinkin3a950e92007-03-27 14:36:59 +04003045 pack $w.m -side top -fill x -padx 2 -pady 2
Pat Thoytsd93f1712009-04-17 01:24:35 +01003046 ${NS}::button $w.ok -text [mc "Close"] -command "destroy $w" -default active
Paul Mackerras9a40c502005-05-12 23:46:16 +00003047 pack $w.ok -side bottom
Eygene Ryabinkin3a950e92007-03-27 14:36:59 +04003048 bind $w <Visibility> "focus $w.ok"
3049 bind $w <Key-Escape> "destroy $w"
3050 bind $w <Key-Return> "destroy $w"
Pat Thoytsd93f1712009-04-17 01:24:35 +01003051 tk::PlaceWindow $w widget .
Paul Mackerras9a40c502005-05-12 23:46:16 +00003052}
3053
Paul Mackerras4e95e1f2006-04-05 09:39:51 +10003054proc keys {} {
Guillermo S. Romero22a713c2016-02-04 03:32:19 +01003055 global bgcolor NS
Paul Mackerras4e95e1f2006-04-05 09:39:51 +10003056 set w .keys
3057 if {[winfo exists $w]} {
3058 raise $w
3059 return
3060 }
Shawn O. Pearced23d98d2007-07-19 00:37:58 -04003061 if {[tk windowingsystem] eq {aqua}} {
3062 set M1T Cmd
3063 } else {
3064 set M1T Ctrl
3065 }
Pat Thoytsd93f1712009-04-17 01:24:35 +01003066 ttk_toplevel $w
Christian Stimmingd990ced2007-11-07 18:42:55 +01003067 wm title $w [mc "Gitk key bindings"]
Alexander Gavrilove7d64002008-11-11 23:55:42 +03003068 make_transient $w .
Michele Ballabio3d2c9982008-01-15 23:31:49 +01003069 message $w.m -text "
3070[mc "Gitk key bindings:"]
Paul Mackerras4e95e1f2006-04-05 09:39:51 +10003071
Michele Ballabio3d2c9982008-01-15 23:31:49 +01003072[mc "<%s-Q> Quit" $M1T]
Jens Lehmanndecd0a12010-02-02 23:11:28 +01003073[mc "<%s-W> Close window" $M1T]
Michele Ballabio3d2c9982008-01-15 23:31:49 +01003074[mc "<Home> Move to first commit"]
3075[mc "<End> Move to last commit"]
Jonathan Nieder811c70f2011-09-19 11:49:50 -05003076[mc "<Up>, p, k Move up one commit"]
3077[mc "<Down>, n, j Move down one commit"]
3078[mc "<Left>, z, h Go back in history list"]
Michele Ballabio3d2c9982008-01-15 23:31:49 +01003079[mc "<Right>, x, l Go forward in history list"]
Max Kirillovd4ec30b2014-07-08 23:45:35 +03003080[mc "<%s-n> Go to n-th parent of current commit in history list" $M1T]
Michele Ballabio3d2c9982008-01-15 23:31:49 +01003081[mc "<PageUp> Move up one page in commit list"]
3082[mc "<PageDown> Move down one page in commit list"]
3083[mc "<%s-Home> Scroll to top of commit list" $M1T]
3084[mc "<%s-End> Scroll to bottom of commit list" $M1T]
3085[mc "<%s-Up> Scroll commit list up one line" $M1T]
3086[mc "<%s-Down> Scroll commit list down one line" $M1T]
3087[mc "<%s-PageUp> Scroll commit list up one page" $M1T]
3088[mc "<%s-PageDown> Scroll commit list down one page" $M1T]
3089[mc "<Shift-Up> Find backwards (upwards, later commits)"]
3090[mc "<Shift-Down> Find forwards (downwards, earlier commits)"]
3091[mc "<Delete>, b Scroll diff view up one page"]
3092[mc "<Backspace> Scroll diff view up one page"]
3093[mc "<Space> Scroll diff view down one page"]
3094[mc "u Scroll diff view up 18 lines"]
3095[mc "d Scroll diff view down 18 lines"]
3096[mc "<%s-F> Find" $M1T]
3097[mc "<%s-G> Move to next find hit" $M1T]
3098[mc "<Return> Move to next find hit"]
Ismael Luceno0deb5c92015-04-15 13:18:17 -03003099[mc "g Go to commit"]
Giuseppe Bilotta97bed032008-12-02 02:19:22 +01003100[mc "/ Focus the search box"]
Michele Ballabio3d2c9982008-01-15 23:31:49 +01003101[mc "? Move to previous find hit"]
3102[mc "f Scroll diff view to next file"]
3103[mc "<%s-S> Search for next hit in diff view" $M1T]
3104[mc "<%s-R> Search for previous hit in diff view" $M1T]
3105[mc "<%s-KP+> Increase font size" $M1T]
3106[mc "<%s-plus> Increase font size" $M1T]
3107[mc "<%s-KP-> Decrease font size" $M1T]
3108[mc "<%s-minus> Decrease font size" $M1T]
3109[mc "<F5> Update"]
3110" \
Guillermo S. Romero22a713c2016-02-04 03:32:19 +01003111 -justify left -bg $bgcolor -border 2 -relief groove
Eygene Ryabinkin3a950e92007-03-27 14:36:59 +04003112 pack $w.m -side top -fill both -padx 2 -pady 2
Pat Thoytsd93f1712009-04-17 01:24:35 +01003113 ${NS}::button $w.ok -text [mc "Close"] -command "destroy $w" -default active
Alexander Gavrilov76f15942008-11-02 21:59:44 +03003114 bind $w <Key-Escape> [list destroy $w]
Paul Mackerras4e95e1f2006-04-05 09:39:51 +10003115 pack $w.ok -side bottom
Eygene Ryabinkin3a950e92007-03-27 14:36:59 +04003116 bind $w <Visibility> "focus $w.ok"
3117 bind $w <Key-Escape> "destroy $w"
3118 bind $w <Key-Return> "destroy $w"
Paul Mackerras4e95e1f2006-04-05 09:39:51 +10003119}
3120
Paul Mackerras7fcceed2006-04-27 19:21:49 +10003121# Procedures for manipulating the file list window at the
3122# bottom right of the overall window.
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10003123
3124proc treeview {w l openlevs} {
3125 global treecontents treediropen treeheight treeparent treeindex
3126
3127 set ix 0
3128 set treeindex() 0
3129 set lev 0
3130 set prefix {}
3131 set prefixend -1
3132 set prefendstack {}
3133 set htstack {}
3134 set ht 0
3135 set treecontents() {}
3136 $w conf -state normal
3137 foreach f $l {
3138 while {[string range $f 0 $prefixend] ne $prefix} {
3139 if {$lev <= $openlevs} {
3140 $w mark set e:$treeindex($prefix) "end -1c"
3141 $w mark gravity e:$treeindex($prefix) left
3142 }
3143 set treeheight($prefix) $ht
3144 incr ht [lindex $htstack end]
3145 set htstack [lreplace $htstack end end]
3146 set prefixend [lindex $prefendstack end]
3147 set prefendstack [lreplace $prefendstack end end]
3148 set prefix [string range $prefix 0 $prefixend]
3149 incr lev -1
3150 }
3151 set tail [string range $f [expr {$prefixend+1}] end]
3152 while {[set slash [string first "/" $tail]] >= 0} {
3153 lappend htstack $ht
3154 set ht 0
3155 lappend prefendstack $prefixend
3156 incr prefixend [expr {$slash + 1}]
3157 set d [string range $tail 0 $slash]
3158 lappend treecontents($prefix) $d
3159 set oldprefix $prefix
3160 append prefix $d
3161 set treecontents($prefix) {}
3162 set treeindex($prefix) [incr ix]
3163 set treeparent($prefix) $oldprefix
3164 set tail [string range $tail [expr {$slash+1}] end]
3165 if {$lev <= $openlevs} {
3166 set ht 1
3167 set treediropen($prefix) [expr {$lev < $openlevs}]
3168 set bm [expr {$lev == $openlevs? "tri-rt": "tri-dn"}]
3169 $w mark set d:$ix "end -1c"
3170 $w mark gravity d:$ix left
3171 set str "\n"
3172 for {set i 0} {$i < $lev} {incr i} {append str "\t"}
3173 $w insert end $str
3174 $w image create end -align center -image $bm -padx 1 \
3175 -name a:$ix
Paul Mackerras45a9d502006-05-20 22:56:27 +10003176 $w insert end $d [highlight_tag $prefix]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10003177 $w mark set s:$ix "end -1c"
3178 $w mark gravity s:$ix left
3179 }
3180 incr lev
3181 }
3182 if {$tail ne {}} {
3183 if {$lev <= $openlevs} {
3184 incr ht
3185 set str "\n"
3186 for {set i 0} {$i < $lev} {incr i} {append str "\t"}
3187 $w insert end $str
Paul Mackerras45a9d502006-05-20 22:56:27 +10003188 $w insert end $tail [highlight_tag $f]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10003189 }
3190 lappend treecontents($prefix) $tail
3191 }
3192 }
3193 while {$htstack ne {}} {
3194 set treeheight($prefix) $ht
3195 incr ht [lindex $htstack end]
3196 set htstack [lreplace $htstack end end]
Brian Downing096e96b2007-07-05 06:33:02 -05003197 set prefixend [lindex $prefendstack end]
3198 set prefendstack [lreplace $prefendstack end end]
3199 set prefix [string range $prefix 0 $prefixend]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10003200 }
3201 $w conf -state disabled
3202}
3203
3204proc linetoelt {l} {
3205 global treeheight treecontents
3206
3207 set y 2
3208 set prefix {}
3209 while {1} {
3210 foreach e $treecontents($prefix) {
3211 if {$y == $l} {
3212 return "$prefix$e"
3213 }
3214 set n 1
3215 if {[string index $e end] eq "/"} {
3216 set n $treeheight($prefix$e)
3217 if {$y + $n > $l} {
3218 append prefix $e
3219 incr y
3220 break
3221 }
3222 }
3223 incr y $n
3224 }
3225 }
3226}
3227
Paul Mackerras45a9d502006-05-20 22:56:27 +10003228proc highlight_tree {y prefix} {
3229 global treeheight treecontents cflist
3230
3231 foreach e $treecontents($prefix) {
3232 set path $prefix$e
3233 if {[highlight_tag $path] ne {}} {
3234 $cflist tag add bold $y.0 "$y.0 lineend"
3235 }
3236 incr y
3237 if {[string index $e end] eq "/" && $treeheight($path) > 1} {
3238 set y [highlight_tree $y $path]
3239 }
3240 }
3241 return $y
3242}
3243
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10003244proc treeclosedir {w dir} {
3245 global treediropen treeheight treeparent treeindex
3246
3247 set ix $treeindex($dir)
3248 $w conf -state normal
3249 $w delete s:$ix e:$ix
3250 set treediropen($dir) 0
3251 $w image configure a:$ix -image tri-rt
3252 $w conf -state disabled
3253 set n [expr {1 - $treeheight($dir)}]
3254 while {$dir ne {}} {
3255 incr treeheight($dir) $n
3256 set dir $treeparent($dir)
3257 }
3258}
3259
3260proc treeopendir {w dir} {
3261 global treediropen treeheight treeparent treecontents treeindex
3262
3263 set ix $treeindex($dir)
3264 $w conf -state normal
3265 $w image configure a:$ix -image tri-dn
3266 $w mark set e:$ix s:$ix
3267 $w mark gravity e:$ix right
3268 set lev 0
3269 set str "\n"
3270 set n [llength $treecontents($dir)]
3271 for {set x $dir} {$x ne {}} {set x $treeparent($x)} {
3272 incr lev
3273 append str "\t"
3274 incr treeheight($x) $n
3275 }
3276 foreach e $treecontents($dir) {
Paul Mackerras45a9d502006-05-20 22:56:27 +10003277 set de $dir$e
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10003278 if {[string index $e end] eq "/"} {
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10003279 set iy $treeindex($de)
3280 $w mark set d:$iy e:$ix
3281 $w mark gravity d:$iy left
3282 $w insert e:$ix $str
3283 set treediropen($de) 0
3284 $w image create e:$ix -align center -image tri-rt -padx 1 \
3285 -name a:$iy
Paul Mackerras45a9d502006-05-20 22:56:27 +10003286 $w insert e:$ix $e [highlight_tag $de]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10003287 $w mark set s:$iy e:$ix
3288 $w mark gravity s:$iy left
3289 set treeheight($de) 1
3290 } else {
3291 $w insert e:$ix $str
Paul Mackerras45a9d502006-05-20 22:56:27 +10003292 $w insert e:$ix $e [highlight_tag $de]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10003293 }
3294 }
Alexander Gavrilovb8a640e2008-09-08 11:28:16 +04003295 $w mark gravity e:$ix right
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10003296 $w conf -state disabled
3297 set treediropen($dir) 1
3298 set top [lindex [split [$w index @0,0] .] 0]
3299 set ht [$w cget -height]
3300 set l [lindex [split [$w index s:$ix] .] 0]
3301 if {$l < $top} {
3302 $w yview $l.0
3303 } elseif {$l + $n + 1 > $top + $ht} {
3304 set top [expr {$l + $n + 2 - $ht}]
3305 if {$l < $top} {
3306 set top $l
3307 }
3308 $w yview $top.0
3309 }
3310}
3311
3312proc treeclick {w x y} {
3313 global treediropen cmitmode ctext cflist cflist_top
3314
3315 if {$cmitmode ne "tree"} return
3316 if {![info exists cflist_top]} return
3317 set l [lindex [split [$w index "@$x,$y"] "."] 0]
3318 $cflist tag remove highlight $cflist_top.0 "$cflist_top.0 lineend"
3319 $cflist tag add highlight $l.0 "$l.0 lineend"
3320 set cflist_top $l
3321 if {$l == 1} {
3322 $ctext yview 1.0
3323 return
3324 }
3325 set e [linetoelt $l]
3326 if {[string index $e end] ne "/"} {
3327 showfile $e
3328 } elseif {$treediropen($e)} {
3329 treeclosedir $w $e
3330 } else {
3331 treeopendir $w $e
3332 }
3333}
3334
3335proc setfilelist {id} {
Paul Mackerras8a897742008-10-27 21:36:25 +11003336 global treefilelist cflist jump_to_here
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10003337
3338 treeview $cflist $treefilelist($id) 0
Paul Mackerras8a897742008-10-27 21:36:25 +11003339 if {$jump_to_here ne {}} {
3340 set f [lindex $jump_to_here 0]
3341 if {[lsearch -exact $treefilelist($id) $f] >= 0} {
3342 showfile $f
3343 }
3344 }
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10003345}
3346
3347image create bitmap tri-rt -background black -foreground blue -data {
3348 #define tri-rt_width 13
3349 #define tri-rt_height 13
3350 static unsigned char tri-rt_bits[] = {
3351 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x30, 0x00, 0x70, 0x00, 0xf0, 0x00,
3352 0xf0, 0x01, 0xf0, 0x00, 0x70, 0x00, 0x30, 0x00, 0x10, 0x00, 0x00, 0x00,
3353 0x00, 0x00};
3354} -maskdata {
3355 #define tri-rt-mask_width 13
3356 #define tri-rt-mask_height 13
3357 static unsigned char tri-rt-mask_bits[] = {
3358 0x08, 0x00, 0x18, 0x00, 0x38, 0x00, 0x78, 0x00, 0xf8, 0x00, 0xf8, 0x01,
3359 0xf8, 0x03, 0xf8, 0x01, 0xf8, 0x00, 0x78, 0x00, 0x38, 0x00, 0x18, 0x00,
3360 0x08, 0x00};
3361}
3362image create bitmap tri-dn -background black -foreground blue -data {
3363 #define tri-dn_width 13
3364 #define tri-dn_height 13
3365 static unsigned char tri-dn_bits[] = {
3366 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x07, 0xf8, 0x03,
3367 0xf0, 0x01, 0xe0, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3368 0x00, 0x00};
3369} -maskdata {
3370 #define tri-dn-mask_width 13
3371 #define tri-dn-mask_height 13
3372 static unsigned char tri-dn-mask_bits[] = {
3373 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x1f, 0xfe, 0x0f, 0xfc, 0x07,
3374 0xf8, 0x03, 0xf0, 0x01, 0xe0, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00,
3375 0x00, 0x00};
3376}
3377
Paul Mackerras887c9962007-08-20 19:36:20 +10003378image create bitmap reficon-T -background black -foreground yellow -data {
3379 #define tagicon_width 13
3380 #define tagicon_height 9
3381 static unsigned char tagicon_bits[] = {
3382 0x00, 0x00, 0x00, 0x00, 0xf0, 0x07, 0xf8, 0x07,
3383 0xfc, 0x07, 0xf8, 0x07, 0xf0, 0x07, 0x00, 0x00, 0x00, 0x00};
3384} -maskdata {
3385 #define tagicon-mask_width 13
3386 #define tagicon-mask_height 9
3387 static unsigned char tagicon-mask_bits[] = {
3388 0x00, 0x00, 0xf0, 0x0f, 0xf8, 0x0f, 0xfc, 0x0f,
3389 0xfe, 0x0f, 0xfc, 0x0f, 0xf8, 0x0f, 0xf0, 0x0f, 0x00, 0x00};
3390}
3391set rectdata {
3392 #define headicon_width 13
3393 #define headicon_height 9
3394 static unsigned char headicon_bits[] = {
3395 0x00, 0x00, 0x00, 0x00, 0xf8, 0x07, 0xf8, 0x07,
3396 0xf8, 0x07, 0xf8, 0x07, 0xf8, 0x07, 0x00, 0x00, 0x00, 0x00};
3397}
3398set rectmask {
3399 #define headicon-mask_width 13
3400 #define headicon-mask_height 9
3401 static unsigned char headicon-mask_bits[] = {
3402 0x00, 0x00, 0xfc, 0x0f, 0xfc, 0x0f, 0xfc, 0x0f,
3403 0xfc, 0x0f, 0xfc, 0x0f, 0xfc, 0x0f, 0xfc, 0x0f, 0x00, 0x00};
3404}
Paul Mackerras6e8fda52016-12-12 11:29:21 +11003405image create bitmap reficon-H -background black -foreground "#00ff00" \
Paul Mackerras887c9962007-08-20 19:36:20 +10003406 -data $rectdata -maskdata $rectmask
Paul Wised7cc4fb2019-03-21 15:05:32 +08003407image create bitmap reficon-R -background black -foreground "#ffddaa" \
3408 -data $rectdata -maskdata $rectmask
Paul Mackerras887c9962007-08-20 19:36:20 +10003409image create bitmap reficon-o -background black -foreground "#ddddff" \
3410 -data $rectdata -maskdata $rectmask
3411
Paul Mackerras7fcceed2006-04-27 19:21:49 +10003412proc init_flist {first} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11003413 global cflist cflist_top difffilestart
Paul Mackerras7fcceed2006-04-27 19:21:49 +10003414
3415 $cflist conf -state normal
3416 $cflist delete 0.0 end
3417 if {$first ne {}} {
3418 $cflist insert end $first
3419 set cflist_top 1
Paul Mackerras7fcceed2006-04-27 19:21:49 +10003420 $cflist tag add highlight 1.0 "1.0 lineend"
3421 } else {
Paul Mackerras009409f2015-05-02 20:53:36 +10003422 unset -nocomplain cflist_top
Paul Mackerras7fcceed2006-04-27 19:21:49 +10003423 }
3424 $cflist conf -state disabled
3425 set difffilestart {}
3426}
3427
Paul Mackerras63b79192006-05-20 21:31:52 +10003428proc highlight_tag {f} {
3429 global highlight_paths
3430
3431 foreach p $highlight_paths {
3432 if {[string match $p $f]} {
3433 return "bold"
3434 }
3435 }
3436 return {}
3437}
3438
3439proc highlight_filelist {} {
Paul Mackerras45a9d502006-05-20 22:56:27 +10003440 global cmitmode cflist
Paul Mackerras63b79192006-05-20 21:31:52 +10003441
Paul Mackerras45a9d502006-05-20 22:56:27 +10003442 $cflist conf -state normal
3443 if {$cmitmode ne "tree"} {
Paul Mackerras63b79192006-05-20 21:31:52 +10003444 set end [lindex [split [$cflist index end] .] 0]
3445 for {set l 2} {$l < $end} {incr l} {
3446 set line [$cflist get $l.0 "$l.0 lineend"]
3447 if {[highlight_tag $line] ne {}} {
3448 $cflist tag add bold $l.0 "$l.0 lineend"
3449 }
3450 }
Paul Mackerras45a9d502006-05-20 22:56:27 +10003451 } else {
3452 highlight_tree 2 {}
Paul Mackerras63b79192006-05-20 21:31:52 +10003453 }
Paul Mackerras45a9d502006-05-20 22:56:27 +10003454 $cflist conf -state disabled
Paul Mackerras63b79192006-05-20 21:31:52 +10003455}
3456
3457proc unhighlight_filelist {} {
Paul Mackerras45a9d502006-05-20 22:56:27 +10003458 global cflist
Paul Mackerras63b79192006-05-20 21:31:52 +10003459
Paul Mackerras45a9d502006-05-20 22:56:27 +10003460 $cflist conf -state normal
3461 $cflist tag remove bold 1.0 end
3462 $cflist conf -state disabled
Paul Mackerras63b79192006-05-20 21:31:52 +10003463}
3464
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10003465proc add_flist {fl} {
Paul Mackerras45a9d502006-05-20 22:56:27 +10003466 global cflist
Paul Mackerras7fcceed2006-04-27 19:21:49 +10003467
Paul Mackerras45a9d502006-05-20 22:56:27 +10003468 $cflist conf -state normal
3469 foreach f $fl {
3470 $cflist insert end "\n"
3471 $cflist insert end $f [highlight_tag $f]
Paul Mackerras7fcceed2006-04-27 19:21:49 +10003472 }
Paul Mackerras45a9d502006-05-20 22:56:27 +10003473 $cflist conf -state disabled
Paul Mackerras7fcceed2006-04-27 19:21:49 +10003474}
3475
3476proc sel_flist {w x y} {
Paul Mackerras45a9d502006-05-20 22:56:27 +10003477 global ctext difffilestart cflist cflist_top cmitmode
Paul Mackerras7fcceed2006-04-27 19:21:49 +10003478
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10003479 if {$cmitmode eq "tree"} return
Paul Mackerras7fcceed2006-04-27 19:21:49 +10003480 if {![info exists cflist_top]} return
3481 set l [lindex [split [$w index "@$x,$y"] "."] 0]
Paul Mackerras89b11d32006-05-02 19:55:31 +10003482 $cflist tag remove highlight $cflist_top.0 "$cflist_top.0 lineend"
3483 $cflist tag add highlight $l.0 "$l.0 lineend"
3484 set cflist_top $l
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10003485 if {$l == 1} {
3486 $ctext yview 1.0
3487 } else {
3488 catch {$ctext yview [lindex $difffilestart [expr {$l - 2}]]}
Paul Mackerras7fcceed2006-04-27 19:21:49 +10003489 }
Stefan Hallerb9671352012-09-19 20:17:27 +02003490 suppress_highlighting_file_for_current_scrollpos
Paul Mackerras7fcceed2006-04-27 19:21:49 +10003491}
3492
Paul Mackerras32447292007-07-27 22:30:15 +10003493proc pop_flist_menu {w X Y x y} {
3494 global ctext cflist cmitmode flist_menu flist_menu_file
3495 global treediffs diffids
3496
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10003497 stopfinding
Paul Mackerras32447292007-07-27 22:30:15 +10003498 set l [lindex [split [$w index "@$x,$y"] "."] 0]
3499 if {$l <= 1} return
3500 if {$cmitmode eq "tree"} {
3501 set e [linetoelt $l]
3502 if {[string index $e end] eq "/"} return
3503 } else {
3504 set e [lindex $treediffs($diffids) [expr {$l-2}]]
3505 }
3506 set flist_menu_file $e
Thomas Arcila314f5de2008-03-24 12:55:36 +01003507 set xdiffstate "normal"
3508 if {$cmitmode eq "tree"} {
3509 set xdiffstate "disabled"
3510 }
3511 # Disable "External diff" item in tree mode
3512 $flist_menu entryconf 2 -state $xdiffstate
Paul Mackerras32447292007-07-27 22:30:15 +10003513 tk_popup $flist_menu $X $Y
3514}
3515
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003516proc find_ctext_fileinfo {line} {
3517 global ctext_file_names ctext_file_lines
3518
3519 set ok [bsearch $ctext_file_lines $line]
3520 set tline [lindex $ctext_file_lines $ok]
3521
3522 if {$ok >= [llength $ctext_file_lines] || $line < $tline} {
3523 return {}
3524 } else {
3525 return [list [lindex $ctext_file_names $ok] $tline]
3526 }
3527}
3528
3529proc pop_diff_menu {w X Y x y} {
3530 global ctext diff_menu flist_menu_file
3531 global diff_menu_txtpos diff_menu_line
3532 global diff_menu_filebase
3533
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003534 set diff_menu_txtpos [split [$w index "@$x,$y"] "."]
3535 set diff_menu_line [lindex $diff_menu_txtpos 0]
Paul Mackerras190ec522008-10-27 21:13:37 +11003536 # don't pop up the menu on hunk-separator or file-separator lines
3537 if {[lsearch -glob [$ctext tag names $diff_menu_line.0] "*sep"] >= 0} {
3538 return
3539 }
3540 stopfinding
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003541 set f [find_ctext_fileinfo $diff_menu_line]
3542 if {$f eq {}} return
3543 set flist_menu_file [lindex $f 0]
3544 set diff_menu_filebase [lindex $f 1]
3545 tk_popup $diff_menu $X $Y
3546}
3547
Paul Mackerras32447292007-07-27 22:30:15 +10003548proc flist_hl {only} {
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10003549 global flist_menu_file findstring gdttype
Paul Mackerras32447292007-07-27 22:30:15 +10003550
3551 set x [shellquote $flist_menu_file]
Christian Stimmingb007ee22007-11-07 18:44:35 +01003552 if {$only || $findstring eq {} || $gdttype ne [mc "touching paths:"]} {
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10003553 set findstring $x
Paul Mackerras32447292007-07-27 22:30:15 +10003554 } else {
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10003555 append findstring " " $x
Paul Mackerras32447292007-07-27 22:30:15 +10003556 }
Christian Stimmingb007ee22007-11-07 18:44:35 +01003557 set gdttype [mc "touching paths:"]
Paul Mackerras32447292007-07-27 22:30:15 +10003558}
3559
Paul Mackerrasc21398b2009-09-07 10:08:21 +10003560proc gitknewtmpdir {} {
David Aguilarc7664f12014-06-13 14:13:37 -07003561 global diffnum gitktmpdir gitdir env
Paul Mackerrasc21398b2009-09-07 10:08:21 +10003562
3563 if {![info exists gitktmpdir]} {
David Aguilarc7664f12014-06-13 14:13:37 -07003564 if {[info exists env(GITK_TMPDIR)]} {
3565 set tmpdir $env(GITK_TMPDIR)
3566 } elseif {[info exists env(TMPDIR)]} {
3567 set tmpdir $env(TMPDIR)
3568 } else {
3569 set tmpdir $gitdir
3570 }
David Aguilar105b5d32014-06-13 14:43:48 -07003571 set gitktmpformat [file join $tmpdir ".gitk-tmp.XXXXXX"]
David Aguilarac54a4b2014-06-18 19:53:14 -07003572 if {[catch {set gitktmpdir [exec mktemp -d $gitktmpformat]}]} {
3573 set gitktmpdir [file join $gitdir [format ".gitk-tmp.%s" [pid]]]
3574 }
Paul Mackerrasc21398b2009-09-07 10:08:21 +10003575 if {[catch {file mkdir $gitktmpdir} err]} {
3576 error_popup "[mc "Error creating temporary directory %s:" $gitktmpdir] $err"
3577 unset gitktmpdir
3578 return {}
3579 }
3580 set diffnum 0
3581 }
3582 incr diffnum
3583 set diffdir [file join $gitktmpdir $diffnum]
3584 if {[catch {file mkdir $diffdir} err]} {
3585 error_popup "[mc "Error creating temporary directory %s:" $diffdir] $err"
3586 return {}
3587 }
3588 return $diffdir
3589}
3590
Thomas Arcila314f5de2008-03-24 12:55:36 +01003591proc save_file_from_commit {filename output what} {
3592 global nullfile
3593
3594 if {[catch {exec git show $filename -- > $output} err]} {
3595 if {[string match "fatal: bad revision *" $err]} {
3596 return $nullfile
3597 }
Christian Stimming3945d2c2008-09-12 11:39:43 +02003598 error_popup "[mc "Error getting \"%s\" from %s:" $filename $what] $err"
Thomas Arcila314f5de2008-03-24 12:55:36 +01003599 return {}
3600 }
3601 return $output
3602}
3603
3604proc external_diff_get_one_file {diffid filename diffdir} {
3605 global nullid nullid2 nullfile
Martin von Zweigbergk784b7e22011-04-04 22:14:15 -04003606 global worktree
Thomas Arcila314f5de2008-03-24 12:55:36 +01003607
3608 if {$diffid == $nullid} {
Martin von Zweigbergk784b7e22011-04-04 22:14:15 -04003609 set difffile [file join $worktree $filename]
Thomas Arcila314f5de2008-03-24 12:55:36 +01003610 if {[file exists $difffile]} {
3611 return $difffile
3612 }
3613 return $nullfile
3614 }
3615 if {$diffid == $nullid2} {
3616 set difffile [file join $diffdir "\[index\] [file tail $filename]"]
3617 return [save_file_from_commit :$filename $difffile index]
3618 }
3619 set difffile [file join $diffdir "\[$diffid\] [file tail $filename]"]
3620 return [save_file_from_commit $diffid:$filename $difffile \
3621 "revision $diffid"]
3622}
3623
3624proc external_diff {} {
Paul Mackerrasc21398b2009-09-07 10:08:21 +10003625 global nullid nullid2
Thomas Arcila314f5de2008-03-24 12:55:36 +01003626 global flist_menu_file
3627 global diffids
Paul Mackerrasc21398b2009-09-07 10:08:21 +10003628 global extdifftool
Thomas Arcila314f5de2008-03-24 12:55:36 +01003629
3630 if {[llength $diffids] == 1} {
3631 # no reference commit given
3632 set diffidto [lindex $diffids 0]
3633 if {$diffidto eq $nullid} {
3634 # diffing working copy with index
3635 set diffidfrom $nullid2
3636 } elseif {$diffidto eq $nullid2} {
3637 # diffing index with HEAD
3638 set diffidfrom "HEAD"
3639 } else {
3640 # use first parent commit
3641 global parentlist selectedline
3642 set diffidfrom [lindex $parentlist $selectedline 0]
3643 }
3644 } else {
3645 set diffidfrom [lindex $diffids 0]
3646 set diffidto [lindex $diffids 1]
3647 }
3648
3649 # make sure that several diffs wont collide
Paul Mackerrasc21398b2009-09-07 10:08:21 +10003650 set diffdir [gitknewtmpdir]
3651 if {$diffdir eq {}} return
Thomas Arcila314f5de2008-03-24 12:55:36 +01003652
3653 # gather files to diff
3654 set difffromfile [external_diff_get_one_file $diffidfrom $flist_menu_file $diffdir]
3655 set difftofile [external_diff_get_one_file $diffidto $flist_menu_file $diffdir]
3656
3657 if {$difffromfile ne {} && $difftofile ne {}} {
Pat Thoytsb575b2f2009-04-15 16:54:19 +01003658 set cmd [list [shellsplit $extdifftool] $difffromfile $difftofile]
3659 if {[catch {set fl [open |$cmd r]} err]} {
Thomas Arcila314f5de2008-03-24 12:55:36 +01003660 file delete -force $diffdir
Christian Stimming3945d2c2008-09-12 11:39:43 +02003661 error_popup "$extdifftool: [mc "command failed:"] $err"
Thomas Arcila314f5de2008-03-24 12:55:36 +01003662 } else {
3663 fconfigure $fl -blocking 0
3664 filerun $fl [list delete_at_eof $fl $diffdir]
3665 }
3666 }
3667}
3668
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003669proc find_hunk_blamespec {base line} {
3670 global ctext
3671
3672 # Find and parse the hunk header
3673 set s_lix [$ctext search -backwards -regexp ^@@ "$line.0 lineend" $base.0]
3674 if {$s_lix eq {}} return
3675
3676 set s_line [$ctext get $s_lix "$s_lix + 1 lines"]
3677 if {![regexp {^@@@*(( -\d+(,\d+)?)+) \+(\d+)(,\d+)? @@} $s_line \
3678 s_line old_specs osz osz1 new_line nsz]} {
3679 return
3680 }
3681
3682 # base lines for the parents
3683 set base_lines [list $new_line]
3684 foreach old_spec [lrange [split $old_specs " "] 1 end] {
3685 if {![regexp -- {-(\d+)(,\d+)?} $old_spec \
3686 old_spec old_line osz]} {
3687 return
3688 }
3689 lappend base_lines $old_line
3690 }
3691
3692 # Now scan the lines to determine offset within the hunk
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003693 set max_parent [expr {[llength $base_lines]-2}]
3694 set dline 0
3695 set s_lno [lindex [split $s_lix "."] 0]
3696
Paul Mackerras190ec522008-10-27 21:13:37 +11003697 # Determine if the line is removed
3698 set chunk [$ctext get $line.0 "$line.1 + $max_parent chars"]
3699 if {[string match {[-+ ]*} $chunk]} {
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003700 set removed_idx [string first "-" $chunk]
3701 # Choose a parent index
Paul Mackerras190ec522008-10-27 21:13:37 +11003702 if {$removed_idx >= 0} {
3703 set parent $removed_idx
3704 } else {
3705 set unchanged_idx [string first " " $chunk]
3706 if {$unchanged_idx >= 0} {
3707 set parent $unchanged_idx
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003708 } else {
Paul Mackerras190ec522008-10-27 21:13:37 +11003709 # blame the current commit
3710 set parent -1
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003711 }
3712 }
3713 # then count other lines that belong to it
Paul Mackerras190ec522008-10-27 21:13:37 +11003714 for {set i $line} {[incr i -1] > $s_lno} {} {
3715 set chunk [$ctext get $i.0 "$i.1 + $max_parent chars"]
3716 # Determine if the line is removed
3717 set removed_idx [string first "-" $chunk]
3718 if {$parent >= 0} {
3719 set code [string index $chunk $parent]
3720 if {$code eq "-" || ($removed_idx < 0 && $code ne "+")} {
3721 incr dline
3722 }
3723 } else {
3724 if {$removed_idx < 0} {
3725 incr dline
3726 }
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003727 }
3728 }
Paul Mackerras190ec522008-10-27 21:13:37 +11003729 incr parent
3730 } else {
3731 set parent 0
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003732 }
3733
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003734 incr dline [lindex $base_lines $parent]
3735 return [list $parent $dline]
3736}
3737
3738proc external_blame_diff {} {
Paul Mackerras8b07dca2008-11-02 22:34:47 +11003739 global currentid cmitmode
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003740 global diff_menu_txtpos diff_menu_line
3741 global diff_menu_filebase flist_menu_file
3742
3743 if {$cmitmode eq "tree"} {
3744 set parent_idx 0
Paul Mackerras190ec522008-10-27 21:13:37 +11003745 set line [expr {$diff_menu_line - $diff_menu_filebase}]
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003746 } else {
3747 set hinfo [find_hunk_blamespec $diff_menu_filebase $diff_menu_line]
3748 if {$hinfo ne {}} {
3749 set parent_idx [lindex $hinfo 0]
3750 set line [lindex $hinfo 1]
3751 } else {
3752 set parent_idx 0
3753 set line 0
3754 }
3755 }
3756
3757 external_blame $parent_idx $line
3758}
3759
Paul Mackerrasfc4977e2008-11-04 12:57:44 +11003760# Find the SHA1 ID of the blob for file $fname in the index
3761# at stage 0 or 2
3762proc index_sha1 {fname} {
3763 set f [open [list | git ls-files -s $fname] r]
3764 while {[gets $f line] >= 0} {
3765 set info [lindex [split $line "\t"] 0]
3766 set stage [lindex $info 2]
3767 if {$stage eq "0" || $stage eq "2"} {
3768 close $f
3769 return [lindex $info 1]
3770 }
3771 }
3772 close $f
3773 return {}
3774}
3775
Paul Mackerras9712b812008-12-06 21:44:05 +11003776# Turn an absolute path into one relative to the current directory
3777proc make_relative {f} {
Markus Heidelberga4390ac2009-11-04 00:21:41 +01003778 if {[file pathtype $f] eq "relative"} {
3779 return $f
3780 }
Paul Mackerras9712b812008-12-06 21:44:05 +11003781 set elts [file split $f]
3782 set here [file split [pwd]]
3783 set ei 0
3784 set hi 0
3785 set res {}
3786 foreach d $here {
3787 if {$ei < $hi || $ei >= [llength $elts] || [lindex $elts $ei] ne $d} {
3788 lappend res ".."
3789 } else {
3790 incr ei
3791 }
3792 incr hi
3793 }
3794 set elts [concat $res [lrange $elts $ei end]]
3795 return [eval file join $elts]
3796}
3797
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003798proc external_blame {parent_idx {line {}}} {
Martin von Zweigbergk0a2a9792011-04-04 22:14:14 -04003799 global flist_menu_file cdup
Alexander Gavrilov77aa0ae2008-08-23 12:29:08 +04003800 global nullid nullid2
3801 global parentlist selectedline currentid
3802
3803 if {$parent_idx > 0} {
3804 set base_commit [lindex $parentlist $selectedline [expr {$parent_idx-1}]]
3805 } else {
3806 set base_commit $currentid
3807 }
3808
3809 if {$base_commit eq {} || $base_commit eq $nullid || $base_commit eq $nullid2} {
3810 error_popup [mc "No such commit"]
3811 return
3812 }
3813
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003814 set cmdline [list git gui blame]
3815 if {$line ne {} && $line > 1} {
3816 lappend cmdline "--line=$line"
3817 }
Martin von Zweigbergk0a2a9792011-04-04 22:14:14 -04003818 set f [file join $cdup $flist_menu_file]
Paul Mackerras9712b812008-12-06 21:44:05 +11003819 # Unfortunately it seems git gui blame doesn't like
3820 # being given an absolute path...
3821 set f [make_relative $f]
3822 lappend cmdline $base_commit $f
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003823 if {[catch {eval exec $cmdline &} err]} {
Christian Stimming3945d2c2008-09-12 11:39:43 +02003824 error_popup "[mc "git gui blame: command failed:"] $err"
Alexander Gavrilov77aa0ae2008-08-23 12:29:08 +04003825 }
3826}
3827
Paul Mackerras8a897742008-10-27 21:36:25 +11003828proc show_line_source {} {
3829 global cmitmode currentid parents curview blamestuff blameinst
3830 global diff_menu_line diff_menu_filebase flist_menu_file
Martin von Zweigbergk9b6adf32011-04-04 22:14:13 -04003831 global nullid nullid2 gitdir cdup
Paul Mackerras8a897742008-10-27 21:36:25 +11003832
Paul Mackerrasfc4977e2008-11-04 12:57:44 +11003833 set from_index {}
Paul Mackerras8a897742008-10-27 21:36:25 +11003834 if {$cmitmode eq "tree"} {
3835 set id $currentid
3836 set line [expr {$diff_menu_line - $diff_menu_filebase}]
3837 } else {
3838 set h [find_hunk_blamespec $diff_menu_filebase $diff_menu_line]
3839 if {$h eq {}} return
3840 set pi [lindex $h 0]
3841 if {$pi == 0} {
3842 mark_ctext_line $diff_menu_line
3843 return
3844 }
Paul Mackerrasfc4977e2008-11-04 12:57:44 +11003845 incr pi -1
3846 if {$currentid eq $nullid} {
3847 if {$pi > 0} {
3848 # must be a merge in progress...
3849 if {[catch {
3850 # get the last line from .git/MERGE_HEAD
3851 set f [open [file join $gitdir MERGE_HEAD] r]
3852 set id [lindex [split [read $f] "\n"] end-1]
3853 close $f
3854 } err]} {
3855 error_popup [mc "Couldn't read merge head: %s" $err]
3856 return
3857 }
3858 } elseif {$parents($curview,$currentid) eq $nullid2} {
3859 # need to do the blame from the index
3860 if {[catch {
3861 set from_index [index_sha1 $flist_menu_file]
3862 } err]} {
3863 error_popup [mc "Error reading index: %s" $err]
3864 return
3865 }
Paul Mackerras9712b812008-12-06 21:44:05 +11003866 } else {
3867 set id $parents($curview,$currentid)
Paul Mackerrasfc4977e2008-11-04 12:57:44 +11003868 }
3869 } else {
3870 set id [lindex $parents($curview,$currentid) $pi]
3871 }
Paul Mackerras8a897742008-10-27 21:36:25 +11003872 set line [lindex $h 1]
3873 }
Paul Mackerrasfc4977e2008-11-04 12:57:44 +11003874 set blameargs {}
3875 if {$from_index ne {}} {
3876 lappend blameargs | git cat-file blob $from_index
3877 }
3878 lappend blameargs | git blame -p -L$line,+1
3879 if {$from_index ne {}} {
3880 lappend blameargs --contents -
3881 } else {
3882 lappend blameargs $id
3883 }
Martin von Zweigbergk9b6adf32011-04-04 22:14:13 -04003884 lappend blameargs -- [file join $cdup $flist_menu_file]
Paul Mackerras8a897742008-10-27 21:36:25 +11003885 if {[catch {
Paul Mackerrasfc4977e2008-11-04 12:57:44 +11003886 set f [open $blameargs r]
Paul Mackerras8a897742008-10-27 21:36:25 +11003887 } err]} {
3888 error_popup [mc "Couldn't start git blame: %s" $err]
3889 return
3890 }
Alexander Gavrilovf3413072008-12-01 20:30:09 +03003891 nowbusy blaming [mc "Searching"]
Paul Mackerras8a897742008-10-27 21:36:25 +11003892 fconfigure $f -blocking 0
3893 set i [reg_instance $f]
3894 set blamestuff($i) {}
3895 set blameinst $i
3896 filerun $f [list read_line_source $f $i]
3897}
3898
3899proc stopblaming {} {
3900 global blameinst
3901
3902 if {[info exists blameinst]} {
3903 stop_instance $blameinst
3904 unset blameinst
Alexander Gavrilovf3413072008-12-01 20:30:09 +03003905 notbusy blaming
Paul Mackerras8a897742008-10-27 21:36:25 +11003906 }
3907}
3908
3909proc read_line_source {fd inst} {
Paul Mackerrasfc4977e2008-11-04 12:57:44 +11003910 global blamestuff curview commfd blameinst nullid nullid2
Paul Mackerras8a897742008-10-27 21:36:25 +11003911
3912 while {[gets $fd line] >= 0} {
3913 lappend blamestuff($inst) $line
3914 }
3915 if {![eof $fd]} {
3916 return 1
3917 }
3918 unset commfd($inst)
3919 unset blameinst
Alexander Gavrilovf3413072008-12-01 20:30:09 +03003920 notbusy blaming
Paul Mackerras8a897742008-10-27 21:36:25 +11003921 fconfigure $fd -blocking 1
3922 if {[catch {close $fd} err]} {
3923 error_popup [mc "Error running git blame: %s" $err]
3924 return 0
3925 }
3926
3927 set fname {}
3928 set line [split [lindex $blamestuff($inst) 0] " "]
3929 set id [lindex $line 0]
3930 set lnum [lindex $line 1]
3931 if {[string length $id] == 40 && [string is xdigit $id] &&
3932 [string is digit -strict $lnum]} {
3933 # look for "filename" line
3934 foreach l $blamestuff($inst) {
3935 if {[string match "filename *" $l]} {
3936 set fname [string range $l 9 end]
3937 break
3938 }
3939 }
3940 }
3941 if {$fname ne {}} {
3942 # all looks good, select it
Paul Mackerrasfc4977e2008-11-04 12:57:44 +11003943 if {$id eq $nullid} {
3944 # blame uses all-zeroes to mean not committed,
3945 # which would mean a change in the index
3946 set id $nullid2
3947 }
Paul Mackerras8a897742008-10-27 21:36:25 +11003948 if {[commitinview $id $curview]} {
Max Kirillov4135d362014-04-05 23:38:50 +03003949 selectline [rowofcommit $id] 1 [list $fname $lnum] 1
Paul Mackerras8a897742008-10-27 21:36:25 +11003950 } else {
3951 error_popup [mc "That line comes from commit %s, \
3952 which is not in this view" [shortids $id]]
3953 }
3954 } else {
3955 puts "oops couldn't parse git blame output"
3956 }
3957 return 0
3958}
3959
Thomas Arcila314f5de2008-03-24 12:55:36 +01003960# delete $dir when we see eof on $f (presumably because the child has exited)
3961proc delete_at_eof {f dir} {
3962 while {[gets $f line] >= 0} {}
3963 if {[eof $f]} {
3964 if {[catch {close $f} err]} {
Christian Stimming3945d2c2008-09-12 11:39:43 +02003965 error_popup "[mc "External diff viewer failed:"] $err"
Thomas Arcila314f5de2008-03-24 12:55:36 +01003966 }
3967 file delete -force $dir
3968 return 0
3969 }
3970 return 1
3971}
3972
Paul Mackerras098dd8a2006-05-03 09:32:53 +10003973# Functions for adding and removing shell-type quoting
3974
3975proc shellquote {str} {
3976 if {![string match "*\['\"\\ \t]*" $str]} {
3977 return $str
3978 }
3979 if {![string match "*\['\"\\]*" $str]} {
3980 return "\"$str\""
3981 }
3982 if {![string match "*'*" $str]} {
3983 return "'$str'"
3984 }
3985 return "\"[string map {\" \\\" \\ \\\\} $str]\""
3986}
3987
3988proc shellarglist {l} {
3989 set str {}
3990 foreach a $l {
3991 if {$str ne {}} {
3992 append str " "
3993 }
3994 append str [shellquote $a]
3995 }
3996 return $str
3997}
3998
3999proc shelldequote {str} {
4000 set ret {}
4001 set used -1
4002 while {1} {
4003 incr used
4004 if {![regexp -start $used -indices "\['\"\\\\ \t]" $str first]} {
4005 append ret [string range $str $used end]
4006 set used [string length $str]
4007 break
4008 }
4009 set first [lindex $first 0]
4010 set ch [string index $str $first]
4011 if {$first > $used} {
4012 append ret [string range $str $used [expr {$first - 1}]]
4013 set used $first
4014 }
4015 if {$ch eq " " || $ch eq "\t"} break
4016 incr used
4017 if {$ch eq "'"} {
4018 set first [string first "'" $str $used]
4019 if {$first < 0} {
4020 error "unmatched single-quote"
4021 }
4022 append ret [string range $str $used [expr {$first - 1}]]
4023 set used $first
4024 continue
4025 }
4026 if {$ch eq "\\"} {
4027 if {$used >= [string length $str]} {
4028 error "trailing backslash"
4029 }
4030 append ret [string index $str $used]
4031 continue
4032 }
4033 # here ch == "\""
4034 while {1} {
4035 if {![regexp -start $used -indices "\[\"\\\\]" $str first]} {
4036 error "unmatched double-quote"
4037 }
4038 set first [lindex $first 0]
4039 set ch [string index $str $first]
4040 if {$first > $used} {
4041 append ret [string range $str $used [expr {$first - 1}]]
4042 set used $first
4043 }
4044 if {$ch eq "\""} break
4045 incr used
4046 append ret [string index $str $used]
4047 incr used
4048 }
4049 }
4050 return [list $used $ret]
4051}
4052
4053proc shellsplit {str} {
4054 set l {}
4055 while {1} {
4056 set str [string trimleft $str]
4057 if {$str eq {}} break
4058 set dq [shelldequote $str]
4059 set n [lindex $dq 0]
4060 set word [lindex $dq 1]
4061 set str [string range $str $n end]
4062 lappend l $word
4063 }
4064 return $l
4065}
4066
Marc Branchaud9922c5a2015-04-07 11:51:51 -04004067proc set_window_title {} {
4068 global appname curview viewname vrevs
4069 set rev [mc "All files"]
4070 if {$curview ne 0} {
4071 if {$viewname($curview) eq [mc "Command line"]} {
4072 set rev [string map {"--gitk-symmetric-diff-marker" "--merge"} $vrevs($curview)]
4073 } else {
4074 set rev $viewname($curview)
4075 }
4076 }
4077 wm title . "[reponame]: $rev - $appname"
4078}
4079
Paul Mackerras7fcceed2006-04-27 19:21:49 +10004080# Code to implement multiple views
4081
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004082proc newview {ishighlight} {
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004083 global nextviewnum newviewname newishighlight
4084 global revtreeargs viewargscmd newviewopts curview
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004085
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004086 set newishighlight $ishighlight
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004087 set top .gitkview
4088 if {[winfo exists $top]} {
4089 raise $top
4090 return
4091 }
Jonathan Nieder5d11f792010-03-06 16:58:42 -06004092 decode_view_opts $nextviewnum $revtreeargs
Michele Ballabioa3a1f572008-03-03 21:12:47 +01004093 set newviewname($nextviewnum) "[mc "View"] $nextviewnum"
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004094 set newviewopts($nextviewnum,perm) 0
4095 set newviewopts($nextviewnum,cmd) $viewargscmd($curview)
Christian Stimmingd990ced2007-11-07 18:42:55 +01004096 vieweditor $top $nextviewnum [mc "Gitk view definition"]
Paul Mackerrasd16c0812006-04-25 21:21:10 +10004097}
4098
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004099set known_view_options {
Elijah Newren13d40b62009-03-23 11:57:46 -06004100 {perm b . {} {mc "Remember this view"}}
4101 {reflabel l + {} {mc "References (space separated list):"}}
4102 {refs t15 .. {} {mc "Branches & tags:"}}
4103 {allrefs b *. "--all" {mc "All refs"}}
4104 {branches b . "--branches" {mc "All (local) branches"}}
4105 {tags b . "--tags" {mc "All tags"}}
4106 {remotes b . "--remotes" {mc "All remote-tracking branches"}}
4107 {commitlbl l + {} {mc "Commit Info (regular expressions):"}}
4108 {author t15 .. "--author=*" {mc "Author:"}}
4109 {committer t15 . "--committer=*" {mc "Committer:"}}
4110 {loginfo t15 .. "--grep=*" {mc "Commit Message:"}}
4111 {allmatch b .. "--all-match" {mc "Matches all Commit Info criteria"}}
Alex Henrie00132512015-04-02 15:05:06 -06004112 {igrep b .. "--invert-grep" {mc "Matches no Commit Info criteria"}}
Elijah Newren13d40b62009-03-23 11:57:46 -06004113 {changes_l l + {} {mc "Changes to Files:"}}
4114 {pickaxe_s r0 . {} {mc "Fixed String"}}
4115 {pickaxe_t r1 . "--pickaxe-regex" {mc "Regular Expression"}}
4116 {pickaxe t15 .. "-S*" {mc "Search string:"}}
4117 {datelabel l + {} {mc "Commit Dates (\"2 weeks ago\", \"2009-03-17 15:27:38\", \"March 17, 2009 15:27:38\"):"}}
4118 {since t15 .. {"--since=*" "--after=*"} {mc "Since:"}}
4119 {until t15 . {"--until=*" "--before=*"} {mc "Until:"}}
4120 {limit_lbl l + {} {mc "Limit and/or skip a number of revisions (positive integer):"}}
4121 {limit t10 *. "--max-count=*" {mc "Number to show:"}}
4122 {skip t10 . "--skip=*" {mc "Number to skip:"}}
4123 {misc_lbl l + {} {mc "Miscellaneous options:"}}
4124 {dorder b *. {"--date-order" "-d"} {mc "Strictly sort by date"}}
4125 {lright b . "--left-right" {mc "Mark branch sides"}}
4126 {first b . "--first-parent" {mc "Limit to first parent"}}
Dirk Suesserottf687aaa2009-05-21 15:35:40 +02004127 {smplhst b . "--simplify-by-decoration" {mc "Simple history"}}
Elijah Newren13d40b62009-03-23 11:57:46 -06004128 {args t50 *. {} {mc "Additional arguments to git log:"}}
4129 {allpaths path + {} {mc "Enter files and directories to include, one per line:"}}
4130 {cmd t50= + {} {mc "Command to generate more commits to include:"}}
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004131 }
4132
Jonathan Niedere7feb692010-03-06 16:48:38 -06004133# Convert $newviewopts($n, ...) into args for git log.
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004134proc encode_view_opts {n} {
4135 global known_view_options newviewopts
4136
4137 set rargs [list]
4138 foreach opt $known_view_options {
4139 set patterns [lindex $opt 3]
4140 if {$patterns eq {}} continue
4141 set pattern [lindex $patterns 0]
4142
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004143 if {[lindex $opt 1] eq "b"} {
Elijah Newren13d40b62009-03-23 11:57:46 -06004144 set val $newviewopts($n,[lindex $opt 0])
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004145 if {$val} {
4146 lappend rargs $pattern
4147 }
Elijah Newren13d40b62009-03-23 11:57:46 -06004148 } elseif {[regexp {^r(\d+)$} [lindex $opt 1] type value]} {
4149 regexp {^(.*_)} [lindex $opt 0] uselessvar button_id
4150 set val $newviewopts($n,$button_id)
4151 if {$val eq $value} {
4152 lappend rargs $pattern
4153 }
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004154 } else {
Elijah Newren13d40b62009-03-23 11:57:46 -06004155 set val $newviewopts($n,[lindex $opt 0])
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004156 set val [string trim $val]
4157 if {$val ne {}} {
4158 set pfix [string range $pattern 0 end-1]
4159 lappend rargs $pfix$val
4160 }
4161 }
4162 }
Elijah Newren13d40b62009-03-23 11:57:46 -06004163 set rargs [concat $rargs [shellsplit $newviewopts($n,refs)]]
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004164 return [concat $rargs [shellsplit $newviewopts($n,args)]]
4165}
4166
Jonathan Niedere7feb692010-03-06 16:48:38 -06004167# Fill $newviewopts($n, ...) based on args for git log.
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004168proc decode_view_opts {n view_args} {
4169 global known_view_options newviewopts
4170
4171 foreach opt $known_view_options {
Elijah Newren13d40b62009-03-23 11:57:46 -06004172 set id [lindex $opt 0]
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004173 if {[lindex $opt 1] eq "b"} {
Elijah Newren13d40b62009-03-23 11:57:46 -06004174 # Checkboxes
4175 set val 0
4176 } elseif {[regexp {^r(\d+)$} [lindex $opt 1]]} {
4177 # Radiobuttons
4178 regexp {^(.*_)} $id uselessvar id
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004179 set val 0
4180 } else {
Elijah Newren13d40b62009-03-23 11:57:46 -06004181 # Text fields
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004182 set val {}
4183 }
Elijah Newren13d40b62009-03-23 11:57:46 -06004184 set newviewopts($n,$id) $val
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004185 }
4186 set oargs [list]
Elijah Newren13d40b62009-03-23 11:57:46 -06004187 set refargs [list]
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004188 foreach arg $view_args {
4189 if {[regexp -- {^-([0-9]+)$} $arg arg cnt]
4190 && ![info exists found(limit)]} {
4191 set newviewopts($n,limit) $cnt
4192 set found(limit) 1
4193 continue
4194 }
4195 catch { unset val }
4196 foreach opt $known_view_options {
4197 set id [lindex $opt 0]
4198 if {[info exists found($id)]} continue
4199 foreach pattern [lindex $opt 3] {
4200 if {![string match $pattern $arg]} continue
Elijah Newren13d40b62009-03-23 11:57:46 -06004201 if {[lindex $opt 1] eq "b"} {
4202 # Check buttons
4203 set val 1
4204 } elseif {[regexp {^r(\d+)$} [lindex $opt 1] match num]} {
4205 # Radio buttons
4206 regexp {^(.*_)} $id uselessvar id
4207 set val $num
4208 } else {
4209 # Text input fields
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004210 set size [string length $pattern]
4211 set val [string range $arg [expr {$size-1}] end]
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004212 }
4213 set newviewopts($n,$id) $val
4214 set found($id) 1
4215 break
4216 }
4217 if {[info exists val]} break
4218 }
4219 if {[info exists val]} continue
Elijah Newren13d40b62009-03-23 11:57:46 -06004220 if {[regexp {^-} $arg]} {
4221 lappend oargs $arg
4222 } else {
4223 lappend refargs $arg
4224 }
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004225 }
Elijah Newren13d40b62009-03-23 11:57:46 -06004226 set newviewopts($n,refs) [shellarglist $refargs]
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004227 set newviewopts($n,args) [shellarglist $oargs]
4228}
4229
Alexander Gavrilovcea07cf2008-11-09 13:00:45 +03004230proc edit_or_newview {} {
4231 global curview
4232
4233 if {$curview > 0} {
4234 editview
4235 } else {
4236 newview 0
4237 }
4238}
4239
Paul Mackerrasd16c0812006-04-25 21:21:10 +10004240proc editview {} {
4241 global curview
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004242 global viewname viewperm newviewname newviewopts
4243 global viewargs viewargscmd
Paul Mackerrasd16c0812006-04-25 21:21:10 +10004244
4245 set top .gitkvedit-$curview
4246 if {[winfo exists $top]} {
4247 raise $top
4248 return
4249 }
Jonathan Nieder5d11f792010-03-06 16:58:42 -06004250 decode_view_opts $curview $viewargs($curview)
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004251 set newviewname($curview) $viewname($curview)
4252 set newviewopts($curview,perm) $viewperm($curview)
4253 set newviewopts($curview,cmd) $viewargscmd($curview)
Michele Ballabiob56e0a92009-03-30 21:17:25 +02004254 vieweditor $top $curview "[mc "Gitk: edit view"] $viewname($curview)"
Paul Mackerrasd16c0812006-04-25 21:21:10 +10004255}
4256
4257proc vieweditor {top n title} {
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004258 global newviewname newviewopts viewfiles bgcolor
Pat Thoytsd93f1712009-04-17 01:24:35 +01004259 global known_view_options NS
Paul Mackerrasd16c0812006-04-25 21:21:10 +10004260
Pat Thoytsd93f1712009-04-17 01:24:35 +01004261 ttk_toplevel $top
Michele Ballabioe0a01992009-05-23 11:48:25 +02004262 wm title $top [concat $title [mc "-- criteria for selecting revisions"]]
Alexander Gavrilove7d64002008-11-11 23:55:42 +03004263 make_transient $top .
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004264
4265 # View name
Pat Thoytsd93f1712009-04-17 01:24:35 +01004266 ${NS}::frame $top.nfr
Paul Mackerraseae7d642009-09-05 17:34:03 +10004267 ${NS}::label $top.nl -text [mc "View Name"]
Pat Thoytsd93f1712009-04-17 01:24:35 +01004268 ${NS}::entry $top.name -width 20 -textvariable newviewname($n)
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004269 pack $top.nfr -in $top -fill x -pady 5 -padx 3
Elijah Newren13d40b62009-03-23 11:57:46 -06004270 pack $top.nl -in $top.nfr -side left -padx {0 5}
4271 pack $top.name -in $top.nfr -side left -padx {0 25}
Yann Dirson2d480852008-02-21 21:23:31 +01004272
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004273 # View options
4274 set cframe $top.nfr
4275 set cexpand 0
4276 set cnt 0
4277 foreach opt $known_view_options {
4278 set id [lindex $opt 0]
4279 set type [lindex $opt 1]
4280 set flags [lindex $opt 2]
4281 set title [eval [lindex $opt 4]]
4282 set lxpad 0
Yann Dirson2d480852008-02-21 21:23:31 +01004283
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004284 if {$flags eq "+" || $flags eq "*"} {
4285 set cframe $top.fr$cnt
4286 incr cnt
Pat Thoytsd93f1712009-04-17 01:24:35 +01004287 ${NS}::frame $cframe
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004288 pack $cframe -in $top -fill x -pady 3 -padx 3
4289 set cexpand [expr {$flags eq "*"}]
Elijah Newren13d40b62009-03-23 11:57:46 -06004290 } elseif {$flags eq ".." || $flags eq "*."} {
4291 set cframe $top.fr$cnt
4292 incr cnt
Paul Mackerraseae7d642009-09-05 17:34:03 +10004293 ${NS}::frame $cframe
Elijah Newren13d40b62009-03-23 11:57:46 -06004294 pack $cframe -in $top -fill x -pady 3 -padx [list 15 3]
4295 set cexpand [expr {$flags eq "*."}]
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004296 } else {
4297 set lxpad 5
4298 }
4299
Elijah Newren13d40b62009-03-23 11:57:46 -06004300 if {$type eq "l"} {
Paul Mackerraseae7d642009-09-05 17:34:03 +10004301 ${NS}::label $cframe.l_$id -text $title
Elijah Newren13d40b62009-03-23 11:57:46 -06004302 pack $cframe.l_$id -in $cframe -side left -pady [list 3 0] -anchor w
4303 } elseif {$type eq "b"} {
Pat Thoytsd93f1712009-04-17 01:24:35 +01004304 ${NS}::checkbutton $cframe.c_$id -text $title -variable newviewopts($n,$id)
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004305 pack $cframe.c_$id -in $cframe -side left \
4306 -padx [list $lxpad 0] -expand $cexpand -anchor w
Elijah Newren13d40b62009-03-23 11:57:46 -06004307 } elseif {[regexp {^r(\d+)$} $type type sz]} {
4308 regexp {^(.*_)} $id uselessvar button_id
Paul Mackerraseae7d642009-09-05 17:34:03 +10004309 ${NS}::radiobutton $cframe.c_$id -text $title -variable newviewopts($n,$button_id) -value $sz
Elijah Newren13d40b62009-03-23 11:57:46 -06004310 pack $cframe.c_$id -in $cframe -side left \
4311 -padx [list $lxpad 0] -expand $cexpand -anchor w
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004312 } elseif {[regexp {^t(\d+)$} $type type sz]} {
Pat Thoytsd93f1712009-04-17 01:24:35 +01004313 ${NS}::label $cframe.l_$id -text $title
4314 ${NS}::entry $cframe.e_$id -width $sz -background $bgcolor \
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004315 -textvariable newviewopts($n,$id)
4316 pack $cframe.l_$id -in $cframe -side left -padx [list $lxpad 0]
4317 pack $cframe.e_$id -in $cframe -side left -expand 1 -fill x
4318 } elseif {[regexp {^t(\d+)=$} $type type sz]} {
Pat Thoytsd93f1712009-04-17 01:24:35 +01004319 ${NS}::label $cframe.l_$id -text $title
4320 ${NS}::entry $cframe.e_$id -width $sz -background $bgcolor \
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004321 -textvariable newviewopts($n,$id)
4322 pack $cframe.l_$id -in $cframe -side top -pady [list 3 0] -anchor w
4323 pack $cframe.e_$id -in $cframe -side top -fill x
Elijah Newren13d40b62009-03-23 11:57:46 -06004324 } elseif {$type eq "path"} {
Paul Mackerraseae7d642009-09-05 17:34:03 +10004325 ${NS}::label $top.l -text $title
Elijah Newren13d40b62009-03-23 11:57:46 -06004326 pack $top.l -in $top -side top -pady [list 3 0] -anchor w -padx 3
Mark Hillsb9b142f2010-01-13 20:40:22 +00004327 text $top.t -width 40 -height 5 -background $bgcolor
Elijah Newren13d40b62009-03-23 11:57:46 -06004328 if {[info exists viewfiles($n)]} {
4329 foreach f $viewfiles($n) {
4330 $top.t insert end $f
4331 $top.t insert end "\n"
4332 }
4333 $top.t delete {end - 1c} end
4334 $top.t mark set insert 0.0
4335 }
4336 pack $top.t -in $top -side top -pady [list 0 5] -fill both -expand 1 -padx 3
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004337 }
4338 }
4339
Pat Thoytsd93f1712009-04-17 01:24:35 +01004340 ${NS}::frame $top.buts
4341 ${NS}::button $top.buts.ok -text [mc "OK"] -command [list newviewok $top $n]
4342 ${NS}::button $top.buts.apply -text [mc "Apply (F5)"] -command [list newviewok $top $n 1]
4343 ${NS}::button $top.buts.can -text [mc "Cancel"] -command [list destroy $top]
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004344 bind $top <Control-Return> [list newviewok $top $n]
4345 bind $top <F5> [list newviewok $top $n 1]
Alexander Gavrilov76f15942008-11-02 21:59:44 +03004346 bind $top <Escape> [list destroy $top]
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004347 grid $top.buts.ok $top.buts.apply $top.buts.can
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004348 grid columnconfigure $top.buts 0 -weight 1 -uniform a
4349 grid columnconfigure $top.buts 1 -weight 1 -uniform a
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004350 grid columnconfigure $top.buts 2 -weight 1 -uniform a
4351 pack $top.buts -in $top -side top -fill x
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004352 focus $top.t
4353}
4354
Paul Mackerras908c3582006-05-20 09:38:11 +10004355proc doviewmenu {m first cmd op argv} {
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004356 set nmenu [$m index end]
4357 for {set i $first} {$i <= $nmenu} {incr i} {
4358 if {[$m entrycget $i -command] eq $cmd} {
Paul Mackerras908c3582006-05-20 09:38:11 +10004359 eval $m $op $i $argv
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004360 break
Paul Mackerrasd16c0812006-04-25 21:21:10 +10004361 }
4362 }
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004363}
4364
4365proc allviewmenus {n op args} {
Paul Mackerras687c8762007-09-22 12:49:33 +10004366 # global viewhlmenu
Paul Mackerras908c3582006-05-20 09:38:11 +10004367
Paul Mackerras3cd204e2006-11-23 21:06:16 +11004368 doviewmenu .bar.view 5 [list showview $n] $op $args
Paul Mackerras687c8762007-09-22 12:49:33 +10004369 # doviewmenu $viewhlmenu 1 [list addvhighlight $n] $op $args
Paul Mackerrasd16c0812006-04-25 21:21:10 +10004370}
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004371
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004372proc newviewok {top n {apply 0}} {
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004373 global nextviewnum newviewperm newviewname newishighlight
Max Kirillov995f7922015-03-04 05:58:16 +02004374 global viewname viewfiles viewperm viewchanged selectedview curview
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004375 global viewargs viewargscmd newviewopts viewhlmenu
Paul Mackerrasd16c0812006-04-25 21:21:10 +10004376
Paul Mackerras098dd8a2006-05-03 09:32:53 +10004377 if {[catch {
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004378 set newargs [encode_view_opts $n]
Paul Mackerras098dd8a2006-05-03 09:32:53 +10004379 } err]} {
Alexander Gavrilov84a76f12008-11-02 21:59:45 +03004380 error_popup "[mc "Error in commit selection arguments:"] $err" $top
Paul Mackerras098dd8a2006-05-03 09:32:53 +10004381 return
4382 }
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004383 set files {}
Paul Mackerrasd16c0812006-04-25 21:21:10 +10004384 foreach f [split [$top.t get 0.0 end] "\n"] {
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004385 set ft [string trim $f]
4386 if {$ft ne {}} {
4387 lappend files $ft
4388 }
4389 }
Paul Mackerrasd16c0812006-04-25 21:21:10 +10004390 if {![info exists viewfiles($n)]} {
4391 # creating a new view
4392 incr nextviewnum
4393 set viewname($n) $newviewname($n)
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004394 set viewperm($n) $newviewopts($n,perm)
Max Kirillov995f7922015-03-04 05:58:16 +02004395 set viewchanged($n) 1
Paul Mackerrasd16c0812006-04-25 21:21:10 +10004396 set viewfiles($n) $files
Paul Mackerras098dd8a2006-05-03 09:32:53 +10004397 set viewargs($n) $newargs
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004398 set viewargscmd($n) $newviewopts($n,cmd)
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004399 addviewmenu $n
4400 if {!$newishighlight} {
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004401 run showview $n
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004402 } else {
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004403 run addvhighlight $n
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004404 }
Paul Mackerrasd16c0812006-04-25 21:21:10 +10004405 } else {
4406 # editing an existing view
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004407 set viewperm($n) $newviewopts($n,perm)
Max Kirillov995f7922015-03-04 05:58:16 +02004408 set viewchanged($n) 1
Paul Mackerrasd16c0812006-04-25 21:21:10 +10004409 if {$newviewname($n) ne $viewname($n)} {
4410 set viewname($n) $newviewname($n)
Paul Mackerras3cd204e2006-11-23 21:06:16 +11004411 doviewmenu .bar.view 5 [list showview $n] \
Paul Mackerras908c3582006-05-20 09:38:11 +10004412 entryconf [list -label $viewname($n)]
Paul Mackerras687c8762007-09-22 12:49:33 +10004413 # doviewmenu $viewhlmenu 1 [list addvhighlight $n] \
4414 # entryconf [list -label $viewname($n) -value $viewname($n)]
Paul Mackerrasd16c0812006-04-25 21:21:10 +10004415 }
Yann Dirson2d480852008-02-21 21:23:31 +01004416 if {$files ne $viewfiles($n) || $newargs ne $viewargs($n) || \
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004417 $newviewopts($n,cmd) ne $viewargscmd($n)} {
Paul Mackerrasd16c0812006-04-25 21:21:10 +10004418 set viewfiles($n) $files
Paul Mackerras098dd8a2006-05-03 09:32:53 +10004419 set viewargs($n) $newargs
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004420 set viewargscmd($n) $newviewopts($n,cmd)
Paul Mackerrasd16c0812006-04-25 21:21:10 +10004421 if {$curview == $n} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004422 run reloadcommits
Paul Mackerrasd16c0812006-04-25 21:21:10 +10004423 }
4424 }
4425 }
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004426 if {$apply} return
Paul Mackerrasd16c0812006-04-25 21:21:10 +10004427 catch {destroy $top}
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004428}
4429
4430proc delview {} {
Max Kirillov995f7922015-03-04 05:58:16 +02004431 global curview viewperm hlview selectedhlview viewchanged
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004432
4433 if {$curview == 0} return
Paul Mackerras908c3582006-05-20 09:38:11 +10004434 if {[info exists hlview] && $hlview == $curview} {
Christian Stimmingb007ee22007-11-07 18:44:35 +01004435 set selectedhlview [mc "None"]
Paul Mackerras908c3582006-05-20 09:38:11 +10004436 unset hlview
4437 }
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004438 allviewmenus $curview delete
Paul Mackerrasa90a6d22006-04-25 17:12:46 +10004439 set viewperm($curview) 0
Max Kirillov995f7922015-03-04 05:58:16 +02004440 set viewchanged($curview) 1
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004441 showview 0
4442}
4443
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004444proc addviewmenu {n} {
Paul Mackerras908c3582006-05-20 09:38:11 +10004445 global viewname viewhlmenu
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004446
4447 .bar.view add radiobutton -label $viewname($n) \
4448 -command [list showview $n] -variable selectedview -value $n
Paul Mackerras687c8762007-09-22 12:49:33 +10004449 #$viewhlmenu add radiobutton -label $viewname($n) \
4450 # -command [list addvhighlight $n] -variable selectedhlview
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004451}
4452
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004453proc showview {n} {
Paul Mackerras3ed31a82008-04-26 16:00:00 +10004454 global curview cached_commitrow ordertok
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10004455 global displayorder parentlist rowidlist rowisopt rowfinal
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004456 global colormap rowtextx nextcolor canvxmax
4457 global numcommits viewcomplete
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004458 global selectedline currentid canv canvy0
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004459 global treediffs
Paul Mackerras3e766082008-01-13 17:26:30 +11004460 global pending_select mainheadid
Paul Mackerras03800812007-08-29 21:45:21 +10004461 global commitidx
Paul Mackerras3e766082008-01-13 17:26:30 +11004462 global selectedview
Paul Mackerras97645682007-08-23 22:24:38 +10004463 global hlview selectedhlview commitinterest
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004464
4465 if {$n == $curview} return
4466 set selid {}
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004467 set ymax [lindex [$canv cget -scrollregion] 3]
4468 set span [$canv yview]
4469 set ytop [expr {[lindex $span 0] * $ymax}]
4470 set ybot [expr {[lindex $span 1] * $ymax}]
4471 set yscreen [expr {($ybot - $ytop) / 2}]
Paul Mackerras94b4a692008-05-20 20:51:06 +10004472 if {$selectedline ne {}} {
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004473 set selid $currentid
4474 set y [yc $selectedline]
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004475 if {$ytop < $y && $y < $ybot} {
4476 set yscreen [expr {$y - $ytop}]
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004477 }
Paul Mackerrase507fd42007-06-16 21:51:08 +10004478 } elseif {[info exists pending_select]} {
4479 set selid $pending_select
4480 unset pending_select
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004481 }
4482 unselectline
Paul Mackerrasfdedbcf2006-04-06 21:22:52 +10004483 normalline
Paul Mackerras009409f2015-05-02 20:53:36 +10004484 unset -nocomplain treediffs
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004485 clear_display
Paul Mackerras908c3582006-05-20 09:38:11 +10004486 if {[info exists hlview] && $hlview == $n} {
4487 unset hlview
Christian Stimmingb007ee22007-11-07 18:44:35 +01004488 set selectedhlview [mc "None"]
Paul Mackerras908c3582006-05-20 09:38:11 +10004489 }
Paul Mackerras009409f2015-05-02 20:53:36 +10004490 unset -nocomplain commitinterest
4491 unset -nocomplain cached_commitrow
4492 unset -nocomplain ordertok
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004493
4494 set curview $n
Paul Mackerrasa90a6d22006-04-25 17:12:46 +10004495 set selectedview $n
Giuseppe Bilottad99b4b02015-09-09 15:20:53 +02004496 .bar.view entryconf [mca "&Edit view..."] -state [expr {$n == 0? "disabled": "normal"}]
4497 .bar.view entryconf [mca "&Delete view"] -state [expr {$n == 0? "disabled": "normal"}]
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004498
Paul Mackerrasdf904492007-08-29 22:03:07 +10004499 run refill_reflist
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004500 if {![info exists viewcomplete($n)]} {
Alexander Gavrilov567c34e2008-07-26 20:13:45 +04004501 getcommits $selid
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004502 return
4503 }
4504
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004505 set displayorder {}
4506 set parentlist {}
4507 set rowidlist {}
4508 set rowisopt {}
4509 set rowfinal {}
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10004510 set numcommits $commitidx($n)
Paul Mackerras22626ef2006-04-17 09:56:02 +10004511
Paul Mackerras009409f2015-05-02 20:53:36 +10004512 unset -nocomplain colormap
4513 unset -nocomplain rowtextx
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004514 set nextcolor 0
4515 set canvxmax [$canv cget -width]
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004516 set curview $n
4517 set row 0
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004518 setcanvscroll
4519 set yf 0
Paul Mackerrase507fd42007-06-16 21:51:08 +10004520 set row {}
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004521 if {$selid ne {} && [commitinview $selid $n]} {
4522 set row [rowofcommit $selid]
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004523 # try to get the selected row in the same position on the screen
4524 set ymax [lindex [$canv cget -scrollregion] 3]
4525 set ytop [expr {[yc $row] - $yscreen}]
4526 if {$ytop < 0} {
4527 set ytop 0
4528 }
4529 set yf [expr {$ytop * 1.0 / $ymax}]
4530 }
4531 allcanvs yview moveto $yf
4532 drawvisible
Paul Mackerrase507fd42007-06-16 21:51:08 +10004533 if {$row ne {}} {
4534 selectline $row 0
Paul Mackerras3e766082008-01-13 17:26:30 +11004535 } elseif {!$viewcomplete($n)} {
Alexander Gavrilov567c34e2008-07-26 20:13:45 +04004536 reset_pending_select $selid
Paul Mackerrase507fd42007-06-16 21:51:08 +10004537 } else {
Alexander Gavrilov835e62a2008-07-26 20:15:54 +04004538 reset_pending_select {}
4539
4540 if {[commitinview $pending_select $curview]} {
4541 selectline [rowofcommit $pending_select] 1
4542 } else {
4543 set row [first_real_row]
4544 if {$row < $numcommits} {
4545 selectline $row 0
4546 }
Paul Mackerrase507fd42007-06-16 21:51:08 +10004547 }
4548 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004549 if {!$viewcomplete($n)} {
4550 if {$numcommits == 0} {
Christian Stimmingd990ced2007-11-07 18:42:55 +01004551 show_status [mc "Reading commits..."]
Paul Mackerrasd16c0812006-04-25 21:21:10 +10004552 }
Paul Mackerras098dd8a2006-05-03 09:32:53 +10004553 } elseif {$numcommits == 0} {
Christian Stimmingd990ced2007-11-07 18:42:55 +01004554 show_status [mc "No commits selected"]
Paul Mackerras2516dae2006-04-21 10:35:31 +10004555 }
Marc Branchaud9922c5a2015-04-07 11:51:51 -04004556 set_window_title
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004557}
4558
Paul Mackerras908c3582006-05-20 09:38:11 +10004559# Stuff relating to the highlighting facility
4560
Paul Mackerras476ca632008-01-07 22:16:31 +11004561proc ishighlighted {id} {
Paul Mackerras164ff272006-05-29 19:50:02 +10004562 global vhighlights fhighlights nhighlights rhighlights
Paul Mackerras908c3582006-05-20 09:38:11 +10004563
Paul Mackerras476ca632008-01-07 22:16:31 +11004564 if {[info exists nhighlights($id)] && $nhighlights($id) > 0} {
4565 return $nhighlights($id)
Paul Mackerras908c3582006-05-20 09:38:11 +10004566 }
Paul Mackerras476ca632008-01-07 22:16:31 +11004567 if {[info exists vhighlights($id)] && $vhighlights($id) > 0} {
4568 return $vhighlights($id)
Paul Mackerras908c3582006-05-20 09:38:11 +10004569 }
Paul Mackerras476ca632008-01-07 22:16:31 +11004570 if {[info exists fhighlights($id)] && $fhighlights($id) > 0} {
4571 return $fhighlights($id)
Paul Mackerras908c3582006-05-20 09:38:11 +10004572 }
Paul Mackerras476ca632008-01-07 22:16:31 +11004573 if {[info exists rhighlights($id)] && $rhighlights($id) > 0} {
4574 return $rhighlights($id)
Paul Mackerras164ff272006-05-29 19:50:02 +10004575 }
Paul Mackerras908c3582006-05-20 09:38:11 +10004576 return 0
4577}
4578
Paul Mackerras28593d32008-11-13 23:01:46 +11004579proc bolden {id font} {
Paul Mackerrasb9fdba72009-04-09 09:34:46 +10004580 global canv linehtag currentid boldids need_redisplay markedid
Paul Mackerras908c3582006-05-20 09:38:11 +10004581
Paul Mackerrasd98d50e2008-11-13 22:39:00 +11004582 # need_redisplay = 1 means the display is stale and about to be redrawn
4583 if {$need_redisplay} return
Paul Mackerras28593d32008-11-13 23:01:46 +11004584 lappend boldids $id
4585 $canv itemconf $linehtag($id) -font $font
4586 if {[info exists currentid] && $id eq $currentid} {
Paul Mackerras908c3582006-05-20 09:38:11 +10004587 $canv delete secsel
Paul Mackerras28593d32008-11-13 23:01:46 +11004588 set t [eval $canv create rect [$canv bbox $linehtag($id)] \
Paul Mackerras908c3582006-05-20 09:38:11 +10004589 -outline {{}} -tags secsel \
4590 -fill [$canv cget -selectbackground]]
4591 $canv lower $t
4592 }
Paul Mackerrasb9fdba72009-04-09 09:34:46 +10004593 if {[info exists markedid] && $id eq $markedid} {
4594 make_idmark $id
4595 }
Paul Mackerras908c3582006-05-20 09:38:11 +10004596}
4597
Paul Mackerras28593d32008-11-13 23:01:46 +11004598proc bolden_name {id font} {
4599 global canv2 linentag currentid boldnameids need_redisplay
Paul Mackerras908c3582006-05-20 09:38:11 +10004600
Paul Mackerrasd98d50e2008-11-13 22:39:00 +11004601 if {$need_redisplay} return
Paul Mackerras28593d32008-11-13 23:01:46 +11004602 lappend boldnameids $id
4603 $canv2 itemconf $linentag($id) -font $font
4604 if {[info exists currentid] && $id eq $currentid} {
Paul Mackerras908c3582006-05-20 09:38:11 +10004605 $canv2 delete secsel
Paul Mackerras28593d32008-11-13 23:01:46 +11004606 set t [eval $canv2 create rect [$canv2 bbox $linentag($id)] \
Paul Mackerras908c3582006-05-20 09:38:11 +10004607 -outline {{}} -tags secsel \
4608 -fill [$canv2 cget -selectbackground]]
4609 $canv2 lower $t
4610 }
4611}
4612
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004613proc unbolden {} {
Paul Mackerras28593d32008-11-13 23:01:46 +11004614 global boldids
Paul Mackerras908c3582006-05-20 09:38:11 +10004615
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004616 set stillbold {}
Paul Mackerras28593d32008-11-13 23:01:46 +11004617 foreach id $boldids {
4618 if {![ishighlighted $id]} {
4619 bolden $id mainfont
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004620 } else {
Paul Mackerras28593d32008-11-13 23:01:46 +11004621 lappend stillbold $id
Paul Mackerras908c3582006-05-20 09:38:11 +10004622 }
4623 }
Paul Mackerras28593d32008-11-13 23:01:46 +11004624 set boldids $stillbold
Paul Mackerras908c3582006-05-20 09:38:11 +10004625}
4626
4627proc addvhighlight {n} {
Paul Mackerras476ca632008-01-07 22:16:31 +11004628 global hlview viewcomplete curview vhl_done commitidx
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004629
4630 if {[info exists hlview]} {
Paul Mackerras908c3582006-05-20 09:38:11 +10004631 delvhighlight
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004632 }
4633 set hlview $n
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004634 if {$n != $curview && ![info exists viewcomplete($n)]} {
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004635 start_rev_list $n
Paul Mackerras908c3582006-05-20 09:38:11 +10004636 }
4637 set vhl_done $commitidx($hlview)
4638 if {$vhl_done > 0} {
4639 drawvisible
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004640 }
4641}
4642
Paul Mackerras908c3582006-05-20 09:38:11 +10004643proc delvhighlight {} {
4644 global hlview vhighlights
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004645
4646 if {![info exists hlview]} return
4647 unset hlview
Paul Mackerras009409f2015-05-02 20:53:36 +10004648 unset -nocomplain vhighlights
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004649 unbolden
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004650}
4651
Paul Mackerras908c3582006-05-20 09:38:11 +10004652proc vhighlightmore {} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004653 global hlview vhl_done commitidx vhighlights curview
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004654
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004655 set max $commitidx($hlview)
Paul Mackerras908c3582006-05-20 09:38:11 +10004656 set vr [visiblerows]
4657 set r0 [lindex $vr 0]
4658 set r1 [lindex $vr 1]
4659 for {set i $vhl_done} {$i < $max} {incr i} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004660 set id [commitonrow $i $hlview]
4661 if {[commitinview $id $curview]} {
4662 set row [rowofcommit $id]
Paul Mackerras908c3582006-05-20 09:38:11 +10004663 if {$r0 <= $row && $row <= $r1} {
4664 if {![highlighted $row]} {
Paul Mackerras28593d32008-11-13 23:01:46 +11004665 bolden $id mainfontbold
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004666 }
Paul Mackerras476ca632008-01-07 22:16:31 +11004667 set vhighlights($id) 1
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004668 }
4669 }
4670 }
Paul Mackerras908c3582006-05-20 09:38:11 +10004671 set vhl_done $max
Paul Mackerrasac1276a2008-03-03 10:11:08 +11004672 return 0
Paul Mackerras908c3582006-05-20 09:38:11 +10004673}
4674
4675proc askvhighlight {row id} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004676 global hlview vhighlights iddrawn
Paul Mackerras908c3582006-05-20 09:38:11 +10004677
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004678 if {[commitinview $id $hlview]} {
Paul Mackerras476ca632008-01-07 22:16:31 +11004679 if {[info exists iddrawn($id)] && ![ishighlighted $id]} {
Paul Mackerras28593d32008-11-13 23:01:46 +11004680 bolden $id mainfontbold
Paul Mackerras908c3582006-05-20 09:38:11 +10004681 }
Paul Mackerras476ca632008-01-07 22:16:31 +11004682 set vhighlights($id) 1
Paul Mackerras908c3582006-05-20 09:38:11 +10004683 } else {
Paul Mackerras476ca632008-01-07 22:16:31 +11004684 set vhighlights($id) 0
Paul Mackerras908c3582006-05-20 09:38:11 +10004685 }
4686}
4687
Paul Mackerras687c8762007-09-22 12:49:33 +10004688proc hfiles_change {} {
Paul Mackerras908c3582006-05-20 09:38:11 +10004689 global highlight_files filehighlight fhighlights fh_serial
Paul Mackerras8b39e042008-12-02 09:02:46 +11004690 global highlight_paths
Paul Mackerras908c3582006-05-20 09:38:11 +10004691
4692 if {[info exists filehighlight]} {
4693 # delete previous highlights
4694 catch {close $filehighlight}
4695 unset filehighlight
Paul Mackerras009409f2015-05-02 20:53:36 +10004696 unset -nocomplain fhighlights
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004697 unbolden
Paul Mackerras63b79192006-05-20 21:31:52 +10004698 unhighlight_filelist
Paul Mackerras908c3582006-05-20 09:38:11 +10004699 }
Paul Mackerras63b79192006-05-20 21:31:52 +10004700 set highlight_paths {}
Paul Mackerras908c3582006-05-20 09:38:11 +10004701 after cancel do_file_hl $fh_serial
4702 incr fh_serial
4703 if {$highlight_files ne {}} {
4704 after 300 do_file_hl $fh_serial
4705 }
4706}
4707
Paul Mackerras687c8762007-09-22 12:49:33 +10004708proc gdttype_change {name ix op} {
4709 global gdttype highlight_files findstring findpattern
4710
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10004711 stopfinding
Paul Mackerras687c8762007-09-22 12:49:33 +10004712 if {$findstring ne {}} {
Christian Stimmingb007ee22007-11-07 18:44:35 +01004713 if {$gdttype eq [mc "containing:"]} {
Paul Mackerras687c8762007-09-22 12:49:33 +10004714 if {$highlight_files ne {}} {
4715 set highlight_files {}
4716 hfiles_change
4717 }
4718 findcom_change
4719 } else {
4720 if {$findpattern ne {}} {
4721 set findpattern {}
4722 findcom_change
4723 }
4724 set highlight_files $findstring
4725 hfiles_change
4726 }
4727 drawvisible
4728 }
4729 # enable/disable findtype/findloc menus too
4730}
4731
4732proc find_change {name ix op} {
4733 global gdttype findstring highlight_files
4734
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10004735 stopfinding
Christian Stimmingb007ee22007-11-07 18:44:35 +01004736 if {$gdttype eq [mc "containing:"]} {
Paul Mackerras687c8762007-09-22 12:49:33 +10004737 findcom_change
4738 } else {
4739 if {$highlight_files ne $findstring} {
4740 set highlight_files $findstring
4741 hfiles_change
4742 }
4743 }
4744 drawvisible
4745}
4746
Paul Mackerras64b5f142007-10-04 22:19:24 +10004747proc findcom_change args {
Paul Mackerras28593d32008-11-13 23:01:46 +11004748 global nhighlights boldnameids
Paul Mackerras687c8762007-09-22 12:49:33 +10004749 global findpattern findtype findstring gdttype
4750
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10004751 stopfinding
Paul Mackerras687c8762007-09-22 12:49:33 +10004752 # delete previous highlights, if any
Paul Mackerras28593d32008-11-13 23:01:46 +11004753 foreach id $boldnameids {
4754 bolden_name $id mainfont
Paul Mackerras687c8762007-09-22 12:49:33 +10004755 }
Paul Mackerras28593d32008-11-13 23:01:46 +11004756 set boldnameids {}
Paul Mackerras009409f2015-05-02 20:53:36 +10004757 unset -nocomplain nhighlights
Paul Mackerras687c8762007-09-22 12:49:33 +10004758 unbolden
4759 unmarkmatches
Christian Stimmingb007ee22007-11-07 18:44:35 +01004760 if {$gdttype ne [mc "containing:"] || $findstring eq {}} {
Paul Mackerras687c8762007-09-22 12:49:33 +10004761 set findpattern {}
Christian Stimmingb007ee22007-11-07 18:44:35 +01004762 } elseif {$findtype eq [mc "Regexp"]} {
Paul Mackerras687c8762007-09-22 12:49:33 +10004763 set findpattern $findstring
4764 } else {
4765 set e [string map {"*" "\\*" "?" "\\?" "\[" "\\\[" "\\" "\\\\"} \
4766 $findstring]
4767 set findpattern "*$e*"
4768 }
4769}
4770
Paul Mackerras63b79192006-05-20 21:31:52 +10004771proc makepatterns {l} {
4772 set ret {}
4773 foreach e $l {
4774 set ee [string map {"*" "\\*" "?" "\\?" "\[" "\\\[" "\\" "\\\\"} $e]
4775 if {[string index $ee end] eq "/"} {
4776 lappend ret "$ee*"
4777 } else {
4778 lappend ret $ee
4779 lappend ret "$ee/*"
4780 }
4781 }
4782 return $ret
4783}
4784
Paul Mackerras908c3582006-05-20 09:38:11 +10004785proc do_file_hl {serial} {
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004786 global highlight_files filehighlight highlight_paths gdttype fhl_list
Yggy Kingde665fd2011-07-13 01:30:26 -07004787 global cdup findtype
Paul Mackerras908c3582006-05-20 09:38:11 +10004788
Christian Stimmingb007ee22007-11-07 18:44:35 +01004789 if {$gdttype eq [mc "touching paths:"]} {
Yggy Kingde665fd2011-07-13 01:30:26 -07004790 # If "exact" match then convert backslashes to forward slashes.
4791 # Most useful to support Windows-flavoured file paths.
4792 if {$findtype eq [mc "Exact"]} {
4793 set highlight_files [string map {"\\" "/"} $highlight_files]
4794 }
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10004795 if {[catch {set paths [shellsplit $highlight_files]}]} return
4796 set highlight_paths [makepatterns $paths]
4797 highlight_filelist
Martin von Zweigbergkc332f442011-04-04 22:14:12 -04004798 set relative_paths {}
4799 foreach path $paths {
4800 lappend relative_paths [file join $cdup $path]
4801 }
4802 set gdtargs [concat -- $relative_paths]
Christian Stimmingb007ee22007-11-07 18:44:35 +01004803 } elseif {$gdttype eq [mc "adding/removing string:"]} {
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10004804 set gdtargs [list "-S$highlight_files"]
Martin Langhoffc33cb902012-06-14 20:34:11 +02004805 } elseif {$gdttype eq [mc "changing lines matching:"]} {
4806 set gdtargs [list "-G$highlight_files"]
Paul Mackerras687c8762007-09-22 12:49:33 +10004807 } else {
4808 # must be "containing:", i.e. we're searching commit info
4809 return
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10004810 }
Brandon Casey1ce09dd2007-03-19 18:00:37 -05004811 set cmd [concat | git diff-tree -r -s --stdin $gdtargs]
Paul Mackerras908c3582006-05-20 09:38:11 +10004812 set filehighlight [open $cmd r+]
4813 fconfigure $filehighlight -blocking 0
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004814 filerun $filehighlight readfhighlight
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004815 set fhl_list {}
Paul Mackerras908c3582006-05-20 09:38:11 +10004816 drawvisible
4817 flushhighlights
4818}
4819
4820proc flushhighlights {} {
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004821 global filehighlight fhl_list
Paul Mackerras908c3582006-05-20 09:38:11 +10004822
4823 if {[info exists filehighlight]} {
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004824 lappend fhl_list {}
Paul Mackerras908c3582006-05-20 09:38:11 +10004825 puts $filehighlight ""
4826 flush $filehighlight
4827 }
4828}
4829
4830proc askfilehighlight {row id} {
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004831 global filehighlight fhighlights fhl_list
Paul Mackerras908c3582006-05-20 09:38:11 +10004832
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004833 lappend fhl_list $id
Paul Mackerras476ca632008-01-07 22:16:31 +11004834 set fhighlights($id) -1
Paul Mackerras908c3582006-05-20 09:38:11 +10004835 puts $filehighlight $id
4836}
4837
4838proc readfhighlight {} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004839 global filehighlight fhighlights curview iddrawn
Paul Mackerras687c8762007-09-22 12:49:33 +10004840 global fhl_list find_dirn
Paul Mackerras908c3582006-05-20 09:38:11 +10004841
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004842 if {![info exists filehighlight]} {
4843 return 0
4844 }
4845 set nr 0
4846 while {[incr nr] <= 100 && [gets $filehighlight line] >= 0} {
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004847 set line [string trim $line]
4848 set i [lsearch -exact $fhl_list $line]
4849 if {$i < 0} continue
4850 for {set j 0} {$j < $i} {incr j} {
4851 set id [lindex $fhl_list $j]
Paul Mackerras476ca632008-01-07 22:16:31 +11004852 set fhighlights($id) 0
Paul Mackerras908c3582006-05-20 09:38:11 +10004853 }
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004854 set fhl_list [lrange $fhl_list [expr {$i+1}] end]
4855 if {$line eq {}} continue
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004856 if {![commitinview $line $curview]} continue
Paul Mackerras476ca632008-01-07 22:16:31 +11004857 if {[info exists iddrawn($line)] && ![ishighlighted $line]} {
Paul Mackerras28593d32008-11-13 23:01:46 +11004858 bolden $line mainfontbold
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004859 }
Paul Mackerras476ca632008-01-07 22:16:31 +11004860 set fhighlights($line) 1
Paul Mackerras908c3582006-05-20 09:38:11 +10004861 }
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004862 if {[eof $filehighlight]} {
4863 # strange...
Brandon Casey1ce09dd2007-03-19 18:00:37 -05004864 puts "oops, git diff-tree died"
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004865 catch {close $filehighlight}
4866 unset filehighlight
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004867 return 0
Paul Mackerras908c3582006-05-20 09:38:11 +10004868 }
Paul Mackerras687c8762007-09-22 12:49:33 +10004869 if {[info exists find_dirn]} {
Paul Mackerrascca5d942007-10-27 21:16:56 +10004870 run findmore
Paul Mackerras687c8762007-09-22 12:49:33 +10004871 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004872 return 1
Paul Mackerras908c3582006-05-20 09:38:11 +10004873}
4874
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004875proc doesmatch {f} {
Paul Mackerras687c8762007-09-22 12:49:33 +10004876 global findtype findpattern
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004877
Christian Stimmingb007ee22007-11-07 18:44:35 +01004878 if {$findtype eq [mc "Regexp"]} {
Paul Mackerras687c8762007-09-22 12:49:33 +10004879 return [regexp $findpattern $f]
Christian Stimmingb007ee22007-11-07 18:44:35 +01004880 } elseif {$findtype eq [mc "IgnCase"]} {
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004881 return [string match -nocase $findpattern $f]
4882 } else {
4883 return [string match $findpattern $f]
4884 }
4885}
4886
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10004887proc askfindhighlight {row id} {
Paul Mackerras9c311b32007-10-04 22:27:13 +10004888 global nhighlights commitinfo iddrawn
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004889 global findloc
4890 global markingmatches
Paul Mackerras908c3582006-05-20 09:38:11 +10004891
4892 if {![info exists commitinfo($id)]} {
4893 getcommit $id
4894 }
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10004895 set info $commitinfo($id)
Paul Mackerras908c3582006-05-20 09:38:11 +10004896 set isbold 0
Frédéric Brière585c27c2010-03-14 18:59:09 -04004897 set fldtypes [list [mc Headline] [mc Author] "" [mc Committer] "" [mc Comments]]
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10004898 foreach f $info ty $fldtypes {
Frédéric Brière585c27c2010-03-14 18:59:09 -04004899 if {$ty eq ""} continue
Christian Stimmingb007ee22007-11-07 18:44:35 +01004900 if {($findloc eq [mc "All fields"] || $findloc eq $ty) &&
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004901 [doesmatch $f]} {
Christian Stimmingb007ee22007-11-07 18:44:35 +01004902 if {$ty eq [mc "Author"]} {
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10004903 set isbold 2
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004904 break
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10004905 }
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004906 set isbold 1
Paul Mackerras908c3582006-05-20 09:38:11 +10004907 }
4908 }
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004909 if {$isbold && [info exists iddrawn($id)]} {
Paul Mackerras476ca632008-01-07 22:16:31 +11004910 if {![ishighlighted $id]} {
Paul Mackerras28593d32008-11-13 23:01:46 +11004911 bolden $id mainfontbold
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004912 if {$isbold > 1} {
Paul Mackerras28593d32008-11-13 23:01:46 +11004913 bolden_name $id mainfontbold
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004914 }
Paul Mackerras908c3582006-05-20 09:38:11 +10004915 }
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004916 if {$markingmatches} {
Paul Mackerras005a2f42007-07-26 22:36:39 +10004917 markrowmatches $row $id
Paul Mackerras908c3582006-05-20 09:38:11 +10004918 }
4919 }
Paul Mackerras476ca632008-01-07 22:16:31 +11004920 set nhighlights($id) $isbold
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004921}
4922
Paul Mackerras005a2f42007-07-26 22:36:39 +10004923proc markrowmatches {row id} {
4924 global canv canv2 linehtag linentag commitinfo findloc
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004925
Paul Mackerras005a2f42007-07-26 22:36:39 +10004926 set headline [lindex $commitinfo($id) 0]
4927 set author [lindex $commitinfo($id) 1]
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004928 $canv delete match$row
4929 $canv2 delete match$row
Christian Stimmingb007ee22007-11-07 18:44:35 +01004930 if {$findloc eq [mc "All fields"] || $findloc eq [mc "Headline"]} {
Paul Mackerras005a2f42007-07-26 22:36:39 +10004931 set m [findmatches $headline]
4932 if {$m ne {}} {
Paul Mackerras28593d32008-11-13 23:01:46 +11004933 markmatches $canv $row $headline $linehtag($id) $m \
4934 [$canv itemcget $linehtag($id) -font] $row
Paul Mackerras005a2f42007-07-26 22:36:39 +10004935 }
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004936 }
Christian Stimmingb007ee22007-11-07 18:44:35 +01004937 if {$findloc eq [mc "All fields"] || $findloc eq [mc "Author"]} {
Paul Mackerras005a2f42007-07-26 22:36:39 +10004938 set m [findmatches $author]
4939 if {$m ne {}} {
Paul Mackerras28593d32008-11-13 23:01:46 +11004940 markmatches $canv2 $row $author $linentag($id) $m \
4941 [$canv2 itemcget $linentag($id) -font] $row
Paul Mackerras005a2f42007-07-26 22:36:39 +10004942 }
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004943 }
4944}
4945
Paul Mackerras164ff272006-05-29 19:50:02 +10004946proc vrel_change {name ix op} {
4947 global highlight_related
4948
4949 rhighlight_none
Christian Stimmingb007ee22007-11-07 18:44:35 +01004950 if {$highlight_related ne [mc "None"]} {
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004951 run drawvisible
Paul Mackerras164ff272006-05-29 19:50:02 +10004952 }
4953}
4954
4955# prepare for testing whether commits are descendents or ancestors of a
4956proc rhighlight_sel {a} {
4957 global descendent desc_todo ancestor anc_todo
Paul Mackerras476ca632008-01-07 22:16:31 +11004958 global highlight_related
Paul Mackerras164ff272006-05-29 19:50:02 +10004959
Paul Mackerras009409f2015-05-02 20:53:36 +10004960 unset -nocomplain descendent
Paul Mackerras164ff272006-05-29 19:50:02 +10004961 set desc_todo [list $a]
Paul Mackerras009409f2015-05-02 20:53:36 +10004962 unset -nocomplain ancestor
Paul Mackerras164ff272006-05-29 19:50:02 +10004963 set anc_todo [list $a]
Christian Stimmingb007ee22007-11-07 18:44:35 +01004964 if {$highlight_related ne [mc "None"]} {
Paul Mackerras164ff272006-05-29 19:50:02 +10004965 rhighlight_none
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004966 run drawvisible
Paul Mackerras164ff272006-05-29 19:50:02 +10004967 }
4968}
4969
4970proc rhighlight_none {} {
4971 global rhighlights
4972
Paul Mackerras009409f2015-05-02 20:53:36 +10004973 unset -nocomplain rhighlights
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004974 unbolden
Paul Mackerras164ff272006-05-29 19:50:02 +10004975}
4976
4977proc is_descendent {a} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004978 global curview children descendent desc_todo
Paul Mackerras164ff272006-05-29 19:50:02 +10004979
4980 set v $curview
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004981 set la [rowofcommit $a]
Paul Mackerras164ff272006-05-29 19:50:02 +10004982 set todo $desc_todo
4983 set leftover {}
4984 set done 0
4985 for {set i 0} {$i < [llength $todo]} {incr i} {
4986 set do [lindex $todo $i]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004987 if {[rowofcommit $do] < $la} {
Paul Mackerras164ff272006-05-29 19:50:02 +10004988 lappend leftover $do
4989 continue
4990 }
4991 foreach nk $children($v,$do) {
4992 if {![info exists descendent($nk)]} {
4993 set descendent($nk) 1
4994 lappend todo $nk
4995 if {$nk eq $a} {
4996 set done 1
4997 }
4998 }
4999 }
5000 if {$done} {
5001 set desc_todo [concat $leftover [lrange $todo [expr {$i+1}] end]]
5002 return
5003 }
5004 }
5005 set descendent($a) 0
5006 set desc_todo $leftover
5007}
5008
5009proc is_ancestor {a} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005010 global curview parents ancestor anc_todo
Paul Mackerras164ff272006-05-29 19:50:02 +10005011
5012 set v $curview
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005013 set la [rowofcommit $a]
Paul Mackerras164ff272006-05-29 19:50:02 +10005014 set todo $anc_todo
5015 set leftover {}
5016 set done 0
5017 for {set i 0} {$i < [llength $todo]} {incr i} {
5018 set do [lindex $todo $i]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005019 if {![commitinview $do $v] || [rowofcommit $do] > $la} {
Paul Mackerras164ff272006-05-29 19:50:02 +10005020 lappend leftover $do
5021 continue
5022 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005023 foreach np $parents($v,$do) {
Paul Mackerras164ff272006-05-29 19:50:02 +10005024 if {![info exists ancestor($np)]} {
5025 set ancestor($np) 1
5026 lappend todo $np
5027 if {$np eq $a} {
5028 set done 1
5029 }
5030 }
5031 }
5032 if {$done} {
5033 set anc_todo [concat $leftover [lrange $todo [expr {$i+1}] end]]
5034 return
5035 }
5036 }
5037 set ancestor($a) 0
5038 set anc_todo $leftover
5039}
5040
5041proc askrelhighlight {row id} {
Paul Mackerras9c311b32007-10-04 22:27:13 +10005042 global descendent highlight_related iddrawn rhighlights
Paul Mackerras164ff272006-05-29 19:50:02 +10005043 global selectedline ancestor
5044
Paul Mackerras94b4a692008-05-20 20:51:06 +10005045 if {$selectedline eq {}} return
Paul Mackerras164ff272006-05-29 19:50:02 +10005046 set isbold 0
Christian Stimming55e34432008-01-09 22:23:18 +01005047 if {$highlight_related eq [mc "Descendant"] ||
5048 $highlight_related eq [mc "Not descendant"]} {
Paul Mackerras164ff272006-05-29 19:50:02 +10005049 if {![info exists descendent($id)]} {
5050 is_descendent $id
5051 }
Christian Stimming55e34432008-01-09 22:23:18 +01005052 if {$descendent($id) == ($highlight_related eq [mc "Descendant"])} {
Paul Mackerras164ff272006-05-29 19:50:02 +10005053 set isbold 1
5054 }
Christian Stimmingb007ee22007-11-07 18:44:35 +01005055 } elseif {$highlight_related eq [mc "Ancestor"] ||
5056 $highlight_related eq [mc "Not ancestor"]} {
Paul Mackerras164ff272006-05-29 19:50:02 +10005057 if {![info exists ancestor($id)]} {
5058 is_ancestor $id
5059 }
Christian Stimmingb007ee22007-11-07 18:44:35 +01005060 if {$ancestor($id) == ($highlight_related eq [mc "Ancestor"])} {
Paul Mackerras164ff272006-05-29 19:50:02 +10005061 set isbold 1
5062 }
5063 }
5064 if {[info exists iddrawn($id)]} {
Paul Mackerras476ca632008-01-07 22:16:31 +11005065 if {$isbold && ![ishighlighted $id]} {
Paul Mackerras28593d32008-11-13 23:01:46 +11005066 bolden $id mainfontbold
Paul Mackerras164ff272006-05-29 19:50:02 +10005067 }
5068 }
Paul Mackerras476ca632008-01-07 22:16:31 +11005069 set rhighlights($id) $isbold
Paul Mackerras164ff272006-05-29 19:50:02 +10005070}
5071
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10005072# Graph layout functions
5073
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005074proc shortids {ids} {
5075 set res {}
5076 foreach id $ids {
5077 if {[llength $id] > 1} {
5078 lappend res [shortids $id]
5079 } elseif {[regexp {^[0-9a-f]{40}$} $id]} {
5080 lappend res [string range $id 0 7]
5081 } else {
5082 lappend res $id
5083 }
5084 }
5085 return $res
5086}
5087
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005088proc ntimes {n o} {
5089 set ret {}
Paul Mackerras03800812007-08-29 21:45:21 +10005090 set o [list $o]
5091 for {set mask 1} {$mask <= $n} {incr mask $mask} {
5092 if {($n & $mask) != 0} {
5093 set ret [concat $ret $o]
5094 }
5095 set o [concat $o $o]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005096 }
5097 return $ret
5098}
5099
Paul Mackerras9257d8f2007-12-11 10:45:38 +11005100proc ordertoken {id} {
5101 global ordertok curview varcid varcstart varctok curview parents children
5102 global nullid nullid2
5103
5104 if {[info exists ordertok($id)]} {
5105 return $ordertok($id)
5106 }
5107 set origid $id
5108 set todo {}
5109 while {1} {
5110 if {[info exists varcid($curview,$id)]} {
5111 set a $varcid($curview,$id)
5112 set p [lindex $varcstart($curview) $a]
5113 } else {
5114 set p [lindex $children($curview,$id) 0]
5115 }
5116 if {[info exists ordertok($p)]} {
5117 set tok $ordertok($p)
5118 break
5119 }
Paul Mackerrasc8c9f3d2008-01-06 13:54:58 +11005120 set id [first_real_child $curview,$p]
5121 if {$id eq {}} {
Paul Mackerras9257d8f2007-12-11 10:45:38 +11005122 # it's a root
Paul Mackerras46308ea2008-01-15 22:16:32 +11005123 set tok [lindex $varctok($curview) $varcid($curview,$p)]
Paul Mackerras9257d8f2007-12-11 10:45:38 +11005124 break
5125 }
Paul Mackerras9257d8f2007-12-11 10:45:38 +11005126 if {[llength $parents($curview,$id)] == 1} {
5127 lappend todo [list $p {}]
5128 } else {
5129 set j [lsearch -exact $parents($curview,$id) $p]
5130 if {$j < 0} {
5131 puts "oops didn't find [shortids $p] in parents of [shortids $id]"
5132 }
5133 lappend todo [list $p [strrep $j]]
5134 }
5135 }
5136 for {set i [llength $todo]} {[incr i -1] >= 0} {} {
5137 set p [lindex $todo $i 0]
5138 append tok [lindex $todo $i 1]
5139 set ordertok($p) $tok
5140 }
5141 set ordertok($origid) $tok
5142 return $tok
5143}
5144
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005145# Work out where id should go in idlist so that order-token
5146# values increase from left to right
5147proc idcol {idlist id {i 0}} {
Paul Mackerras9257d8f2007-12-11 10:45:38 +11005148 set t [ordertoken $id]
Paul Mackerrase5b37ac2007-12-12 18:13:51 +11005149 if {$i < 0} {
5150 set i 0
5151 }
Paul Mackerras9257d8f2007-12-11 10:45:38 +11005152 if {$i >= [llength $idlist] || $t < [ordertoken [lindex $idlist $i]]} {
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005153 if {$i > [llength $idlist]} {
5154 set i [llength $idlist]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005155 }
Paul Mackerras9257d8f2007-12-11 10:45:38 +11005156 while {[incr i -1] >= 0 && $t < [ordertoken [lindex $idlist $i]]} {}
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005157 incr i
5158 } else {
Paul Mackerras9257d8f2007-12-11 10:45:38 +11005159 if {$t > [ordertoken [lindex $idlist $i]]} {
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005160 while {[incr i] < [llength $idlist] &&
Paul Mackerras9257d8f2007-12-11 10:45:38 +11005161 $t >= [ordertoken [lindex $idlist $i]]} {}
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005162 }
5163 }
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005164 return $i
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005165}
5166
5167proc initlayout {} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005168 global rowidlist rowisopt rowfinal displayorder parentlist
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10005169 global numcommits canvxmax canv
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11005170 global nextcolor
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10005171 global colormap rowtextx
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005172
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11005173 set numcommits 0
5174 set displayorder {}
Paul Mackerras79b2c752006-04-02 20:47:40 +10005175 set parentlist {}
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11005176 set nextcolor 0
Paul Mackerras03800812007-08-29 21:45:21 +10005177 set rowidlist {}
5178 set rowisopt {}
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10005179 set rowfinal {}
Paul Mackerrasbe0cd092006-03-31 09:55:11 +11005180 set canvxmax [$canv cget -width]
Paul Mackerras009409f2015-05-02 20:53:36 +10005181 unset -nocomplain colormap
5182 unset -nocomplain rowtextx
Paul Mackerrasac1276a2008-03-03 10:11:08 +11005183 setcanvscroll
Paul Mackerrasbe0cd092006-03-31 09:55:11 +11005184}
5185
5186proc setcanvscroll {} {
5187 global canv canv2 canv3 numcommits linespc canvxmax canvy0
Paul Mackerrasac1276a2008-03-03 10:11:08 +11005188 global lastscrollset lastscrollrows
Paul Mackerrasbe0cd092006-03-31 09:55:11 +11005189
5190 set ymax [expr {$canvy0 + ($numcommits - 0.5) * $linespc + 2}]
5191 $canv conf -scrollregion [list 0 0 $canvxmax $ymax]
5192 $canv2 conf -scrollregion [list 0 0 0 $ymax]
5193 $canv3 conf -scrollregion [list 0 0 0 $ymax]
Paul Mackerrasac1276a2008-03-03 10:11:08 +11005194 set lastscrollset [clock clicks -milliseconds]
5195 set lastscrollrows $numcommits
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005196}
5197
5198proc visiblerows {} {
5199 global canv numcommits linespc
5200
5201 set ymax [lindex [$canv cget -scrollregion] 3]
5202 if {$ymax eq {} || $ymax == 0} return
5203 set f [$canv yview]
5204 set y0 [expr {int([lindex $f 0] * $ymax)}]
5205 set r0 [expr {int(($y0 - 3) / $linespc) - 1}]
5206 if {$r0 < 0} {
5207 set r0 0
5208 }
5209 set y1 [expr {int([lindex $f 1] * $ymax)}]
5210 set r1 [expr {int(($y1 - 3) / $linespc) + 1}]
5211 if {$r1 >= $numcommits} {
5212 set r1 [expr {$numcommits - 1}]
5213 }
5214 return [list $r0 $r1]
5215}
5216
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10005217proc layoutmore {} {
Paul Mackerras38dfe932007-12-06 20:50:31 +11005218 global commitidx viewcomplete curview
Paul Mackerras94b4a692008-05-20 20:51:06 +10005219 global numcommits pending_select curview
Paul Mackerrasd375ef92008-10-21 10:18:12 +11005220 global lastscrollset lastscrollrows
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005221
Paul Mackerrasac1276a2008-03-03 10:11:08 +11005222 if {$lastscrollrows < 100 || $viewcomplete($curview) ||
5223 [clock clicks -milliseconds] - $lastscrollset > 500} {
Paul Mackerrasa2c22362006-10-31 15:00:53 +11005224 setcanvscroll
5225 }
Paul Mackerrasd94f8cd2006-04-06 10:18:23 +10005226 if {[info exists pending_select] &&
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005227 [commitinview $pending_select $curview]} {
Alexander Gavrilov567c34e2008-07-26 20:13:45 +04005228 update
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005229 selectline [rowofcommit $pending_select] 1
Paul Mackerrasd94f8cd2006-04-06 10:18:23 +10005230 }
Paul Mackerrasac1276a2008-03-03 10:11:08 +11005231 drawvisible
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005232}
5233
Paul Mackerrascdc84292008-11-18 19:54:14 +11005234# With path limiting, we mightn't get the actual HEAD commit,
5235# so ask git rev-list what is the first ancestor of HEAD that
5236# touches a file in the path limit.
5237proc get_viewmainhead {view} {
5238 global viewmainheadid vfilelimit viewinstances mainheadid
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005239
Paul Mackerrascdc84292008-11-18 19:54:14 +11005240 catch {
5241 set rfd [open [concat | git rev-list -1 $mainheadid \
5242 -- $vfilelimit($view)] r]
5243 set j [reg_instance $rfd]
5244 lappend viewinstances($view) $j
5245 fconfigure $rfd -blocking 0
5246 filerun $rfd [list getviewhead $rfd $j $view]
5247 set viewmainheadid($curview) {}
5248 }
5249}
5250
5251# git rev-list should give us just 1 line to use as viewmainheadid($view)
5252proc getviewhead {fd inst view} {
5253 global viewmainheadid commfd curview viewinstances showlocalchanges
5254
5255 set id {}
5256 if {[gets $fd line] < 0} {
5257 if {![eof $fd]} {
5258 return 1
5259 }
5260 } elseif {[string length $line] == 40 && [string is xdigit $line]} {
5261 set id $line
5262 }
5263 set viewmainheadid($view) $id
5264 close $fd
5265 unset commfd($inst)
5266 set i [lsearch -exact $viewinstances($view) $inst]
5267 if {$i >= 0} {
5268 set viewinstances($view) [lreplace $viewinstances($view) $i $i]
5269 }
5270 if {$showlocalchanges && $id ne {} && $view == $curview} {
5271 doshowlocalchanges
5272 }
5273 return 0
5274}
5275
5276proc doshowlocalchanges {} {
5277 global curview viewmainheadid
5278
5279 if {$viewmainheadid($curview) eq {}} return
5280 if {[commitinview $viewmainheadid($curview) $curview]} {
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005281 dodiffindex
Paul Mackerras38dfe932007-12-06 20:50:31 +11005282 } else {
Paul Mackerrascdc84292008-11-18 19:54:14 +11005283 interestedin $viewmainheadid($curview) dodiffindex
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005284 }
5285}
5286
5287proc dohidelocalchanges {} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005288 global nullid nullid2 lserial curview
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005289
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005290 if {[commitinview $nullid $curview]} {
Paul Mackerrasb8a938c2008-02-13 22:12:31 +11005291 removefakerow $nullid
Paul Mackerras8f489362007-07-13 19:49:37 +10005292 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005293 if {[commitinview $nullid2 $curview]} {
Paul Mackerrasb8a938c2008-02-13 22:12:31 +11005294 removefakerow $nullid2
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005295 }
5296 incr lserial
5297}
5298
Paul Mackerras8f489362007-07-13 19:49:37 +10005299# spawn off a process to do git diff-index --cached HEAD
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005300proc dodiffindex {} {
Paul Mackerrascdc84292008-11-18 19:54:14 +11005301 global lserial showlocalchanges vfilelimit curview
Jens Lehmann17f98362014-04-08 21:36:08 +02005302 global hasworktree git_version
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005303
Martin von Zweigbergk74cb8842011-05-23 22:44:08 -04005304 if {!$showlocalchanges || !$hasworktree} return
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005305 incr lserial
Jens Lehmann17f98362014-04-08 21:36:08 +02005306 if {[package vcompare $git_version "1.7.2"] >= 0} {
5307 set cmd "|git diff-index --cached --ignore-submodules=dirty HEAD"
5308 } else {
5309 set cmd "|git diff-index --cached HEAD"
5310 }
Paul Mackerrascdc84292008-11-18 19:54:14 +11005311 if {$vfilelimit($curview) ne {}} {
5312 set cmd [concat $cmd -- $vfilelimit($curview)]
5313 }
5314 set fd [open $cmd r]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005315 fconfigure $fd -blocking 0
Alexander Gavrilove439e092008-07-13 16:40:47 +04005316 set i [reg_instance $fd]
5317 filerun $fd [list readdiffindex $fd $lserial $i]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005318}
5319
Alexander Gavrilove439e092008-07-13 16:40:47 +04005320proc readdiffindex {fd serial inst} {
Paul Mackerrascdc84292008-11-18 19:54:14 +11005321 global viewmainheadid nullid nullid2 curview commitinfo commitdata lserial
5322 global vfilelimit
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005323
Paul Mackerras8f489362007-07-13 19:49:37 +10005324 set isdiff 1
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005325 if {[gets $fd line] < 0} {
Paul Mackerras8f489362007-07-13 19:49:37 +10005326 if {![eof $fd]} {
5327 return 1
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005328 }
Paul Mackerras8f489362007-07-13 19:49:37 +10005329 set isdiff 0
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005330 }
5331 # we only need to see one line and we don't really care what it says...
Alexander Gavrilove439e092008-07-13 16:40:47 +04005332 stop_instance $inst
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005333
Paul Mackerras24f7a662007-12-19 09:35:33 +11005334 if {$serial != $lserial} {
5335 return 0
Paul Mackerras8f489362007-07-13 19:49:37 +10005336 }
5337
Paul Mackerras24f7a662007-12-19 09:35:33 +11005338 # now see if there are any local changes not checked in to the index
Paul Mackerrascdc84292008-11-18 19:54:14 +11005339 set cmd "|git diff-files"
5340 if {$vfilelimit($curview) ne {}} {
5341 set cmd [concat $cmd -- $vfilelimit($curview)]
5342 }
5343 set fd [open $cmd r]
Paul Mackerras24f7a662007-12-19 09:35:33 +11005344 fconfigure $fd -blocking 0
Alexander Gavrilove439e092008-07-13 16:40:47 +04005345 set i [reg_instance $fd]
5346 filerun $fd [list readdifffiles $fd $serial $i]
Paul Mackerras24f7a662007-12-19 09:35:33 +11005347
5348 if {$isdiff && ![commitinview $nullid2 $curview]} {
Paul Mackerras8f489362007-07-13 19:49:37 +10005349 # add the line for the changes in the index to the graph
Christian Stimmingd990ced2007-11-07 18:42:55 +01005350 set hl [mc "Local changes checked in to index but not committed"]
Paul Mackerras8f489362007-07-13 19:49:37 +10005351 set commitinfo($nullid2) [list $hl {} {} {} {} " $hl\n"]
5352 set commitdata($nullid2) "\n $hl\n"
Paul Mackerrasfc2a2562007-12-26 23:03:43 +11005353 if {[commitinview $nullid $curview]} {
Paul Mackerrasb8a938c2008-02-13 22:12:31 +11005354 removefakerow $nullid
Paul Mackerrasfc2a2562007-12-26 23:03:43 +11005355 }
Paul Mackerrascdc84292008-11-18 19:54:14 +11005356 insertfakerow $nullid2 $viewmainheadid($curview)
Paul Mackerras24f7a662007-12-19 09:35:33 +11005357 } elseif {!$isdiff && [commitinview $nullid2 $curview]} {
Paul Mackerrascdc84292008-11-18 19:54:14 +11005358 if {[commitinview $nullid $curview]} {
5359 removefakerow $nullid
5360 }
Paul Mackerrasb8a938c2008-02-13 22:12:31 +11005361 removefakerow $nullid2
Paul Mackerras8f489362007-07-13 19:49:37 +10005362 }
5363 return 0
5364}
5365
Alexander Gavrilove439e092008-07-13 16:40:47 +04005366proc readdifffiles {fd serial inst} {
Paul Mackerrascdc84292008-11-18 19:54:14 +11005367 global viewmainheadid nullid nullid2 curview
Paul Mackerras8f489362007-07-13 19:49:37 +10005368 global commitinfo commitdata lserial
5369
5370 set isdiff 1
5371 if {[gets $fd line] < 0} {
5372 if {![eof $fd]} {
5373 return 1
5374 }
5375 set isdiff 0
5376 }
5377 # we only need to see one line and we don't really care what it says...
Alexander Gavrilove439e092008-07-13 16:40:47 +04005378 stop_instance $inst
Paul Mackerras8f489362007-07-13 19:49:37 +10005379
Paul Mackerras24f7a662007-12-19 09:35:33 +11005380 if {$serial != $lserial} {
5381 return 0
5382 }
5383
5384 if {$isdiff && ![commitinview $nullid $curview]} {
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005385 # add the line for the local diff to the graph
Christian Stimmingd990ced2007-11-07 18:42:55 +01005386 set hl [mc "Local uncommitted changes, not checked in to index"]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005387 set commitinfo($nullid) [list $hl {} {} {} {} " $hl\n"]
5388 set commitdata($nullid) "\n $hl\n"
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005389 if {[commitinview $nullid2 $curview]} {
5390 set p $nullid2
5391 } else {
Paul Mackerrascdc84292008-11-18 19:54:14 +11005392 set p $viewmainheadid($curview)
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005393 }
Paul Mackerrasb8a938c2008-02-13 22:12:31 +11005394 insertfakerow $nullid $p
Paul Mackerras24f7a662007-12-19 09:35:33 +11005395 } elseif {!$isdiff && [commitinview $nullid $curview]} {
Paul Mackerrasb8a938c2008-02-13 22:12:31 +11005396 removefakerow $nullid
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005397 }
5398 return 0
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005399}
5400
Paul Mackerras8f0bc7e2007-08-24 22:16:42 +10005401proc nextuse {id row} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005402 global curview children
Paul Mackerras8f0bc7e2007-08-24 22:16:42 +10005403
5404 if {[info exists children($curview,$id)]} {
5405 foreach kid $children($curview,$id) {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005406 if {![commitinview $kid $curview]} {
Paul Mackerras03800812007-08-29 21:45:21 +10005407 return -1
5408 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005409 if {[rowofcommit $kid] > $row} {
5410 return [rowofcommit $kid]
Paul Mackerras8f0bc7e2007-08-24 22:16:42 +10005411 }
5412 }
5413 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005414 if {[commitinview $id $curview]} {
5415 return [rowofcommit $id]
Paul Mackerras8f0bc7e2007-08-24 22:16:42 +10005416 }
5417 return -1
5418}
5419
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10005420proc prevuse {id row} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005421 global curview children
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10005422
5423 set ret -1
5424 if {[info exists children($curview,$id)]} {
5425 foreach kid $children($curview,$id) {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005426 if {![commitinview $kid $curview]} break
5427 if {[rowofcommit $kid] < $row} {
5428 set ret [rowofcommit $kid]
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10005429 }
5430 }
5431 }
5432 return $ret
5433}
5434
Paul Mackerras03800812007-08-29 21:45:21 +10005435proc make_idlist {row} {
5436 global displayorder parentlist uparrowlen downarrowlen mingaplen
Paul Mackerras9257d8f2007-12-11 10:45:38 +11005437 global commitidx curview children
Paul Mackerras03800812007-08-29 21:45:21 +10005438
5439 set r [expr {$row - $mingaplen - $downarrowlen - 1}]
5440 if {$r < 0} {
5441 set r 0
5442 }
5443 set ra [expr {$row - $downarrowlen}]
5444 if {$ra < 0} {
5445 set ra 0
5446 }
5447 set rb [expr {$row + $uparrowlen}]
5448 if {$rb > $commitidx($curview)} {
5449 set rb $commitidx($curview)
5450 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005451 make_disporder $r [expr {$rb + 1}]
Paul Mackerras03800812007-08-29 21:45:21 +10005452 set ids {}
5453 for {} {$r < $ra} {incr r} {
5454 set nextid [lindex $displayorder [expr {$r + 1}]]
5455 foreach p [lindex $parentlist $r] {
5456 if {$p eq $nextid} continue
5457 set rn [nextuse $p $r]
5458 if {$rn >= $row &&
5459 $rn <= $r + $downarrowlen + $mingaplen + $uparrowlen} {
Paul Mackerras9257d8f2007-12-11 10:45:38 +11005460 lappend ids [list [ordertoken $p] $p]
Paul Mackerras03800812007-08-29 21:45:21 +10005461 }
5462 }
5463 }
5464 for {} {$r < $row} {incr r} {
5465 set nextid [lindex $displayorder [expr {$r + 1}]]
5466 foreach p [lindex $parentlist $r] {
5467 if {$p eq $nextid} continue
5468 set rn [nextuse $p $r]
5469 if {$rn < 0 || $rn >= $row} {
Paul Mackerras9257d8f2007-12-11 10:45:38 +11005470 lappend ids [list [ordertoken $p] $p]
Paul Mackerras03800812007-08-29 21:45:21 +10005471 }
5472 }
5473 }
5474 set id [lindex $displayorder $row]
Paul Mackerras9257d8f2007-12-11 10:45:38 +11005475 lappend ids [list [ordertoken $id] $id]
Paul Mackerras03800812007-08-29 21:45:21 +10005476 while {$r < $rb} {
5477 foreach p [lindex $parentlist $r] {
5478 set firstkid [lindex $children($curview,$p) 0]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005479 if {[rowofcommit $firstkid] < $row} {
Paul Mackerras9257d8f2007-12-11 10:45:38 +11005480 lappend ids [list [ordertoken $p] $p]
Paul Mackerras03800812007-08-29 21:45:21 +10005481 }
5482 }
5483 incr r
5484 set id [lindex $displayorder $r]
5485 if {$id ne {}} {
5486 set firstkid [lindex $children($curview,$id) 0]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005487 if {$firstkid ne {} && [rowofcommit $firstkid] < $row} {
Paul Mackerras9257d8f2007-12-11 10:45:38 +11005488 lappend ids [list [ordertoken $id] $id]
Paul Mackerras03800812007-08-29 21:45:21 +10005489 }
5490 }
5491 }
5492 set idlist {}
5493 foreach idx [lsort -unique $ids] {
5494 lappend idlist [lindex $idx 1]
5495 }
5496 return $idlist
5497}
5498
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10005499proc rowsequal {a b} {
5500 while {[set i [lsearch -exact $a {}]] >= 0} {
5501 set a [lreplace $a $i $i]
5502 }
5503 while {[set i [lsearch -exact $b {}]] >= 0} {
5504 set b [lreplace $b $i $i]
5505 }
5506 return [expr {$a eq $b}]
5507}
5508
5509proc makeupline {id row rend col} {
5510 global rowidlist uparrowlen downarrowlen mingaplen
5511
5512 for {set r $rend} {1} {set r $rstart} {
5513 set rstart [prevuse $id $r]
5514 if {$rstart < 0} return
5515 if {$rstart < $row} break
5516 }
5517 if {$rstart + $uparrowlen + $mingaplen + $downarrowlen < $rend} {
5518 set rstart [expr {$rend - $uparrowlen - 1}]
5519 }
5520 for {set r $rstart} {[incr r] <= $row} {} {
5521 set idlist [lindex $rowidlist $r]
5522 if {$idlist ne {} && [lsearch -exact $idlist $id] < 0} {
5523 set col [idcol $idlist $id $col]
5524 lset rowidlist $r [linsert $idlist $col $id]
5525 changedrow $r
5526 }
5527 }
5528}
5529
Paul Mackerras03800812007-08-29 21:45:21 +10005530proc layoutrows {row endrow} {
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10005531 global rowidlist rowisopt rowfinal displayorder
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005532 global uparrowlen downarrowlen maxwidth mingaplen
Paul Mackerras6a90bff2007-06-18 09:48:23 +10005533 global children parentlist
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005534 global commitidx viewcomplete curview
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005535
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005536 make_disporder [expr {$row - 1}] [expr {$endrow + $uparrowlen}]
Paul Mackerras03800812007-08-29 21:45:21 +10005537 set idlist {}
5538 if {$row > 0} {
Paul Mackerrasf56782a2007-09-15 09:04:11 +10005539 set rm1 [expr {$row - 1}]
5540 foreach id [lindex $rowidlist $rm1] {
Paul Mackerras03800812007-08-29 21:45:21 +10005541 if {$id ne {}} {
5542 lappend idlist $id
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005543 }
5544 }
Paul Mackerrasf56782a2007-09-15 09:04:11 +10005545 set final [lindex $rowfinal $rm1]
Paul Mackerras8f0bc7e2007-08-24 22:16:42 +10005546 }
Paul Mackerras03800812007-08-29 21:45:21 +10005547 for {} {$row < $endrow} {incr row} {
5548 set rm1 [expr {$row - 1}]
Paul Mackerrasf56782a2007-09-15 09:04:11 +10005549 if {$rm1 < 0 || $idlist eq {}} {
Paul Mackerras03800812007-08-29 21:45:21 +10005550 set idlist [make_idlist $row]
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10005551 set final 1
Paul Mackerras03800812007-08-29 21:45:21 +10005552 } else {
5553 set id [lindex $displayorder $rm1]
5554 set col [lsearch -exact $idlist $id]
5555 set idlist [lreplace $idlist $col $col]
5556 foreach p [lindex $parentlist $rm1] {
5557 if {[lsearch -exact $idlist $p] < 0} {
5558 set col [idcol $idlist $p $col]
5559 set idlist [linsert $idlist $col $p]
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10005560 # if not the first child, we have to insert a line going up
5561 if {$id ne [lindex $children($curview,$p) 0]} {
5562 makeupline $p $rm1 $row $col
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005563 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005564 }
5565 }
Paul Mackerras03800812007-08-29 21:45:21 +10005566 set id [lindex $displayorder $row]
5567 if {$row > $downarrowlen} {
5568 set termrow [expr {$row - $downarrowlen - 1}]
5569 foreach p [lindex $parentlist $termrow] {
5570 set i [lsearch -exact $idlist $p]
5571 if {$i < 0} continue
5572 set nr [nextuse $p $termrow]
5573 if {$nr < 0 || $nr >= $row + $mingaplen + $uparrowlen} {
5574 set idlist [lreplace $idlist $i $i]
5575 }
5576 }
5577 }
5578 set col [lsearch -exact $idlist $id]
5579 if {$col < 0} {
5580 set col [idcol $idlist $id]
5581 set idlist [linsert $idlist $col $id]
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10005582 if {$children($curview,$id) ne {}} {
5583 makeupline $id $rm1 $row $col
5584 }
Paul Mackerras03800812007-08-29 21:45:21 +10005585 }
5586 set r [expr {$row + $uparrowlen - 1}]
5587 if {$r < $commitidx($curview)} {
5588 set x $col
5589 foreach p [lindex $parentlist $r] {
5590 if {[lsearch -exact $idlist $p] >= 0} continue
5591 set fk [lindex $children($curview,$p) 0]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005592 if {[rowofcommit $fk] < $row} {
Paul Mackerras03800812007-08-29 21:45:21 +10005593 set x [idcol $idlist $p $x]
5594 set idlist [linsert $idlist $x $p]
5595 }
5596 }
5597 if {[incr r] < $commitidx($curview)} {
5598 set p [lindex $displayorder $r]
5599 if {[lsearch -exact $idlist $p] < 0} {
5600 set fk [lindex $children($curview,$p) 0]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005601 if {$fk ne {} && [rowofcommit $fk] < $row} {
Paul Mackerras03800812007-08-29 21:45:21 +10005602 set x [idcol $idlist $p $x]
5603 set idlist [linsert $idlist $x $p]
5604 }
5605 }
5606 }
Paul Mackerras7b459a12007-08-13 14:52:00 +10005607 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005608 }
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10005609 if {$final && !$viewcomplete($curview) &&
5610 $row + $uparrowlen + $mingaplen + $downarrowlen
5611 >= $commitidx($curview)} {
5612 set final 0
Paul Mackerras7b459a12007-08-13 14:52:00 +10005613 }
Paul Mackerras03800812007-08-29 21:45:21 +10005614 set l [llength $rowidlist]
5615 if {$row == $l} {
5616 lappend rowidlist $idlist
5617 lappend rowisopt 0
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10005618 lappend rowfinal $final
Paul Mackerras03800812007-08-29 21:45:21 +10005619 } elseif {$row < $l} {
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10005620 if {![rowsequal $idlist [lindex $rowidlist $row]]} {
Paul Mackerras03800812007-08-29 21:45:21 +10005621 lset rowidlist $row $idlist
5622 changedrow $row
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005623 }
Paul Mackerrasf56782a2007-09-15 09:04:11 +10005624 lset rowfinal $row $final
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005625 } else {
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10005626 set pad [ntimes [expr {$row - $l}] {}]
5627 set rowidlist [concat $rowidlist $pad]
Paul Mackerras03800812007-08-29 21:45:21 +10005628 lappend rowidlist $idlist
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10005629 set rowfinal [concat $rowfinal $pad]
5630 lappend rowfinal $final
Paul Mackerras03800812007-08-29 21:45:21 +10005631 set rowisopt [concat $rowisopt [ntimes [expr {$row - $l + 1}] 0]]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005632 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005633 }
5634 return $row
5635}
5636
Paul Mackerras03800812007-08-29 21:45:21 +10005637proc changedrow {row} {
5638 global displayorder iddrawn rowisopt need_redisplay
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005639
Paul Mackerras03800812007-08-29 21:45:21 +10005640 set l [llength $rowisopt]
5641 if {$row < $l} {
5642 lset rowisopt $row 0
5643 if {$row + 1 < $l} {
5644 lset rowisopt [expr {$row + 1}] 0
5645 if {$row + 2 < $l} {
5646 lset rowisopt [expr {$row + 2}] 0
5647 }
5648 }
Paul Mackerras79b2c752006-04-02 20:47:40 +10005649 }
Paul Mackerras03800812007-08-29 21:45:21 +10005650 set id [lindex $displayorder $row]
5651 if {[info exists iddrawn($id)]} {
5652 set need_redisplay 1
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005653 }
5654}
5655
5656proc insert_pad {row col npad} {
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005657 global rowidlist
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005658
5659 set pad [ntimes $npad {}]
Paul Mackerrase341c062007-08-12 12:42:57 +10005660 set idlist [lindex $rowidlist $row]
5661 set bef [lrange $idlist 0 [expr {$col - 1}]]
5662 set aft [lrange $idlist $col end]
5663 set i [lsearch -exact $aft {}]
5664 if {$i > 0} {
5665 set aft [lreplace $aft $i $i]
5666 }
5667 lset rowidlist $row [concat $bef $pad $aft]
Paul Mackerras03800812007-08-29 21:45:21 +10005668 changedrow $row
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005669}
5670
5671proc optimize_rows {row col endrow} {
Paul Mackerras03800812007-08-29 21:45:21 +10005672 global rowidlist rowisopt displayorder curview children
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005673
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005674 if {$row < 1} {
5675 set row 1
5676 }
Paul Mackerras03800812007-08-29 21:45:21 +10005677 for {} {$row < $endrow} {incr row; set col 0} {
5678 if {[lindex $rowisopt $row]} continue
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005679 set haspad 0
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005680 set y0 [expr {$row - 1}]
5681 set ym [expr {$row - 2}]
Paul Mackerras03800812007-08-29 21:45:21 +10005682 set idlist [lindex $rowidlist $row]
5683 set previdlist [lindex $rowidlist $y0]
5684 if {$idlist eq {} || $previdlist eq {}} continue
5685 if {$ym >= 0} {
5686 set pprevidlist [lindex $rowidlist $ym]
5687 if {$pprevidlist eq {}} continue
5688 } else {
5689 set pprevidlist {}
5690 }
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005691 set x0 -1
5692 set xm -1
5693 for {} {$col < [llength $idlist]} {incr col} {
5694 set id [lindex $idlist $col]
5695 if {[lindex $previdlist $col] eq $id} continue
5696 if {$id eq {}} {
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005697 set haspad 1
5698 continue
5699 }
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005700 set x0 [lsearch -exact $previdlist $id]
5701 if {$x0 < 0} continue
5702 set z [expr {$x0 - $col}]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005703 set isarrow 0
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005704 set z0 {}
5705 if {$ym >= 0} {
5706 set xm [lsearch -exact $pprevidlist $id]
5707 if {$xm >= 0} {
5708 set z0 [expr {$xm - $x0}]
5709 }
5710 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005711 if {$z0 eq {}} {
Paul Mackerras92ed6662007-08-22 22:35:28 +10005712 # if row y0 is the first child of $id then it's not an arrow
5713 if {[lindex $children($curview,$id) 0] ne
5714 [lindex $displayorder $y0]} {
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005715 set isarrow 1
5716 }
5717 }
Paul Mackerrase341c062007-08-12 12:42:57 +10005718 if {!$isarrow && $id ne [lindex $displayorder $row] &&
5719 [lsearch -exact [lindex $rowidlist [expr {$row+1}]] $id] < 0} {
5720 set isarrow 1
5721 }
Paul Mackerras3fc42792006-09-15 09:45:23 +10005722 # Looking at lines from this row to the previous row,
5723 # make them go straight up if they end in an arrow on
5724 # the previous row; otherwise make them go straight up
5725 # or at 45 degrees.
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005726 if {$z < -1 || ($z < 0 && $isarrow)} {
Paul Mackerras3fc42792006-09-15 09:45:23 +10005727 # Line currently goes left too much;
5728 # insert pads in the previous row, then optimize it
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005729 set npad [expr {-1 - $z + $isarrow}]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005730 insert_pad $y0 $x0 $npad
5731 if {$y0 > 0} {
5732 optimize_rows $y0 $x0 $row
5733 }
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005734 set previdlist [lindex $rowidlist $y0]
5735 set x0 [lsearch -exact $previdlist $id]
5736 set z [expr {$x0 - $col}]
5737 if {$z0 ne {}} {
5738 set pprevidlist [lindex $rowidlist $ym]
5739 set xm [lsearch -exact $pprevidlist $id]
5740 set z0 [expr {$xm - $x0}]
5741 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005742 } elseif {$z > 1 || ($z > 0 && $isarrow)} {
Paul Mackerras3fc42792006-09-15 09:45:23 +10005743 # Line currently goes right too much;
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005744 # insert pads in this line
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005745 set npad [expr {$z - 1 + $isarrow}]
Paul Mackerrase341c062007-08-12 12:42:57 +10005746 insert_pad $row $col $npad
5747 set idlist [lindex $rowidlist $row]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005748 incr col $npad
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005749 set z [expr {$x0 - $col}]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005750 set haspad 1
5751 }
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005752 if {$z0 eq {} && !$isarrow && $ym >= 0} {
Paul Mackerraseb447a12006-03-18 23:11:37 +11005753 # this line links to its first child on row $row-2
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005754 set id [lindex $displayorder $ym]
5755 set xc [lsearch -exact $pprevidlist $id]
Paul Mackerraseb447a12006-03-18 23:11:37 +11005756 if {$xc >= 0} {
5757 set z0 [expr {$xc - $x0}]
5758 }
5759 }
Paul Mackerras3fc42792006-09-15 09:45:23 +10005760 # avoid lines jigging left then immediately right
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005761 if {$z0 ne {} && $z < 0 && $z0 > 0} {
5762 insert_pad $y0 $x0 1
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005763 incr x0
5764 optimize_rows $y0 $x0 $row
5765 set previdlist [lindex $rowidlist $y0]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005766 }
5767 }
5768 if {!$haspad} {
Paul Mackerras3fc42792006-09-15 09:45:23 +10005769 # Find the first column that doesn't have a line going right
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005770 for {set col [llength $idlist]} {[incr col -1] >= 0} {} {
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005771 set id [lindex $idlist $col]
5772 if {$id eq {}} break
5773 set x0 [lsearch -exact $previdlist $id]
5774 if {$x0 < 0} {
Paul Mackerraseb447a12006-03-18 23:11:37 +11005775 # check if this is the link to the first child
Paul Mackerras92ed6662007-08-22 22:35:28 +10005776 set kid [lindex $displayorder $y0]
5777 if {[lindex $children($curview,$id) 0] eq $kid} {
Paul Mackerraseb447a12006-03-18 23:11:37 +11005778 # it is, work out offset to child
Paul Mackerras92ed6662007-08-22 22:35:28 +10005779 set x0 [lsearch -exact $previdlist $kid]
Paul Mackerraseb447a12006-03-18 23:11:37 +11005780 }
5781 }
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005782 if {$x0 <= $col} break
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005783 }
Paul Mackerras3fc42792006-09-15 09:45:23 +10005784 # Insert a pad at that column as long as it has a line and
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005785 # isn't the last column
5786 if {$x0 >= 0 && [incr col] < [llength $idlist]} {
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005787 set idlist [linsert $idlist $col {}]
Paul Mackerras03800812007-08-29 21:45:21 +10005788 lset rowidlist $row $idlist
5789 changedrow $row
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005790 }
5791 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005792 }
5793}
5794
5795proc xc {row col} {
5796 global canvx0 linespc
5797 return [expr {$canvx0 + $col * $linespc}]
5798}
5799
5800proc yc {row} {
5801 global canvy0 linespc
5802 return [expr {$canvy0 + $row * $linespc}]
5803}
5804
Paul Mackerrasc934a8a2006-03-02 23:00:44 +11005805proc linewidth {id} {
5806 global thickerline lthickness
5807
5808 set wid $lthickness
5809 if {[info exists thickerline] && $id eq $thickerline} {
5810 set wid [expr {2 * $lthickness}]
5811 }
5812 return $wid
5813}
5814
Paul Mackerras50b44ec2006-04-04 10:16:22 +10005815proc rowranges {id} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005816 global curview children uparrowlen downarrowlen
Paul Mackerras92ed6662007-08-22 22:35:28 +10005817 global rowidlist
Paul Mackerras50b44ec2006-04-04 10:16:22 +10005818
Paul Mackerras92ed6662007-08-22 22:35:28 +10005819 set kids $children($curview,$id)
5820 if {$kids eq {}} {
5821 return {}
Paul Mackerras50b44ec2006-04-04 10:16:22 +10005822 }
Paul Mackerras92ed6662007-08-22 22:35:28 +10005823 set ret {}
5824 lappend kids $id
5825 foreach child $kids {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005826 if {![commitinview $child $curview]} break
5827 set row [rowofcommit $child]
Paul Mackerras92ed6662007-08-22 22:35:28 +10005828 if {![info exists prev]} {
5829 lappend ret [expr {$row + 1}]
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005830 } else {
Paul Mackerras92ed6662007-08-22 22:35:28 +10005831 if {$row <= $prevrow} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005832 puts "oops children of [shortids $id] out of order [shortids $child] $row <= [shortids $prev] $prevrow"
Paul Mackerras92ed6662007-08-22 22:35:28 +10005833 }
5834 # see if the line extends the whole way from prevrow to row
5835 if {$row > $prevrow + $uparrowlen + $downarrowlen &&
5836 [lsearch -exact [lindex $rowidlist \
5837 [expr {int(($row + $prevrow) / 2)}]] $id] < 0} {
5838 # it doesn't, see where it ends
5839 set r [expr {$prevrow + $downarrowlen}]
5840 if {[lsearch -exact [lindex $rowidlist $r] $id] < 0} {
5841 while {[incr r -1] > $prevrow &&
5842 [lsearch -exact [lindex $rowidlist $r] $id] < 0} {}
5843 } else {
5844 while {[incr r] <= $row &&
5845 [lsearch -exact [lindex $rowidlist $r] $id] >= 0} {}
5846 incr r -1
5847 }
5848 lappend ret $r
5849 # see where it starts up again
5850 set r [expr {$row - $uparrowlen}]
5851 if {[lsearch -exact [lindex $rowidlist $r] $id] < 0} {
5852 while {[incr r] < $row &&
5853 [lsearch -exact [lindex $rowidlist $r] $id] < 0} {}
5854 } else {
5855 while {[incr r -1] >= $prevrow &&
5856 [lsearch -exact [lindex $rowidlist $r] $id] >= 0} {}
5857 incr r
5858 }
5859 lappend ret $r
5860 }
Paul Mackerraseb447a12006-03-18 23:11:37 +11005861 }
Paul Mackerras92ed6662007-08-22 22:35:28 +10005862 if {$child eq $id} {
5863 lappend ret $row
5864 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005865 set prev $child
Paul Mackerras92ed6662007-08-22 22:35:28 +10005866 set prevrow $row
Paul Mackerraseb447a12006-03-18 23:11:37 +11005867 }
Paul Mackerras92ed6662007-08-22 22:35:28 +10005868 return $ret
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005869}
5870
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005871proc drawlineseg {id row endrow arrowlow} {
5872 global rowidlist displayorder iddrawn linesegs
Paul Mackerrase341c062007-08-12 12:42:57 +10005873 global canv colormap linespc curview maxlinelen parentlist
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005874
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005875 set cols [list [lsearch -exact [lindex $rowidlist $row] $id]]
5876 set le [expr {$row + 1}]
5877 set arrowhigh 1
5878 while {1} {
5879 set c [lsearch -exact [lindex $rowidlist $le] $id]
5880 if {$c < 0} {
5881 incr le -1
5882 break
5883 }
5884 lappend cols $c
5885 set x [lindex $displayorder $le]
5886 if {$x eq $id} {
5887 set arrowhigh 0
5888 break
5889 }
5890 if {[info exists iddrawn($x)] || $le == $endrow} {
5891 set c [lsearch -exact [lindex $rowidlist [expr {$le+1}]] $id]
5892 if {$c >= 0} {
5893 lappend cols $c
5894 set arrowhigh 0
5895 }
5896 break
5897 }
5898 incr le
5899 }
5900 if {$le <= $row} {
5901 return $row
5902 }
5903
5904 set lines {}
5905 set i 0
5906 set joinhigh 0
5907 if {[info exists linesegs($id)]} {
5908 set lines $linesegs($id)
5909 foreach li $lines {
5910 set r0 [lindex $li 0]
5911 if {$r0 > $row} {
5912 if {$r0 == $le && [lindex $li 1] - $row <= $maxlinelen} {
5913 set joinhigh 1
5914 }
5915 break
5916 }
5917 incr i
5918 }
5919 }
5920 set joinlow 0
5921 if {$i > 0} {
5922 set li [lindex $lines [expr {$i-1}]]
5923 set r1 [lindex $li 1]
5924 if {$r1 == $row && $le - [lindex $li 0] <= $maxlinelen} {
5925 set joinlow 1
5926 }
5927 }
5928
5929 set x [lindex $cols [expr {$le - $row}]]
5930 set xp [lindex $cols [expr {$le - 1 - $row}]]
5931 set dir [expr {$xp - $x}]
5932 if {$joinhigh} {
5933 set ith [lindex $lines $i 2]
5934 set coords [$canv coords $ith]
5935 set ah [$canv itemcget $ith -arrow]
5936 set arrowhigh [expr {$ah eq "first" || $ah eq "both"}]
5937 set x2 [lindex $cols [expr {$le + 1 - $row}]]
5938 if {$x2 ne {} && $x - $x2 == $dir} {
5939 set coords [lrange $coords 0 end-2]
5940 }
5941 } else {
5942 set coords [list [xc $le $x] [yc $le]]
5943 }
5944 if {$joinlow} {
5945 set itl [lindex $lines [expr {$i-1}] 2]
5946 set al [$canv itemcget $itl -arrow]
5947 set arrowlow [expr {$al eq "last" || $al eq "both"}]
Paul Mackerrase341c062007-08-12 12:42:57 +10005948 } elseif {$arrowlow} {
5949 if {[lsearch -exact [lindex $rowidlist [expr {$row-1}]] $id] >= 0 ||
5950 [lsearch -exact [lindex $parentlist [expr {$row-1}]] $id] >= 0} {
5951 set arrowlow 0
5952 }
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005953 }
5954 set arrow [lindex {none first last both} [expr {$arrowhigh + 2*$arrowlow}]]
5955 for {set y $le} {[incr y -1] > $row} {} {
5956 set x $xp
5957 set xp [lindex $cols [expr {$y - 1 - $row}]]
5958 set ndir [expr {$xp - $x}]
5959 if {$dir != $ndir || $xp < 0} {
5960 lappend coords [xc $y $x] [yc $y]
5961 }
5962 set dir $ndir
5963 }
5964 if {!$joinlow} {
5965 if {$xp < 0} {
5966 # join parent line to first child
5967 set ch [lindex $displayorder $row]
5968 set xc [lsearch -exact [lindex $rowidlist $row] $ch]
5969 if {$xc < 0} {
5970 puts "oops: drawlineseg: child $ch not on row $row"
Paul Mackerrase341c062007-08-12 12:42:57 +10005971 } elseif {$xc != $x} {
5972 if {($arrowhigh && $le == $row + 1) || $dir == 0} {
5973 set d [expr {int(0.5 * $linespc)}]
5974 set x1 [xc $row $x]
5975 if {$xc < $x} {
5976 set x2 [expr {$x1 - $d}]
5977 } else {
5978 set x2 [expr {$x1 + $d}]
5979 }
5980 set y2 [yc $row]
5981 set y1 [expr {$y2 + $d}]
5982 lappend coords $x1 $y1 $x2 $y2
5983 } elseif {$xc < $x - 1} {
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005984 lappend coords [xc $row [expr {$x-1}]] [yc $row]
5985 } elseif {$xc > $x + 1} {
5986 lappend coords [xc $row [expr {$x+1}]] [yc $row]
5987 }
5988 set x $xc
5989 }
5990 lappend coords [xc $row $x] [yc $row]
5991 } else {
5992 set xn [xc $row $xp]
5993 set yn [yc $row]
Paul Mackerrase341c062007-08-12 12:42:57 +10005994 lappend coords $xn $yn
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005995 }
5996 if {!$joinhigh} {
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005997 assigncolor $id
5998 set t [$canv create line $coords -width [linewidth $id] \
5999 -fill $colormap($id) -tags lines.$id -arrow $arrow]
6000 $canv lower $t
6001 bindline $t $id
6002 set lines [linsert $lines $i [list $row $le $t]]
6003 } else {
6004 $canv coords $ith $coords
6005 if {$arrow ne $ah} {
6006 $canv itemconf $ith -arrow $arrow
6007 }
6008 lset lines $i 0 $row
6009 }
6010 } else {
6011 set xo [lsearch -exact [lindex $rowidlist [expr {$row - 1}]] $id]
6012 set ndir [expr {$xo - $xp}]
6013 set clow [$canv coords $itl]
6014 if {$dir == $ndir} {
6015 set clow [lrange $clow 2 end]
6016 }
6017 set coords [concat $coords $clow]
6018 if {!$joinhigh} {
6019 lset lines [expr {$i-1}] 1 $le
Paul Mackerras322a8cc2006-10-15 18:03:46 +10006020 } else {
6021 # coalesce two pieces
6022 $canv delete $ith
6023 set b [lindex $lines [expr {$i-1}] 0]
6024 set e [lindex $lines $i 1]
6025 set lines [lreplace $lines [expr {$i-1}] $i [list $b $e $itl]]
6026 }
6027 $canv coords $itl $coords
6028 if {$arrow ne $al} {
6029 $canv itemconf $itl -arrow $arrow
6030 }
6031 }
6032
6033 set linesegs($id) $lines
6034 return $le
6035}
6036
6037proc drawparentlinks {id row} {
6038 global rowidlist canv colormap curview parentlist
Paul Mackerras513a54d2007-08-01 22:27:57 +10006039 global idpos linespc
Paul Mackerras322a8cc2006-10-15 18:03:46 +10006040
6041 set rowids [lindex $rowidlist $row]
6042 set col [lsearch -exact $rowids $id]
6043 if {$col < 0} return
6044 set olds [lindex $parentlist $row]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006045 set row2 [expr {$row + 1}]
6046 set x [xc $row $col]
6047 set y [yc $row]
6048 set y2 [yc $row2]
Paul Mackerrase341c062007-08-12 12:42:57 +10006049 set d [expr {int(0.5 * $linespc)}]
Paul Mackerras513a54d2007-08-01 22:27:57 +10006050 set ymid [expr {$y + $d}]
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11006051 set ids [lindex $rowidlist $row2]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006052 # rmx = right-most X coord used
6053 set rmx 0
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006054 foreach p $olds {
Paul Mackerrasf3408442006-03-31 09:54:24 +11006055 set i [lsearch -exact $ids $p]
6056 if {$i < 0} {
6057 puts "oops, parent $p of $id not in list"
6058 continue
6059 }
6060 set x2 [xc $row2 $i]
6061 if {$x2 > $rmx} {
6062 set rmx $x2
6063 }
Paul Mackerras513a54d2007-08-01 22:27:57 +10006064 set j [lsearch -exact $rowids $p]
6065 if {$j < 0} {
Paul Mackerraseb447a12006-03-18 23:11:37 +11006066 # drawlineseg will do this one for us
6067 continue
6068 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006069 assigncolor $p
6070 # should handle duplicated parents here...
6071 set coords [list $x $y]
Paul Mackerras513a54d2007-08-01 22:27:57 +10006072 if {$i != $col} {
6073 # if attaching to a vertical segment, draw a smaller
6074 # slant for visual distinctness
6075 if {$i == $j} {
6076 if {$i < $col} {
6077 lappend coords [expr {$x2 + $d}] $y $x2 $ymid
6078 } else {
6079 lappend coords [expr {$x2 - $d}] $y $x2 $ymid
6080 }
6081 } elseif {$i < $col && $i < $j} {
6082 # segment slants towards us already
6083 lappend coords [xc $row $j] $y
6084 } else {
6085 if {$i < $col - 1} {
6086 lappend coords [expr {$x2 + $linespc}] $y
6087 } elseif {$i > $col + 1} {
6088 lappend coords [expr {$x2 - $linespc}] $y
6089 }
6090 lappend coords $x2 $y2
6091 }
6092 } else {
6093 lappend coords $x2 $y2
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006094 }
Paul Mackerrasc934a8a2006-03-02 23:00:44 +11006095 set t [$canv create line $coords -width [linewidth $p] \
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006096 -fill $colormap($p) -tags lines.$p]
6097 $canv lower $t
6098 bindline $t $p
6099 }
Paul Mackerras322a8cc2006-10-15 18:03:46 +10006100 if {$rmx > [lindex $idpos($id) 1]} {
6101 lset idpos($id) 1 $rmx
6102 redrawtags $id
6103 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006104}
6105
Paul Mackerrasc934a8a2006-03-02 23:00:44 +11006106proc drawlines {id} {
Paul Mackerras322a8cc2006-10-15 18:03:46 +10006107 global canv
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006108
Paul Mackerras322a8cc2006-10-15 18:03:46 +10006109 $canv itemconf lines.$id -width [linewidth $id]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006110}
6111
Paul Mackerras322a8cc2006-10-15 18:03:46 +10006112proc drawcmittext {id row col} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11006113 global linespc canv canv2 canv3 fgcolor curview
6114 global cmitlisted commitinfo rowidlist parentlist
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006115 global rowtextx idpos idtags idheads idotherrefs
Paul Mackerras03800812007-08-29 21:45:21 +10006116 global linehtag linentag linedtag selectedline
Paul Mackerrasb9fdba72009-04-09 09:34:46 +10006117 global canvxmax boldids boldnameids fgcolor markedid
Paul Mackerrasd277e892008-09-21 18:11:37 -05006118 global mainheadid nullid nullid2 circleitem circlecolors ctxbut
Gauthier Östervall252c52d2013-03-27 14:40:51 +01006119 global mainheadcirclecolor workingfilescirclecolor indexcirclecolor
6120 global circleoutlinecolor
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006121
Linus Torvalds1407ade2008-02-09 14:02:07 -08006122 # listed is 0 for boundary, 1 for normal, 2 for negative, 3 for left, 4 for right
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11006123 set listed $cmitlisted($curview,$id)
Paul Mackerras219ea3a2006-09-07 10:21:39 +10006124 if {$id eq $nullid} {
Gauthier Östervall252c52d2013-03-27 14:40:51 +01006125 set ofill $workingfilescirclecolor
Paul Mackerras8f489362007-07-13 19:49:37 +10006126 } elseif {$id eq $nullid2} {
Gauthier Östervall252c52d2013-03-27 14:40:51 +01006127 set ofill $indexcirclecolor
Paul Mackerrasc11ff122008-05-26 10:11:33 +10006128 } elseif {$id eq $mainheadid} {
Gauthier Östervall252c52d2013-03-27 14:40:51 +01006129 set ofill $mainheadcirclecolor
Paul Mackerras219ea3a2006-09-07 10:21:39 +10006130 } else {
Paul Mackerrasc11ff122008-05-26 10:11:33 +10006131 set ofill [lindex $circlecolors $listed]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10006132 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006133 set x [xc $row $col]
6134 set y [yc $row]
6135 set orad [expr {$linespc / 3}]
Linus Torvalds1407ade2008-02-09 14:02:07 -08006136 if {$listed <= 2} {
Paul Mackerrasc961b222007-07-09 22:45:47 +10006137 set t [$canv create oval [expr {$x - $orad}] [expr {$y - $orad}] \
6138 [expr {$x + $orad - 1}] [expr {$y + $orad - 1}] \
Gauthier Östervall252c52d2013-03-27 14:40:51 +01006139 -fill $ofill -outline $circleoutlinecolor -width 1 -tags circle]
Linus Torvalds1407ade2008-02-09 14:02:07 -08006140 } elseif {$listed == 3} {
Paul Mackerrasc961b222007-07-09 22:45:47 +10006141 # triangle pointing left for left-side commits
6142 set t [$canv create polygon \
6143 [expr {$x - $orad}] $y \
6144 [expr {$x + $orad - 1}] [expr {$y - $orad}] \
6145 [expr {$x + $orad - 1}] [expr {$y + $orad - 1}] \
Gauthier Östervall252c52d2013-03-27 14:40:51 +01006146 -fill $ofill -outline $circleoutlinecolor -width 1 -tags circle]
Paul Mackerrasc961b222007-07-09 22:45:47 +10006147 } else {
6148 # triangle pointing right for right-side commits
6149 set t [$canv create polygon \
6150 [expr {$x + $orad - 1}] $y \
6151 [expr {$x - $orad}] [expr {$y - $orad}] \
6152 [expr {$x - $orad}] [expr {$y + $orad - 1}] \
Gauthier Östervall252c52d2013-03-27 14:40:51 +01006153 -fill $ofill -outline $circleoutlinecolor -width 1 -tags circle]
Paul Mackerrasc961b222007-07-09 22:45:47 +10006154 }
Paul Mackerrasc11ff122008-05-26 10:11:33 +10006155 set circleitem($row) $t
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006156 $canv raise $t
6157 $canv bind $t <1> {selcanvline {} %x %y}
Paul Mackerras322a8cc2006-10-15 18:03:46 +10006158 set rmx [llength [lindex $rowidlist $row]]
6159 set olds [lindex $parentlist $row]
6160 if {$olds ne {}} {
6161 set nextids [lindex $rowidlist [expr {$row + 1}]]
6162 foreach p $olds {
6163 set i [lsearch -exact $nextids $p]
6164 if {$i > $rmx} {
6165 set rmx $i
6166 }
6167 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006168 }
Paul Mackerras322a8cc2006-10-15 18:03:46 +10006169 set xt [xc $row $rmx]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006170 set rowtextx($row) $xt
6171 set idpos($id) [list $x $xt $y]
6172 if {[info exists idtags($id)] || [info exists idheads($id)]
6173 || [info exists idotherrefs($id)]} {
6174 set xt [drawtags $id $x $xt $y]
6175 }
Raphael Zimmerer36242492011-04-19 22:37:09 +02006176 if {[lindex $commitinfo($id) 6] > 0} {
6177 set xt [drawnotesign $xt $y]
6178 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006179 set headline [lindex $commitinfo($id) 0]
6180 set name [lindex $commitinfo($id) 1]
6181 set date [lindex $commitinfo($id) 2]
6182 set date [formatdate $date]
Paul Mackerras9c311b32007-10-04 22:27:13 +10006183 set font mainfont
6184 set nfont mainfont
Paul Mackerras476ca632008-01-07 22:16:31 +11006185 set isbold [ishighlighted $id]
Paul Mackerras908c3582006-05-20 09:38:11 +10006186 if {$isbold > 0} {
Paul Mackerras28593d32008-11-13 23:01:46 +11006187 lappend boldids $id
Paul Mackerras9c311b32007-10-04 22:27:13 +10006188 set font mainfontbold
Paul Mackerras908c3582006-05-20 09:38:11 +10006189 if {$isbold > 1} {
Paul Mackerras28593d32008-11-13 23:01:46 +11006190 lappend boldnameids $id
Paul Mackerras9c311b32007-10-04 22:27:13 +10006191 set nfont mainfontbold
Paul Mackerras908c3582006-05-20 09:38:11 +10006192 }
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10006193 }
Paul Mackerras28593d32008-11-13 23:01:46 +11006194 set linehtag($id) [$canv create text $xt $y -anchor w -fill $fgcolor \
6195 -text $headline -font $font -tags text]
6196 $canv bind $linehtag($id) $ctxbut "rowmenu %X %Y $id"
6197 set linentag($id) [$canv2 create text 3 $y -anchor w -fill $fgcolor \
6198 -text $name -font $nfont -tags text]
6199 set linedtag($id) [$canv3 create text 3 $y -anchor w -fill $fgcolor \
6200 -text $date -font mainfont -tags text]
Paul Mackerras94b4a692008-05-20 20:51:06 +10006201 if {$selectedline == $row} {
Paul Mackerras28593d32008-11-13 23:01:46 +11006202 make_secsel $id
Paul Mackerras03800812007-08-29 21:45:21 +10006203 }
Paul Mackerrasb9fdba72009-04-09 09:34:46 +10006204 if {[info exists markedid] && $markedid eq $id} {
6205 make_idmark $id
6206 }
Paul Mackerras9c311b32007-10-04 22:27:13 +10006207 set xr [expr {$xt + [font measure $font $headline]}]
Paul Mackerrasbe0cd092006-03-31 09:55:11 +11006208 if {$xr > $canvxmax} {
6209 set canvxmax $xr
6210 setcanvscroll
6211 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006212}
6213
6214proc drawcmitrow {row} {
Paul Mackerras03800812007-08-29 21:45:21 +10006215 global displayorder rowidlist nrows_drawn
Paul Mackerras005a2f42007-07-26 22:36:39 +10006216 global iddrawn markingmatches
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11006217 global commitinfo numcommits
Paul Mackerras687c8762007-09-22 12:49:33 +10006218 global filehighlight fhighlights findpattern nhighlights
Paul Mackerras908c3582006-05-20 09:38:11 +10006219 global hlview vhighlights
Paul Mackerras164ff272006-05-29 19:50:02 +10006220 global highlight_related rhighlights
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006221
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11006222 if {$row >= $numcommits} return
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006223
6224 set id [lindex $displayorder $row]
Paul Mackerras476ca632008-01-07 22:16:31 +11006225 if {[info exists hlview] && ![info exists vhighlights($id)]} {
Paul Mackerras908c3582006-05-20 09:38:11 +10006226 askvhighlight $row $id
6227 }
Paul Mackerras476ca632008-01-07 22:16:31 +11006228 if {[info exists filehighlight] && ![info exists fhighlights($id)]} {
Paul Mackerras908c3582006-05-20 09:38:11 +10006229 askfilehighlight $row $id
6230 }
Paul Mackerras476ca632008-01-07 22:16:31 +11006231 if {$findpattern ne {} && ![info exists nhighlights($id)]} {
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10006232 askfindhighlight $row $id
Paul Mackerras908c3582006-05-20 09:38:11 +10006233 }
Paul Mackerras476ca632008-01-07 22:16:31 +11006234 if {$highlight_related ne [mc "None"] && ![info exists rhighlights($id)]} {
Paul Mackerras164ff272006-05-29 19:50:02 +10006235 askrelhighlight $row $id
6236 }
Paul Mackerras005a2f42007-07-26 22:36:39 +10006237 if {![info exists iddrawn($id)]} {
6238 set col [lsearch -exact [lindex $rowidlist $row] $id]
6239 if {$col < 0} {
6240 puts "oops, row $row id $id not in list"
6241 return
6242 }
6243 if {![info exists commitinfo($id)]} {
6244 getcommit $id
6245 }
6246 assigncolor $id
6247 drawcmittext $id $row $col
6248 set iddrawn($id) 1
Paul Mackerras03800812007-08-29 21:45:21 +10006249 incr nrows_drawn
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006250 }
Paul Mackerras005a2f42007-07-26 22:36:39 +10006251 if {$markingmatches} {
6252 markrowmatches $row $id
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006253 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006254}
6255
Paul Mackerras322a8cc2006-10-15 18:03:46 +10006256proc drawcommits {row {endrow {}}} {
Paul Mackerras03800812007-08-29 21:45:21 +10006257 global numcommits iddrawn displayorder curview need_redisplay
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10006258 global parentlist rowidlist rowfinal uparrowlen downarrowlen nrows_drawn
Paul Mackerras322a8cc2006-10-15 18:03:46 +10006259
6260 if {$row < 0} {
6261 set row 0
6262 }
6263 if {$endrow eq {}} {
6264 set endrow $row
6265 }
6266 if {$endrow >= $numcommits} {
6267 set endrow [expr {$numcommits - 1}]
6268 }
6269
Paul Mackerras03800812007-08-29 21:45:21 +10006270 set rl1 [expr {$row - $downarrowlen - 3}]
6271 if {$rl1 < 0} {
6272 set rl1 0
6273 }
6274 set ro1 [expr {$row - 3}]
6275 if {$ro1 < 0} {
6276 set ro1 0
6277 }
6278 set r2 [expr {$endrow + $uparrowlen + 3}]
6279 if {$r2 > $numcommits} {
6280 set r2 $numcommits
6281 }
6282 for {set r $rl1} {$r < $r2} {incr r} {
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10006283 if {[lindex $rowidlist $r] ne {} && [lindex $rowfinal $r]} {
Paul Mackerras03800812007-08-29 21:45:21 +10006284 if {$rl1 < $r} {
6285 layoutrows $rl1 $r
6286 }
6287 set rl1 [expr {$r + 1}]
6288 }
6289 }
6290 if {$rl1 < $r} {
6291 layoutrows $rl1 $r
6292 }
6293 optimize_rows $ro1 0 $r2
6294 if {$need_redisplay || $nrows_drawn > 2000} {
6295 clear_display
Paul Mackerras03800812007-08-29 21:45:21 +10006296 }
6297
Paul Mackerras322a8cc2006-10-15 18:03:46 +10006298 # make the lines join to already-drawn rows either side
6299 set r [expr {$row - 1}]
6300 if {$r < 0 || ![info exists iddrawn([lindex $displayorder $r])]} {
6301 set r $row
6302 }
6303 set er [expr {$endrow + 1}]
6304 if {$er >= $numcommits ||
6305 ![info exists iddrawn([lindex $displayorder $er])]} {
6306 set er $endrow
6307 }
6308 for {} {$r <= $er} {incr r} {
6309 set id [lindex $displayorder $r]
6310 set wasdrawn [info exists iddrawn($id)]
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006311 drawcmitrow $r
Paul Mackerras322a8cc2006-10-15 18:03:46 +10006312 if {$r == $er} break
6313 set nextid [lindex $displayorder [expr {$r + 1}]]
Paul Mackerrase5ef6f92007-10-21 12:58:42 +10006314 if {$wasdrawn && [info exists iddrawn($nextid)]} continue
Paul Mackerras322a8cc2006-10-15 18:03:46 +10006315 drawparentlinks $id $r
6316
Paul Mackerras322a8cc2006-10-15 18:03:46 +10006317 set rowids [lindex $rowidlist $r]
6318 foreach lid $rowids {
6319 if {$lid eq {}} continue
Paul Mackerrase5ef6f92007-10-21 12:58:42 +10006320 if {[info exists lineend($lid)] && $lineend($lid) > $r} continue
Paul Mackerras322a8cc2006-10-15 18:03:46 +10006321 if {$lid eq $id} {
6322 # see if this is the first child of any of its parents
6323 foreach p [lindex $parentlist $r] {
6324 if {[lsearch -exact $rowids $p] < 0} {
6325 # make this line extend up to the child
Paul Mackerrase5ef6f92007-10-21 12:58:42 +10006326 set lineend($p) [drawlineseg $p $r $er 0]
Paul Mackerras322a8cc2006-10-15 18:03:46 +10006327 }
6328 }
Paul Mackerrase5ef6f92007-10-21 12:58:42 +10006329 } else {
6330 set lineend($lid) [drawlineseg $lid $r $er 1]
Paul Mackerras322a8cc2006-10-15 18:03:46 +10006331 }
6332 }
6333 }
6334}
6335
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11006336proc undolayout {row} {
6337 global uparrowlen mingaplen downarrowlen
6338 global rowidlist rowisopt rowfinal need_redisplay
6339
6340 set r [expr {$row - ($uparrowlen + $mingaplen + $downarrowlen)}]
6341 if {$r < 0} {
6342 set r 0
6343 }
6344 if {[llength $rowidlist] > $r} {
6345 incr r -1
6346 set rowidlist [lrange $rowidlist 0 $r]
6347 set rowfinal [lrange $rowfinal 0 $r]
6348 set rowisopt [lrange $rowisopt 0 $r]
6349 set need_redisplay 1
6350 run drawvisible
6351 }
6352}
6353
Paul Mackerras31c0eaa2007-12-30 22:41:14 +11006354proc drawvisible {} {
6355 global canv linespc curview vrowmod selectedline targetrow targetid
Paul Mackerras42a671f2008-01-02 09:59:39 +11006356 global need_redisplay cscroll numcommits
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006357
Paul Mackerras31c0eaa2007-12-30 22:41:14 +11006358 set fs [$canv yview]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006359 set ymax [lindex [$canv cget -scrollregion] 3]
Paul Mackerras5a7f5772008-01-15 22:45:36 +11006360 if {$ymax eq {} || $ymax == 0 || $numcommits == 0} return
Paul Mackerras31c0eaa2007-12-30 22:41:14 +11006361 set f0 [lindex $fs 0]
6362 set f1 [lindex $fs 1]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006363 set y0 [expr {int($f0 * $ymax)}]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006364 set y1 [expr {int($f1 * $ymax)}]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006365
Paul Mackerras31c0eaa2007-12-30 22:41:14 +11006366 if {[info exists targetid]} {
Paul Mackerras42a671f2008-01-02 09:59:39 +11006367 if {[commitinview $targetid $curview]} {
6368 set r [rowofcommit $targetid]
6369 if {$r != $targetrow} {
6370 # Fix up the scrollregion and change the scrolling position
6371 # now that our target row has moved.
6372 set diff [expr {($r - $targetrow) * $linespc}]
6373 set targetrow $r
6374 setcanvscroll
6375 set ymax [lindex [$canv cget -scrollregion] 3]
6376 incr y0 $diff
6377 incr y1 $diff
6378 set f0 [expr {$y0 / $ymax}]
6379 set f1 [expr {$y1 / $ymax}]
6380 allcanvs yview moveto $f0
6381 $cscroll set $f0 $f1
6382 set need_redisplay 1
6383 }
6384 } else {
6385 unset targetid
Paul Mackerras31c0eaa2007-12-30 22:41:14 +11006386 }
6387 }
6388
6389 set row [expr {int(($y0 - 3) / $linespc) - 1}]
6390 set endrow [expr {int(($y1 - 3) / $linespc) + 1}]
6391 if {$endrow >= $vrowmod($curview)} {
6392 update_arcrows $curview
6393 }
Paul Mackerras94b4a692008-05-20 20:51:06 +10006394 if {$selectedline ne {} &&
Paul Mackerras31c0eaa2007-12-30 22:41:14 +11006395 $row <= $selectedline && $selectedline <= $endrow} {
6396 set targetrow $selectedline
Paul Mackerrasac1276a2008-03-03 10:11:08 +11006397 } elseif {[info exists targetid]} {
Paul Mackerras31c0eaa2007-12-30 22:41:14 +11006398 set targetrow [expr {int(($row + $endrow) / 2)}]
6399 }
Paul Mackerrasac1276a2008-03-03 10:11:08 +11006400 if {[info exists targetrow]} {
6401 if {$targetrow >= $numcommits} {
6402 set targetrow [expr {$numcommits - 1}]
6403 }
6404 set targetid [commitonrow $targetrow]
Paul Mackerras42a671f2008-01-02 09:59:39 +11006405 }
Paul Mackerras31c0eaa2007-12-30 22:41:14 +11006406 drawcommits $row $endrow
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006407}
6408
6409proc clear_display {} {
Paul Mackerras03800812007-08-29 21:45:21 +10006410 global iddrawn linesegs need_redisplay nrows_drawn
Paul Mackerras164ff272006-05-29 19:50:02 +10006411 global vhighlights fhighlights nhighlights rhighlights
Paul Mackerras28593d32008-11-13 23:01:46 +11006412 global linehtag linentag linedtag boldids boldnameids
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006413
6414 allcanvs delete all
Paul Mackerras009409f2015-05-02 20:53:36 +10006415 unset -nocomplain iddrawn
6416 unset -nocomplain linesegs
6417 unset -nocomplain linehtag
6418 unset -nocomplain linentag
6419 unset -nocomplain linedtag
Paul Mackerras28593d32008-11-13 23:01:46 +11006420 set boldids {}
6421 set boldnameids {}
Paul Mackerras009409f2015-05-02 20:53:36 +10006422 unset -nocomplain vhighlights
6423 unset -nocomplain fhighlights
6424 unset -nocomplain nhighlights
6425 unset -nocomplain rhighlights
Paul Mackerras03800812007-08-29 21:45:21 +10006426 set need_redisplay 0
6427 set nrows_drawn 0
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006428}
6429
Paul Mackerras50b44ec2006-04-04 10:16:22 +10006430proc findcrossings {id} {
Paul Mackerras6e8c8702007-07-31 21:03:06 +10006431 global rowidlist parentlist numcommits displayorder
Paul Mackerras50b44ec2006-04-04 10:16:22 +10006432
6433 set cross {}
6434 set ccross {}
6435 foreach {s e} [rowranges $id] {
6436 if {$e >= $numcommits} {
6437 set e [expr {$numcommits - 1}]
Paul Mackerras50b44ec2006-04-04 10:16:22 +10006438 }
Paul Mackerrasd94f8cd2006-04-06 10:18:23 +10006439 if {$e <= $s} continue
Paul Mackerras50b44ec2006-04-04 10:16:22 +10006440 for {set row $e} {[incr row -1] >= $s} {} {
Paul Mackerras6e8c8702007-07-31 21:03:06 +10006441 set x [lsearch -exact [lindex $rowidlist $row] $id]
6442 if {$x < 0} break
Paul Mackerras50b44ec2006-04-04 10:16:22 +10006443 set olds [lindex $parentlist $row]
6444 set kid [lindex $displayorder $row]
6445 set kidx [lsearch -exact [lindex $rowidlist $row] $kid]
6446 if {$kidx < 0} continue
6447 set nextrow [lindex $rowidlist [expr {$row + 1}]]
6448 foreach p $olds {
6449 set px [lsearch -exact $nextrow $p]
6450 if {$px < 0} continue
6451 if {($kidx < $x && $x < $px) || ($px < $x && $x < $kidx)} {
6452 if {[lsearch -exact $ccross $p] >= 0} continue
6453 if {$x == $px + ($kidx < $px? -1: 1)} {
6454 lappend ccross $p
6455 } elseif {[lsearch -exact $cross $p] < 0} {
6456 lappend cross $p
6457 }
6458 }
6459 }
Paul Mackerras50b44ec2006-04-04 10:16:22 +10006460 }
6461 }
6462 return [concat $ccross {{}} $cross]
6463}
6464
Paul Mackerrase5c2d852005-05-11 23:44:54 +00006465proc assigncolor {id} {
Paul Mackerrasaa81d972006-02-28 11:27:12 +11006466 global colormap colors nextcolor
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11006467 global parents children children curview
Paul Mackerras6c20ff32005-06-22 19:53:32 +10006468
Paul Mackerras418c4c72006-02-07 09:10:18 +11006469 if {[info exists colormap($id)]} return
Paul Mackerrase5c2d852005-05-11 23:44:54 +00006470 set ncolors [llength $colors]
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10006471 if {[info exists children($curview,$id)]} {
6472 set kids $children($curview,$id)
Paul Mackerras79b2c752006-04-02 20:47:40 +10006473 } else {
6474 set kids {}
6475 }
6476 if {[llength $kids] == 1} {
6477 set child [lindex $kids 0]
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +00006478 if {[info exists colormap($child)]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11006479 && [llength $parents($curview,$child)] == 1} {
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +00006480 set colormap($id) $colormap($child)
6481 return
Paul Mackerrase5c2d852005-05-11 23:44:54 +00006482 }
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +00006483 }
6484 set badcolors {}
Paul Mackerras50b44ec2006-04-04 10:16:22 +10006485 set origbad {}
6486 foreach x [findcrossings $id] {
6487 if {$x eq {}} {
6488 # delimiter between corner crossings and other crossings
6489 if {[llength $badcolors] >= $ncolors - 1} break
6490 set origbad $badcolors
Paul Mackerrase5c2d852005-05-11 23:44:54 +00006491 }
Paul Mackerras50b44ec2006-04-04 10:16:22 +10006492 if {[info exists colormap($x)]
6493 && [lsearch -exact $badcolors $colormap($x)] < 0} {
6494 lappend badcolors $colormap($x)
Paul Mackerras6c20ff32005-06-22 19:53:32 +10006495 }
6496 }
Paul Mackerras50b44ec2006-04-04 10:16:22 +10006497 if {[llength $badcolors] >= $ncolors} {
6498 set badcolors $origbad
6499 }
Paul Mackerras6c20ff32005-06-22 19:53:32 +10006500 set origbad $badcolors
6501 if {[llength $badcolors] < $ncolors - 1} {
Paul Mackerras79b2c752006-04-02 20:47:40 +10006502 foreach child $kids {
Paul Mackerras6c20ff32005-06-22 19:53:32 +10006503 if {[info exists colormap($child)]
6504 && [lsearch -exact $badcolors $colormap($child)] < 0} {
6505 lappend badcolors $colormap($child)
6506 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11006507 foreach p $parents($curview,$child) {
Paul Mackerras79b2c752006-04-02 20:47:40 +10006508 if {[info exists colormap($p)]
6509 && [lsearch -exact $badcolors $colormap($p)] < 0} {
6510 lappend badcolors $colormap($p)
Paul Mackerrase5c2d852005-05-11 23:44:54 +00006511 }
6512 }
6513 }
Paul Mackerras6c20ff32005-06-22 19:53:32 +10006514 if {[llength $badcolors] >= $ncolors} {
6515 set badcolors $origbad
6516 }
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +00006517 }
6518 for {set i 0} {$i <= $ncolors} {incr i} {
6519 set c [lindex $colors $nextcolor]
6520 if {[incr nextcolor] >= $ncolors} {
6521 set nextcolor 0
Paul Mackerrase5c2d852005-05-11 23:44:54 +00006522 }
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +00006523 if {[lsearch -exact $badcolors $c]} break
6524 }
6525 set colormap($id) $c
6526}
6527
Paul Mackerrasa823a912005-06-21 10:01:38 +10006528proc bindline {t id} {
6529 global canv
6530
Paul Mackerrasa823a912005-06-21 10:01:38 +10006531 $canv bind $t <Enter> "lineenter %x %y $id"
6532 $canv bind $t <Motion> "linemotion %x %y $id"
6533 $canv bind $t <Leave> "lineleave $id"
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10006534 $canv bind $t <Button-1> "lineclick %x %y $id 1"
Paul Mackerrasa823a912005-06-21 10:01:38 +10006535}
6536
Paul Mackerras4399fe32013-01-03 10:10:31 +11006537proc graph_pane_width {} {
6538 global use_ttk
6539
6540 if {$use_ttk} {
6541 set g [.tf.histframe.pwclist sashpos 0]
6542 } else {
6543 set g [.tf.histframe.pwclist sash coord 0]
6544 }
6545 return [lindex $g 0]
6546}
6547
6548proc totalwidth {l font extra} {
6549 set tot 0
6550 foreach str $l {
6551 set tot [expr {$tot + [font measure $font $str] + $extra}]
6552 }
6553 return $tot
6554}
6555
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006556proc drawtags {id x xt y1} {
Paul Mackerras8a485712006-07-06 10:21:23 +10006557 global idtags idheads idotherrefs mainhead
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006558 global linespc lthickness
Paul Mackerrasd277e892008-09-21 18:11:37 -05006559 global canv rowtextx curview fgcolor bgcolor ctxbut
Gauthier Östervall252c52d2013-03-27 14:40:51 +01006560 global headbgcolor headfgcolor headoutlinecolor remotebgcolor
6561 global tagbgcolor tagfgcolor tagoutlinecolor
6562 global reflinecolor
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006563
6564 set marks {}
6565 set ntags 0
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10006566 set nheads 0
Paul Mackerras4399fe32013-01-03 10:10:31 +11006567 set singletag 0
6568 set maxtags 3
6569 set maxtagpct 25
6570 set maxwidth [expr {[graph_pane_width] * $maxtagpct / 100}]
6571 set delta [expr {int(0.5 * ($linespc - $lthickness))}]
6572 set extra [expr {$delta + $lthickness + $linespc}]
6573
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006574 if {[info exists idtags($id)]} {
6575 set marks $idtags($id)
6576 set ntags [llength $marks]
Paul Mackerras4399fe32013-01-03 10:10:31 +11006577 if {$ntags > $maxtags ||
6578 [totalwidth $marks mainfont $extra] > $maxwidth} {
6579 # show just a single "n tags..." tag
6580 set singletag 1
6581 if {$ntags == 1} {
6582 set marks [list "tag..."]
6583 } else {
6584 set marks [list [format "%d tags..." $ntags]]
6585 }
6586 set ntags 1
6587 }
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006588 }
6589 if {[info exists idheads($id)]} {
6590 set marks [concat $marks $idheads($id)]
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10006591 set nheads [llength $idheads($id)]
6592 }
6593 if {[info exists idotherrefs($id)]} {
6594 set marks [concat $marks $idotherrefs($id)]
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006595 }
6596 if {$marks eq {}} {
6597 return $xt
6598 }
6599
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08006600 set yt [expr {$y1 - 0.5 * $linespc}]
6601 set yb [expr {$yt + $linespc - 1}]
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006602 set xvals {}
6603 set wvals {}
Paul Mackerras8a485712006-07-06 10:21:23 +10006604 set i -1
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006605 foreach tag $marks {
Paul Mackerras8a485712006-07-06 10:21:23 +10006606 incr i
6607 if {$i >= $ntags && $i < $ntags + $nheads && $tag eq $mainhead} {
Paul Mackerras9c311b32007-10-04 22:27:13 +10006608 set wid [font measure mainfontbold $tag]
Paul Mackerras8a485712006-07-06 10:21:23 +10006609 } else {
Paul Mackerras9c311b32007-10-04 22:27:13 +10006610 set wid [font measure mainfont $tag]
Paul Mackerras8a485712006-07-06 10:21:23 +10006611 }
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006612 lappend xvals $xt
6613 lappend wvals $wid
Paul Mackerras4399fe32013-01-03 10:10:31 +11006614 set xt [expr {$xt + $wid + $extra}]
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006615 }
6616 set t [$canv create line $x $y1 [lindex $xvals end] $y1 \
Gauthier Östervall252c52d2013-03-27 14:40:51 +01006617 -width $lthickness -fill $reflinecolor -tags tag.$id]
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006618 $canv lower $t
6619 foreach tag $marks x $xvals wid $wvals {
Pat Thoyts8dd60f52011-03-01 23:50:50 +00006620 set tag_quoted [string map {% %%} $tag]
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08006621 set xl [expr {$x + $delta}]
6622 set xr [expr {$x + $delta + $wid + $lthickness}]
Paul Mackerras9c311b32007-10-04 22:27:13 +10006623 set font mainfont
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006624 if {[incr ntags -1] >= 0} {
6625 # draw a tag
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08006626 set t [$canv create polygon $x [expr {$yt + $delta}] $xl $yt \
6627 $xr $yt $xr $yb $xl $yb $x [expr {$yb - $delta}] \
Gauthier Östervall252c52d2013-03-27 14:40:51 +01006628 -width 1 -outline $tagoutlinecolor -fill $tagbgcolor \
6629 -tags tag.$id]
Paul Mackerras4399fe32013-01-03 10:10:31 +11006630 if {$singletag} {
6631 set tagclick [list showtags $id 1]
6632 } else {
6633 set tagclick [list showtag $tag_quoted 1]
6634 }
6635 $canv bind $t <1> $tagclick
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11006636 set rowtextx([rowofcommit $id]) [expr {$xr + $linespc}]
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006637 } else {
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10006638 # draw a head or other ref
6639 if {[incr nheads -1] >= 0} {
Gauthier Östervall252c52d2013-03-27 14:40:51 +01006640 set col $headbgcolor
Paul Mackerras8a485712006-07-06 10:21:23 +10006641 if {$tag eq $mainhead} {
Paul Mackerras9c311b32007-10-04 22:27:13 +10006642 set font mainfontbold
Paul Mackerras8a485712006-07-06 10:21:23 +10006643 }
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10006644 } else {
6645 set col "#ddddff"
6646 }
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08006647 set xl [expr {$xl - $delta/2}]
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006648 $canv create polygon $x $yt $xr $yt $xr $yb $x $yb \
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10006649 -width 1 -outline black -fill $col -tags tag.$id
Josef Weidendorfera970fcf2006-04-18 23:53:07 +02006650 if {[regexp {^(remotes/.*/|remotes/)} $tag match remoteprefix]} {
Paul Mackerras9c311b32007-10-04 22:27:13 +10006651 set rwid [font measure mainfont $remoteprefix]
Josef Weidendorfera970fcf2006-04-18 23:53:07 +02006652 set xi [expr {$x + 1}]
6653 set yti [expr {$yt + 1}]
6654 set xri [expr {$x + $rwid}]
6655 $canv create polygon $xi $yti $xri $yti $xri $yb $xi $yb \
Gauthier Östervall252c52d2013-03-27 14:40:51 +01006656 -width 0 -fill $remotebgcolor -tags tag.$id
Josef Weidendorfera970fcf2006-04-18 23:53:07 +02006657 }
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006658 }
Gauthier Östervall252c52d2013-03-27 14:40:51 +01006659 set t [$canv create text $xl $y1 -anchor w -text $tag -fill $headfgcolor \
Paul Mackerras8a485712006-07-06 10:21:23 +10006660 -font $font -tags [list tag.$id text]]
Paul Mackerras106288c2005-08-19 23:11:39 +10006661 if {$ntags >= 0} {
Paul Mackerras4399fe32013-01-03 10:10:31 +11006662 $canv bind $t <1> $tagclick
Paul Mackerras10299152006-08-02 09:52:01 +10006663 } elseif {$nheads >= 0} {
Pat Thoyts8dd60f52011-03-01 23:50:50 +00006664 $canv bind $t $ctxbut [list headmenu %X %Y $id $tag_quoted]
Paul Mackerras106288c2005-08-19 23:11:39 +10006665 }
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006666 }
6667 return $xt
6668}
6669
Raphael Zimmerer36242492011-04-19 22:37:09 +02006670proc drawnotesign {xt y} {
6671 global linespc canv fgcolor
6672
6673 set orad [expr {$linespc / 3}]
6674 set t [$canv create rectangle [expr {$xt - $orad}] [expr {$y - $orad}] \
6675 [expr {$xt + $orad - 1}] [expr {$y + $orad - 1}] \
6676 -fill yellow -outline $fgcolor -width 1 -tags circle]
6677 set xt [expr {$xt + $orad * 3}]
6678 return $xt
6679}
6680
Paul Mackerras8d858d12005-08-05 09:52:16 +10006681proc xcoord {i level ln} {
6682 global canvx0 xspc1 xspc2
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +00006683
Paul Mackerras8d858d12005-08-05 09:52:16 +10006684 set x [expr {$canvx0 + $i * $xspc1($ln)}]
6685 if {$i > 0 && $i == $level} {
6686 set x [expr {$x + 0.5 * ($xspc2 - $xspc1($ln))}]
6687 } elseif {$i > $level} {
6688 set x [expr {$x + $xspc2 - $xspc1($ln)}]
6689 }
6690 return $x
6691}
6692
Paul Mackerras098dd8a2006-05-03 09:32:53 +10006693proc show_status {msg} {
Paul Mackerras9c311b32007-10-04 22:27:13 +10006694 global canv fgcolor
Paul Mackerras098dd8a2006-05-03 09:32:53 +10006695
6696 clear_display
Marc Branchaud9922c5a2015-04-07 11:51:51 -04006697 set_window_title
Paul Mackerras9c311b32007-10-04 22:27:13 +10006698 $canv create text 3 3 -anchor nw -text $msg -font mainfont \
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10006699 -tags text -fill $fgcolor
Paul Mackerras098dd8a2006-05-03 09:32:53 +10006700}
6701
Paul Mackerras94a2eed2005-08-07 15:27:57 +10006702# Don't change the text pane cursor if it is currently the hand cursor,
6703# showing that we are over a sha1 ID link.
6704proc settextcursor {c} {
6705 global ctext curtextcursor
6706
6707 if {[$ctext cget -cursor] == $curtextcursor} {
6708 $ctext config -cursor $c
6709 }
6710 set curtextcursor $c
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +00006711}
6712
Paul Mackerrasa137a902007-10-23 21:12:49 +10006713proc nowbusy {what {name {}}} {
6714 global isbusy busyname statusw
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10006715
6716 if {[array names isbusy] eq {}} {
6717 . config -cursor watch
6718 settextcursor watch
6719 }
6720 set isbusy($what) 1
Paul Mackerrasa137a902007-10-23 21:12:49 +10006721 set busyname($what) $name
6722 if {$name ne {}} {
6723 $statusw conf -text $name
6724 }
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10006725}
6726
6727proc notbusy {what} {
Paul Mackerrasa137a902007-10-23 21:12:49 +10006728 global isbusy maincursor textcursor busyname statusw
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10006729
Paul Mackerrasa137a902007-10-23 21:12:49 +10006730 catch {
6731 unset isbusy($what)
6732 if {$busyname($what) ne {} &&
6733 [$statusw cget -text] eq $busyname($what)} {
6734 $statusw conf -text {}
6735 }
6736 }
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10006737 if {[array names isbusy] eq {}} {
6738 . config -cursor $maincursor
6739 settextcursor $textcursor
6740 }
6741}
6742
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00006743proc findmatches {f} {
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006744 global findtype findstring
Christian Stimmingb007ee22007-11-07 18:44:35 +01006745 if {$findtype == [mc "Regexp"]} {
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006746 set matches [regexp -indices -all -inline $findstring $f]
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00006747 } else {
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006748 set fs $findstring
Christian Stimmingb007ee22007-11-07 18:44:35 +01006749 if {$findtype == [mc "IgnCase"]} {
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006750 set f [string tolower $f]
6751 set fs [string tolower $fs]
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00006752 }
6753 set matches {}
6754 set i 0
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006755 set l [string length $fs]
6756 while {[set j [string first $fs $f $i]] >= 0} {
6757 lappend matches [list $j [expr {$j+$l-1}]]
6758 set i [expr {$j + $l}]
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00006759 }
6760 }
6761 return $matches
6762}
6763
Paul Mackerrascca5d942007-10-27 21:16:56 +10006764proc dofind {{dirn 1} {wrap 1}} {
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006765 global findstring findstartline findcurline selectedline numcommits
Paul Mackerrascca5d942007-10-27 21:16:56 +10006766 global gdttype filehighlight fh_serial find_dirn findallowwrap
Paul Mackerrasb74fd572005-07-16 07:46:13 -04006767
Paul Mackerrascca5d942007-10-27 21:16:56 +10006768 if {[info exists find_dirn]} {
6769 if {$find_dirn == $dirn} return
6770 stopfinding
6771 }
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00006772 focus .
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006773 if {$findstring eq {} || $numcommits == 0} return
Paul Mackerras94b4a692008-05-20 20:51:06 +10006774 if {$selectedline eq {}} {
Paul Mackerrascca5d942007-10-27 21:16:56 +10006775 set findstartline [lindex [visiblerows] [expr {$dirn < 0}]]
Paul Mackerras98f350e2005-05-15 05:56:51 +00006776 } else {
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006777 set findstartline $selectedline
Paul Mackerras98f350e2005-05-15 05:56:51 +00006778 }
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006779 set findcurline $findstartline
Christian Stimmingb007ee22007-11-07 18:44:35 +01006780 nowbusy finding [mc "Searching"]
6781 if {$gdttype ne [mc "containing:"] && ![info exists filehighlight]} {
Paul Mackerras687c8762007-09-22 12:49:33 +10006782 after cancel do_file_hl $fh_serial
6783 do_file_hl $fh_serial
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006784 }
Paul Mackerrascca5d942007-10-27 21:16:56 +10006785 set find_dirn $dirn
6786 set findallowwrap $wrap
6787 run findmore
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006788}
6789
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10006790proc stopfinding {} {
6791 global find_dirn findcurline fprogcoord
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006792
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10006793 if {[info exists find_dirn]} {
6794 unset find_dirn
6795 unset findcurline
6796 notbusy finding
6797 set fprogcoord 0
6798 adjustprogress
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006799 }
Paul Mackerras8a897742008-10-27 21:36:25 +11006800 stopblaming
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006801}
6802
6803proc findmore {} {
Paul Mackerras687c8762007-09-22 12:49:33 +10006804 global commitdata commitinfo numcommits findpattern findloc
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11006805 global findstartline findcurline findallowwrap
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10006806 global find_dirn gdttype fhighlights fprogcoord
Paul Mackerrascd2bcae2008-01-02 21:44:06 +11006807 global curview varcorder vrownum varccommits vrowmod
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006808
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10006809 if {![info exists find_dirn]} {
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006810 return 0
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00006811 }
Frédéric Brière585c27c2010-03-14 18:59:09 -04006812 set fldtypes [list [mc "Headline"] [mc "Author"] "" [mc "Committer"] "" [mc "Comments"]]
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006813 set l $findcurline
Paul Mackerrascca5d942007-10-27 21:16:56 +10006814 set moretodo 0
6815 if {$find_dirn > 0} {
6816 incr l
6817 if {$l >= $numcommits} {
6818 set l 0
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006819 }
Paul Mackerrascca5d942007-10-27 21:16:56 +10006820 if {$l <= $findstartline} {
6821 set lim [expr {$findstartline + 1}]
6822 } else {
6823 set lim $numcommits
6824 set moretodo $findallowwrap
6825 }
Paul Mackerras98f350e2005-05-15 05:56:51 +00006826 } else {
Paul Mackerrascca5d942007-10-27 21:16:56 +10006827 if {$l == 0} {
6828 set l $numcommits
6829 }
6830 incr l -1
6831 if {$l >= $findstartline} {
6832 set lim [expr {$findstartline - 1}]
6833 } else {
6834 set lim -1
6835 set moretodo $findallowwrap
6836 }
Paul Mackerras98f350e2005-05-15 05:56:51 +00006837 }
Paul Mackerrascca5d942007-10-27 21:16:56 +10006838 set n [expr {($lim - $l) * $find_dirn}]
6839 if {$n > 500} {
6840 set n 500
6841 set moretodo 1
Paul Mackerras98f350e2005-05-15 05:56:51 +00006842 }
Paul Mackerrascd2bcae2008-01-02 21:44:06 +11006843 if {$l + ($find_dirn > 0? $n: 1) > $vrowmod($curview)} {
6844 update_arcrows $curview
6845 }
Paul Mackerras687c8762007-09-22 12:49:33 +10006846 set found 0
6847 set domore 1
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11006848 set ai [bsearch $vrownum($curview) $l]
6849 set a [lindex $varcorder($curview) $ai]
6850 set arow [lindex $vrownum($curview) $ai]
6851 set ids [lindex $varccommits($curview,$a)]
6852 set arowend [expr {$arow + [llength $ids]}]
Christian Stimmingb007ee22007-11-07 18:44:35 +01006853 if {$gdttype eq [mc "containing:"]} {
Paul Mackerrascca5d942007-10-27 21:16:56 +10006854 for {} {$n > 0} {incr n -1; incr l $find_dirn} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11006855 if {$l < $arow || $l >= $arowend} {
6856 incr ai $find_dirn
6857 set a [lindex $varcorder($curview) $ai]
6858 set arow [lindex $vrownum($curview) $ai]
6859 set ids [lindex $varccommits($curview,$a)]
6860 set arowend [expr {$arow + [llength $ids]}]
6861 }
6862 set id [lindex $ids [expr {$l - $arow}]]
Paul Mackerras687c8762007-09-22 12:49:33 +10006863 # shouldn't happen unless git log doesn't give all the commits...
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11006864 if {![info exists commitdata($id)] ||
6865 ![doesmatch $commitdata($id)]} {
6866 continue
6867 }
Paul Mackerras687c8762007-09-22 12:49:33 +10006868 if {![info exists commitinfo($id)]} {
6869 getcommit $id
6870 }
6871 set info $commitinfo($id)
6872 foreach f $info ty $fldtypes {
Frédéric Brière585c27c2010-03-14 18:59:09 -04006873 if {$ty eq ""} continue
Christian Stimmingb007ee22007-11-07 18:44:35 +01006874 if {($findloc eq [mc "All fields"] || $findloc eq $ty) &&
Paul Mackerras687c8762007-09-22 12:49:33 +10006875 [doesmatch $f]} {
6876 set found 1
6877 break
6878 }
6879 }
6880 if {$found} break
Paul Mackerras98f350e2005-05-15 05:56:51 +00006881 }
Paul Mackerras687c8762007-09-22 12:49:33 +10006882 } else {
Paul Mackerrascca5d942007-10-27 21:16:56 +10006883 for {} {$n > 0} {incr n -1; incr l $find_dirn} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11006884 if {$l < $arow || $l >= $arowend} {
6885 incr ai $find_dirn
6886 set a [lindex $varcorder($curview) $ai]
6887 set arow [lindex $vrownum($curview) $ai]
6888 set ids [lindex $varccommits($curview,$a)]
6889 set arowend [expr {$arow + [llength $ids]}]
6890 }
6891 set id [lindex $ids [expr {$l - $arow}]]
Paul Mackerras476ca632008-01-07 22:16:31 +11006892 if {![info exists fhighlights($id)]} {
6893 # this sets fhighlights($id) to -1
Paul Mackerras687c8762007-09-22 12:49:33 +10006894 askfilehighlight $l $id
Paul Mackerrascd2bcae2008-01-02 21:44:06 +11006895 }
Paul Mackerras476ca632008-01-07 22:16:31 +11006896 if {$fhighlights($id) > 0} {
Paul Mackerrascd2bcae2008-01-02 21:44:06 +11006897 set found $domore
6898 break
6899 }
Paul Mackerras476ca632008-01-07 22:16:31 +11006900 if {$fhighlights($id) < 0} {
Paul Mackerras687c8762007-09-22 12:49:33 +10006901 if {$domore} {
6902 set domore 0
Paul Mackerrascca5d942007-10-27 21:16:56 +10006903 set findcurline [expr {$l - $find_dirn}]
Paul Mackerras687c8762007-09-22 12:49:33 +10006904 }
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006905 }
6906 }
6907 }
Paul Mackerrascca5d942007-10-27 21:16:56 +10006908 if {$found || ($domore && !$moretodo)} {
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006909 unset findcurline
Paul Mackerras687c8762007-09-22 12:49:33 +10006910 unset find_dirn
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006911 notbusy finding
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10006912 set fprogcoord 0
6913 adjustprogress
6914 if {$found} {
6915 findselectline $l
6916 } else {
6917 bell
6918 }
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006919 return 0
6920 }
Paul Mackerras687c8762007-09-22 12:49:33 +10006921 if {!$domore} {
6922 flushhighlights
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10006923 } else {
Paul Mackerrascca5d942007-10-27 21:16:56 +10006924 set findcurline [expr {$l - $find_dirn}]
Paul Mackerras687c8762007-09-22 12:49:33 +10006925 }
Paul Mackerrascca5d942007-10-27 21:16:56 +10006926 set n [expr {($findcurline - $findstartline) * $find_dirn - 1}]
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10006927 if {$n < 0} {
6928 incr n $numcommits
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006929 }
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10006930 set fprogcoord [expr {$n * 1.0 / $numcommits}]
6931 adjustprogress
6932 return $domore
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00006933}
6934
6935proc findselectline {l} {
Paul Mackerras687c8762007-09-22 12:49:33 +10006936 global findloc commentend ctext findcurline markingmatches gdttype
Paul Mackerras005a2f42007-07-26 22:36:39 +10006937
Paul Mackerras8b39e042008-12-02 09:02:46 +11006938 set markingmatches [expr {$gdttype eq [mc "containing:"]}]
Paul Mackerras005a2f42007-07-26 22:36:39 +10006939 set findcurline $l
Paul Mackerrasd6982062005-08-06 22:06:06 +10006940 selectline $l 1
Paul Mackerras8b39e042008-12-02 09:02:46 +11006941 if {$markingmatches &&
6942 ($findloc eq [mc "All fields"] || $findloc eq [mc "Comments"])} {
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00006943 # highlight the matches in the comments
6944 set f [$ctext get 1.0 $commentend]
6945 set matches [findmatches $f]
6946 foreach match $matches {
6947 set start [lindex $match 0]
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08006948 set end [expr {[lindex $match 1] + 1}]
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00006949 $ctext tag add found "1.0 + $start c" "1.0 + $end c"
6950 }
Paul Mackerras98f350e2005-05-15 05:56:51 +00006951 }
Paul Mackerras005a2f42007-07-26 22:36:39 +10006952 drawvisible
Paul Mackerras98f350e2005-05-15 05:56:51 +00006953}
6954
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006955# mark the bits of a headline or author that match a find string
Paul Mackerras005a2f42007-07-26 22:36:39 +10006956proc markmatches {canv l str tag matches font row} {
6957 global selectedline
6958
Paul Mackerras98f350e2005-05-15 05:56:51 +00006959 set bbox [$canv bbox $tag]
6960 set x0 [lindex $bbox 0]
6961 set y0 [lindex $bbox 1]
6962 set y1 [lindex $bbox 3]
6963 foreach match $matches {
6964 set start [lindex $match 0]
6965 set end [lindex $match 1]
6966 if {$start > $end} continue
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08006967 set xoff [font measure $font [string range $str 0 [expr {$start-1}]]]
6968 set xlen [font measure $font [string range $str 0 [expr {$end}]]]
6969 set t [$canv create rect [expr {$x0+$xoff}] $y0 \
6970 [expr {$x0+$xlen+2}] $y1 \
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006971 -outline {} -tags [list match$l matches] -fill yellow]
Paul Mackerras98f350e2005-05-15 05:56:51 +00006972 $canv lower $t
Paul Mackerras94b4a692008-05-20 20:51:06 +10006973 if {$row == $selectedline} {
Paul Mackerras005a2f42007-07-26 22:36:39 +10006974 $canv raise $t secsel
6975 }
Paul Mackerras98f350e2005-05-15 05:56:51 +00006976 }
6977}
6978
6979proc unmarkmatches {} {
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10006980 global markingmatches
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006981
Paul Mackerras98f350e2005-05-15 05:56:51 +00006982 allcanvs delete matches
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006983 set markingmatches 0
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10006984 stopfinding
Paul Mackerras98f350e2005-05-15 05:56:51 +00006985}
6986
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10006987proc selcanvline {w x y} {
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10006988 global canv canvy0 ctext linespc
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006989 global rowtextx
Paul Mackerras1db95b02005-05-09 04:08:39 +00006990 set ymax [lindex [$canv cget -scrollregion] 3]
Paul Mackerrascfb45632005-05-31 12:14:42 +00006991 if {$ymax == {}} return
Paul Mackerras1db95b02005-05-09 04:08:39 +00006992 set yfrac [lindex [$canv yview] 0]
6993 set y [expr {$y + $yfrac * $ymax}]
6994 set l [expr {int(($y - $canvy0) / $linespc + 0.5)}]
6995 if {$l < 0} {
6996 set l 0
6997 }
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10006998 if {$w eq $canv} {
Paul Mackerrasfc2a2562007-12-26 23:03:43 +11006999 set xmax [lindex [$canv cget -scrollregion] 2]
7000 set xleft [expr {[lindex [$canv xview] 0] * $xmax}]
7001 if {![info exists rowtextx($l)] || $xleft + $x < $rowtextx($l)} return
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10007002 }
Paul Mackerras98f350e2005-05-15 05:56:51 +00007003 unmarkmatches
Paul Mackerrasd6982062005-08-06 22:06:06 +10007004 selectline $l 1
Paul Mackerras5ad588d2005-05-10 01:02:55 +00007005}
7006
Linus Torvaldsb1ba39e2005-08-08 20:04:20 -07007007proc commit_descriptor {p} {
7008 global commitinfo
Paul Mackerrasb0934482006-05-15 09:56:08 +10007009 if {![info exists commitinfo($p)]} {
7010 getcommit $p
7011 }
Linus Torvaldsb1ba39e2005-08-08 20:04:20 -07007012 set l "..."
Paul Mackerrasb0934482006-05-15 09:56:08 +10007013 if {[llength $commitinfo($p)] > 1} {
Linus Torvaldsb1ba39e2005-08-08 20:04:20 -07007014 set l [lindex $commitinfo($p) 0]
7015 }
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10007016 return "$p ($l)\n"
Linus Torvaldsb1ba39e2005-08-08 20:04:20 -07007017}
7018
Paul Mackerras106288c2005-08-19 23:11:39 +10007019# append some text to the ctext widget, and make any SHA1 ID
7020# that we know about be a clickable link.
Paul Mackerras3441de52019-08-27 08:12:34 +10007021# Also look for URLs of the form "http[s]://..." and make them web links.
Sergey Vlasovf1b86292006-05-15 19:13:14 +04007022proc appendwithlinks {text tags} {
Paul Mackerrasd375ef92008-10-21 10:18:12 +11007023 global ctext linknum curview
Paul Mackerras106288c2005-08-19 23:11:39 +10007024
7025 set start [$ctext index "end - 1c"]
Sergey Vlasovf1b86292006-05-15 19:13:14 +04007026 $ctext insert end $text $tags
Jim Meyering6c9e2d12011-12-10 16:08:57 +01007027 set links [regexp -indices -all -inline {(?:\m|-g)[0-9a-f]{6,40}\M} $text]
Paul Mackerras106288c2005-08-19 23:11:39 +10007028 foreach l $links {
7029 set s [lindex $l 0]
7030 set e [lindex $l 1]
7031 set linkid [string range $text $s $e]
Paul Mackerras106288c2005-08-19 23:11:39 +10007032 incr e
Paul Mackerrasc73adce2007-09-27 10:35:05 +10007033 $ctext tag delete link$linknum
Paul Mackerras106288c2005-08-19 23:11:39 +10007034 $ctext tag add link$linknum "$start + $s c" "$start + $e c"
Paul Mackerras97645682007-08-23 22:24:38 +10007035 setlink $linkid link$linknum
Paul Mackerras106288c2005-08-19 23:11:39 +10007036 incr linknum
7037 }
Paul Mackerras3441de52019-08-27 08:12:34 +10007038 set wlinks [regexp -indices -all -inline -line \
7039 {https?://[^[:space:]]+} $text]
7040 foreach l $wlinks {
7041 set s2 [lindex $l 0]
7042 set e2 [lindex $l 1]
7043 set url [string range $text $s2 $e2]
7044 incr e2
7045 $ctext tag delete link$linknum
7046 $ctext tag add link$linknum "$start + $s2 c" "$start + $e2 c"
7047 setwlink $url link$linknum
7048 incr linknum
7049 }
Paul Mackerras97645682007-08-23 22:24:38 +10007050}
7051
7052proc setlink {id lk} {
Paul Mackerrasd375ef92008-10-21 10:18:12 +11007053 global curview ctext pendinglinks
Gauthier Östervall252c52d2013-03-27 14:40:51 +01007054 global linkfgcolor
Paul Mackerras97645682007-08-23 22:24:38 +10007055
Jim Meyering6c9e2d12011-12-10 16:08:57 +01007056 if {[string range $id 0 1] eq "-g"} {
7057 set id [string range $id 2 end]
7058 }
7059
Paul Mackerrasd375ef92008-10-21 10:18:12 +11007060 set known 0
7061 if {[string length $id] < 40} {
7062 set matches [longid $id]
7063 if {[llength $matches] > 0} {
7064 if {[llength $matches] > 1} return
7065 set known 1
7066 set id [lindex $matches 0]
7067 }
7068 } else {
7069 set known [commitinview $id $curview]
7070 }
7071 if {$known} {
Gauthier Östervall252c52d2013-03-27 14:40:51 +01007072 $ctext tag conf $lk -foreground $linkfgcolor -underline 1
Paul Mackerrasd375ef92008-10-21 10:18:12 +11007073 $ctext tag bind $lk <1> [list selbyid $id]
Paul Mackerras97645682007-08-23 22:24:38 +10007074 $ctext tag bind $lk <Enter> {linkcursor %W 1}
7075 $ctext tag bind $lk <Leave> {linkcursor %W -1}
7076 } else {
7077 lappend pendinglinks($id) $lk
Paul Mackerrasd375ef92008-10-21 10:18:12 +11007078 interestedin $id {makelink %P}
Paul Mackerras97645682007-08-23 22:24:38 +10007079 }
7080}
7081
Paul Mackerras3441de52019-08-27 08:12:34 +10007082proc setwlink {url lk} {
7083 global ctext
7084 global linkfgcolor
7085 global web_browser
7086
7087 if {$web_browser eq {}} return
7088 $ctext tag conf $lk -foreground $linkfgcolor -underline 1
7089 $ctext tag bind $lk <1> [list browseweb $url]
7090 $ctext tag bind $lk <Enter> {linkcursor %W 1}
7091 $ctext tag bind $lk <Leave> {linkcursor %W -1}
7092}
7093
Paul Mackerras6f63fc12009-04-21 22:22:31 +10007094proc appendshortlink {id {pre {}} {post {}}} {
7095 global ctext linknum
7096
7097 $ctext insert end $pre
7098 $ctext tag delete link$linknum
7099 $ctext insert end [string range $id 0 7] link$linknum
7100 $ctext insert end $post
7101 setlink $id link$linknum
7102 incr linknum
7103}
7104
Paul Mackerras97645682007-08-23 22:24:38 +10007105proc makelink {id} {
7106 global pendinglinks
7107
7108 if {![info exists pendinglinks($id)]} return
7109 foreach lk $pendinglinks($id) {
7110 setlink $id $lk
7111 }
7112 unset pendinglinks($id)
7113}
7114
7115proc linkcursor {w inc} {
7116 global linkentercount curtextcursor
7117
7118 if {[incr linkentercount $inc] > 0} {
7119 $w configure -cursor hand2
7120 } else {
7121 $w configure -cursor $curtextcursor
7122 if {$linkentercount < 0} {
7123 set linkentercount 0
7124 }
7125 }
Paul Mackerras106288c2005-08-19 23:11:39 +10007126}
7127
Paul Mackerras3441de52019-08-27 08:12:34 +10007128proc browseweb {url} {
7129 global web_browser
7130
7131 if {$web_browser eq {}} return
7132 # Use eval here in case $web_browser is a command plus some arguments
7133 if {[catch {eval exec $web_browser [list $url] &} err]} {
7134 error_popup "[mc "Error starting web browser:"] $err"
7135 }
7136}
7137
Rutger Nijlunsing6e5f7202006-04-05 10:24:03 +10007138proc viewnextline {dir} {
7139 global canv linespc
7140
7141 $canv delete hover
7142 set ymax [lindex [$canv cget -scrollregion] 3]
7143 set wnow [$canv yview]
7144 set wtop [expr {[lindex $wnow 0] * $ymax}]
7145 set newtop [expr {$wtop + $dir * $linespc}]
7146 if {$newtop < 0} {
7147 set newtop 0
7148 } elseif {$newtop > $ymax} {
7149 set newtop $ymax
7150 }
7151 allcanvs yview moveto [expr {$newtop * 1.0 / $ymax}]
7152}
7153
Paul Mackerrasef030b82006-06-04 11:50:38 +10007154# add a list of tag or branch names at position pos
7155# returns the number of names inserted
Paul Mackerrase11f1232007-06-16 20:29:25 +10007156proc appendrefs {pos ids var} {
Max Kirillovbde4a0f2014-06-24 08:19:44 +03007157 global ctext linknum curview $var maxrefs visiblerefs mainheadid
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10007158
Paul Mackerrasef030b82006-06-04 11:50:38 +10007159 if {[catch {$ctext index $pos}]} {
7160 return 0
7161 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10007162 $ctext conf -state normal
7163 $ctext delete $pos "$pos lineend"
7164 set tags {}
7165 foreach id $ids {
7166 foreach tag [set $var\($id\)] {
7167 lappend tags [list $tag $id]
7168 }
7169 }
Paul Mackerras386befb2013-01-02 15:25:29 +11007170
7171 set sep {}
7172 set tags [lsort -index 0 -decreasing $tags]
7173 set nutags 0
7174
Paul Mackerras0a4dd8b2007-06-16 21:21:57 +10007175 if {[llength $tags] > $maxrefs} {
Paul Mackerras386befb2013-01-02 15:25:29 +11007176 # If we are displaying heads, and there are too many,
7177 # see if there are some important heads to display.
Max Kirillovbde4a0f2014-06-24 08:19:44 +03007178 # Currently that are the current head and heads listed in $visiblerefs option
Paul Mackerras386befb2013-01-02 15:25:29 +11007179 set itags {}
7180 if {$var eq "idheads"} {
7181 set utags {}
7182 foreach ti $tags {
7183 set hname [lindex $ti 0]
7184 set id [lindex $ti 1]
Max Kirillovbde4a0f2014-06-24 08:19:44 +03007185 if {([lsearch -exact $visiblerefs $hname] != -1 || $id eq $mainheadid) &&
Paul Mackerras386befb2013-01-02 15:25:29 +11007186 [llength $itags] < $maxrefs} {
7187 lappend itags $ti
7188 } else {
7189 lappend utags $ti
7190 }
7191 }
7192 set tags $utags
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10007193 }
Paul Mackerras386befb2013-01-02 15:25:29 +11007194 if {$itags ne {}} {
7195 set str [mc "and many more"]
7196 set sep " "
7197 } else {
7198 set str [mc "many"]
7199 }
7200 $ctext insert $pos "$str ([llength $tags])"
7201 set nutags [llength $tags]
7202 set tags $itags
7203 }
7204
7205 foreach ti $tags {
7206 set id [lindex $ti 1]
7207 set lk link$linknum
7208 incr linknum
7209 $ctext tag delete $lk
7210 $ctext insert $pos $sep
7211 $ctext insert $pos [lindex $ti 0] $lk
7212 setlink $id $lk
7213 set sep ", "
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10007214 }
Paul Mackerrasd34835c2013-01-01 23:08:12 +11007215 $ctext tag add wwrap "$pos linestart" "$pos lineend"
Paul Mackerrase11f1232007-06-16 20:29:25 +10007216 $ctext conf -state disabled
Paul Mackerras386befb2013-01-02 15:25:29 +11007217 return [expr {[llength $tags] + $nutags}]
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10007218}
7219
7220# called when we have finished computing the nearby tags
Paul Mackerrase11f1232007-06-16 20:29:25 +10007221proc dispneartags {delay} {
7222 global selectedline currentid showneartags tagphase
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10007223
Paul Mackerras94b4a692008-05-20 20:51:06 +10007224 if {$selectedline eq {} || !$showneartags} return
Paul Mackerrase11f1232007-06-16 20:29:25 +10007225 after cancel dispnexttag
7226 if {$delay} {
7227 after 200 dispnexttag
7228 set tagphase -1
7229 } else {
7230 after idle dispnexttag
7231 set tagphase 0
7232 }
7233}
7234
7235proc dispnexttag {} {
7236 global selectedline currentid showneartags tagphase ctext
7237
Paul Mackerras94b4a692008-05-20 20:51:06 +10007238 if {$selectedline eq {} || !$showneartags} return
Paul Mackerrase11f1232007-06-16 20:29:25 +10007239 switch -- $tagphase {
7240 0 {
7241 set dtags [desctags $currentid]
7242 if {$dtags ne {}} {
7243 appendrefs precedes $dtags idtags
7244 }
7245 }
7246 1 {
7247 set atags [anctags $currentid]
7248 if {$atags ne {}} {
7249 appendrefs follows $atags idtags
7250 }
7251 }
7252 2 {
7253 set dheads [descheads $currentid]
7254 if {$dheads ne {}} {
7255 if {[appendrefs branch $dheads idheads] > 1
7256 && [$ctext get "branch -3c"] eq "h"} {
7257 # turn "Branch" into "Branches"
7258 $ctext conf -state normal
7259 $ctext insert "branch -2c" "es"
7260 $ctext conf -state disabled
7261 }
7262 }
Paul Mackerrasef030b82006-06-04 11:50:38 +10007263 }
7264 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10007265 if {[incr tagphase] <= 2} {
7266 after idle dispnexttag
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10007267 }
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10007268}
7269
Paul Mackerras28593d32008-11-13 23:01:46 +11007270proc make_secsel {id} {
Paul Mackerras03800812007-08-29 21:45:21 +10007271 global linehtag linentag linedtag canv canv2 canv3
7272
Paul Mackerras28593d32008-11-13 23:01:46 +11007273 if {![info exists linehtag($id)]} return
Paul Mackerras03800812007-08-29 21:45:21 +10007274 $canv delete secsel
Paul Mackerras28593d32008-11-13 23:01:46 +11007275 set t [eval $canv create rect [$canv bbox $linehtag($id)] -outline {{}} \
Paul Mackerras03800812007-08-29 21:45:21 +10007276 -tags secsel -fill [$canv cget -selectbackground]]
7277 $canv lower $t
7278 $canv2 delete secsel
Paul Mackerras28593d32008-11-13 23:01:46 +11007279 set t [eval $canv2 create rect [$canv2 bbox $linentag($id)] -outline {{}} \
Paul Mackerras03800812007-08-29 21:45:21 +10007280 -tags secsel -fill [$canv2 cget -selectbackground]]
7281 $canv2 lower $t
7282 $canv3 delete secsel
Paul Mackerras28593d32008-11-13 23:01:46 +11007283 set t [eval $canv3 create rect [$canv3 bbox $linedtag($id)] -outline {{}} \
Paul Mackerras03800812007-08-29 21:45:21 +10007284 -tags secsel -fill [$canv3 cget -selectbackground]]
7285 $canv3 lower $t
7286}
7287
Paul Mackerrasb9fdba72009-04-09 09:34:46 +10007288proc make_idmark {id} {
7289 global linehtag canv fgcolor
7290
7291 if {![info exists linehtag($id)]} return
7292 $canv delete markid
7293 set t [eval $canv create rect [$canv bbox $linehtag($id)] \
7294 -tags markid -outline $fgcolor]
7295 $canv raise $t
7296}
7297
Max Kirillov4135d362014-04-05 23:38:50 +03007298proc selectline {l isnew {desired_loc {}} {switch_to_patch 0}} {
Paul Mackerras03800812007-08-29 21:45:21 +10007299 global canv ctext commitinfo selectedline
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11007300 global canvy0 linespc parents children curview
Paul Mackerras7fcceed2006-04-27 19:21:49 +10007301 global currentid sha1entry
Paul Mackerras9f1afe02006-02-19 22:44:47 +11007302 global commentend idtags linknum
Paul Mackerrasd94f8cd2006-04-06 10:18:23 +10007303 global mergemax numcommits pending_select
Paul Mackerrase11f1232007-06-16 20:29:25 +10007304 global cmitmode showneartags allcommits
Paul Mackerrasc30acc72008-03-07 22:51:55 +11007305 global targetrow targetid lastscrollrows
Paul Mackerras21ac8a82011-03-09 20:52:38 +11007306 global autoselect autosellen jump_to_here
Thomas Rast9403bd02013-11-16 18:37:43 +01007307 global vinlinediff
Paul Mackerrasd6982062005-08-06 22:06:06 +10007308
Paul Mackerras009409f2015-05-02 20:53:36 +10007309 unset -nocomplain pending_select
Paul Mackerras84ba7342005-06-17 00:12:26 +00007310 $canv delete hover
Paul Mackerras9843c302005-08-30 10:57:11 +10007311 normalline
Paul Mackerras887c9962007-08-20 19:36:20 +10007312 unsel_reflist
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10007313 stopfinding
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11007314 if {$l < 0 || $l >= $numcommits} return
Paul Mackerrasac1276a2008-03-03 10:11:08 +11007315 set id [commitonrow $l]
7316 set targetid $id
7317 set targetrow $l
Paul Mackerrasc30acc72008-03-07 22:51:55 +11007318 set selectedline $l
7319 set currentid $id
7320 if {$lastscrollrows < $numcommits} {
7321 setcanvscroll
7322 }
Paul Mackerrasac1276a2008-03-03 10:11:08 +11007323
Max Kirillov4135d362014-04-05 23:38:50 +03007324 if {$cmitmode ne "patch" && $switch_to_patch} {
7325 set cmitmode "patch"
7326 }
7327
Paul Mackerras5ad588d2005-05-10 01:02:55 +00007328 set y [expr {$canvy0 + $l * $linespc}]
Paul Mackerras17386062005-05-18 22:51:00 +00007329 set ymax [lindex [$canv cget -scrollregion] 3]
Paul Mackerras58422152005-05-19 10:56:42 +00007330 set ytop [expr {$y - $linespc - 1}]
7331 set ybot [expr {$y + $linespc + 1}]
Paul Mackerras5ad588d2005-05-10 01:02:55 +00007332 set wnow [$canv yview]
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08007333 set wtop [expr {[lindex $wnow 0] * $ymax}]
7334 set wbot [expr {[lindex $wnow 1] * $ymax}]
Paul Mackerras58422152005-05-19 10:56:42 +00007335 set wh [expr {$wbot - $wtop}]
7336 set newtop $wtop
Paul Mackerras17386062005-05-18 22:51:00 +00007337 if {$ytop < $wtop} {
Paul Mackerras58422152005-05-19 10:56:42 +00007338 if {$ybot < $wtop} {
7339 set newtop [expr {$y - $wh / 2.0}]
7340 } else {
7341 set newtop $ytop
7342 if {$newtop > $wtop - $linespc} {
7343 set newtop [expr {$wtop - $linespc}]
7344 }
Paul Mackerras17386062005-05-18 22:51:00 +00007345 }
Paul Mackerras58422152005-05-19 10:56:42 +00007346 } elseif {$ybot > $wbot} {
7347 if {$ytop > $wbot} {
7348 set newtop [expr {$y - $wh / 2.0}]
7349 } else {
7350 set newtop [expr {$ybot - $wh}]
7351 if {$newtop < $wtop + $linespc} {
7352 set newtop [expr {$wtop + $linespc}]
7353 }
Paul Mackerras17386062005-05-18 22:51:00 +00007354 }
Paul Mackerras58422152005-05-19 10:56:42 +00007355 }
7356 if {$newtop != $wtop} {
7357 if {$newtop < 0} {
7358 set newtop 0
7359 }
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08007360 allcanvs yview moveto [expr {$newtop * 1.0 / $ymax}]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11007361 drawvisible
Paul Mackerras5ad588d2005-05-10 01:02:55 +00007362 }
Paul Mackerrasd6982062005-08-06 22:06:06 +10007363
Paul Mackerras28593d32008-11-13 23:01:46 +11007364 make_secsel $id
Paul Mackerras9f1afe02006-02-19 22:44:47 +11007365
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10007366 if {$isnew} {
Paul Mackerras354af6b2008-11-23 13:14:23 +11007367 addtohistory [list selbyid $id 0] savecmitpos
Paul Mackerrasd6982062005-08-06 22:06:06 +10007368 }
7369
Paul Mackerras98f350e2005-05-15 05:56:51 +00007370 $sha1entry delete 0 end
7371 $sha1entry insert 0 $id
Jeff King95293b52008-03-06 06:49:25 -05007372 if {$autoselect} {
Paul Mackerras21ac8a82011-03-09 20:52:38 +11007373 $sha1entry selection range 0 $autosellen
Jeff King95293b52008-03-06 06:49:25 -05007374 }
Paul Mackerras164ff272006-05-29 19:50:02 +10007375 rhighlight_sel $id
Paul Mackerras98f350e2005-05-15 05:56:51 +00007376
Paul Mackerras5ad588d2005-05-10 01:02:55 +00007377 $ctext conf -state normal
Paul Mackerras3ea06f92006-05-24 10:16:03 +10007378 clear_ctext
Paul Mackerras106288c2005-08-19 23:11:39 +10007379 set linknum 0
Paul Mackerrasd76afb12008-03-07 21:19:18 +11007380 if {![info exists commitinfo($id)]} {
7381 getcommit $id
7382 }
Paul Mackerras1db95b02005-05-09 04:08:39 +00007383 set info $commitinfo($id)
Paul Mackerras232475d2005-11-15 10:34:03 +11007384 set date [formatdate [lindex $info 2]]
Christian Stimmingd990ced2007-11-07 18:42:55 +01007385 $ctext insert end "[mc "Author"]: [lindex $info 1] $date\n"
Paul Mackerras232475d2005-11-15 10:34:03 +11007386 set date [formatdate [lindex $info 4]]
Christian Stimmingd990ced2007-11-07 18:42:55 +01007387 $ctext insert end "[mc "Committer"]: [lindex $info 3] $date\n"
Paul Mackerras887fe3c2005-05-21 07:35:37 +00007388 if {[info exists idtags($id)]} {
Christian Stimmingd990ced2007-11-07 18:42:55 +01007389 $ctext insert end [mc "Tags:"]
Paul Mackerras887fe3c2005-05-21 07:35:37 +00007390 foreach tag $idtags($id) {
7391 $ctext insert end " $tag"
7392 }
7393 $ctext insert end "\n"
7394 }
Mark Levedahl40b87ff2007-02-01 08:44:46 -05007395
Sergey Vlasovf1b86292006-05-15 19:13:14 +04007396 set headers {}
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11007397 set olds $parents($curview,$id)
Paul Mackerras79b2c752006-04-02 20:47:40 +10007398 if {[llength $olds] > 1} {
Paul Mackerrasb77b0272006-02-07 09:13:52 +11007399 set np 0
Paul Mackerras79b2c752006-04-02 20:47:40 +10007400 foreach p $olds {
Paul Mackerrasb77b0272006-02-07 09:13:52 +11007401 if {$np >= $mergemax} {
7402 set tag mmax
7403 } else {
7404 set tag m$np
7405 }
Christian Stimmingd990ced2007-11-07 18:42:55 +01007406 $ctext insert end "[mc "Parent"]: " $tag
Sergey Vlasovf1b86292006-05-15 19:13:14 +04007407 appendwithlinks [commit_descriptor $p] {}
Paul Mackerrasb77b0272006-02-07 09:13:52 +11007408 incr np
7409 }
7410 } else {
Paul Mackerras79b2c752006-04-02 20:47:40 +10007411 foreach p $olds {
Christian Stimmingd990ced2007-11-07 18:42:55 +01007412 append headers "[mc "Parent"]: [commit_descriptor $p]"
Linus Torvalds8b192802005-08-07 13:58:56 -07007413 }
Linus Torvaldsb1ba39e2005-08-08 20:04:20 -07007414 }
Paul Mackerrasb77b0272006-02-07 09:13:52 +11007415
Paul Mackerras6a90bff2007-06-18 09:48:23 +10007416 foreach c $children($curview,$id) {
Christian Stimmingd990ced2007-11-07 18:42:55 +01007417 append headers "[mc "Child"]: [commit_descriptor $c]"
Linus Torvalds8b192802005-08-07 13:58:56 -07007418 }
Paul Mackerrasd6982062005-08-06 22:06:06 +10007419
7420 # make anything that looks like a SHA1 ID be a clickable link
Sergey Vlasovf1b86292006-05-15 19:13:14 +04007421 appendwithlinks $headers {}
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10007422 if {$showneartags} {
7423 if {![info exists allcommits]} {
7424 getallcommits
7425 }
Christian Stimmingd990ced2007-11-07 18:42:55 +01007426 $ctext insert end "[mc "Branch"]: "
Paul Mackerrasef030b82006-06-04 11:50:38 +10007427 $ctext mark set branch "end -1c"
7428 $ctext mark gravity branch left
Christian Stimmingd990ced2007-11-07 18:42:55 +01007429 $ctext insert end "\n[mc "Follows"]: "
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10007430 $ctext mark set follows "end -1c"
7431 $ctext mark gravity follows left
Christian Stimmingd990ced2007-11-07 18:42:55 +01007432 $ctext insert end "\n[mc "Precedes"]: "
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10007433 $ctext mark set precedes "end -1c"
7434 $ctext mark gravity precedes left
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10007435 $ctext insert end "\n"
Paul Mackerrase11f1232007-06-16 20:29:25 +10007436 dispneartags 1
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10007437 }
7438 $ctext insert end "\n"
Paul Mackerras43c25072006-09-27 10:56:02 +10007439 set comment [lindex $info 5]
7440 if {[string first "\r" $comment] >= 0} {
7441 set comment [string map {"\r" "\n "} $comment]
7442 }
7443 appendwithlinks $comment {comment}
Paul Mackerrasd6982062005-08-06 22:06:06 +10007444
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00007445 $ctext tag remove found 1.0 end
Paul Mackerras5ad588d2005-05-10 01:02:55 +00007446 $ctext conf -state disabled
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00007447 set commentend [$ctext index "end - 1c"]
Paul Mackerras5ad588d2005-05-10 01:02:55 +00007448
Paul Mackerras8a897742008-10-27 21:36:25 +11007449 set jump_to_here $desired_loc
Christian Stimmingb007ee22007-11-07 18:44:35 +01007450 init_flist [mc "Comments"]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007451 if {$cmitmode eq "tree"} {
7452 gettree $id
Thomas Rast9403bd02013-11-16 18:37:43 +01007453 } elseif {$vinlinediff($curview) == 1} {
7454 showinlinediff $id
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007455 } elseif {[llength $olds] <= 1} {
Paul Mackerrasd3272442005-11-28 20:41:56 +11007456 startdiff $id
Paul Mackerras7b5ff7e2006-03-30 20:50:40 +11007457 } else {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11007458 mergediff $id
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10007459 }
7460}
7461
Rutger Nijlunsing6e5f7202006-04-05 10:24:03 +10007462proc selfirstline {} {
7463 unmarkmatches
7464 selectline 0 1
7465}
7466
7467proc sellastline {} {
7468 global numcommits
7469 unmarkmatches
7470 set l [expr {$numcommits - 1}]
7471 selectline $l 1
7472}
7473
Paul Mackerrase5c2d852005-05-11 23:44:54 +00007474proc selnextline {dir} {
7475 global selectedline
Mark Levedahlbd441de2007-08-07 21:40:34 -04007476 focus .
Paul Mackerras94b4a692008-05-20 20:51:06 +10007477 if {$selectedline eq {}} return
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08007478 set l [expr {$selectedline + $dir}]
Paul Mackerras98f350e2005-05-15 05:56:51 +00007479 unmarkmatches
Paul Mackerrasd6982062005-08-06 22:06:06 +10007480 selectline $l 1
7481}
7482
Rutger Nijlunsing6e5f7202006-04-05 10:24:03 +10007483proc selnextpage {dir} {
7484 global canv linespc selectedline numcommits
7485
7486 set lpp [expr {([winfo height $canv] - 2) / $linespc}]
7487 if {$lpp < 1} {
7488 set lpp 1
7489 }
7490 allcanvs yview scroll [expr {$dir * $lpp}] units
Paul Mackerrase72ee5e2006-05-20 09:58:49 +10007491 drawvisible
Paul Mackerras94b4a692008-05-20 20:51:06 +10007492 if {$selectedline eq {}} return
Rutger Nijlunsing6e5f7202006-04-05 10:24:03 +10007493 set l [expr {$selectedline + $dir * $lpp}]
7494 if {$l < 0} {
7495 set l 0
7496 } elseif {$l >= $numcommits} {
7497 set l [expr $numcommits - 1]
7498 }
7499 unmarkmatches
Mark Levedahl40b87ff2007-02-01 08:44:46 -05007500 selectline $l 1
Rutger Nijlunsing6e5f7202006-04-05 10:24:03 +10007501}
7502
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10007503proc unselectline {} {
Paul Mackerras50b44ec2006-04-04 10:16:22 +10007504 global selectedline currentid
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10007505
Paul Mackerras94b4a692008-05-20 20:51:06 +10007506 set selectedline {}
Paul Mackerras009409f2015-05-02 20:53:36 +10007507 unset -nocomplain currentid
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10007508 allcanvs delete secsel
Paul Mackerras164ff272006-05-29 19:50:02 +10007509 rhighlight_none
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10007510}
7511
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007512proc reselectline {} {
7513 global selectedline
7514
Paul Mackerras94b4a692008-05-20 20:51:06 +10007515 if {$selectedline ne {}} {
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007516 selectline $selectedline 0
7517 }
7518}
7519
Paul Mackerras354af6b2008-11-23 13:14:23 +11007520proc addtohistory {cmd {saveproc {}}} {
Paul Mackerras2516dae2006-04-21 10:35:31 +10007521 global history historyindex curview
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10007522
Paul Mackerras354af6b2008-11-23 13:14:23 +11007523 unset_posvars
7524 save_position
7525 set elt [list $curview $cmd $saveproc {}]
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10007526 if {$historyindex > 0
Paul Mackerras2516dae2006-04-21 10:35:31 +10007527 && [lindex $history [expr {$historyindex - 1}]] == $elt} {
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10007528 return
7529 }
7530
7531 if {$historyindex < [llength $history]} {
Paul Mackerras2516dae2006-04-21 10:35:31 +10007532 set history [lreplace $history $historyindex end $elt]
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10007533 } else {
Paul Mackerras2516dae2006-04-21 10:35:31 +10007534 lappend history $elt
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10007535 }
7536 incr historyindex
7537 if {$historyindex > 1} {
Junio C Hamanoe9937d22007-02-01 08:46:38 -05007538 .tf.bar.leftbut conf -state normal
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10007539 } else {
Junio C Hamanoe9937d22007-02-01 08:46:38 -05007540 .tf.bar.leftbut conf -state disabled
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10007541 }
Junio C Hamanoe9937d22007-02-01 08:46:38 -05007542 .tf.bar.rightbut conf -state disabled
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10007543}
7544
Paul Mackerras354af6b2008-11-23 13:14:23 +11007545# save the scrolling position of the diff display pane
7546proc save_position {} {
7547 global historyindex history
7548
7549 if {$historyindex < 1} return
7550 set hi [expr {$historyindex - 1}]
7551 set fn [lindex $history $hi 2]
7552 if {$fn ne {}} {
7553 lset history $hi 3 [eval $fn]
7554 }
7555}
7556
7557proc unset_posvars {} {
7558 global last_posvars
7559
7560 if {[info exists last_posvars]} {
7561 foreach {var val} $last_posvars {
7562 global $var
Paul Mackerras009409f2015-05-02 20:53:36 +10007563 unset -nocomplain $var
Paul Mackerras354af6b2008-11-23 13:14:23 +11007564 }
7565 unset last_posvars
7566 }
7567}
7568
Paul Mackerras2516dae2006-04-21 10:35:31 +10007569proc godo {elt} {
Paul Mackerras354af6b2008-11-23 13:14:23 +11007570 global curview last_posvars
Paul Mackerras2516dae2006-04-21 10:35:31 +10007571
7572 set view [lindex $elt 0]
7573 set cmd [lindex $elt 1]
Paul Mackerras354af6b2008-11-23 13:14:23 +11007574 set pv [lindex $elt 3]
Paul Mackerras2516dae2006-04-21 10:35:31 +10007575 if {$curview != $view} {
7576 showview $view
7577 }
Paul Mackerras354af6b2008-11-23 13:14:23 +11007578 unset_posvars
7579 foreach {var val} $pv {
7580 global $var
7581 set $var $val
7582 }
7583 set last_posvars $pv
Paul Mackerras2516dae2006-04-21 10:35:31 +10007584 eval $cmd
7585}
7586
Paul Mackerrasd6982062005-08-06 22:06:06 +10007587proc goback {} {
7588 global history historyindex
Mark Levedahlbd441de2007-08-07 21:40:34 -04007589 focus .
Paul Mackerrasd6982062005-08-06 22:06:06 +10007590
7591 if {$historyindex > 1} {
Paul Mackerras354af6b2008-11-23 13:14:23 +11007592 save_position
Paul Mackerrasd6982062005-08-06 22:06:06 +10007593 incr historyindex -1
Paul Mackerras2516dae2006-04-21 10:35:31 +10007594 godo [lindex $history [expr {$historyindex - 1}]]
Junio C Hamanoe9937d22007-02-01 08:46:38 -05007595 .tf.bar.rightbut conf -state normal
Paul Mackerrasd6982062005-08-06 22:06:06 +10007596 }
7597 if {$historyindex <= 1} {
Junio C Hamanoe9937d22007-02-01 08:46:38 -05007598 .tf.bar.leftbut conf -state disabled
Paul Mackerrasd6982062005-08-06 22:06:06 +10007599 }
7600}
7601
7602proc goforw {} {
7603 global history historyindex
Mark Levedahlbd441de2007-08-07 21:40:34 -04007604 focus .
Paul Mackerrasd6982062005-08-06 22:06:06 +10007605
7606 if {$historyindex < [llength $history]} {
Paul Mackerras354af6b2008-11-23 13:14:23 +11007607 save_position
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10007608 set cmd [lindex $history $historyindex]
Paul Mackerrasd6982062005-08-06 22:06:06 +10007609 incr historyindex
Paul Mackerras2516dae2006-04-21 10:35:31 +10007610 godo $cmd
Junio C Hamanoe9937d22007-02-01 08:46:38 -05007611 .tf.bar.leftbut conf -state normal
Paul Mackerrasd6982062005-08-06 22:06:06 +10007612 }
7613 if {$historyindex >= [llength $history]} {
Junio C Hamanoe9937d22007-02-01 08:46:38 -05007614 .tf.bar.rightbut conf -state disabled
Paul Mackerrasd6982062005-08-06 22:06:06 +10007615 }
Paul Mackerras5ad588d2005-05-10 01:02:55 +00007616}
7617
Max Kirillovd4ec30b2014-07-08 23:45:35 +03007618proc go_to_parent {i} {
7619 global parents curview targetid
7620 set ps $parents($curview,$targetid)
7621 if {[llength $ps] >= $i} {
7622 selbyid [lindex $ps [expr $i - 1]]
7623 }
7624}
7625
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007626proc gettree {id} {
Paul Mackerras8f489362007-07-13 19:49:37 +10007627 global treefilelist treeidlist diffids diffmergeid treepending
7628 global nullid nullid2
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007629
7630 set diffids $id
Paul Mackerras009409f2015-05-02 20:53:36 +10007631 unset -nocomplain diffmergeid
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007632 if {![info exists treefilelist($id)]} {
7633 if {![info exists treepending]} {
Paul Mackerras8f489362007-07-13 19:49:37 +10007634 if {$id eq $nullid} {
7635 set cmd [list | git ls-files]
7636 } elseif {$id eq $nullid2} {
7637 set cmd [list | git ls-files --stage -t]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007638 } else {
Paul Mackerras8f489362007-07-13 19:49:37 +10007639 set cmd [list | git ls-tree -r $id]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007640 }
7641 if {[catch {set gtf [open $cmd r]}]} {
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007642 return
7643 }
7644 set treepending $id
7645 set treefilelist($id) {}
7646 set treeidlist($id) {}
Alexander Gavrilov09c70292008-10-13 12:12:31 +04007647 fconfigure $gtf -blocking 0 -encoding binary
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007648 filerun $gtf [list gettreeline $gtf $id]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007649 }
7650 } else {
7651 setfilelist $id
7652 }
7653}
7654
7655proc gettreeline {gtf id} {
Paul Mackerras8f489362007-07-13 19:49:37 +10007656 global treefilelist treeidlist treepending cmitmode diffids nullid nullid2
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007657
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007658 set nl 0
7659 while {[incr nl] <= 1000 && [gets $gtf line] >= 0} {
Paul Mackerras8f489362007-07-13 19:49:37 +10007660 if {$diffids eq $nullid} {
7661 set fname $line
7662 } else {
Paul Mackerras9396cd32007-06-23 20:28:15 +10007663 set i [string first "\t" $line]
7664 if {$i < 0} continue
Paul Mackerras9396cd32007-06-23 20:28:15 +10007665 set fname [string range $line [expr {$i+1}] end]
Paul Mackerrasf31fa2c2008-04-28 09:40:50 +10007666 set line [string range $line 0 [expr {$i-1}]]
7667 if {$diffids ne $nullid2 && [lindex $line 1] ne "blob"} continue
7668 set sha1 [lindex $line 2]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007669 lappend treeidlist($id) $sha1
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007670 }
Alexander Gavrilov09c70292008-10-13 12:12:31 +04007671 if {[string index $fname 0] eq "\""} {
7672 set fname [lindex $fname 0]
7673 }
7674 set fname [encoding convertfrom $fname]
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007675 lappend treefilelist($id) $fname
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007676 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007677 if {![eof $gtf]} {
7678 return [expr {$nl >= 1000? 2: 1}]
7679 }
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007680 close $gtf
7681 unset treepending
7682 if {$cmitmode ne "tree"} {
7683 if {![info exists diffmergeid]} {
7684 gettreediffs $diffids
7685 }
7686 } elseif {$id ne $diffids} {
7687 gettree $diffids
7688 } else {
7689 setfilelist $id
7690 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007691 return 0
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007692}
7693
7694proc showfile {f} {
Paul Mackerras8f489362007-07-13 19:49:37 +10007695 global treefilelist treeidlist diffids nullid nullid2
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04007696 global ctext_file_names ctext_file_lines
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007697 global ctext commentend
7698
7699 set i [lsearch -exact $treefilelist($diffids) $f]
7700 if {$i < 0} {
7701 puts "oops, $f not in list for id $diffids"
7702 return
7703 }
Paul Mackerras8f489362007-07-13 19:49:37 +10007704 if {$diffids eq $nullid} {
7705 if {[catch {set bf [open $f r]} err]} {
7706 puts "oops, can't read $f: $err"
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007707 return
7708 }
7709 } else {
Paul Mackerras8f489362007-07-13 19:49:37 +10007710 set blob [lindex $treeidlist($diffids) $i]
7711 if {[catch {set bf [open [concat | git cat-file blob $blob] r]} err]} {
7712 puts "oops, error reading blob $blob: $err"
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007713 return
7714 }
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007715 }
Alexander Gavrilov09c70292008-10-13 12:12:31 +04007716 fconfigure $bf -blocking 0 -encoding [get_path_encoding $f]
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007717 filerun $bf [list getblobline $bf $diffids]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007718 $ctext config -state normal
Paul Mackerras3ea06f92006-05-24 10:16:03 +10007719 clear_ctext $commentend
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04007720 lappend ctext_file_names $f
7721 lappend ctext_file_lines [lindex [split $commentend "."] 0]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007722 $ctext insert end "\n"
7723 $ctext insert end "$f\n" filesep
7724 $ctext config -state disabled
7725 $ctext yview $commentend
Paul Mackerras32f1b3e2007-09-28 21:27:39 +10007726 settabs 0
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007727}
7728
7729proc getblobline {bf id} {
7730 global diffids cmitmode ctext
7731
7732 if {$id ne $diffids || $cmitmode ne "tree"} {
7733 catch {close $bf}
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007734 return 0
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007735 }
7736 $ctext config -state normal
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007737 set nl 0
7738 while {[incr nl] <= 1000 && [gets $bf line] >= 0} {
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007739 $ctext insert end "$line\n"
7740 }
7741 if {[eof $bf]} {
Paul Mackerras8a897742008-10-27 21:36:25 +11007742 global jump_to_here ctext_file_names commentend
7743
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007744 # delete last newline
7745 $ctext delete "end - 2c" "end - 1c"
7746 close $bf
Paul Mackerras8a897742008-10-27 21:36:25 +11007747 if {$jump_to_here ne {} &&
7748 [lindex $jump_to_here 0] eq [lindex $ctext_file_names 0]} {
7749 set lnum [expr {[lindex $jump_to_here 1] +
7750 [lindex [split $commentend .] 0]}]
7751 mark_ctext_line $lnum
7752 }
Stefan Haller120ea892010-11-14 13:21:50 +01007753 $ctext config -state disabled
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007754 return 0
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007755 }
7756 $ctext config -state disabled
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007757 return [expr {$nl >= 1000? 2: 1}]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007758}
7759
Paul Mackerras8a897742008-10-27 21:36:25 +11007760proc mark_ctext_line {lnum} {
Paul Mackerrase3e901b2008-10-27 22:37:21 +11007761 global ctext markbgcolor
Paul Mackerras8a897742008-10-27 21:36:25 +11007762
7763 $ctext tag delete omark
7764 $ctext tag add omark $lnum.0 "$lnum.0 + 1 line"
Paul Mackerrase3e901b2008-10-27 22:37:21 +11007765 $ctext tag conf omark -background $markbgcolor
Paul Mackerras8a897742008-10-27 21:36:25 +11007766 $ctext see $lnum.0
7767}
7768
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11007769proc mergediff {id} {
Paul Mackerras8b07dca2008-11-02 22:34:47 +11007770 global diffmergeid
Alexander Gavrilov2df64422008-10-08 11:05:37 +04007771 global diffids treediffs
Paul Mackerras8b07dca2008-11-02 22:34:47 +11007772 global parents curview
Paul Mackerrase2ed4322005-07-17 03:39:44 -04007773
Paul Mackerras3c461ff2005-07-20 09:13:46 -04007774 set diffmergeid $id
Paul Mackerras7a1d9d12006-03-22 10:21:45 +11007775 set diffids $id
Alexander Gavrilov2df64422008-10-08 11:05:37 +04007776 set treediffs($id) {}
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11007777 set np [llength $parents($curview,$id)]
Paul Mackerras32f1b3e2007-09-28 21:27:39 +10007778 settabs $np
Paul Mackerras8b07dca2008-11-02 22:34:47 +11007779 getblobdiffs $id
Paul Mackerrasc8a4acb2005-07-29 09:23:03 -05007780}
7781
Paul Mackerras3c461ff2005-07-20 09:13:46 -04007782proc startdiff {ids} {
Paul Mackerras8f489362007-07-13 19:49:37 +10007783 global treediffs diffids treepending diffmergeid nullid nullid2
Paul Mackerras3c461ff2005-07-20 09:13:46 -04007784
Paul Mackerras32f1b3e2007-09-28 21:27:39 +10007785 settabs 1
Paul Mackerras3c461ff2005-07-20 09:13:46 -04007786 set diffids $ids
Paul Mackerras009409f2015-05-02 20:53:36 +10007787 unset -nocomplain diffmergeid
Paul Mackerras8f489362007-07-13 19:49:37 +10007788 if {![info exists treediffs($ids)] ||
7789 [lsearch -exact $ids $nullid] >= 0 ||
7790 [lsearch -exact $ids $nullid2] >= 0} {
Paul Mackerras3c461ff2005-07-20 09:13:46 -04007791 if {![info exists treepending]} {
7792 gettreediffs $ids
7793 }
7794 } else {
7795 addtocflist $ids
7796 }
7797}
7798
Thomas Rast9403bd02013-11-16 18:37:43 +01007799proc showinlinediff {ids} {
7800 global commitinfo commitdata ctext
7801 global treediffs
7802
7803 set info $commitinfo($ids)
7804 set diff [lindex $info 7]
7805 set difflines [split $diff "\n"]
7806
7807 initblobdiffvars
7808 set treediff {}
7809
7810 set inhdr 0
7811 foreach line $difflines {
7812 if {![string compare -length 5 "diff " $line]} {
7813 set inhdr 1
7814 } elseif {$inhdr && ![string compare -length 4 "+++ " $line]} {
7815 # offset also accounts for the b/ prefix
7816 lappend treediff [string range $line 6 end]
7817 set inhdr 0
7818 }
7819 }
7820
7821 set treediffs($ids) $treediff
7822 add_flist $treediff
7823
7824 $ctext conf -state normal
7825 foreach line $difflines {
7826 parseblobdiffline $ids $line
7827 }
7828 maybe_scroll_ctext 1
7829 $ctext conf -state disabled
7830}
7831
Pat Thoyts65bb0bd2011-12-13 16:50:50 +00007832# If the filename (name) is under any of the passed filter paths
7833# then return true to include the file in the listing.
Paul Mackerras7a39a172007-10-23 10:15:11 +10007834proc path_filter {filter name} {
Pat Thoyts65bb0bd2011-12-13 16:50:50 +00007835 set worktree [gitworktree]
Paul Mackerras7a39a172007-10-23 10:15:11 +10007836 foreach p $filter {
Pat Thoyts65bb0bd2011-12-13 16:50:50 +00007837 set fq_p [file normalize $p]
7838 set fq_n [file normalize [file join $worktree $name]]
7839 if {[string match [file normalize $fq_p]* $fq_n]} {
7840 return 1
Paul Mackerras7a39a172007-10-23 10:15:11 +10007841 }
7842 }
7843 return 0
7844}
7845
Paul Mackerras3c461ff2005-07-20 09:13:46 -04007846proc addtocflist {ids} {
Paul Mackerras74a40c72007-10-24 10:16:56 +10007847 global treediffs
Paul Mackerras7a39a172007-10-23 10:15:11 +10007848
Paul Mackerras74a40c72007-10-24 10:16:56 +10007849 add_flist $treediffs($ids)
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10007850 getblobdiffs $ids
Paul Mackerrasd2610d12005-05-11 00:45:38 +00007851}
7852
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007853proc diffcmd {ids flags} {
Jens Lehmann17f98362014-04-08 21:36:08 +02007854 global log_showroot nullid nullid2 git_version
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007855
7856 set i [lsearch -exact $ids $nullid]
Paul Mackerras8f489362007-07-13 19:49:37 +10007857 set j [lsearch -exact $ids $nullid2]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007858 if {$i >= 0} {
Paul Mackerras8f489362007-07-13 19:49:37 +10007859 if {[llength $ids] > 1 && $j < 0} {
7860 # comparing working directory with some specific revision
7861 set cmd [concat | git diff-index $flags]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007862 if {$i == 0} {
7863 lappend cmd -R [lindex $ids 1]
7864 } else {
7865 lappend cmd [lindex $ids 0]
7866 }
7867 } else {
Paul Mackerras8f489362007-07-13 19:49:37 +10007868 # comparing working directory with index
7869 set cmd [concat | git diff-files $flags]
7870 if {$j == 1} {
7871 lappend cmd -R
7872 }
7873 }
7874 } elseif {$j >= 0} {
Jens Lehmann17f98362014-04-08 21:36:08 +02007875 if {[package vcompare $git_version "1.7.2"] >= 0} {
7876 set flags "$flags --ignore-submodules=dirty"
7877 }
Paul Mackerras8f489362007-07-13 19:49:37 +10007878 set cmd [concat | git diff-index --cached $flags]
7879 if {[llength $ids] > 1} {
7880 # comparing index with specific revision
Jens Lehmann90a77922009-10-27 18:13:42 +01007881 if {$j == 0} {
Paul Mackerras8f489362007-07-13 19:49:37 +10007882 lappend cmd -R [lindex $ids 1]
7883 } else {
7884 lappend cmd [lindex $ids 0]
7885 }
7886 } else {
7887 # comparing index with HEAD
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007888 lappend cmd HEAD
7889 }
7890 } else {
Marcus Karlssonb2b76d12011-10-04 22:08:13 +02007891 if {$log_showroot} {
7892 lappend flags --root
7893 }
Paul Mackerras8f489362007-07-13 19:49:37 +10007894 set cmd [concat | git diff-tree -r $flags $ids]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007895 }
7896 return $cmd
7897}
7898
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10007899proc gettreediffs {ids} {
Felipe Contreras2c8cd902013-04-27 17:01:39 -05007900 global treediff treepending limitdiffs vfilelimit curview
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007901
Felipe Contreras2c8cd902013-04-27 17:01:39 -05007902 set cmd [diffcmd $ids {--no-commit-id}]
7903 if {$limitdiffs && $vfilelimit($curview) ne {}} {
7904 set cmd [concat $cmd -- $vfilelimit($curview)]
7905 }
7906 if {[catch {set gdtf [open $cmd r]}]} return
Alexander Gavrilov72721312008-07-26 18:48:41 +04007907
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10007908 set treepending $ids
Paul Mackerras3c461ff2005-07-20 09:13:46 -04007909 set treediff {}
Alexander Gavrilov09c70292008-10-13 12:12:31 +04007910 fconfigure $gdtf -blocking 0 -encoding binary
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007911 filerun $gdtf [list gettreediffline $gdtf $ids]
Paul Mackerrasd2610d12005-05-11 00:45:38 +00007912}
7913
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10007914proc gettreediffline {gdtf ids} {
Paul Mackerras3c461ff2005-07-20 09:13:46 -04007915 global treediff treediffs treepending diffids diffmergeid
Paul Mackerras39ee47e2008-10-15 22:23:03 +11007916 global cmitmode vfilelimit curview limitdiffs perfile_attrs
Paul Mackerras3c461ff2005-07-20 09:13:46 -04007917
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007918 set nr 0
Alexander Gavrilov4db09302008-10-13 12:12:33 +04007919 set sublist {}
Paul Mackerras39ee47e2008-10-15 22:23:03 +11007920 set max 1000
7921 if {$perfile_attrs} {
7922 # cache_gitattr is slow, and even slower on win32 where we
7923 # have to invoke it for only about 30 paths at a time
7924 set max 500
7925 if {[tk windowingsystem] == "win32"} {
7926 set max 120
7927 }
7928 }
7929 while {[incr nr] <= $max && [gets $gdtf line] >= 0} {
Paul Mackerras9396cd32007-06-23 20:28:15 +10007930 set i [string first "\t" $line]
7931 if {$i >= 0} {
7932 set file [string range $line [expr {$i+1}] end]
7933 if {[string index $file 0] eq "\""} {
7934 set file [lindex $file 0]
7935 }
Alexander Gavrilov09c70292008-10-13 12:12:31 +04007936 set file [encoding convertfrom $file]
Paul Mackerras48a81b72008-11-04 21:09:00 +11007937 if {$file ne [lindex $treediff end]} {
7938 lappend treediff $file
7939 lappend sublist $file
7940 }
Paul Mackerras9396cd32007-06-23 20:28:15 +10007941 }
Paul Mackerrasd2610d12005-05-11 00:45:38 +00007942 }
Paul Mackerras39ee47e2008-10-15 22:23:03 +11007943 if {$perfile_attrs} {
7944 cache_gitattr encoding $sublist
7945 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007946 if {![eof $gdtf]} {
Paul Mackerras39ee47e2008-10-15 22:23:03 +11007947 return [expr {$nr >= $max? 2: 1}]
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007948 }
7949 close $gdtf
Felipe Contreras2c8cd902013-04-27 17:01:39 -05007950 set treediffs($ids) $treediff
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007951 unset treepending
Paul Mackerrase1160132008-11-18 21:40:32 +11007952 if {$cmitmode eq "tree" && [llength $diffids] == 1} {
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007953 gettree $diffids
7954 } elseif {$ids != $diffids} {
7955 if {![info exists diffmergeid]} {
7956 gettreediffs $diffids
7957 }
7958 } else {
7959 addtocflist $ids
7960 }
7961 return 0
Paul Mackerrasd2610d12005-05-11 00:45:38 +00007962}
7963
Steffen Prohaska890fae72007-08-12 12:05:46 +02007964# empty string or positive integer
7965proc diffcontextvalidate {v} {
7966 return [regexp {^(|[1-9][0-9]*)$} $v]
7967}
7968
7969proc diffcontextchange {n1 n2 op} {
7970 global diffcontextstring diffcontext
7971
7972 if {[string is integer -strict $diffcontextstring]} {
Markus Heidelberga41ddbb2009-05-23 19:31:37 +02007973 if {$diffcontextstring >= 0} {
Steffen Prohaska890fae72007-08-12 12:05:46 +02007974 set diffcontext $diffcontextstring
7975 reselectline
7976 }
7977 }
7978}
7979
Steffen Prohaskab9b86002008-01-17 23:42:55 +01007980proc changeignorespace {} {
7981 reselectline
7982}
7983
Thomas Rastae4e3ff2010-10-16 12:15:10 +02007984proc changeworddiff {name ix op} {
7985 reselectline
7986}
7987
Thomas Rast5de460a2013-11-16 18:37:41 +01007988proc initblobdiffvars {} {
7989 global diffencoding targetline diffnparents
7990 global diffinhdr currdiffsubmod diffseehere
7991 set targetline {}
7992 set diffnparents 0
7993 set diffinhdr 0
7994 set diffencoding [get_path_encoding {}]
7995 set currdiffsubmod ""
7996 set diffseehere -1
7997}
7998
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10007999proc getblobdiffs {ids} {
Paul Mackerras8d73b242007-10-06 20:22:00 +10008000 global blobdifffd diffids env
Thomas Rast5de460a2013-11-16 18:37:41 +01008001 global treediffs
Steffen Prohaska890fae72007-08-12 12:05:46 +02008002 global diffcontext
Steffen Prohaskab9b86002008-01-17 23:42:55 +01008003 global ignorespace
Thomas Rastae4e3ff2010-10-16 12:15:10 +02008004 global worddiff
Paul Mackerras3ed31a82008-04-26 16:00:00 +10008005 global limitdiffs vfilelimit curview
Thomas Rast5de460a2013-11-16 18:37:41 +01008006 global git_version
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008007
Paul Mackerrasa8138732009-05-16 21:06:01 +10008008 set textconv {}
8009 if {[package vcompare $git_version "1.6.1"] >= 0} {
8010 set textconv "--textconv"
8011 }
Jens Lehmann5c838d22009-10-28 12:40:45 +01008012 set submodule {}
8013 if {[package vcompare $git_version "1.6.6"] >= 0} {
8014 set submodule "--submodule"
8015 }
8016 set cmd [diffcmd $ids "-p $textconv $submodule -C --cc --no-commit-id -U$diffcontext"]
Steffen Prohaskab9b86002008-01-17 23:42:55 +01008017 if {$ignorespace} {
8018 append cmd " -w"
8019 }
Thomas Rastae4e3ff2010-10-16 12:15:10 +02008020 if {$worddiff ne [mc "Line diff"]} {
8021 append cmd " --word-diff=porcelain"
8022 }
Paul Mackerras3ed31a82008-04-26 16:00:00 +10008023 if {$limitdiffs && $vfilelimit($curview) ne {}} {
8024 set cmd [concat $cmd -- $vfilelimit($curview)]
Paul Mackerras7a39a172007-10-23 10:15:11 +10008025 }
8026 if {[catch {set bdf [open $cmd r]} err]} {
Paul Mackerras8b07dca2008-11-02 22:34:47 +11008027 error_popup [mc "Error getting diffs: %s" $err]
Paul Mackerrase5c2d852005-05-11 23:44:54 +00008028 return
8029 }
Pat Thoyts681c3292009-03-16 10:24:40 +00008030 fconfigure $bdf -blocking 0 -encoding binary -eofchar {}
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008031 set blobdifffd($ids) $bdf
Thomas Rast5de460a2013-11-16 18:37:41 +01008032 initblobdiffvars
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10008033 filerun $bdf [list getblobdiffline $bdf $diffids]
Paul Mackerrase5c2d852005-05-11 23:44:54 +00008034}
8035
Paul Mackerras354af6b2008-11-23 13:14:23 +11008036proc savecmitpos {} {
8037 global ctext cmitmode
8038
8039 if {$cmitmode eq "tree"} {
8040 return {}
8041 }
8042 return [list target_scrollpos [$ctext index @0,0]]
8043}
8044
8045proc savectextpos {} {
8046 global ctext
8047
8048 return [list target_scrollpos [$ctext index @0,0]]
8049}
8050
8051proc maybe_scroll_ctext {ateof} {
8052 global ctext target_scrollpos
8053
8054 if {![info exists target_scrollpos]} return
8055 if {!$ateof} {
8056 set nlines [expr {[winfo height $ctext]
8057 / [font metrics textfont -linespace]}]
8058 if {[$ctext compare "$target_scrollpos + $nlines lines" <= end]} return
8059 }
8060 $ctext yview $target_scrollpos
8061 unset target_scrollpos
8062}
8063
Paul Mackerras89b11d32006-05-02 19:55:31 +10008064proc setinlist {var i val} {
8065 global $var
8066
8067 while {[llength [set $var]] < $i} {
8068 lappend $var {}
8069 }
8070 if {[llength [set $var]] == $i} {
8071 lappend $var $val
8072 } else {
8073 lset $var $i $val
8074 }
8075}
8076
Paul Mackerras9396cd32007-06-23 20:28:15 +10008077proc makediffhdr {fname ids} {
Paul Mackerras8b07dca2008-11-02 22:34:47 +11008078 global ctext curdiffstart treediffs diffencoding
Paul Mackerras8a897742008-10-27 21:36:25 +11008079 global ctext_file_names jump_to_here targetline diffline
Paul Mackerras9396cd32007-06-23 20:28:15 +10008080
Paul Mackerras8b07dca2008-11-02 22:34:47 +11008081 set fname [encoding convertfrom $fname]
8082 set diffencoding [get_path_encoding $fname]
Paul Mackerras9396cd32007-06-23 20:28:15 +10008083 set i [lsearch -exact $treediffs($ids) $fname]
8084 if {$i >= 0} {
8085 setinlist difffilestart $i $curdiffstart
8086 }
Paul Mackerras48a81b72008-11-04 21:09:00 +11008087 lset ctext_file_names end $fname
Paul Mackerras9396cd32007-06-23 20:28:15 +10008088 set l [expr {(78 - [string length $fname]) / 2}]
8089 set pad [string range "----------------------------------------" 1 $l]
8090 $ctext insert $curdiffstart "$pad $fname $pad" filesep
Paul Mackerras8a897742008-10-27 21:36:25 +11008091 set targetline {}
8092 if {$jump_to_here ne {} && [lindex $jump_to_here 0] eq $fname} {
8093 set targetline [lindex $jump_to_here 1]
8094 }
8095 set diffline 0
Paul Mackerras9396cd32007-06-23 20:28:15 +10008096}
8097
Thomas Rast5de460a2013-11-16 18:37:41 +01008098proc blobdiffmaybeseehere {ateof} {
8099 global diffseehere
8100 if {$diffseehere >= 0} {
8101 mark_ctext_line [lindex [split $diffseehere .] 0]
8102 }
Max Kirillov1f3c8722014-01-18 14:58:51 +02008103 maybe_scroll_ctext $ateof
Thomas Rast5de460a2013-11-16 18:37:41 +01008104}
8105
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008106proc getblobdiffline {bdf ids} {
Thomas Rast5de460a2013-11-16 18:37:41 +01008107 global diffids blobdifffd
8108 global ctext
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008109
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10008110 set nr 0
Paul Mackerrase5c2d852005-05-11 23:44:54 +00008111 $ctext conf -state normal
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10008112 while {[incr nr] <= 1000 && [gets $bdf line] >= 0} {
8113 if {$ids != $diffids || $bdf != $blobdifffd($ids)} {
Markus Hitter0748f412016-11-07 16:01:17 +01008114 # Older diff read. Abort it.
Paul Mackerrasc21398b2009-09-07 10:08:21 +10008115 catch {close $bdf}
Markus Hitter0748f412016-11-07 16:01:17 +01008116 if {$ids != $diffids} {
8117 array unset blobdifffd $ids
8118 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10008119 return 0
Paul Mackerras89b11d32006-05-02 19:55:31 +10008120 }
Thomas Rast5de460a2013-11-16 18:37:41 +01008121 parseblobdiffline $ids $line
Paul Mackerrase5c2d852005-05-11 23:44:54 +00008122 }
8123 $ctext conf -state disabled
Thomas Rast5de460a2013-11-16 18:37:41 +01008124 blobdiffmaybeseehere [eof $bdf]
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10008125 if {[eof $bdf]} {
Paul Mackerrasc21398b2009-09-07 10:08:21 +10008126 catch {close $bdf}
Markus Hitter0748f412016-11-07 16:01:17 +01008127 array unset blobdifffd $ids
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10008128 return 0
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008129 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10008130 return [expr {$nr >= 1000? 2: 1}]
Paul Mackerrase5c2d852005-05-11 23:44:54 +00008131}
8132
Thomas Rast5de460a2013-11-16 18:37:41 +01008133proc parseblobdiffline {ids line} {
8134 global ctext curdiffstart
8135 global diffnexthead diffnextnote difffilestart
8136 global ctext_file_names ctext_file_lines
8137 global diffinhdr treediffs mergemax diffnparents
8138 global diffencoding jump_to_here targetline diffline currdiffsubmod
8139 global worddiff diffseehere
8140
8141 if {![string compare -length 5 "diff " $line]} {
8142 if {![regexp {^diff (--cc|--git) } $line m type]} {
8143 set line [encoding convertfrom $line]
8144 $ctext insert end "$line\n" hunksep
8145 continue
8146 }
8147 # start of a new file
8148 set diffinhdr 1
8149 $ctext insert end "\n"
8150 set curdiffstart [$ctext index "end - 1c"]
8151 lappend ctext_file_names ""
8152 lappend ctext_file_lines [lindex [split $curdiffstart "."] 0]
8153 $ctext insert end "\n" filesep
8154
8155 if {$type eq "--cc"} {
8156 # start of a new file in a merge diff
8157 set fname [string range $line 10 end]
8158 if {[lsearch -exact $treediffs($ids) $fname] < 0} {
8159 lappend treediffs($ids) $fname
8160 add_flist [list $fname]
8161 }
8162
8163 } else {
8164 set line [string range $line 11 end]
8165 # If the name hasn't changed the length will be odd,
8166 # the middle char will be a space, and the two bits either
8167 # side will be a/name and b/name, or "a/name" and "b/name".
8168 # If the name has changed we'll get "rename from" and
8169 # "rename to" or "copy from" and "copy to" lines following
8170 # this, and we'll use them to get the filenames.
8171 # This complexity is necessary because spaces in the
8172 # filename(s) don't get escaped.
8173 set l [string length $line]
8174 set i [expr {$l / 2}]
8175 if {!(($l & 1) && [string index $line $i] eq " " &&
8176 [string range $line 2 [expr {$i - 1}]] eq \
8177 [string range $line [expr {$i + 3}] end])} {
8178 return
8179 }
8180 # unescape if quoted and chop off the a/ from the front
8181 if {[string index $line 0] eq "\""} {
8182 set fname [string range [lindex $line 0] 2 end]
8183 } else {
8184 set fname [string range $line 2 [expr {$i - 1}]]
8185 }
8186 }
8187 makediffhdr $fname $ids
8188
8189 } elseif {![string compare -length 16 "* Unmerged path " $line]} {
8190 set fname [encoding convertfrom [string range $line 16 end]]
8191 $ctext insert end "\n"
8192 set curdiffstart [$ctext index "end - 1c"]
8193 lappend ctext_file_names $fname
8194 lappend ctext_file_lines [lindex [split $curdiffstart "."] 0]
8195 $ctext insert end "$line\n" filesep
8196 set i [lsearch -exact $treediffs($ids) $fname]
8197 if {$i >= 0} {
8198 setinlist difffilestart $i $curdiffstart
8199 }
8200
8201 } elseif {![string compare -length 2 "@@" $line]} {
8202 regexp {^@@+} $line ats
8203 set line [encoding convertfrom $diffencoding $line]
8204 $ctext insert end "$line\n" hunksep
8205 if {[regexp { \+(\d+),\d+ @@} $line m nl]} {
8206 set diffline $nl
8207 }
8208 set diffnparents [expr {[string length $ats] - 1}]
8209 set diffinhdr 0
8210
8211 } elseif {![string compare -length 10 "Submodule " $line]} {
8212 # start of a new submodule
8213 if {[regexp -indices "\[0-9a-f\]+\\.\\." $line nameend]} {
8214 set fname [string range $line 10 [expr [lindex $nameend 0] - 2]]
8215 } else {
8216 set fname [string range $line 10 [expr [string first "contains " $line] - 2]]
8217 }
8218 if {$currdiffsubmod != $fname} {
8219 $ctext insert end "\n"; # Add newline after commit message
8220 }
8221 set curdiffstart [$ctext index "end - 1c"]
8222 lappend ctext_file_names ""
8223 if {$currdiffsubmod != $fname} {
8224 lappend ctext_file_lines $fname
8225 makediffhdr $fname $ids
8226 set currdiffsubmod $fname
8227 $ctext insert end "\n$line\n" filesep
8228 } else {
8229 $ctext insert end "$line\n" filesep
8230 }
Gabriele Mazzotta9ea831a2019-03-23 18:00:36 +01008231 } elseif {$currdiffsubmod != "" && ![string compare -length 3 " >" $line]} {
Thomas Rast5de460a2013-11-16 18:37:41 +01008232 set $currdiffsubmod ""
8233 set line [encoding convertfrom $diffencoding $line]
8234 $ctext insert end "$line\n" dresult
Gabriele Mazzotta9ea831a2019-03-23 18:00:36 +01008235 } elseif {$currdiffsubmod != "" && ![string compare -length 3 " <" $line]} {
Thomas Rast5de460a2013-11-16 18:37:41 +01008236 set $currdiffsubmod ""
8237 set line [encoding convertfrom $diffencoding $line]
8238 $ctext insert end "$line\n" d0
8239 } elseif {$diffinhdr} {
8240 if {![string compare -length 12 "rename from " $line]} {
8241 set fname [string range $line [expr 6 + [string first " from " $line] ] end]
8242 if {[string index $fname 0] eq "\""} {
8243 set fname [lindex $fname 0]
8244 }
8245 set fname [encoding convertfrom $fname]
8246 set i [lsearch -exact $treediffs($ids) $fname]
8247 if {$i >= 0} {
8248 setinlist difffilestart $i $curdiffstart
8249 }
8250 } elseif {![string compare -length 10 $line "rename to "] ||
8251 ![string compare -length 8 $line "copy to "]} {
8252 set fname [string range $line [expr 4 + [string first " to " $line] ] end]
8253 if {[string index $fname 0] eq "\""} {
8254 set fname [lindex $fname 0]
8255 }
8256 makediffhdr $fname $ids
8257 } elseif {[string compare -length 3 $line "---"] == 0} {
8258 # do nothing
8259 return
8260 } elseif {[string compare -length 3 $line "+++"] == 0} {
8261 set diffinhdr 0
8262 return
8263 }
8264 $ctext insert end "$line\n" filesep
8265
8266 } else {
8267 set line [string map {\x1A ^Z} \
8268 [encoding convertfrom $diffencoding $line]]
8269 # parse the prefix - one ' ', '-' or '+' for each parent
8270 set prefix [string range $line 0 [expr {$diffnparents - 1}]]
8271 set tag [expr {$diffnparents > 1? "m": "d"}]
8272 set dowords [expr {$worddiff ne [mc "Line diff"] && $diffnparents == 1}]
8273 set words_pre_markup ""
8274 set words_post_markup ""
8275 if {[string trim $prefix " -+"] eq {}} {
8276 # prefix only has " ", "-" and "+" in it: normal diff line
8277 set num [string first "-" $prefix]
8278 if {$dowords} {
8279 set line [string range $line 1 end]
8280 }
8281 if {$num >= 0} {
8282 # removed line, first parent with line is $num
8283 if {$num >= $mergemax} {
8284 set num "max"
8285 }
8286 if {$dowords && $worddiff eq [mc "Markup words"]} {
8287 $ctext insert end "\[-$line-\]" $tag$num
8288 } else {
8289 $ctext insert end "$line" $tag$num
8290 }
8291 if {!$dowords} {
8292 $ctext insert end "\n" $tag$num
8293 }
8294 } else {
8295 set tags {}
8296 if {[string first "+" $prefix] >= 0} {
8297 # added line
8298 lappend tags ${tag}result
8299 if {$diffnparents > 1} {
8300 set num [string first " " $prefix]
8301 if {$num >= 0} {
8302 if {$num >= $mergemax} {
8303 set num "max"
8304 }
8305 lappend tags m$num
8306 }
8307 }
8308 set words_pre_markup "{+"
8309 set words_post_markup "+}"
8310 }
8311 if {$targetline ne {}} {
8312 if {$diffline == $targetline} {
8313 set diffseehere [$ctext index "end - 1 chars"]
8314 set targetline {}
8315 } else {
8316 incr diffline
8317 }
8318 }
8319 if {$dowords && $worddiff eq [mc "Markup words"]} {
8320 $ctext insert end "$words_pre_markup$line$words_post_markup" $tags
8321 } else {
8322 $ctext insert end "$line" $tags
8323 }
8324 if {!$dowords} {
8325 $ctext insert end "\n" $tags
8326 }
8327 }
8328 } elseif {$dowords && $prefix eq "~"} {
8329 $ctext insert end "\n" {}
8330 } else {
8331 # "\ No newline at end of file",
8332 # or something else we don't recognize
8333 $ctext insert end "$line\n" hunksep
8334 }
8335 }
8336}
8337
Paul Mackerrasa8d610a2007-04-19 11:39:12 +10008338proc changediffdisp {} {
8339 global ctext diffelide
8340
8341 $ctext tag conf d0 -elide [lindex $diffelide 0]
Paul Mackerras8b07dca2008-11-02 22:34:47 +11008342 $ctext tag conf dresult -elide [lindex $diffelide 1]
Paul Mackerrasa8d610a2007-04-19 11:39:12 +10008343}
8344
Stefan Hallerb9671352012-09-19 20:17:27 +02008345proc highlightfile {cline} {
8346 global cflist cflist_top
Paul Mackerrasf4c54b32008-05-10 13:15:36 +10008347
Stefan Hallerce837c92012-10-04 22:50:16 +02008348 if {![info exists cflist_top]} return
8349
Paul Mackerrasf4c54b32008-05-10 13:15:36 +10008350 $cflist tag remove highlight $cflist_top.0 "$cflist_top.0 lineend"
8351 $cflist tag add highlight $cline.0 "$cline.0 lineend"
8352 $cflist see $cline.0
8353 set cflist_top $cline
8354}
8355
Stefan Hallerb9671352012-09-19 20:17:27 +02008356proc highlightfile_for_scrollpos {topidx} {
Stefan Haller978904b2012-10-04 22:50:17 +02008357 global cmitmode difffilestart
Stefan Hallerb9671352012-09-19 20:17:27 +02008358
Stefan Haller978904b2012-10-04 22:50:17 +02008359 if {$cmitmode eq "tree"} return
Stefan Hallerb9671352012-09-19 20:17:27 +02008360 if {![info exists difffilestart]} return
8361
8362 set top [lindex [split $topidx .] 0]
8363 if {$difffilestart eq {} || $top < [lindex $difffilestart 0]} {
8364 highlightfile 0
8365 } else {
8366 highlightfile [expr {[bsearch $difffilestart $top] + 2}]
8367 }
8368}
8369
OGAWA Hirofumi67c22872006-09-27 12:32:19 +09008370proc prevfile {} {
Paul Mackerrasf4c54b32008-05-10 13:15:36 +10008371 global difffilestart ctext cmitmode
8372
8373 if {$cmitmode eq "tree"} return
8374 set prev 0.0
OGAWA Hirofumi67c22872006-09-27 12:32:19 +09008375 set here [$ctext index @0,0]
8376 foreach loc $difffilestart {
8377 if {[$ctext compare $loc >= $here]} {
Stefan Hallerb9671352012-09-19 20:17:27 +02008378 $ctext yview $prev
OGAWA Hirofumi67c22872006-09-27 12:32:19 +09008379 return
8380 }
8381 set prev $loc
8382 }
Stefan Hallerb9671352012-09-19 20:17:27 +02008383 $ctext yview $prev
OGAWA Hirofumi67c22872006-09-27 12:32:19 +09008384}
8385
Paul Mackerras39ad8572005-05-19 12:35:53 +00008386proc nextfile {} {
Paul Mackerrasf4c54b32008-05-10 13:15:36 +10008387 global difffilestart ctext cmitmode
8388
8389 if {$cmitmode eq "tree"} return
Paul Mackerras39ad8572005-05-19 12:35:53 +00008390 set here [$ctext index @0,0]
Paul Mackerras7fcceed2006-04-27 19:21:49 +10008391 foreach loc $difffilestart {
8392 if {[$ctext compare $loc > $here]} {
Stefan Hallerb9671352012-09-19 20:17:27 +02008393 $ctext yview $loc
OGAWA Hirofumi67c22872006-09-27 12:32:19 +09008394 return
Paul Mackerras39ad8572005-05-19 12:35:53 +00008395 }
8396 }
Paul Mackerras1db95b02005-05-09 04:08:39 +00008397}
8398
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008399proc clear_ctext {{first 1.0}} {
8400 global ctext smarktop smarkbot
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04008401 global ctext_file_names ctext_file_lines
Paul Mackerras97645682007-08-23 22:24:38 +10008402 global pendinglinks
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008403
Paul Mackerras1902c272006-05-25 21:25:13 +10008404 set l [lindex [split $first .] 0]
8405 if {![info exists smarktop] || [$ctext compare $first < $smarktop.0]} {
8406 set smarktop $l
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008407 }
Paul Mackerras1902c272006-05-25 21:25:13 +10008408 if {![info exists smarkbot] || [$ctext compare $first < $smarkbot.0]} {
8409 set smarkbot $l
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008410 }
8411 $ctext delete $first end
Paul Mackerras97645682007-08-23 22:24:38 +10008412 if {$first eq "1.0"} {
Paul Mackerras009409f2015-05-02 20:53:36 +10008413 unset -nocomplain pendinglinks
Paul Mackerras97645682007-08-23 22:24:38 +10008414 }
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04008415 set ctext_file_names {}
8416 set ctext_file_lines {}
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008417}
8418
Paul Mackerras32f1b3e2007-09-28 21:27:39 +10008419proc settabs {{firstab {}}} {
Paul Mackerras9c311b32007-10-04 22:27:13 +10008420 global firsttabstop tabstop ctext have_tk85
Paul Mackerras32f1b3e2007-09-28 21:27:39 +10008421
8422 if {$firstab ne {} && $have_tk85} {
8423 set firsttabstop $firstab
8424 }
Paul Mackerras9c311b32007-10-04 22:27:13 +10008425 set w [font measure textfont "0"]
Paul Mackerras32f1b3e2007-09-28 21:27:39 +10008426 if {$firsttabstop != 0} {
Paul Mackerras64b5f142007-10-04 22:19:24 +10008427 $ctext conf -tabs [list [expr {($firsttabstop + $tabstop) * $w}] \
8428 [expr {($firsttabstop + 2 * $tabstop) * $w}]]
Paul Mackerras32f1b3e2007-09-28 21:27:39 +10008429 } elseif {$have_tk85 || $tabstop != 8} {
8430 $ctext conf -tabs [expr {$tabstop * $w}]
8431 } else {
8432 $ctext conf -tabs {}
8433 }
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008434}
8435
8436proc incrsearch {name ix op} {
Paul Mackerras1902c272006-05-25 21:25:13 +10008437 global ctext searchstring searchdirn
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008438
Paul Mackerras1902c272006-05-25 21:25:13 +10008439 if {[catch {$ctext index anchor}]} {
8440 # no anchor set, use start of selection, or of visible area
8441 set sel [$ctext tag ranges sel]
8442 if {$sel ne {}} {
8443 $ctext mark set anchor [lindex $sel 0]
8444 } elseif {$searchdirn eq "-forwards"} {
8445 $ctext mark set anchor @0,0
8446 } else {
8447 $ctext mark set anchor @0,[winfo height $ctext]
8448 }
8449 }
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008450 if {$searchstring ne {}} {
Stefan Haller30441a62012-09-22 09:40:25 +02008451 set here [$ctext search -count mlen $searchdirn -- $searchstring anchor]
Paul Mackerras1902c272006-05-25 21:25:13 +10008452 if {$here ne {}} {
8453 $ctext see $here
Stefan Haller30441a62012-09-22 09:40:25 +02008454 set mend "$here + $mlen c"
8455 $ctext tag remove sel 1.0 end
8456 $ctext tag add sel $here $mend
Stefan Hallerb9671352012-09-19 20:17:27 +02008457 suppress_highlighting_file_for_current_scrollpos
8458 highlightfile_for_scrollpos $here
Paul Mackerras1902c272006-05-25 21:25:13 +10008459 }
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008460 }
Stefan Hallerc4614992012-09-22 09:40:24 +02008461 rehighlight_search_results
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008462}
8463
8464proc dosearch {} {
Paul Mackerras1902c272006-05-25 21:25:13 +10008465 global sstring ctext searchstring searchdirn
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008466
8467 focus $sstring
8468 $sstring icursor end
Paul Mackerras1902c272006-05-25 21:25:13 +10008469 set searchdirn -forwards
8470 if {$searchstring ne {}} {
8471 set sel [$ctext tag ranges sel]
8472 if {$sel ne {}} {
8473 set start "[lindex $sel 0] + 1c"
8474 } elseif {[catch {set start [$ctext index anchor]}]} {
8475 set start "@0,0"
8476 }
8477 set match [$ctext search -count mlen -- $searchstring $start]
8478 $ctext tag remove sel 1.0 end
8479 if {$match eq {}} {
8480 bell
8481 return
8482 }
8483 $ctext see $match
Stefan Hallerb9671352012-09-19 20:17:27 +02008484 suppress_highlighting_file_for_current_scrollpos
8485 highlightfile_for_scrollpos $match
Paul Mackerras1902c272006-05-25 21:25:13 +10008486 set mend "$match + $mlen c"
8487 $ctext tag add sel $match $mend
8488 $ctext mark unset anchor
Stefan Hallerc4614992012-09-22 09:40:24 +02008489 rehighlight_search_results
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008490 }
Paul Mackerras1902c272006-05-25 21:25:13 +10008491}
8492
8493proc dosearchback {} {
8494 global sstring ctext searchstring searchdirn
8495
8496 focus $sstring
8497 $sstring icursor end
8498 set searchdirn -backwards
8499 if {$searchstring ne {}} {
8500 set sel [$ctext tag ranges sel]
8501 if {$sel ne {}} {
8502 set start [lindex $sel 0]
8503 } elseif {[catch {set start [$ctext index anchor]}]} {
8504 set start @0,[winfo height $ctext]
8505 }
8506 set match [$ctext search -backwards -count ml -- $searchstring $start]
8507 $ctext tag remove sel 1.0 end
8508 if {$match eq {}} {
8509 bell
8510 return
8511 }
8512 $ctext see $match
Stefan Hallerb9671352012-09-19 20:17:27 +02008513 suppress_highlighting_file_for_current_scrollpos
8514 highlightfile_for_scrollpos $match
Paul Mackerras1902c272006-05-25 21:25:13 +10008515 set mend "$match + $ml c"
8516 $ctext tag add sel $match $mend
8517 $ctext mark unset anchor
Stefan Hallerc4614992012-09-22 09:40:24 +02008518 rehighlight_search_results
8519 }
8520}
8521
8522proc rehighlight_search_results {} {
8523 global ctext searchstring
8524
8525 $ctext tag remove found 1.0 end
8526 $ctext tag remove currentsearchhit 1.0 end
8527
8528 if {$searchstring ne {}} {
8529 searchmarkvisible 1
Paul Mackerras1902c272006-05-25 21:25:13 +10008530 }
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008531}
8532
8533proc searchmark {first last} {
8534 global ctext searchstring
8535
Stefan Hallerc4614992012-09-22 09:40:24 +02008536 set sel [$ctext tag ranges sel]
8537
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008538 set mend $first.0
8539 while {1} {
8540 set match [$ctext search -count mlen -- $searchstring $mend $last.end]
8541 if {$match eq {}} break
8542 set mend "$match + $mlen c"
Stefan Hallerc4614992012-09-22 09:40:24 +02008543 if {$sel ne {} && [$ctext compare $match == [lindex $sel 0]]} {
8544 $ctext tag add currentsearchhit $match $mend
8545 } else {
8546 $ctext tag add found $match $mend
8547 }
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008548 }
8549}
8550
8551proc searchmarkvisible {doall} {
8552 global ctext smarktop smarkbot
8553
8554 set topline [lindex [split [$ctext index @0,0] .] 0]
8555 set botline [lindex [split [$ctext index @0,[winfo height $ctext]] .] 0]
8556 if {$doall || $botline < $smarktop || $topline > $smarkbot} {
8557 # no overlap with previous
8558 searchmark $topline $botline
8559 set smarktop $topline
8560 set smarkbot $botline
8561 } else {
8562 if {$topline < $smarktop} {
8563 searchmark $topline [expr {$smarktop-1}]
8564 set smarktop $topline
8565 }
8566 if {$botline > $smarkbot} {
8567 searchmark [expr {$smarkbot+1}] $botline
8568 set smarkbot $botline
8569 }
8570 }
8571}
8572
Stefan Hallerb9671352012-09-19 20:17:27 +02008573proc suppress_highlighting_file_for_current_scrollpos {} {
8574 global ctext suppress_highlighting_file_for_this_scrollpos
8575
8576 set suppress_highlighting_file_for_this_scrollpos [$ctext index @0,0]
8577}
8578
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008579proc scrolltext {f0 f1} {
Stefan Hallerb9671352012-09-19 20:17:27 +02008580 global searchstring cmitmode ctext
8581 global suppress_highlighting_file_for_this_scrollpos
8582
Stefan Haller978904b2012-10-04 22:50:17 +02008583 set topidx [$ctext index @0,0]
8584 if {![info exists suppress_highlighting_file_for_this_scrollpos]
8585 || $topidx ne $suppress_highlighting_file_for_this_scrollpos} {
8586 highlightfile_for_scrollpos $topidx
Stefan Hallerb9671352012-09-19 20:17:27 +02008587 }
8588
Paul Mackerras009409f2015-05-02 20:53:36 +10008589 unset -nocomplain suppress_highlighting_file_for_this_scrollpos
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008590
Pekka Kaitaniemi8809d692008-03-08 14:27:23 +02008591 .bleft.bottom.sb set $f0 $f1
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008592 if {$searchstring ne {}} {
8593 searchmarkvisible 0
8594 }
8595}
8596
Paul Mackerras1d10f362005-05-15 12:55:47 +00008597proc setcoords {} {
Paul Mackerras9c311b32007-10-04 22:27:13 +10008598 global linespc charspc canvx0 canvy0
Paul Mackerrasf6075eb2005-08-18 09:30:10 +10008599 global xspc1 xspc2 lthickness
Paul Mackerras8d858d12005-08-05 09:52:16 +10008600
Paul Mackerras9c311b32007-10-04 22:27:13 +10008601 set linespc [font metrics mainfont -linespace]
8602 set charspc [font measure mainfont "m"]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11008603 set canvy0 [expr {int(3 + 0.5 * $linespc)}]
8604 set canvx0 [expr {int(3 + 0.5 * $linespc)}]
Paul Mackerrasf6075eb2005-08-18 09:30:10 +10008605 set lthickness [expr {int($linespc / 9) + 1}]
Paul Mackerras8d858d12005-08-05 09:52:16 +10008606 set xspc1(0) $linespc
8607 set xspc2 $linespc
Paul Mackerras9a40c502005-05-12 23:46:16 +00008608}
Paul Mackerras1db95b02005-05-09 04:08:39 +00008609
Paul Mackerras1d10f362005-05-15 12:55:47 +00008610proc redisplay {} {
Paul Mackerrasbe0cd092006-03-31 09:55:11 +11008611 global canv
Paul Mackerras9f1afe02006-02-19 22:44:47 +11008612 global selectedline
8613
8614 set ymax [lindex [$canv cget -scrollregion] 3]
8615 if {$ymax eq {} || $ymax == 0} return
8616 set span [$canv yview]
8617 clear_display
Paul Mackerrasbe0cd092006-03-31 09:55:11 +11008618 setcanvscroll
Paul Mackerras9f1afe02006-02-19 22:44:47 +11008619 allcanvs yview moveto [lindex $span 0]
8620 drawvisible
Paul Mackerras94b4a692008-05-20 20:51:06 +10008621 if {$selectedline ne {}} {
Paul Mackerras9f1afe02006-02-19 22:44:47 +11008622 selectline $selectedline 0
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10008623 allcanvs yview moveto [lindex $span 0]
Paul Mackerras1db95b02005-05-09 04:08:39 +00008624 }
8625}
Paul Mackerras1d10f362005-05-15 12:55:47 +00008626
Paul Mackerras0ed1dd32007-10-06 18:27:37 +10008627proc parsefont {f n} {
8628 global fontattr
8629
8630 set fontattr($f,family) [lindex $n 0]
8631 set s [lindex $n 1]
8632 if {$s eq {} || $s == 0} {
8633 set s 10
8634 } elseif {$s < 0} {
8635 set s [expr {int(-$s / [winfo fpixels . 1p] + 0.5)}]
Paul Mackerras9c311b32007-10-04 22:27:13 +10008636 }
Paul Mackerras0ed1dd32007-10-06 18:27:37 +10008637 set fontattr($f,size) $s
8638 set fontattr($f,weight) normal
8639 set fontattr($f,slant) roman
8640 foreach style [lrange $n 2 end] {
8641 switch -- $style {
8642 "normal" -
8643 "bold" {set fontattr($f,weight) $style}
8644 "roman" -
8645 "italic" {set fontattr($f,slant) $style}
8646 }
Paul Mackerras9c311b32007-10-04 22:27:13 +10008647 }
Paul Mackerras0ed1dd32007-10-06 18:27:37 +10008648}
8649
8650proc fontflags {f {isbold 0}} {
8651 global fontattr
8652
8653 return [list -family $fontattr($f,family) -size $fontattr($f,size) \
8654 -weight [expr {$isbold? "bold": $fontattr($f,weight)}] \
8655 -slant $fontattr($f,slant)]
8656}
8657
8658proc fontname {f} {
8659 global fontattr
8660
8661 set n [list $fontattr($f,family) $fontattr($f,size)]
8662 if {$fontattr($f,weight) eq "bold"} {
8663 lappend n "bold"
Paul Mackerras9c311b32007-10-04 22:27:13 +10008664 }
Paul Mackerras0ed1dd32007-10-06 18:27:37 +10008665 if {$fontattr($f,slant) eq "italic"} {
8666 lappend n "italic"
Paul Mackerras9c311b32007-10-04 22:27:13 +10008667 }
Paul Mackerras0ed1dd32007-10-06 18:27:37 +10008668 return $n
Paul Mackerras9c311b32007-10-04 22:27:13 +10008669}
8670
Paul Mackerras1d10f362005-05-15 12:55:47 +00008671proc incrfont {inc} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11008672 global mainfont textfont ctext canv cflist showrefstop
Paul Mackerras0ed1dd32007-10-06 18:27:37 +10008673 global stopped entries fontattr
8674
Paul Mackerras1d10f362005-05-15 12:55:47 +00008675 unmarkmatches
Paul Mackerras0ed1dd32007-10-06 18:27:37 +10008676 set s $fontattr(mainfont,size)
Paul Mackerras9c311b32007-10-04 22:27:13 +10008677 incr s $inc
8678 if {$s < 1} {
8679 set s 1
8680 }
Paul Mackerras0ed1dd32007-10-06 18:27:37 +10008681 set fontattr(mainfont,size) $s
Paul Mackerras9c311b32007-10-04 22:27:13 +10008682 font config mainfont -size $s
8683 font config mainfontbold -size $s
Paul Mackerras0ed1dd32007-10-06 18:27:37 +10008684 set mainfont [fontname mainfont]
8685 set s $fontattr(textfont,size)
Paul Mackerras9c311b32007-10-04 22:27:13 +10008686 incr s $inc
8687 if {$s < 1} {
8688 set s 1
8689 }
Paul Mackerras0ed1dd32007-10-06 18:27:37 +10008690 set fontattr(textfont,size) $s
Paul Mackerras9c311b32007-10-04 22:27:13 +10008691 font config textfont -size $s
8692 font config textfontbold -size $s
Paul Mackerras0ed1dd32007-10-06 18:27:37 +10008693 set textfont [fontname textfont]
Paul Mackerras1d10f362005-05-15 12:55:47 +00008694 setcoords
Paul Mackerras32f1b3e2007-09-28 21:27:39 +10008695 settabs
Paul Mackerras1d10f362005-05-15 12:55:47 +00008696 redisplay
Paul Mackerras1db95b02005-05-09 04:08:39 +00008697}
Paul Mackerras1d10f362005-05-15 12:55:47 +00008698
Paul Mackerrasee3dc722005-06-25 16:37:13 +10008699proc clearsha1 {} {
8700 global sha1entry sha1string
8701 if {[string length $sha1string] == 40} {
8702 $sha1entry delete 0 end
8703 }
8704}
8705
Paul Mackerras887fe3c2005-05-21 07:35:37 +00008706proc sha1change {n1 n2 op} {
8707 global sha1string currentid sha1but
8708 if {$sha1string == {}
8709 || ([info exists currentid] && $sha1string == $currentid)} {
8710 set state disabled
8711 } else {
8712 set state normal
8713 }
8714 if {[$sha1but cget -state] == $state} return
8715 if {$state == "normal"} {
Christian Stimmingd990ced2007-11-07 18:42:55 +01008716 $sha1but conf -state normal -relief raised -text "[mc "Goto:"] "
Paul Mackerras887fe3c2005-05-21 07:35:37 +00008717 } else {
Christian Stimmingd990ced2007-11-07 18:42:55 +01008718 $sha1but conf -state disabled -relief flat -text "[mc "SHA1 ID:"] "
Paul Mackerras887fe3c2005-05-21 07:35:37 +00008719 }
8720}
8721
8722proc gotocommit {} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11008723 global sha1string tagids headids curview varcid
Paul Mackerrasf3b8b3c2005-07-18 12:16:35 -04008724
Paul Mackerras887fe3c2005-05-21 07:35:37 +00008725 if {$sha1string == {}
8726 || ([info exists currentid] && $sha1string == $currentid)} return
8727 if {[info exists tagids($sha1string)]} {
8728 set id $tagids($sha1string)
Stephen Rothwelle1007122006-03-30 16:13:12 +11008729 } elseif {[info exists headids($sha1string)]} {
8730 set id $headids($sha1string)
Paul Mackerras887fe3c2005-05-21 07:35:37 +00008731 } else {
8732 set id [string tolower $sha1string]
Paul Mackerrasf3b8b3c2005-07-18 12:16:35 -04008733 if {[regexp {^[0-9a-f]{4,39}$} $id]} {
Paul Mackerrasd375ef92008-10-21 10:18:12 +11008734 set matches [longid $id]
Paul Mackerrasf3b8b3c2005-07-18 12:16:35 -04008735 if {$matches ne {}} {
8736 if {[llength $matches] > 1} {
Christian Stimmingd990ced2007-11-07 18:42:55 +01008737 error_popup [mc "Short SHA1 id %s is ambiguous" $id]
Paul Mackerrasf3b8b3c2005-07-18 12:16:35 -04008738 return
8739 }
Paul Mackerrasd375ef92008-10-21 10:18:12 +11008740 set id [lindex $matches 0]
Paul Mackerrasf3b8b3c2005-07-18 12:16:35 -04008741 }
Thomas Rast9bf3acf2009-08-13 09:25:03 +02008742 } else {
8743 if {[catch {set id [exec git rev-parse --verify $sha1string]}]} {
8744 error_popup [mc "Revision %s is not known" $sha1string]
8745 return
8746 }
Paul Mackerrasf3b8b3c2005-07-18 12:16:35 -04008747 }
Paul Mackerras887fe3c2005-05-21 07:35:37 +00008748 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11008749 if {[commitinview $id $curview]} {
8750 selectline [rowofcommit $id] 1
Paul Mackerras887fe3c2005-05-21 07:35:37 +00008751 return
8752 }
Paul Mackerrasf3b8b3c2005-07-18 12:16:35 -04008753 if {[regexp {^[0-9a-fA-F]{4,}$} $sha1string]} {
Christian Stimmingd990ced2007-11-07 18:42:55 +01008754 set msg [mc "SHA1 id %s is not known" $sha1string]
Paul Mackerras887fe3c2005-05-21 07:35:37 +00008755 } else {
Thomas Rast9bf3acf2009-08-13 09:25:03 +02008756 set msg [mc "Revision %s is not in the current view" $sha1string]
Paul Mackerras887fe3c2005-05-21 07:35:37 +00008757 }
Christian Stimmingd990ced2007-11-07 18:42:55 +01008758 error_popup $msg
Paul Mackerras887fe3c2005-05-21 07:35:37 +00008759}
8760
Paul Mackerras84ba7342005-06-17 00:12:26 +00008761proc lineenter {x y id} {
8762 global hoverx hovery hoverid hovertimer
8763 global commitinfo canv
8764
Paul Mackerras8ed16482006-03-02 22:56:44 +11008765 if {![info exists commitinfo($id)] && ![getcommit $id]} return
Paul Mackerras84ba7342005-06-17 00:12:26 +00008766 set hoverx $x
8767 set hovery $y
8768 set hoverid $id
8769 if {[info exists hovertimer]} {
8770 after cancel $hovertimer
8771 }
8772 set hovertimer [after 500 linehover]
8773 $canv delete hover
8774}
8775
8776proc linemotion {x y id} {
8777 global hoverx hovery hoverid hovertimer
8778
8779 if {[info exists hoverid] && $id == $hoverid} {
8780 set hoverx $x
8781 set hovery $y
8782 if {[info exists hovertimer]} {
8783 after cancel $hovertimer
8784 }
8785 set hovertimer [after 500 linehover]
8786 }
8787}
8788
8789proc lineleave {id} {
8790 global hoverid hovertimer canv
8791
8792 if {[info exists hoverid] && $id == $hoverid} {
8793 $canv delete hover
8794 if {[info exists hovertimer]} {
8795 after cancel $hovertimer
8796 unset hovertimer
8797 }
8798 unset hoverid
8799 }
8800}
8801
8802proc linehover {} {
8803 global hoverx hovery hoverid hovertimer
8804 global canv linespc lthickness
Gauthier Östervall252c52d2013-03-27 14:40:51 +01008805 global linehoverbgcolor linehoverfgcolor linehoveroutlinecolor
8806
Paul Mackerras9c311b32007-10-04 22:27:13 +10008807 global commitinfo
Paul Mackerras84ba7342005-06-17 00:12:26 +00008808
8809 set text [lindex $commitinfo($hoverid) 0]
8810 set ymax [lindex [$canv cget -scrollregion] 3]
8811 if {$ymax == {}} return
8812 set yfrac [lindex [$canv yview] 0]
8813 set x [expr {$hoverx + 2 * $linespc}]
8814 set y [expr {$hovery + $yfrac * $ymax - $linespc / 2}]
8815 set x0 [expr {$x - 2 * $lthickness}]
8816 set y0 [expr {$y - 2 * $lthickness}]
Paul Mackerras9c311b32007-10-04 22:27:13 +10008817 set x1 [expr {$x + [font measure mainfont $text] + 2 * $lthickness}]
Paul Mackerras84ba7342005-06-17 00:12:26 +00008818 set y1 [expr {$y + $linespc + 2 * $lthickness}]
8819 set t [$canv create rectangle $x0 $y0 $x1 $y1 \
Gauthier Östervall252c52d2013-03-27 14:40:51 +01008820 -fill $linehoverbgcolor -outline $linehoveroutlinecolor \
8821 -width 1 -tags hover]
Paul Mackerras84ba7342005-06-17 00:12:26 +00008822 $canv raise $t
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10008823 set t [$canv create text $x $y -anchor nw -text $text -tags hover \
Gauthier Östervall252c52d2013-03-27 14:40:51 +01008824 -font mainfont -fill $linehoverfgcolor]
Paul Mackerras84ba7342005-06-17 00:12:26 +00008825 $canv raise $t
8826}
8827
Paul Mackerras9843c302005-08-30 10:57:11 +10008828proc clickisonarrow {id y} {
Paul Mackerras50b44ec2006-04-04 10:16:22 +10008829 global lthickness
Paul Mackerras9843c302005-08-30 10:57:11 +10008830
Paul Mackerras50b44ec2006-04-04 10:16:22 +10008831 set ranges [rowranges $id]
Paul Mackerras9843c302005-08-30 10:57:11 +10008832 set thresh [expr {2 * $lthickness + 6}]
Paul Mackerras50b44ec2006-04-04 10:16:22 +10008833 set n [expr {[llength $ranges] - 1}]
Paul Mackerrasf6342482006-02-28 10:02:03 +11008834 for {set i 1} {$i < $n} {incr i} {
Paul Mackerras50b44ec2006-04-04 10:16:22 +10008835 set row [lindex $ranges $i]
Paul Mackerrasf6342482006-02-28 10:02:03 +11008836 if {abs([yc $row] - $y) < $thresh} {
8837 return $i
Paul Mackerras9843c302005-08-30 10:57:11 +10008838 }
8839 }
8840 return {}
8841}
8842
Paul Mackerrasf6342482006-02-28 10:02:03 +11008843proc arrowjump {id n y} {
Paul Mackerras50b44ec2006-04-04 10:16:22 +10008844 global canv
Paul Mackerras9843c302005-08-30 10:57:11 +10008845
Paul Mackerrasf6342482006-02-28 10:02:03 +11008846 # 1 <-> 2, 3 <-> 4, etc...
8847 set n [expr {(($n - 1) ^ 1) + 1}]
Paul Mackerras50b44ec2006-04-04 10:16:22 +10008848 set row [lindex [rowranges $id] $n]
Paul Mackerrasf6342482006-02-28 10:02:03 +11008849 set yt [yc $row]
Paul Mackerras9843c302005-08-30 10:57:11 +10008850 set ymax [lindex [$canv cget -scrollregion] 3]
8851 if {$ymax eq {} || $ymax <= 0} return
8852 set view [$canv yview]
8853 set yspan [expr {[lindex $view 1] - [lindex $view 0]}]
8854 set yfrac [expr {$yt / $ymax - $yspan / 2}]
8855 if {$yfrac < 0} {
8856 set yfrac 0
8857 }
Paul Mackerrasf6342482006-02-28 10:02:03 +11008858 allcanvs yview moveto $yfrac
Paul Mackerras9843c302005-08-30 10:57:11 +10008859}
8860
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10008861proc lineclick {x y id isnew} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11008862 global ctext commitinfo children canv thickerline curview
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008863
Paul Mackerras8ed16482006-03-02 22:56:44 +11008864 if {![info exists commitinfo($id)] && ![getcommit $id]} return
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008865 unmarkmatches
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10008866 unselectline
Paul Mackerras9843c302005-08-30 10:57:11 +10008867 normalline
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008868 $canv delete hover
Paul Mackerras9843c302005-08-30 10:57:11 +10008869 # draw this line thicker than normal
Paul Mackerras9843c302005-08-30 10:57:11 +10008870 set thickerline $id
Paul Mackerrasc934a8a2006-03-02 23:00:44 +11008871 drawlines $id
Paul Mackerras9843c302005-08-30 10:57:11 +10008872 if {$isnew} {
8873 set ymax [lindex [$canv cget -scrollregion] 3]
8874 if {$ymax eq {}} return
8875 set yfrac [lindex [$canv yview] 0]
8876 set y [expr {$y + $yfrac * $ymax}]
8877 }
8878 set dirn [clickisonarrow $id $y]
8879 if {$dirn ne {}} {
8880 arrowjump $id $dirn $y
8881 return
8882 }
8883
8884 if {$isnew} {
Paul Mackerras354af6b2008-11-23 13:14:23 +11008885 addtohistory [list lineclick $x $y $id 0] savectextpos
Paul Mackerras9843c302005-08-30 10:57:11 +10008886 }
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008887 # fill the details pane with info about this line
8888 $ctext conf -state normal
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008889 clear_ctext
Paul Mackerras32f1b3e2007-09-28 21:27:39 +10008890 settabs 0
Christian Stimmingd990ced2007-11-07 18:42:55 +01008891 $ctext insert end "[mc "Parent"]:\t"
Paul Mackerras97645682007-08-23 22:24:38 +10008892 $ctext insert end $id link0
8893 setlink $id link0
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008894 set info $commitinfo($id)
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10008895 $ctext insert end "\n\t[lindex $info 0]\n"
Christian Stimmingd990ced2007-11-07 18:42:55 +01008896 $ctext insert end "\t[mc "Author"]:\t[lindex $info 1]\n"
Paul Mackerras232475d2005-11-15 10:34:03 +11008897 set date [formatdate [lindex $info 2]]
Christian Stimmingd990ced2007-11-07 18:42:55 +01008898 $ctext insert end "\t[mc "Date"]:\t$date\n"
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10008899 set kids $children($curview,$id)
Paul Mackerras79b2c752006-04-02 20:47:40 +10008900 if {$kids ne {}} {
Christian Stimmingd990ced2007-11-07 18:42:55 +01008901 $ctext insert end "\n[mc "Children"]:"
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10008902 set i 0
Paul Mackerras79b2c752006-04-02 20:47:40 +10008903 foreach child $kids {
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10008904 incr i
Paul Mackerras8ed16482006-03-02 22:56:44 +11008905 if {![info exists commitinfo($child)] && ![getcommit $child]} continue
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008906 set info $commitinfo($child)
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10008907 $ctext insert end "\n\t"
Paul Mackerras97645682007-08-23 22:24:38 +10008908 $ctext insert end $child link$i
8909 setlink $child link$i
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10008910 $ctext insert end "\n\t[lindex $info 0]"
Christian Stimmingd990ced2007-11-07 18:42:55 +01008911 $ctext insert end "\n\t[mc "Author"]:\t[lindex $info 1]"
Paul Mackerras232475d2005-11-15 10:34:03 +11008912 set date [formatdate [lindex $info 2]]
Christian Stimmingd990ced2007-11-07 18:42:55 +01008913 $ctext insert end "\n\t[mc "Date"]:\t$date\n"
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008914 }
8915 }
Paul Mackerras354af6b2008-11-23 13:14:23 +11008916 maybe_scroll_ctext 1
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008917 $ctext conf -state disabled
Paul Mackerras7fcceed2006-04-27 19:21:49 +10008918 init_flist {}
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008919}
8920
Paul Mackerras9843c302005-08-30 10:57:11 +10008921proc normalline {} {
8922 global thickerline
8923 if {[info exists thickerline]} {
Paul Mackerrasc934a8a2006-03-02 23:00:44 +11008924 set id $thickerline
Paul Mackerras9843c302005-08-30 10:57:11 +10008925 unset thickerline
Paul Mackerrasc934a8a2006-03-02 23:00:44 +11008926 drawlines $id
Paul Mackerras9843c302005-08-30 10:57:11 +10008927 }
8928}
8929
Paul Mackerras354af6b2008-11-23 13:14:23 +11008930proc selbyid {id {isnew 1}} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11008931 global curview
8932 if {[commitinview $id $curview]} {
Paul Mackerras354af6b2008-11-23 13:14:23 +11008933 selectline [rowofcommit $id] $isnew
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008934 }
8935}
8936
8937proc mstime {} {
8938 global startmstime
8939 if {![info exists startmstime]} {
8940 set startmstime [clock clicks -milliseconds]
8941 }
8942 return [format "%.3f" [expr {([clock click -milliseconds] - $startmstime) / 1000.0}]]
8943}
8944
8945proc rowmenu {x y id} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11008946 global rowctxmenu selectedline rowmenuid curview
Paul Mackerrasb9fdba72009-04-09 09:34:46 +10008947 global nullid nullid2 fakerowmenu mainhead markedid
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008948
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10008949 stopfinding
Paul Mackerras219ea3a2006-09-07 10:21:39 +10008950 set rowmenuid $id
Paul Mackerras94b4a692008-05-20 20:51:06 +10008951 if {$selectedline eq {} || [rowofcommit $id] eq $selectedline} {
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008952 set state disabled
8953 } else {
8954 set state normal
8955 }
Paul Mackerras6febded2012-03-23 22:07:27 +11008956 if {[info exists markedid] && $markedid ne $id} {
8957 set mstate normal
8958 } else {
8959 set mstate disabled
8960 }
Paul Mackerras8f489362007-07-13 19:49:37 +10008961 if {$id ne $nullid && $id ne $nullid2} {
Paul Mackerras219ea3a2006-09-07 10:21:39 +10008962 set menu $rowctxmenu
Michele Ballabio5e3502d2008-05-02 17:46:20 +02008963 if {$mainhead ne {}} {
Beat Bollib6f92a82015-09-08 01:16:37 +02008964 $menu entryconfigure 8 -label [mc "Reset %s branch to here" $mainhead] -state normal
Michele Ballabio5e3502d2008-05-02 17:46:20 +02008965 } else {
Beat Bollib6f92a82015-09-08 01:16:37 +02008966 $menu entryconfigure 8 -label [mc "Detached head: can't reset" $mainhead] -state disabled
Michele Ballabio5e3502d2008-05-02 17:46:20 +02008967 }
Paul Mackerras6febded2012-03-23 22:07:27 +11008968 $menu entryconfigure 10 -state $mstate
8969 $menu entryconfigure 11 -state $mstate
Beat Bollib6f92a82015-09-08 01:16:37 +02008970 $menu entryconfigure 12 -state $mstate
Paul Mackerras219ea3a2006-09-07 10:21:39 +10008971 } else {
8972 set menu $fakerowmenu
8973 }
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11008974 $menu entryconfigure [mca "Diff this -> selected"] -state $state
8975 $menu entryconfigure [mca "Diff selected -> this"] -state $state
8976 $menu entryconfigure [mca "Make patch"] -state $state
Paul Mackerras6febded2012-03-23 22:07:27 +11008977 $menu entryconfigure [mca "Diff this -> marked commit"] -state $mstate
8978 $menu entryconfigure [mca "Diff marked commit -> this"] -state $mstate
Paul Mackerras219ea3a2006-09-07 10:21:39 +10008979 tk_popup $menu $x $y
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008980}
8981
Paul Mackerrasb9fdba72009-04-09 09:34:46 +10008982proc markhere {} {
8983 global rowmenuid markedid canv
8984
8985 set markedid $rowmenuid
8986 make_idmark $markedid
8987}
8988
8989proc gotomark {} {
8990 global markedid
8991
8992 if {[info exists markedid]} {
8993 selbyid $markedid
8994 }
8995}
8996
8997proc replace_by_kids {l r} {
8998 global curview children
8999
9000 set id [commitonrow $r]
9001 set l [lreplace $l 0 0]
9002 foreach kid $children($curview,$id) {
9003 lappend l [rowofcommit $kid]
9004 }
9005 return [lsort -integer -decreasing -unique $l]
9006}
9007
9008proc find_common_desc {} {
9009 global markedid rowmenuid curview children
9010
9011 if {![info exists markedid]} return
9012 if {![commitinview $markedid $curview] ||
9013 ![commitinview $rowmenuid $curview]} return
9014 #set t1 [clock clicks -milliseconds]
9015 set l1 [list [rowofcommit $markedid]]
9016 set l2 [list [rowofcommit $rowmenuid]]
9017 while 1 {
9018 set r1 [lindex $l1 0]
9019 set r2 [lindex $l2 0]
9020 if {$r1 eq {} || $r2 eq {}} break
9021 if {$r1 == $r2} {
9022 selectline $r1 1
9023 break
9024 }
9025 if {$r1 > $r2} {
9026 set l1 [replace_by_kids $l1 $r1]
9027 } else {
9028 set l2 [replace_by_kids $l2 $r2]
9029 }
9030 }
9031 #set t2 [clock clicks -milliseconds]
9032 #puts "took [expr {$t2-$t1}]ms"
9033}
9034
Paul Mackerras010509f2009-04-09 22:10:20 +10009035proc compare_commits {} {
9036 global markedid rowmenuid curview children
9037
9038 if {![info exists markedid]} return
9039 if {![commitinview $markedid $curview]} return
9040 addtohistory [list do_cmp_commits $markedid $rowmenuid]
9041 do_cmp_commits $markedid $rowmenuid
9042}
9043
9044proc getpatchid {id} {
9045 global patchids
9046
9047 if {![info exists patchids($id)]} {
Paul Mackerras6f63fc12009-04-21 22:22:31 +10009048 set cmd [diffcmd [list $id] {-p --root}]
9049 # trim off the initial "|"
9050 set cmd [lrange $cmd 1 end]
9051 if {[catch {
9052 set x [eval exec $cmd | git patch-id]
9053 set patchids($id) [lindex $x 0]
9054 }]} {
9055 set patchids($id) "error"
9056 }
Paul Mackerras010509f2009-04-09 22:10:20 +10009057 }
9058 return $patchids($id)
9059}
9060
9061proc do_cmp_commits {a b} {
9062 global ctext curview parents children patchids commitinfo
9063
9064 $ctext conf -state normal
9065 clear_ctext
9066 init_flist {}
9067 for {set i 0} {$i < 100} {incr i} {
Paul Mackerras010509f2009-04-09 22:10:20 +10009068 set skipa 0
9069 set skipb 0
9070 if {[llength $parents($curview,$a)] > 1} {
Paul Mackerras6f63fc12009-04-21 22:22:31 +10009071 appendshortlink $a [mc "Skipping merge commit "] "\n"
Paul Mackerras010509f2009-04-09 22:10:20 +10009072 set skipa 1
9073 } else {
9074 set patcha [getpatchid $a]
9075 }
9076 if {[llength $parents($curview,$b)] > 1} {
Paul Mackerras6f63fc12009-04-21 22:22:31 +10009077 appendshortlink $b [mc "Skipping merge commit "] "\n"
Paul Mackerras010509f2009-04-09 22:10:20 +10009078 set skipb 1
9079 } else {
9080 set patchb [getpatchid $b]
9081 }
9082 if {!$skipa && !$skipb} {
9083 set heada [lindex $commitinfo($a) 0]
9084 set headb [lindex $commitinfo($b) 0]
Paul Mackerras6f63fc12009-04-21 22:22:31 +10009085 if {$patcha eq "error"} {
9086 appendshortlink $a [mc "Error getting patch ID for "] \
9087 [mc " - stopping\n"]
9088 break
9089 }
9090 if {$patchb eq "error"} {
9091 appendshortlink $b [mc "Error getting patch ID for "] \
9092 [mc " - stopping\n"]
9093 break
9094 }
Paul Mackerras010509f2009-04-09 22:10:20 +10009095 if {$patcha eq $patchb} {
9096 if {$heada eq $headb} {
Paul Mackerras6f63fc12009-04-21 22:22:31 +10009097 appendshortlink $a [mc "Commit "]
9098 appendshortlink $b " == " " $heada\n"
Paul Mackerras010509f2009-04-09 22:10:20 +10009099 } else {
Paul Mackerras6f63fc12009-04-21 22:22:31 +10009100 appendshortlink $a [mc "Commit "] " $heada\n"
9101 appendshortlink $b [mc " is the same patch as\n "] \
9102 " $headb\n"
Paul Mackerras010509f2009-04-09 22:10:20 +10009103 }
9104 set skipa 1
9105 set skipb 1
9106 } else {
9107 $ctext insert end "\n"
Paul Mackerras6f63fc12009-04-21 22:22:31 +10009108 appendshortlink $a [mc "Commit "] " $heada\n"
9109 appendshortlink $b [mc " differs from\n "] \
9110 " $headb\n"
Paul Mackerrasc21398b2009-09-07 10:08:21 +10009111 $ctext insert end [mc "Diff of commits:\n\n"]
9112 $ctext conf -state disabled
9113 update
9114 diffcommits $a $b
9115 return
Paul Mackerras010509f2009-04-09 22:10:20 +10009116 }
9117 }
9118 if {$skipa} {
Paul Mackerrasaa435612009-09-10 21:58:40 +10009119 set kids [real_children $curview,$a]
9120 if {[llength $kids] != 1} {
Paul Mackerras010509f2009-04-09 22:10:20 +10009121 $ctext insert end "\n"
Paul Mackerras6f63fc12009-04-21 22:22:31 +10009122 appendshortlink $a [mc "Commit "] \
Paul Mackerrasaa435612009-09-10 21:58:40 +10009123 [mc " has %s children - stopping\n" [llength $kids]]
Paul Mackerras010509f2009-04-09 22:10:20 +10009124 break
9125 }
Paul Mackerrasaa435612009-09-10 21:58:40 +10009126 set a [lindex $kids 0]
Paul Mackerras010509f2009-04-09 22:10:20 +10009127 }
9128 if {$skipb} {
Paul Mackerrasaa435612009-09-10 21:58:40 +10009129 set kids [real_children $curview,$b]
9130 if {[llength $kids] != 1} {
Paul Mackerras6f63fc12009-04-21 22:22:31 +10009131 appendshortlink $b [mc "Commit "] \
Paul Mackerrasaa435612009-09-10 21:58:40 +10009132 [mc " has %s children - stopping\n" [llength $kids]]
Paul Mackerras010509f2009-04-09 22:10:20 +10009133 break
9134 }
Paul Mackerrasaa435612009-09-10 21:58:40 +10009135 set b [lindex $kids 0]
Paul Mackerras010509f2009-04-09 22:10:20 +10009136 }
9137 }
9138 $ctext conf -state disabled
9139}
9140
Paul Mackerrasc21398b2009-09-07 10:08:21 +10009141proc diffcommits {a b} {
Jens Lehmanna1d383c2010-04-09 22:16:42 +02009142 global diffcontext diffids blobdifffd diffinhdr currdiffsubmod
Paul Mackerrasc21398b2009-09-07 10:08:21 +10009143
9144 set tmpdir [gitknewtmpdir]
9145 set fna [file join $tmpdir "commit-[string range $a 0 7]"]
9146 set fnb [file join $tmpdir "commit-[string range $b 0 7]"]
9147 if {[catch {
9148 exec git diff-tree -p --pretty $a >$fna
9149 exec git diff-tree -p --pretty $b >$fnb
9150 } err]} {
9151 error_popup [mc "Error writing commit to file: %s" $err]
9152 return
9153 }
9154 if {[catch {
9155 set fd [open "| diff -U$diffcontext $fna $fnb" r]
9156 } err]} {
9157 error_popup [mc "Error diffing commits: %s" $err]
9158 return
9159 }
9160 set diffids [list commits $a $b]
9161 set blobdifffd($diffids) $fd
9162 set diffinhdr 0
Jens Lehmanna1d383c2010-04-09 22:16:42 +02009163 set currdiffsubmod ""
Paul Mackerrasc21398b2009-09-07 10:08:21 +10009164 filerun $fd [list getblobdiffline $fd $diffids]
9165}
9166
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10009167proc diffvssel {dirn} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11009168 global rowmenuid selectedline
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10009169
Paul Mackerras94b4a692008-05-20 20:51:06 +10009170 if {$selectedline eq {}} return
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10009171 if {$dirn} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11009172 set oldid [commitonrow $selectedline]
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10009173 set newid $rowmenuid
9174 } else {
9175 set oldid $rowmenuid
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11009176 set newid [commitonrow $selectedline]
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10009177 }
Paul Mackerras354af6b2008-11-23 13:14:23 +11009178 addtohistory [list doseldiff $oldid $newid] savectextpos
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10009179 doseldiff $oldid $newid
9180}
9181
Paul Mackerras6febded2012-03-23 22:07:27 +11009182proc diffvsmark {dirn} {
9183 global rowmenuid markedid
9184
9185 if {![info exists markedid]} return
9186 if {$dirn} {
9187 set oldid $markedid
9188 set newid $rowmenuid
9189 } else {
9190 set oldid $rowmenuid
9191 set newid $markedid
9192 }
9193 addtohistory [list doseldiff $oldid $newid] savectextpos
9194 doseldiff $oldid $newid
9195}
9196
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10009197proc doseldiff {oldid newid} {
Paul Mackerras7fcceed2006-04-27 19:21:49 +10009198 global ctext
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10009199 global commitinfo
9200
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10009201 $ctext conf -state normal
Paul Mackerras3ea06f92006-05-24 10:16:03 +10009202 clear_ctext
Christian Stimmingd990ced2007-11-07 18:42:55 +01009203 init_flist [mc "Top"]
9204 $ctext insert end "[mc "From"] "
Paul Mackerras97645682007-08-23 22:24:38 +10009205 $ctext insert end $oldid link0
9206 setlink $oldid link0
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10009207 $ctext insert end "\n "
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10009208 $ctext insert end [lindex $commitinfo($oldid) 0]
Christian Stimmingd990ced2007-11-07 18:42:55 +01009209 $ctext insert end "\n\n[mc "To"] "
Paul Mackerras97645682007-08-23 22:24:38 +10009210 $ctext insert end $newid link1
9211 setlink $newid link1
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10009212 $ctext insert end "\n "
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10009213 $ctext insert end [lindex $commitinfo($newid) 0]
9214 $ctext insert end "\n"
9215 $ctext conf -state disabled
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10009216 $ctext tag remove found 1.0 end
Paul Mackerrasd3272442005-11-28 20:41:56 +11009217 startdiff [list $oldid $newid]
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10009218}
9219
Paul Mackerras74daedb2005-06-27 19:27:32 +10009220proc mkpatch {} {
Pat Thoytsd93f1712009-04-17 01:24:35 +01009221 global rowmenuid currentid commitinfo patchtop patchnum NS
Paul Mackerras74daedb2005-06-27 19:27:32 +10009222
9223 if {![info exists currentid]} return
9224 set oldid $currentid
9225 set oldhead [lindex $commitinfo($oldid) 0]
9226 set newid $rowmenuid
9227 set newhead [lindex $commitinfo($newid) 0]
9228 set top .patch
9229 set patchtop $top
9230 catch {destroy $top}
Pat Thoytsd93f1712009-04-17 01:24:35 +01009231 ttk_toplevel $top
Alexander Gavrilove7d64002008-11-11 23:55:42 +03009232 make_transient $top .
Pat Thoytsd93f1712009-04-17 01:24:35 +01009233 ${NS}::label $top.title -text [mc "Generate patch"]
Paul Mackerras4a2139f2005-06-29 09:47:48 +10009234 grid $top.title - -pady 10
Pat Thoytsd93f1712009-04-17 01:24:35 +01009235 ${NS}::label $top.from -text [mc "From:"]
9236 ${NS}::entry $top.fromsha1 -width 40
Paul Mackerras74daedb2005-06-27 19:27:32 +10009237 $top.fromsha1 insert 0 $oldid
9238 $top.fromsha1 conf -state readonly
9239 grid $top.from $top.fromsha1 -sticky w
Pat Thoytsd93f1712009-04-17 01:24:35 +01009240 ${NS}::entry $top.fromhead -width 60
Paul Mackerras74daedb2005-06-27 19:27:32 +10009241 $top.fromhead insert 0 $oldhead
9242 $top.fromhead conf -state readonly
9243 grid x $top.fromhead -sticky w
Pat Thoytsd93f1712009-04-17 01:24:35 +01009244 ${NS}::label $top.to -text [mc "To:"]
9245 ${NS}::entry $top.tosha1 -width 40
Paul Mackerras74daedb2005-06-27 19:27:32 +10009246 $top.tosha1 insert 0 $newid
9247 $top.tosha1 conf -state readonly
9248 grid $top.to $top.tosha1 -sticky w
Pat Thoytsd93f1712009-04-17 01:24:35 +01009249 ${NS}::entry $top.tohead -width 60
Paul Mackerras74daedb2005-06-27 19:27:32 +10009250 $top.tohead insert 0 $newhead
9251 $top.tohead conf -state readonly
9252 grid x $top.tohead -sticky w
Pat Thoytsd93f1712009-04-17 01:24:35 +01009253 ${NS}::button $top.rev -text [mc "Reverse"] -command mkpatchrev
9254 grid $top.rev x -pady 10 -padx 5
9255 ${NS}::label $top.flab -text [mc "Output file:"]
9256 ${NS}::entry $top.fname -width 60
Paul Mackerras74daedb2005-06-27 19:27:32 +10009257 $top.fname insert 0 [file normalize "patch$patchnum.patch"]
9258 incr patchnum
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10009259 grid $top.flab $top.fname -sticky w
Pat Thoytsd93f1712009-04-17 01:24:35 +01009260 ${NS}::frame $top.buts
9261 ${NS}::button $top.buts.gen -text [mc "Generate"] -command mkpatchgo
9262 ${NS}::button $top.buts.can -text [mc "Cancel"] -command mkpatchcan
Alexander Gavrilov76f15942008-11-02 21:59:44 +03009263 bind $top <Key-Return> mkpatchgo
9264 bind $top <Key-Escape> mkpatchcan
Paul Mackerras74daedb2005-06-27 19:27:32 +10009265 grid $top.buts.gen $top.buts.can
9266 grid columnconfigure $top.buts 0 -weight 1 -uniform a
9267 grid columnconfigure $top.buts 1 -weight 1 -uniform a
9268 grid $top.buts - -pady 10 -sticky ew
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10009269 focus $top.fname
Paul Mackerras74daedb2005-06-27 19:27:32 +10009270}
9271
9272proc mkpatchrev {} {
9273 global patchtop
9274
9275 set oldid [$patchtop.fromsha1 get]
9276 set oldhead [$patchtop.fromhead get]
9277 set newid [$patchtop.tosha1 get]
9278 set newhead [$patchtop.tohead get]
9279 foreach e [list fromsha1 fromhead tosha1 tohead] \
9280 v [list $newid $newhead $oldid $oldhead] {
9281 $patchtop.$e conf -state normal
9282 $patchtop.$e delete 0 end
9283 $patchtop.$e insert 0 $v
9284 $patchtop.$e conf -state readonly
9285 }
9286}
9287
9288proc mkpatchgo {} {
Paul Mackerras8f489362007-07-13 19:49:37 +10009289 global patchtop nullid nullid2
Paul Mackerras74daedb2005-06-27 19:27:32 +10009290
9291 set oldid [$patchtop.fromsha1 get]
9292 set newid [$patchtop.tosha1 get]
9293 set fname [$patchtop.fname get]
Paul Mackerras8f489362007-07-13 19:49:37 +10009294 set cmd [diffcmd [list $oldid $newid] -p]
Paul Mackerrasd372e212007-09-15 12:08:38 +10009295 # trim off the initial "|"
9296 set cmd [lrange $cmd 1 end]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10009297 lappend cmd >$fname &
9298 if {[catch {eval exec $cmd} err]} {
Alexander Gavrilov84a76f12008-11-02 21:59:45 +03009299 error_popup "[mc "Error creating patch:"] $err" $patchtop
Paul Mackerras74daedb2005-06-27 19:27:32 +10009300 }
9301 catch {destroy $patchtop}
9302 unset patchtop
9303}
9304
9305proc mkpatchcan {} {
9306 global patchtop
9307
9308 catch {destroy $patchtop}
9309 unset patchtop
9310}
9311
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10009312proc mktag {} {
Pat Thoytsd93f1712009-04-17 01:24:35 +01009313 global rowmenuid mktagtop commitinfo NS
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10009314
9315 set top .maketag
9316 set mktagtop $top
9317 catch {destroy $top}
Pat Thoytsd93f1712009-04-17 01:24:35 +01009318 ttk_toplevel $top
Alexander Gavrilove7d64002008-11-11 23:55:42 +03009319 make_transient $top .
Pat Thoytsd93f1712009-04-17 01:24:35 +01009320 ${NS}::label $top.title -text [mc "Create tag"]
Paul Mackerras4a2139f2005-06-29 09:47:48 +10009321 grid $top.title - -pady 10
Pat Thoytsd93f1712009-04-17 01:24:35 +01009322 ${NS}::label $top.id -text [mc "ID:"]
9323 ${NS}::entry $top.sha1 -width 40
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10009324 $top.sha1 insert 0 $rowmenuid
9325 $top.sha1 conf -state readonly
9326 grid $top.id $top.sha1 -sticky w
Pat Thoytsd93f1712009-04-17 01:24:35 +01009327 ${NS}::entry $top.head -width 60
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10009328 $top.head insert 0 [lindex $commitinfo($rowmenuid) 0]
9329 $top.head conf -state readonly
9330 grid x $top.head -sticky w
Pat Thoytsd93f1712009-04-17 01:24:35 +01009331 ${NS}::label $top.tlab -text [mc "Tag name:"]
9332 ${NS}::entry $top.tag -width 60
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10009333 grid $top.tlab $top.tag -sticky w
Dave Dulsondfb891e2010-01-03 14:55:52 +00009334 ${NS}::label $top.op -text [mc "Tag message is optional"]
9335 grid $top.op -columnspan 2 -sticky we
9336 ${NS}::label $top.mlab -text [mc "Tag message:"]
9337 ${NS}::entry $top.msg -width 60
9338 grid $top.mlab $top.msg -sticky w
Pat Thoytsd93f1712009-04-17 01:24:35 +01009339 ${NS}::frame $top.buts
9340 ${NS}::button $top.buts.gen -text [mc "Create"] -command mktaggo
9341 ${NS}::button $top.buts.can -text [mc "Cancel"] -command mktagcan
Alexander Gavrilov76f15942008-11-02 21:59:44 +03009342 bind $top <Key-Return> mktaggo
9343 bind $top <Key-Escape> mktagcan
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10009344 grid $top.buts.gen $top.buts.can
9345 grid columnconfigure $top.buts 0 -weight 1 -uniform a
9346 grid columnconfigure $top.buts 1 -weight 1 -uniform a
9347 grid $top.buts - -pady 10 -sticky ew
9348 focus $top.tag
9349}
9350
9351proc domktag {} {
9352 global mktagtop env tagids idtags
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10009353
9354 set id [$mktagtop.sha1 get]
9355 set tag [$mktagtop.tag get]
Dave Dulsondfb891e2010-01-03 14:55:52 +00009356 set msg [$mktagtop.msg get]
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10009357 if {$tag == {}} {
Alexander Gavrilov84a76f12008-11-02 21:59:45 +03009358 error_popup [mc "No tag name specified"] $mktagtop
9359 return 0
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10009360 }
9361 if {[info exists tagids($tag)]} {
Alexander Gavrilov84a76f12008-11-02 21:59:45 +03009362 error_popup [mc "Tag \"%s\" already exists" $tag] $mktagtop
9363 return 0
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10009364 }
9365 if {[catch {
Dave Dulsondfb891e2010-01-03 14:55:52 +00009366 if {$msg != {}} {
9367 exec git tag -a -m $msg $tag $id
9368 } else {
9369 exec git tag $tag $id
9370 }
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10009371 } err]} {
Alexander Gavrilov84a76f12008-11-02 21:59:45 +03009372 error_popup "[mc "Error creating tag:"] $err" $mktagtop
9373 return 0
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10009374 }
9375
9376 set tagids($tag) $id
9377 lappend idtags($id) $tag
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10009378 redrawtags $id
Paul Mackerrasceadfe92006-08-08 20:55:36 +10009379 addedtag $id
Paul Mackerras887c9962007-08-20 19:36:20 +10009380 dispneartags 0
9381 run refill_reflist
Alexander Gavrilov84a76f12008-11-02 21:59:45 +03009382 return 1
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10009383}
9384
9385proc redrawtags {id} {
Paul Mackerrasb9fdba72009-04-09 09:34:46 +10009386 global canv linehtag idpos currentid curview cmitlisted markedid
Paul Mackerrasc11ff122008-05-26 10:11:33 +10009387 global canvxmax iddrawn circleitem mainheadid circlecolors
Gauthier Östervall252c52d2013-03-27 14:40:51 +01009388 global mainheadcirclecolor
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10009389
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11009390 if {![commitinview $id $curview]} return
Paul Mackerras322a8cc2006-10-15 18:03:46 +10009391 if {![info exists iddrawn($id)]} return
Paul Mackerrasfc2a2562007-12-26 23:03:43 +11009392 set row [rowofcommit $id]
Paul Mackerrasc11ff122008-05-26 10:11:33 +10009393 if {$id eq $mainheadid} {
Gauthier Östervall252c52d2013-03-27 14:40:51 +01009394 set ofill $mainheadcirclecolor
Paul Mackerrasc11ff122008-05-26 10:11:33 +10009395 } else {
9396 set ofill [lindex $circlecolors $cmitlisted($curview,$id)]
9397 }
9398 $canv itemconf $circleitem($row) -fill $ofill
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10009399 $canv delete tag.$id
9400 set xt [eval drawtags $id $idpos($id)]
Paul Mackerras28593d32008-11-13 23:01:46 +11009401 $canv coords $linehtag($id) $xt [lindex $idpos($id) 2]
9402 set text [$canv itemcget $linehtag($id) -text]
9403 set font [$canv itemcget $linehtag($id) -font]
Paul Mackerrasfc2a2562007-12-26 23:03:43 +11009404 set xr [expr {$xt + [font measure $font $text]}]
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10009405 if {$xr > $canvxmax} {
9406 set canvxmax $xr
9407 setcanvscroll
9408 }
Paul Mackerrasfc2a2562007-12-26 23:03:43 +11009409 if {[info exists currentid] && $currentid == $id} {
Paul Mackerras28593d32008-11-13 23:01:46 +11009410 make_secsel $id
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10009411 }
Paul Mackerrasb9fdba72009-04-09 09:34:46 +10009412 if {[info exists markedid] && $markedid eq $id} {
9413 make_idmark $id
9414 }
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10009415}
9416
9417proc mktagcan {} {
9418 global mktagtop
9419
9420 catch {destroy $mktagtop}
9421 unset mktagtop
9422}
9423
9424proc mktaggo {} {
Alexander Gavrilov84a76f12008-11-02 21:59:45 +03009425 if {![domktag]} return
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10009426 mktagcan
9427}
9428
Beat Bollid835dbb2015-07-18 13:15:39 +02009429proc copysummary {} {
9430 global rowmenuid autosellen
9431
9432 set format "%h (\"%s\", %ad)"
9433 set cmd [list git show -s --pretty=format:$format --date=short]
9434 if {$autosellen < 40} {
9435 lappend cmd --abbrev=$autosellen
9436 }
9437 set summary [eval exec $cmd $rowmenuid]
9438
9439 clipboard clear
9440 clipboard append $summary
9441}
9442
Paul Mackerras4a2139f2005-06-29 09:47:48 +10009443proc writecommit {} {
Pat Thoytsd93f1712009-04-17 01:24:35 +01009444 global rowmenuid wrcomtop commitinfo wrcomcmd NS
Paul Mackerras4a2139f2005-06-29 09:47:48 +10009445
9446 set top .writecommit
9447 set wrcomtop $top
9448 catch {destroy $top}
Pat Thoytsd93f1712009-04-17 01:24:35 +01009449 ttk_toplevel $top
Alexander Gavrilove7d64002008-11-11 23:55:42 +03009450 make_transient $top .
Pat Thoytsd93f1712009-04-17 01:24:35 +01009451 ${NS}::label $top.title -text [mc "Write commit to file"]
Paul Mackerras4a2139f2005-06-29 09:47:48 +10009452 grid $top.title - -pady 10
Pat Thoytsd93f1712009-04-17 01:24:35 +01009453 ${NS}::label $top.id -text [mc "ID:"]
9454 ${NS}::entry $top.sha1 -width 40
Paul Mackerras4a2139f2005-06-29 09:47:48 +10009455 $top.sha1 insert 0 $rowmenuid
9456 $top.sha1 conf -state readonly
9457 grid $top.id $top.sha1 -sticky w
Pat Thoytsd93f1712009-04-17 01:24:35 +01009458 ${NS}::entry $top.head -width 60
Paul Mackerras4a2139f2005-06-29 09:47:48 +10009459 $top.head insert 0 [lindex $commitinfo($rowmenuid) 0]
9460 $top.head conf -state readonly
9461 grid x $top.head -sticky w
Pat Thoytsd93f1712009-04-17 01:24:35 +01009462 ${NS}::label $top.clab -text [mc "Command:"]
9463 ${NS}::entry $top.cmd -width 60 -textvariable wrcomcmd
Paul Mackerras4a2139f2005-06-29 09:47:48 +10009464 grid $top.clab $top.cmd -sticky w -pady 10
Pat Thoytsd93f1712009-04-17 01:24:35 +01009465 ${NS}::label $top.flab -text [mc "Output file:"]
9466 ${NS}::entry $top.fname -width 60
Paul Mackerras4a2139f2005-06-29 09:47:48 +10009467 $top.fname insert 0 [file normalize "commit-[string range $rowmenuid 0 6]"]
9468 grid $top.flab $top.fname -sticky w
Pat Thoytsd93f1712009-04-17 01:24:35 +01009469 ${NS}::frame $top.buts
9470 ${NS}::button $top.buts.gen -text [mc "Write"] -command wrcomgo
9471 ${NS}::button $top.buts.can -text [mc "Cancel"] -command wrcomcan
Alexander Gavrilov76f15942008-11-02 21:59:44 +03009472 bind $top <Key-Return> wrcomgo
9473 bind $top <Key-Escape> wrcomcan
Paul Mackerras4a2139f2005-06-29 09:47:48 +10009474 grid $top.buts.gen $top.buts.can
9475 grid columnconfigure $top.buts 0 -weight 1 -uniform a
9476 grid columnconfigure $top.buts 1 -weight 1 -uniform a
9477 grid $top.buts - -pady 10 -sticky ew
9478 focus $top.fname
9479}
9480
9481proc wrcomgo {} {
9482 global wrcomtop
9483
9484 set id [$wrcomtop.sha1 get]
9485 set cmd "echo $id | [$wrcomtop.cmd get]"
9486 set fname [$wrcomtop.fname get]
9487 if {[catch {exec sh -c $cmd >$fname &} err]} {
Alexander Gavrilov84a76f12008-11-02 21:59:45 +03009488 error_popup "[mc "Error writing commit:"] $err" $wrcomtop
Paul Mackerras4a2139f2005-06-29 09:47:48 +10009489 }
9490 catch {destroy $wrcomtop}
9491 unset wrcomtop
9492}
9493
9494proc wrcomcan {} {
9495 global wrcomtop
9496
9497 catch {destroy $wrcomtop}
9498 unset wrcomtop
9499}
9500
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10009501proc mkbranch {} {
Rogier Goossens5a046c52016-03-19 19:32:16 +01009502 global NS rowmenuid
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10009503
Rogier Goossens5a046c52016-03-19 19:32:16 +01009504 set top .branchdialog
9505
9506 set val(name) ""
9507 set val(id) $rowmenuid
9508 set val(command) [list mkbrgo $top]
9509
9510 set ui(title) [mc "Create branch"]
9511 set ui(accept) [mc "Create"]
9512
9513 branchdia $top val ui
9514}
9515
9516proc mvbranch {} {
9517 global NS
9518 global headmenuid headmenuhead
9519
9520 set top .branchdialog
9521
9522 set val(name) $headmenuhead
9523 set val(id) $headmenuid
9524 set val(command) [list mvbrgo $top $headmenuhead]
9525
9526 set ui(title) [mc "Rename branch %s" $headmenuhead]
9527 set ui(accept) [mc "Rename"]
9528
9529 branchdia $top val ui
9530}
9531
9532proc branchdia {top valvar uivar} {
Rogier Goossens7f00f4c2016-03-27 09:21:01 +02009533 global NS commitinfo
Rogier Goossens5a046c52016-03-19 19:32:16 +01009534 upvar $valvar val $uivar ui
9535
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10009536 catch {destroy $top}
Pat Thoytsd93f1712009-04-17 01:24:35 +01009537 ttk_toplevel $top
Alexander Gavrilove7d64002008-11-11 23:55:42 +03009538 make_transient $top .
Rogier Goossens5a046c52016-03-19 19:32:16 +01009539 ${NS}::label $top.title -text $ui(title)
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10009540 grid $top.title - -pady 10
Pat Thoytsd93f1712009-04-17 01:24:35 +01009541 ${NS}::label $top.id -text [mc "ID:"]
9542 ${NS}::entry $top.sha1 -width 40
Rogier Goossens5a046c52016-03-19 19:32:16 +01009543 $top.sha1 insert 0 $val(id)
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10009544 $top.sha1 conf -state readonly
9545 grid $top.id $top.sha1 -sticky w
Rogier Goossens7f00f4c2016-03-27 09:21:01 +02009546 ${NS}::entry $top.head -width 60
9547 $top.head insert 0 [lindex $commitinfo($val(id)) 0]
9548 $top.head conf -state readonly
9549 grid x $top.head -sticky ew
9550 grid columnconfigure $top 1 -weight 1
Pat Thoytsd93f1712009-04-17 01:24:35 +01009551 ${NS}::label $top.nlab -text [mc "Name:"]
9552 ${NS}::entry $top.name -width 40
Rogier Goossens5a046c52016-03-19 19:32:16 +01009553 $top.name insert 0 $val(name)
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10009554 grid $top.nlab $top.name -sticky w
Pat Thoytsd93f1712009-04-17 01:24:35 +01009555 ${NS}::frame $top.buts
Rogier Goossens5a046c52016-03-19 19:32:16 +01009556 ${NS}::button $top.buts.go -text $ui(accept) -command $val(command)
Pat Thoytsd93f1712009-04-17 01:24:35 +01009557 ${NS}::button $top.buts.can -text [mc "Cancel"] -command "catch {destroy $top}"
Rogier Goossens5a046c52016-03-19 19:32:16 +01009558 bind $top <Key-Return> $val(command)
Alexander Gavrilov76f15942008-11-02 21:59:44 +03009559 bind $top <Key-Escape> "catch {destroy $top}"
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10009560 grid $top.buts.go $top.buts.can
9561 grid columnconfigure $top.buts 0 -weight 1 -uniform a
9562 grid columnconfigure $top.buts 1 -weight 1 -uniform a
9563 grid $top.buts - -pady 10 -sticky ew
9564 focus $top.name
9565}
9566
9567proc mkbrgo {top} {
9568 global headids idheads
9569
9570 set name [$top.name get]
9571 set id [$top.sha1 get]
Alexander Gavrilovbee866f2008-10-08 11:05:35 +04009572 set cmdargs {}
9573 set old_id {}
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10009574 if {$name eq {}} {
Alexander Gavrilov84a76f12008-11-02 21:59:45 +03009575 error_popup [mc "Please specify a name for the new branch"] $top
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10009576 return
9577 }
Alexander Gavrilovbee866f2008-10-08 11:05:35 +04009578 if {[info exists headids($name)]} {
9579 if {![confirm_popup [mc \
Alexander Gavrilov84a76f12008-11-02 21:59:45 +03009580 "Branch '%s' already exists. Overwrite?" $name] $top]} {
Alexander Gavrilovbee866f2008-10-08 11:05:35 +04009581 return
9582 }
9583 set old_id $headids($name)
9584 lappend cmdargs -f
9585 }
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10009586 catch {destroy $top}
Alexander Gavrilovbee866f2008-10-08 11:05:35 +04009587 lappend cmdargs $name $id
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10009588 nowbusy newbranch
9589 update
9590 if {[catch {
Alexander Gavrilovbee866f2008-10-08 11:05:35 +04009591 eval exec git branch $cmdargs
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10009592 } err]} {
9593 notbusy newbranch
9594 error_popup $err
9595 } else {
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10009596 notbusy newbranch
Alexander Gavrilovbee866f2008-10-08 11:05:35 +04009597 if {$old_id ne {}} {
9598 movehead $id $name
9599 movedhead $id $name
9600 redrawtags $old_id
9601 redrawtags $id
9602 } else {
9603 set headids($name) $id
9604 lappend idheads($id) $name
9605 addedhead $id $name
9606 redrawtags $id
9607 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10009608 dispneartags 0
Paul Mackerras887c9962007-08-20 19:36:20 +10009609 run refill_reflist
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10009610 }
9611}
9612
Rogier Goossens5a046c52016-03-19 19:32:16 +01009613proc mvbrgo {top prevname} {
9614 global headids idheads mainhead mainheadid
9615
9616 set name [$top.name get]
9617 set id [$top.sha1 get]
9618 set cmdargs {}
9619 if {$name eq $prevname} {
9620 catch {destroy $top}
9621 return
9622 }
9623 if {$name eq {}} {
9624 error_popup [mc "Please specify a new name for the branch"] $top
9625 return
9626 }
9627 catch {destroy $top}
9628 lappend cmdargs -m $prevname $name
9629 nowbusy renamebranch
9630 update
9631 if {[catch {
9632 eval exec git branch $cmdargs
9633 } err]} {
9634 notbusy renamebranch
9635 error_popup $err
9636 } else {
9637 notbusy renamebranch
9638 removehead $id $prevname
9639 removedhead $id $prevname
9640 set headids($name) $id
9641 lappend idheads($id) $name
9642 addedhead $id $name
9643 if {$prevname eq $mainhead} {
9644 set mainhead $name
9645 set mainheadid $id
9646 }
9647 redrawtags $id
9648 dispneartags 0
9649 run refill_reflist
9650 }
9651}
9652
Alexander Gavrilov15e35052008-11-02 21:59:47 +03009653proc exec_citool {tool_args {baseid {}}} {
9654 global commitinfo env
9655
9656 set save_env [array get env GIT_AUTHOR_*]
9657
9658 if {$baseid ne {}} {
9659 if {![info exists commitinfo($baseid)]} {
9660 getcommit $baseid
9661 }
9662 set author [lindex $commitinfo($baseid) 1]
9663 set date [lindex $commitinfo($baseid) 2]
9664 if {[regexp {^\s*(\S.*\S|\S)\s*<(.*)>\s*$} \
9665 $author author name email]
9666 && $date ne {}} {
9667 set env(GIT_AUTHOR_NAME) $name
9668 set env(GIT_AUTHOR_EMAIL) $email
9669 set env(GIT_AUTHOR_DATE) $date
9670 }
9671 }
9672
9673 eval exec git citool $tool_args &
9674
9675 array unset env GIT_AUTHOR_*
9676 array set env $save_env
9677}
9678
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10009679proc cherrypick {} {
Paul Mackerras468bcae2008-03-03 10:19:35 +11009680 global rowmenuid curview
Paul Mackerrasb8a938c2008-02-13 22:12:31 +11009681 global mainhead mainheadid
Martin von Zweigbergkda616db2011-04-04 22:14:17 -04009682 global gitdir
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10009683
Paul Mackerrase11f1232007-06-16 20:29:25 +10009684 set oldhead [exec git rev-parse HEAD]
9685 set dheads [descheads $rowmenuid]
9686 if {$dheads ne {} && [lsearch -exact $dheads $oldhead] >= 0} {
Christian Stimmingd990ced2007-11-07 18:42:55 +01009687 set ok [confirm_popup [mc "Commit %s is already\
9688 included in branch %s -- really re-apply it?" \
9689 [string range $rowmenuid 0 7] $mainhead]]
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10009690 if {!$ok} return
9691 }
Christian Stimmingd990ced2007-11-07 18:42:55 +01009692 nowbusy cherrypick [mc "Cherry-picking"]
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10009693 update
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10009694 # Unfortunately git-cherry-pick writes stuff to stderr even when
9695 # no error occurs, and exec takes that as an indication of error...
9696 if {[catch {exec sh -c "git cherry-pick -r $rowmenuid 2>&1"} err]} {
9697 notbusy cherrypick
Alexander Gavrilov15e35052008-11-02 21:59:47 +03009698 if {[regexp -line \
Paul Mackerras887a7912008-11-08 21:37:09 +11009699 {Entry '(.*)' (would be overwritten by merge|not uptodate)} \
9700 $err msg fname]} {
9701 error_popup [mc "Cherry-pick failed because of local changes\
9702 to file '%s'.\nPlease commit, reset or stash\
9703 your changes and try again." $fname]
9704 } elseif {[regexp -line \
Anders Kaseorgb74307f2011-01-19 14:45:00 -05009705 {^(CONFLICT \(.*\):|Automatic cherry-pick failed|error: could not apply)} \
Paul Mackerras887a7912008-11-08 21:37:09 +11009706 $err]} {
9707 if {[confirm_popup [mc "Cherry-pick failed because of merge\
9708 conflict.\nDo you wish to run git citool to\
9709 resolve it?"]]} {
9710 # Force citool to read MERGE_MSG
Martin von Zweigbergkda616db2011-04-04 22:14:17 -04009711 file delete [file join $gitdir "GITGUI_MSG"]
Paul Mackerras887a7912008-11-08 21:37:09 +11009712 exec_citool {} $rowmenuid
9713 }
Alexander Gavrilov15e35052008-11-02 21:59:47 +03009714 } else {
9715 error_popup $err
9716 }
Paul Mackerras887a7912008-11-08 21:37:09 +11009717 run updatecommits
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10009718 return
9719 }
9720 set newhead [exec git rev-parse HEAD]
9721 if {$newhead eq $oldhead} {
9722 notbusy cherrypick
Christian Stimmingd990ced2007-11-07 18:42:55 +01009723 error_popup [mc "No changes committed"]
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10009724 return
9725 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10009726 addnewchild $newhead $oldhead
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11009727 if {[commitinview $oldhead $curview]} {
Paul Mackerrascdc84292008-11-18 19:54:14 +11009728 # XXX this isn't right if we have a path limit...
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11009729 insertrow $newhead $oldhead $curview
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10009730 if {$mainhead ne {}} {
Paul Mackerrase11f1232007-06-16 20:29:25 +10009731 movehead $newhead $mainhead
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10009732 movedhead $newhead $mainhead
9733 }
Paul Mackerrasc11ff122008-05-26 10:11:33 +10009734 set mainheadid $newhead
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10009735 redrawtags $oldhead
9736 redrawtags $newhead
Paul Mackerras46308ea2008-01-15 22:16:32 +11009737 selbyid $newhead
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10009738 }
9739 notbusy cherrypick
9740}
9741
Knut Franke8f3ff932013-04-27 16:36:13 +02009742proc revert {} {
9743 global rowmenuid curview
9744 global mainhead mainheadid
9745 global gitdir
9746
9747 set oldhead [exec git rev-parse HEAD]
9748 set dheads [descheads $rowmenuid]
9749 if { $dheads eq {} || [lsearch -exact $dheads $oldhead] == -1 } {
9750 set ok [confirm_popup [mc "Commit %s is not\
9751 included in branch %s -- really revert it?" \
9752 [string range $rowmenuid 0 7] $mainhead]]
9753 if {!$ok} return
9754 }
9755 nowbusy revert [mc "Reverting"]
9756 update
9757
9758 if [catch {exec git revert --no-edit $rowmenuid} err] {
9759 notbusy revert
9760 if [regexp {files would be overwritten by merge:(\n(( |\t)+[^\n]+\n)+)}\
9761 $err match files] {
9762 regsub {\n( |\t)+} $files "\n" files
9763 error_popup [mc "Revert failed because of local changes to\
9764 the following files:%s Please commit, reset or stash \
9765 your changes and try again." $files]
9766 } elseif [regexp {error: could not revert} $err] {
9767 if [confirm_popup [mc "Revert failed because of merge conflict.\n\
9768 Do you wish to run git citool to resolve it?"]] {
9769 # Force citool to read MERGE_MSG
9770 file delete [file join $gitdir "GITGUI_MSG"]
9771 exec_citool {} $rowmenuid
9772 }
9773 } else { error_popup $err }
9774 run updatecommits
9775 return
9776 }
9777
9778 set newhead [exec git rev-parse HEAD]
9779 if { $newhead eq $oldhead } {
9780 notbusy revert
9781 error_popup [mc "No changes committed"]
9782 return
9783 }
9784
9785 addnewchild $newhead $oldhead
9786
9787 if [commitinview $oldhead $curview] {
9788 # XXX this isn't right if we have a path limit...
9789 insertrow $newhead $oldhead $curview
9790 if {$mainhead ne {}} {
9791 movehead $newhead $mainhead
9792 movedhead $newhead $mainhead
9793 }
9794 set mainheadid $newhead
9795 redrawtags $oldhead
9796 redrawtags $newhead
9797 selbyid $newhead
9798 }
9799
9800 notbusy revert
9801}
9802
Paul Mackerras6fb735a2006-10-19 10:09:06 +10009803proc resethead {} {
Pat Thoytsd93f1712009-04-17 01:24:35 +01009804 global mainhead rowmenuid confirm_ok resettype NS
Paul Mackerras6fb735a2006-10-19 10:09:06 +10009805
9806 set confirm_ok 0
9807 set w ".confirmreset"
Pat Thoytsd93f1712009-04-17 01:24:35 +01009808 ttk_toplevel $w
Alexander Gavrilove7d64002008-11-11 23:55:42 +03009809 make_transient $w .
Christian Stimmingd990ced2007-11-07 18:42:55 +01009810 wm title $w [mc "Confirm reset"]
Pat Thoytsd93f1712009-04-17 01:24:35 +01009811 ${NS}::label $w.m -text \
9812 [mc "Reset branch %s to %s?" $mainhead [string range $rowmenuid 0 7]]
Paul Mackerras6fb735a2006-10-19 10:09:06 +10009813 pack $w.m -side top -fill x -padx 20 -pady 20
Pat Thoytsd93f1712009-04-17 01:24:35 +01009814 ${NS}::labelframe $w.f -text [mc "Reset type:"]
Paul Mackerras6fb735a2006-10-19 10:09:06 +10009815 set resettype mixed
Pat Thoytsd93f1712009-04-17 01:24:35 +01009816 ${NS}::radiobutton $w.f.soft -value soft -variable resettype \
Christian Stimmingd990ced2007-11-07 18:42:55 +01009817 -text [mc "Soft: Leave working tree and index untouched"]
Paul Mackerras6fb735a2006-10-19 10:09:06 +10009818 grid $w.f.soft -sticky w
Pat Thoytsd93f1712009-04-17 01:24:35 +01009819 ${NS}::radiobutton $w.f.mixed -value mixed -variable resettype \
Christian Stimmingd990ced2007-11-07 18:42:55 +01009820 -text [mc "Mixed: Leave working tree untouched, reset index"]
Paul Mackerras6fb735a2006-10-19 10:09:06 +10009821 grid $w.f.mixed -sticky w
Pat Thoytsd93f1712009-04-17 01:24:35 +01009822 ${NS}::radiobutton $w.f.hard -value hard -variable resettype \
Christian Stimmingd990ced2007-11-07 18:42:55 +01009823 -text [mc "Hard: Reset working tree and index\n(discard ALL local changes)"]
Paul Mackerras6fb735a2006-10-19 10:09:06 +10009824 grid $w.f.hard -sticky w
Pat Thoytsd93f1712009-04-17 01:24:35 +01009825 pack $w.f -side top -fill x -padx 4
9826 ${NS}::button $w.ok -text [mc OK] -command "set confirm_ok 1; destroy $w"
Paul Mackerras6fb735a2006-10-19 10:09:06 +10009827 pack $w.ok -side left -fill x -padx 20 -pady 20
Pat Thoytsd93f1712009-04-17 01:24:35 +01009828 ${NS}::button $w.cancel -text [mc Cancel] -command "destroy $w"
Alexander Gavrilov76f15942008-11-02 21:59:44 +03009829 bind $w <Key-Escape> [list destroy $w]
Paul Mackerras6fb735a2006-10-19 10:09:06 +10009830 pack $w.cancel -side right -fill x -padx 20 -pady 20
9831 bind $w <Visibility> "grab $w; focus $w"
9832 tkwait window $w
9833 if {!$confirm_ok} return
Paul Mackerras706d6c32007-06-26 11:09:49 +10009834 if {[catch {set fd [open \
Paul Mackerras08ba8202008-05-12 10:18:38 +10009835 [list | git reset --$resettype $rowmenuid 2>@1] r]} err]} {
Paul Mackerras6fb735a2006-10-19 10:09:06 +10009836 error_popup $err
9837 } else {
Paul Mackerras706d6c32007-06-26 11:09:49 +10009838 dohidelocalchanges
Paul Mackerrasa137a902007-10-23 21:12:49 +10009839 filerun $fd [list readresetstat $fd]
Christian Stimmingd990ced2007-11-07 18:42:55 +01009840 nowbusy reset [mc "Resetting"]
Paul Mackerras46308ea2008-01-15 22:16:32 +11009841 selbyid $rowmenuid
Paul Mackerras706d6c32007-06-26 11:09:49 +10009842 }
9843}
9844
Paul Mackerrasa137a902007-10-23 21:12:49 +10009845proc readresetstat {fd} {
9846 global mainhead mainheadid showlocalchanges rprogcoord
Paul Mackerras706d6c32007-06-26 11:09:49 +10009847
9848 if {[gets $fd line] >= 0} {
9849 if {[regexp {([0-9]+)% \(([0-9]+)/([0-9]+)\)} $line match p m n]} {
Paul Mackerrasa137a902007-10-23 21:12:49 +10009850 set rprogcoord [expr {1.0 * $m / $n}]
9851 adjustprogress
Paul Mackerras706d6c32007-06-26 11:09:49 +10009852 }
9853 return 1
9854 }
Paul Mackerrasa137a902007-10-23 21:12:49 +10009855 set rprogcoord 0
9856 adjustprogress
Paul Mackerras706d6c32007-06-26 11:09:49 +10009857 notbusy reset
9858 if {[catch {close $fd} err]} {
9859 error_popup $err
9860 }
9861 set oldhead $mainheadid
9862 set newhead [exec git rev-parse HEAD]
9863 if {$newhead ne $oldhead} {
9864 movehead $newhead $mainhead
9865 movedhead $newhead $mainhead
9866 set mainheadid $newhead
Paul Mackerras6fb735a2006-10-19 10:09:06 +10009867 redrawtags $oldhead
Paul Mackerras706d6c32007-06-26 11:09:49 +10009868 redrawtags $newhead
Paul Mackerras6fb735a2006-10-19 10:09:06 +10009869 }
9870 if {$showlocalchanges} {
9871 doshowlocalchanges
9872 }
Paul Mackerras706d6c32007-06-26 11:09:49 +10009873 return 0
Paul Mackerras6fb735a2006-10-19 10:09:06 +10009874}
9875
Paul Mackerras10299152006-08-02 09:52:01 +10009876# context menu for a head
9877proc headmenu {x y id head} {
Rogier Goossens02e6a062016-03-19 19:33:03 +01009878 global headmenuid headmenuhead headctxmenu mainhead headids
Paul Mackerras10299152006-08-02 09:52:01 +10009879
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10009880 stopfinding
Paul Mackerras10299152006-08-02 09:52:01 +10009881 set headmenuid $id
9882 set headmenuhead $head
Rogier Goossens5a046c52016-03-19 19:32:16 +01009883 array set state {0 normal 1 normal 2 normal}
Sitaram Chamarty70a5fc42009-11-03 21:30:12 +05309884 if {[string match "remotes/*" $head]} {
Rogier Goossens02e6a062016-03-19 19:33:03 +01009885 set localhead [string range $head [expr [string last / $head] + 1] end]
9886 if {[info exists headids($localhead)]} {
9887 set state(0) disabled
9888 }
9889 array set state {1 disabled 2 disabled}
Sitaram Chamarty70a5fc42009-11-03 21:30:12 +05309890 }
Paul Mackerras00609462007-06-17 17:08:35 +10009891 if {$head eq $mainhead} {
Rogier Goossens5a046c52016-03-19 19:32:16 +01009892 array set state {0 disabled 2 disabled}
Paul Mackerras00609462007-06-17 17:08:35 +10009893 }
Rogier Goossens5a046c52016-03-19 19:32:16 +01009894 foreach i {0 1 2} {
9895 $headctxmenu entryconfigure $i -state $state($i)
9896 }
Paul Mackerras10299152006-08-02 09:52:01 +10009897 tk_popup $headctxmenu $x $y
9898}
9899
9900proc cobranch {} {
Paul Mackerrasc11ff122008-05-26 10:11:33 +10009901 global headmenuid headmenuhead headids
Paul Mackerrascdc84292008-11-18 19:54:14 +11009902 global showlocalchanges
Paul Mackerras10299152006-08-02 09:52:01 +10009903
9904 # check the tree is clean first??
Rogier Goossens02e6a062016-03-19 19:33:03 +01009905 set newhead $headmenuhead
9906 set command [list | git checkout]
9907 if {[string match "remotes/*" $newhead]} {
9908 set remote $newhead
9909 set newhead [string range $newhead [expr [string last / $newhead] + 1] end]
9910 # The following check is redundant - the menu option should
9911 # be disabled to begin with...
9912 if {[info exists headids($newhead)]} {
9913 error_popup [mc "A local branch named %s exists already" $newhead]
9914 return
9915 }
9916 lappend command -b $newhead --track $remote
9917 } else {
9918 lappend command $newhead
9919 }
9920 lappend command 2>@1
Christian Stimmingd990ced2007-11-07 18:42:55 +01009921 nowbusy checkout [mc "Checking out"]
Paul Mackerras10299152006-08-02 09:52:01 +10009922 update
Paul Mackerras219ea3a2006-09-07 10:21:39 +10009923 dohidelocalchanges
Paul Mackerras10299152006-08-02 09:52:01 +10009924 if {[catch {
Rogier Goossens02e6a062016-03-19 19:33:03 +01009925 set fd [open $command r]
Paul Mackerras10299152006-08-02 09:52:01 +10009926 } err]} {
9927 notbusy checkout
9928 error_popup $err
Paul Mackerras08ba8202008-05-12 10:18:38 +10009929 if {$showlocalchanges} {
9930 dodiffindex
Paul Mackerras10299152006-08-02 09:52:01 +10009931 }
Paul Mackerras08ba8202008-05-12 10:18:38 +10009932 } else {
Rogier Goossens02e6a062016-03-19 19:33:03 +01009933 filerun $fd [list readcheckoutstat $fd $newhead $headmenuid]
Paul Mackerras6fb735a2006-10-19 10:09:06 +10009934 }
Paul Mackerras08ba8202008-05-12 10:18:38 +10009935}
9936
9937proc readcheckoutstat {fd newhead newheadid} {
Rogier Goossens02e6a062016-03-19 19:33:03 +01009938 global mainhead mainheadid headids idheads showlocalchanges progresscoords
Paul Mackerrascdc84292008-11-18 19:54:14 +11009939 global viewmainheadid curview
Paul Mackerras08ba8202008-05-12 10:18:38 +10009940
9941 if {[gets $fd line] >= 0} {
9942 if {[regexp {([0-9]+)% \(([0-9]+)/([0-9]+)\)} $line match p m n]} {
9943 set progresscoords [list 0 [expr {1.0 * $m / $n}]]
9944 adjustprogress
9945 }
9946 return 1
9947 }
9948 set progresscoords {0 0}
9949 adjustprogress
9950 notbusy checkout
9951 if {[catch {close $fd} err]} {
9952 error_popup $err
Rogier Goossens02e6a062016-03-19 19:33:03 +01009953 return
Paul Mackerras08ba8202008-05-12 10:18:38 +10009954 }
Paul Mackerrasc11ff122008-05-26 10:11:33 +10009955 set oldmainid $mainheadid
Rogier Goossens02e6a062016-03-19 19:33:03 +01009956 if {! [info exists headids($newhead)]} {
9957 set headids($newhead) $newheadid
9958 lappend idheads($newheadid) $newhead
9959 addedhead $newheadid $newhead
9960 }
Paul Mackerras08ba8202008-05-12 10:18:38 +10009961 set mainhead $newhead
9962 set mainheadid $newheadid
Paul Mackerrascdc84292008-11-18 19:54:14 +11009963 set viewmainheadid($curview) $newheadid
Paul Mackerrasc11ff122008-05-26 10:11:33 +10009964 redrawtags $oldmainid
Paul Mackerras08ba8202008-05-12 10:18:38 +10009965 redrawtags $newheadid
9966 selbyid $newheadid
Paul Mackerras6fb735a2006-10-19 10:09:06 +10009967 if {$showlocalchanges} {
9968 dodiffindex
Paul Mackerras10299152006-08-02 09:52:01 +10009969 }
9970}
9971
9972proc rmbranch {} {
Paul Mackerrase11f1232007-06-16 20:29:25 +10009973 global headmenuid headmenuhead mainhead
Paul Mackerrasb1054ac2007-08-15 10:09:47 +10009974 global idheads
Paul Mackerras10299152006-08-02 09:52:01 +10009975
9976 set head $headmenuhead
9977 set id $headmenuid
Paul Mackerras00609462007-06-17 17:08:35 +10009978 # this check shouldn't be needed any more...
Paul Mackerras10299152006-08-02 09:52:01 +10009979 if {$head eq $mainhead} {
Christian Stimmingd990ced2007-11-07 18:42:55 +01009980 error_popup [mc "Cannot delete the currently checked-out branch"]
Paul Mackerras10299152006-08-02 09:52:01 +10009981 return
9982 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10009983 set dheads [descheads $id]
Paul Mackerrasd7b16112007-08-17 17:57:31 +10009984 if {[llength $dheads] == 1 && $idheads($dheads) eq $head} {
Paul Mackerras10299152006-08-02 09:52:01 +10009985 # the stuff on this branch isn't on any other branch
Christian Stimmingd990ced2007-11-07 18:42:55 +01009986 if {![confirm_popup [mc "The commits on branch %s aren't on any other\
9987 branch.\nReally delete branch %s?" $head $head]]} return
Paul Mackerras10299152006-08-02 09:52:01 +10009988 }
9989 nowbusy rmbranch
9990 update
9991 if {[catch {exec git branch -D $head} err]} {
9992 notbusy rmbranch
9993 error_popup $err
9994 return
9995 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10009996 removehead $id $head
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10009997 removedhead $id $head
Paul Mackerras10299152006-08-02 09:52:01 +10009998 redrawtags $id
9999 notbusy rmbranch
Paul Mackerrase11f1232007-06-16 20:29:25 +100010000 dispneartags 0
Paul Mackerras887c9962007-08-20 19:36:20 +100010001 run refill_reflist
10002}
10003
10004# Display a list of tags and heads
10005proc showrefs {} {
Pat Thoytsd93f1712009-04-17 01:24:35 +010010006 global showrefstop bgcolor fgcolor selectbgcolor NS
Paul Mackerras9c311b32007-10-04 22:27:13 +100010007 global bglist fglist reflistfilter reflist maincursor
Paul Mackerras887c9962007-08-20 19:36:20 +100010008
10009 set top .showrefs
10010 set showrefstop $top
10011 if {[winfo exists $top]} {
10012 raise $top
10013 refill_reflist
10014 return
10015 }
Pat Thoytsd93f1712009-04-17 01:24:35 +010010016 ttk_toplevel $top
Christian Stimmingd990ced2007-11-07 18:42:55 +010010017 wm title $top [mc "Tags and heads: %s" [file tail [pwd]]]
Alexander Gavrilove7d64002008-11-11 23:55:42 +030010018 make_transient $top .
Paul Mackerras887c9962007-08-20 19:36:20 +100010019 text $top.list -background $bgcolor -foreground $fgcolor \
Paul Mackerras9c311b32007-10-04 22:27:13 +100010020 -selectbackground $selectbgcolor -font mainfont \
Paul Mackerras887c9962007-08-20 19:36:20 +100010021 -xscrollcommand "$top.xsb set" -yscrollcommand "$top.ysb set" \
10022 -width 30 -height 20 -cursor $maincursor \
10023 -spacing1 1 -spacing3 1 -state disabled
10024 $top.list tag configure highlight -background $selectbgcolor
Paul Mackerraseb859df2015-05-03 15:11:29 +100010025 if {![lsearch -exact $bglist $top.list]} {
10026 lappend bglist $top.list
10027 lappend fglist $top.list
10028 }
Pat Thoytsd93f1712009-04-17 01:24:35 +010010029 ${NS}::scrollbar $top.ysb -command "$top.list yview" -orient vertical
10030 ${NS}::scrollbar $top.xsb -command "$top.list xview" -orient horizontal
Paul Mackerras887c9962007-08-20 19:36:20 +100010031 grid $top.list $top.ysb -sticky nsew
10032 grid $top.xsb x -sticky ew
Pat Thoytsd93f1712009-04-17 01:24:35 +010010033 ${NS}::frame $top.f
10034 ${NS}::label $top.f.l -text "[mc "Filter"]: "
10035 ${NS}::entry $top.f.e -width 20 -textvariable reflistfilter
Paul Mackerras887c9962007-08-20 19:36:20 +100010036 set reflistfilter "*"
10037 trace add variable reflistfilter write reflistfilter_change
10038 pack $top.f.e -side right -fill x -expand 1
10039 pack $top.f.l -side left
10040 grid $top.f - -sticky ew -pady 2
Pat Thoytsd93f1712009-04-17 01:24:35 +010010041 ${NS}::button $top.close -command [list destroy $top] -text [mc "Close"]
Alexander Gavrilov76f15942008-11-02 21:59:44 +030010042 bind $top <Key-Escape> [list destroy $top]
Paul Mackerras887c9962007-08-20 19:36:20 +100010043 grid $top.close -
10044 grid columnconfigure $top 0 -weight 1
10045 grid rowconfigure $top 0 -weight 1
10046 bind $top.list <1> {break}
10047 bind $top.list <B1-Motion> {break}
10048 bind $top.list <ButtonRelease-1> {sel_reflist %W %x %y; break}
10049 set reflist {}
10050 refill_reflist
10051}
10052
10053proc sel_reflist {w x y} {
10054 global showrefstop reflist headids tagids otherrefids
10055
10056 if {![winfo exists $showrefstop]} return
10057 set l [lindex [split [$w index "@$x,$y"] "."] 0]
10058 set ref [lindex $reflist [expr {$l-1}]]
10059 set n [lindex $ref 0]
10060 switch -- [lindex $ref 1] {
10061 "H" {selbyid $headids($n)}
Paul Wised7cc4fb2019-03-21 15:05:32 +080010062 "R" {selbyid $headids($n)}
Paul Mackerras887c9962007-08-20 19:36:20 +100010063 "T" {selbyid $tagids($n)}
10064 "o" {selbyid $otherrefids($n)}
10065 }
10066 $showrefstop.list tag add highlight $l.0 "$l.0 lineend"
10067}
10068
10069proc unsel_reflist {} {
10070 global showrefstop
10071
10072 if {![info exists showrefstop] || ![winfo exists $showrefstop]} return
10073 $showrefstop.list tag remove highlight 0.0 end
10074}
10075
10076proc reflistfilter_change {n1 n2 op} {
10077 global reflistfilter
10078
10079 after cancel refill_reflist
10080 after 200 refill_reflist
10081}
10082
10083proc refill_reflist {} {
10084 global reflist reflistfilter showrefstop headids tagids otherrefids
Paul Mackerrasd375ef92008-10-21 10:18:12 +110010085 global curview
Paul Mackerras887c9962007-08-20 19:36:20 +100010086
10087 if {![info exists showrefstop] || ![winfo exists $showrefstop]} return
10088 set refs {}
10089 foreach n [array names headids] {
10090 if {[string match $reflistfilter $n]} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +110010091 if {[commitinview $headids($n) $curview]} {
Paul Wised7cc4fb2019-03-21 15:05:32 +080010092 if {[string match "remotes/*" $n]} {
10093 lappend refs [list $n R]
10094 } else {
10095 lappend refs [list $n H]
10096 }
Paul Mackerras887c9962007-08-20 19:36:20 +100010097 } else {
Paul Mackerrasd375ef92008-10-21 10:18:12 +110010098 interestedin $headids($n) {run refill_reflist}
Paul Mackerras887c9962007-08-20 19:36:20 +100010099 }
10100 }
10101 }
10102 foreach n [array names tagids] {
10103 if {[string match $reflistfilter $n]} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +110010104 if {[commitinview $tagids($n) $curview]} {
Paul Mackerras887c9962007-08-20 19:36:20 +100010105 lappend refs [list $n T]
10106 } else {
Paul Mackerrasd375ef92008-10-21 10:18:12 +110010107 interestedin $tagids($n) {run refill_reflist}
Paul Mackerras887c9962007-08-20 19:36:20 +100010108 }
10109 }
10110 }
10111 foreach n [array names otherrefids] {
10112 if {[string match $reflistfilter $n]} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +110010113 if {[commitinview $otherrefids($n) $curview]} {
Paul Mackerras887c9962007-08-20 19:36:20 +100010114 lappend refs [list $n o]
10115 } else {
Paul Mackerrasd375ef92008-10-21 10:18:12 +110010116 interestedin $otherrefids($n) {run refill_reflist}
Paul Mackerras887c9962007-08-20 19:36:20 +100010117 }
10118 }
10119 }
10120 set refs [lsort -index 0 $refs]
10121 if {$refs eq $reflist} return
10122
10123 # Update the contents of $showrefstop.list according to the
10124 # differences between $reflist (old) and $refs (new)
10125 $showrefstop.list conf -state normal
10126 $showrefstop.list insert end "\n"
10127 set i 0
10128 set j 0
10129 while {$i < [llength $reflist] || $j < [llength $refs]} {
10130 if {$i < [llength $reflist]} {
10131 if {$j < [llength $refs]} {
10132 set cmp [string compare [lindex $reflist $i 0] \
10133 [lindex $refs $j 0]]
10134 if {$cmp == 0} {
10135 set cmp [string compare [lindex $reflist $i 1] \
10136 [lindex $refs $j 1]]
10137 }
10138 } else {
10139 set cmp -1
10140 }
10141 } else {
10142 set cmp 1
10143 }
10144 switch -- $cmp {
10145 -1 {
10146 $showrefstop.list delete "[expr {$j+1}].0" "[expr {$j+2}].0"
10147 incr i
10148 }
10149 0 {
10150 incr i
10151 incr j
10152 }
10153 1 {
10154 set l [expr {$j + 1}]
10155 $showrefstop.list image create $l.0 -align baseline \
10156 -image reficon-[lindex $refs $j 1] -padx 2
10157 $showrefstop.list insert $l.1 "[lindex $refs $j 0]\n"
10158 incr j
10159 }
10160 }
10161 }
10162 set reflist $refs
10163 # delete last newline
10164 $showrefstop.list delete end-2c end-1c
10165 $showrefstop.list conf -state disabled
Paul Mackerras10299152006-08-02 09:52:01 +100010166}
10167
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +100010168# Stuff for finding nearby tags
10169proc getallcommits {} {
Paul Mackerras5cd15b62007-08-30 21:54:17 +100010170 global allcommits nextarc seeds allccache allcwait cachedarcs allcupdate
10171 global idheads idtags idotherrefs allparents tagobjid
Martin von Zweigbergkda616db2011-04-04 22:14:17 -040010172 global gitdir
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +100010173
Paul Mackerrasa69b2d12007-08-13 15:02:02 +100010174 if {![info exists allcommits]} {
Paul Mackerrasa69b2d12007-08-13 15:02:02 +100010175 set nextarc 0
10176 set allcommits 0
10177 set seeds {}
Paul Mackerras5cd15b62007-08-30 21:54:17 +100010178 set allcwait 0
10179 set cachedarcs 0
Martin von Zweigbergkda616db2011-04-04 22:14:17 -040010180 set allccache [file join $gitdir "gitk.cache"]
Paul Mackerras5cd15b62007-08-30 21:54:17 +100010181 if {![catch {
10182 set f [open $allccache r]
10183 set allcwait 1
10184 getcache $f
10185 }]} return
Paul Mackerrasa69b2d12007-08-13 15:02:02 +100010186 }
Paul Mackerrase11f1232007-06-16 20:29:25 +100010187
Paul Mackerras5cd15b62007-08-30 21:54:17 +100010188 if {$allcwait} {
10189 return
Paul Mackerrase11f1232007-06-16 20:29:25 +100010190 }
Paul Mackerras5cd15b62007-08-30 21:54:17 +100010191 set cmd [list | git rev-list --parents]
10192 set allcupdate [expr {$seeds ne {}}]
10193 if {!$allcupdate} {
10194 set ids "--all"
10195 } else {
10196 set refs [concat [array names idheads] [array names idtags] \
10197 [array names idotherrefs]]
10198 set ids {}
10199 set tagobjs {}
10200 foreach name [array names tagobjid] {
10201 lappend tagobjs $tagobjid($name)
10202 }
10203 foreach id [lsort -unique $refs] {
10204 if {![info exists allparents($id)] &&
10205 [lsearch -exact $tagobjs $id] < 0} {
10206 lappend ids $id
10207 }
10208 }
10209 if {$ids ne {}} {
10210 foreach id $seeds {
10211 lappend ids "^$id"
10212 }
10213 }
10214 }
10215 if {$ids ne {}} {
10216 set fd [open [concat $cmd $ids] r]
10217 fconfigure $fd -blocking 0
10218 incr allcommits
10219 nowbusy allcommits
10220 filerun $fd [list getallclines $fd]
10221 } else {
10222 dispneartags 0
10223 }
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +100010224}
10225
Paul Mackerrase11f1232007-06-16 20:29:25 +100010226# Since most commits have 1 parent and 1 child, we group strings of
10227# such commits into "arcs" joining branch/merge points (BMPs), which
10228# are commits that either don't have 1 parent or don't have 1 child.
10229#
10230# arcnos(id) - incoming arcs for BMP, arc we're on for other nodes
10231# arcout(id) - outgoing arcs for BMP
10232# arcids(a) - list of IDs on arc including end but not start
10233# arcstart(a) - BMP ID at start of arc
10234# arcend(a) - BMP ID at end of arc
10235# growing(a) - arc a is still growing
10236# arctags(a) - IDs out of arcids (excluding end) that have tags
10237# archeads(a) - IDs out of arcids (excluding end) that have heads
10238# The start of an arc is at the descendent end, so "incoming" means
10239# coming from descendents, and "outgoing" means going towards ancestors.
Paul Mackerrascec7bec2006-08-02 09:38:10 +100010240
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +100010241proc getallclines {fd} {
Paul Mackerras5cd15b62007-08-30 21:54:17 +100010242 global allparents allchildren idtags idheads nextarc
Paul Mackerrase11f1232007-06-16 20:29:25 +100010243 global arcnos arcids arctags arcout arcend arcstart archeads growing
Paul Mackerras5cd15b62007-08-30 21:54:17 +100010244 global seeds allcommits cachedarcs allcupdate
Pat Thoytsd93f1712009-04-17 01:24:35 +010010245
Paul Mackerrase11f1232007-06-16 20:29:25 +100010246 set nid 0
Paul Mackerras7eb3cb92007-06-17 14:45:00 +100010247 while {[incr nid] <= 1000 && [gets $fd line] >= 0} {
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +100010248 set id [lindex $line 0]
Paul Mackerrase11f1232007-06-16 20:29:25 +100010249 if {[info exists allparents($id)]} {
10250 # seen it already
10251 continue
10252 }
Paul Mackerras5cd15b62007-08-30 21:54:17 +100010253 set cachedarcs 0
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +100010254 set olds [lrange $line 1 end]
10255 set allparents($id) $olds
10256 if {![info exists allchildren($id)]} {
10257 set allchildren($id) {}
Paul Mackerrase11f1232007-06-16 20:29:25 +100010258 set arcnos($id) {}
10259 lappend seeds $id
10260 } else {
10261 set a $arcnos($id)
10262 if {[llength $olds] == 1 && [llength $a] == 1} {
10263 lappend arcids($a) $id
10264 if {[info exists idtags($id)]} {
10265 lappend arctags($a) $id
10266 }
10267 if {[info exists idheads($id)]} {
10268 lappend archeads($a) $id
10269 }
10270 if {[info exists allparents($olds)]} {
10271 # seen parent already
10272 if {![info exists arcout($olds)]} {
10273 splitarc $olds
10274 }
10275 lappend arcids($a) $olds
10276 set arcend($a) $olds
10277 unset growing($a)
10278 }
10279 lappend allchildren($olds) $id
10280 lappend arcnos($olds) $a
10281 continue
10282 }
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +100010283 }
Paul Mackerrase11f1232007-06-16 20:29:25 +100010284 foreach a $arcnos($id) {
10285 lappend arcids($a) $id
10286 set arcend($a) $id
10287 unset growing($a)
10288 }
10289
10290 set ao {}
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +100010291 foreach p $olds {
10292 lappend allchildren($p) $id
Paul Mackerrase11f1232007-06-16 20:29:25 +100010293 set a [incr nextarc]
10294 set arcstart($a) $id
10295 set archeads($a) {}
10296 set arctags($a) {}
10297 set archeads($a) {}
10298 set arcids($a) {}
10299 lappend ao $a
10300 set growing($a) 1
10301 if {[info exists allparents($p)]} {
10302 # seen it already, may need to make a new branch
10303 if {![info exists arcout($p)]} {
10304 splitarc $p
10305 }
10306 lappend arcids($a) $p
10307 set arcend($a) $p
10308 unset growing($a)
10309 }
10310 lappend arcnos($p) $a
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +100010311 }
Paul Mackerrase11f1232007-06-16 20:29:25 +100010312 set arcout($id) $ao
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +100010313 }
Paul Mackerrasf3326b62007-06-18 22:39:21 +100010314 if {$nid > 0} {
10315 global cached_dheads cached_dtags cached_atags
Paul Mackerras009409f2015-05-02 20:53:36 +100010316 unset -nocomplain cached_dheads
10317 unset -nocomplain cached_dtags
10318 unset -nocomplain cached_atags
Paul Mackerrasf3326b62007-06-18 22:39:21 +100010319 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +100010320 if {![eof $fd]} {
10321 return [expr {$nid >= 1000? 2: 1}]
10322 }
Paul Mackerras5cd15b62007-08-30 21:54:17 +100010323 set cacheok 1
10324 if {[catch {
10325 fconfigure $fd -blocking 1
10326 close $fd
10327 } err]} {
10328 # got an error reading the list of commits
10329 # if we were updating, try rereading the whole thing again
10330 if {$allcupdate} {
10331 incr allcommits -1
10332 dropcache $err
10333 return
10334 }
Christian Stimmingd990ced2007-11-07 18:42:55 +010010335 error_popup "[mc "Error reading commit topology information;\
Paul Mackerras5cd15b62007-08-30 21:54:17 +100010336 branch and preceding/following tag information\
Christian Stimmingd990ced2007-11-07 18:42:55 +010010337 will be incomplete."]\n($err)"
Paul Mackerras5cd15b62007-08-30 21:54:17 +100010338 set cacheok 0
10339 }
Paul Mackerrase11f1232007-06-16 20:29:25 +100010340 if {[incr allcommits -1] == 0} {
10341 notbusy allcommits
Paul Mackerras5cd15b62007-08-30 21:54:17 +100010342 if {$cacheok} {
10343 run savecache
10344 }
Paul Mackerrase11f1232007-06-16 20:29:25 +100010345 }
10346 dispneartags 0
Paul Mackerras7eb3cb92007-06-17 14:45:00 +100010347 return 0
Paul Mackerrase11f1232007-06-16 20:29:25 +100010348}
10349
10350proc recalcarc {a} {
10351 global arctags archeads arcids idtags idheads
10352
10353 set at {}
10354 set ah {}
10355 foreach id [lrange $arcids($a) 0 end-1] {
10356 if {[info exists idtags($id)]} {
10357 lappend at $id
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +100010358 }
Paul Mackerrase11f1232007-06-16 20:29:25 +100010359 if {[info exists idheads($id)]} {
10360 lappend ah $id
10361 }
10362 }
10363 set arctags($a) $at
10364 set archeads($a) $ah
10365}
10366
10367proc splitarc {p} {
Paul Mackerras5cd15b62007-08-30 21:54:17 +100010368 global arcnos arcids nextarc arctags archeads idtags idheads
Paul Mackerrase11f1232007-06-16 20:29:25 +100010369 global arcstart arcend arcout allparents growing
10370
10371 set a $arcnos($p)
10372 if {[llength $a] != 1} {
10373 puts "oops splitarc called but [llength $a] arcs already"
10374 return
10375 }
10376 set a [lindex $a 0]
10377 set i [lsearch -exact $arcids($a) $p]
10378 if {$i < 0} {
10379 puts "oops splitarc $p not in arc $a"
10380 return
10381 }
10382 set na [incr nextarc]
10383 if {[info exists arcend($a)]} {
10384 set arcend($na) $arcend($a)
10385 } else {
10386 set l [lindex $allparents([lindex $arcids($a) end]) 0]
10387 set j [lsearch -exact $arcnos($l) $a]
10388 set arcnos($l) [lreplace $arcnos($l) $j $j $na]
10389 }
10390 set tail [lrange $arcids($a) [expr {$i+1}] end]
10391 set arcids($a) [lrange $arcids($a) 0 $i]
10392 set arcend($a) $p
10393 set arcstart($na) $p
10394 set arcout($p) $na
10395 set arcids($na) $tail
10396 if {[info exists growing($a)]} {
10397 set growing($na) 1
10398 unset growing($a)
10399 }
Paul Mackerrase11f1232007-06-16 20:29:25 +100010400
10401 foreach id $tail {
10402 if {[llength $arcnos($id)] == 1} {
10403 set arcnos($id) $na
10404 } else {
10405 set j [lsearch -exact $arcnos($id) $a]
10406 set arcnos($id) [lreplace $arcnos($id) $j $j $na]
10407 }
10408 }
10409
10410 # reconstruct tags and heads lists
10411 if {$arctags($a) ne {} || $archeads($a) ne {}} {
10412 recalcarc $a
10413 recalcarc $na
10414 } else {
10415 set arctags($na) {}
10416 set archeads($na) {}
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +100010417 }
10418}
10419
Paul Mackerrase11f1232007-06-16 20:29:25 +100010420# Update things for a new commit added that is a child of one
10421# existing commit. Used when cherry-picking.
10422proc addnewchild {id p} {
Paul Mackerras5cd15b62007-08-30 21:54:17 +100010423 global allparents allchildren idtags nextarc
Paul Mackerrase11f1232007-06-16 20:29:25 +100010424 global arcnos arcids arctags arcout arcend arcstart archeads growing
Paul Mackerras719c2b92007-08-29 22:41:34 +100010425 global seeds allcommits
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +100010426
Paul Mackerras3ebba3c2007-10-20 22:10:52 +100010427 if {![info exists allcommits] || ![info exists arcnos($p)]} return
Paul Mackerrase11f1232007-06-16 20:29:25 +100010428 set allparents($id) [list $p]
10429 set allchildren($id) {}
10430 set arcnos($id) {}
10431 lappend seeds $id
Paul Mackerrase11f1232007-06-16 20:29:25 +100010432 lappend allchildren($p) $id
10433 set a [incr nextarc]
10434 set arcstart($a) $id
10435 set archeads($a) {}
10436 set arctags($a) {}
10437 set arcids($a) [list $p]
10438 set arcend($a) $p
10439 if {![info exists arcout($p)]} {
10440 splitarc $p
10441 }
10442 lappend arcnos($p) $a
10443 set arcout($id) [list $a]
10444}
10445
Paul Mackerras5cd15b62007-08-30 21:54:17 +100010446# This implements a cache for the topology information.
10447# The cache saves, for each arc, the start and end of the arc,
10448# the ids on the arc, and the outgoing arcs from the end.
10449proc readcache {f} {
10450 global arcnos arcids arcout arcstart arcend arctags archeads nextarc
10451 global idtags idheads allparents cachedarcs possible_seeds seeds growing
10452 global allcwait
10453
10454 set a $nextarc
10455 set lim $cachedarcs
10456 if {$lim - $a > 500} {
10457 set lim [expr {$a + 500}]
10458 }
10459 if {[catch {
10460 if {$a == $lim} {
10461 # finish reading the cache and setting up arctags, etc.
10462 set line [gets $f]
10463 if {$line ne "1"} {error "bad final version"}
10464 close $f
10465 foreach id [array names idtags] {
10466 if {[info exists arcnos($id)] && [llength $arcnos($id)] == 1 &&
10467 [llength $allparents($id)] == 1} {
10468 set a [lindex $arcnos($id) 0]
10469 if {$arctags($a) eq {}} {
10470 recalcarc $a
10471 }
10472 }
10473 }
10474 foreach id [array names idheads] {
10475 if {[info exists arcnos($id)] && [llength $arcnos($id)] == 1 &&
10476 [llength $allparents($id)] == 1} {
10477 set a [lindex $arcnos($id) 0]
10478 if {$archeads($a) eq {}} {
10479 recalcarc $a
10480 }
10481 }
10482 }
10483 foreach id [lsort -unique $possible_seeds] {
10484 if {$arcnos($id) eq {}} {
10485 lappend seeds $id
10486 }
10487 }
10488 set allcwait 0
10489 } else {
10490 while {[incr a] <= $lim} {
10491 set line [gets $f]
10492 if {[llength $line] != 3} {error "bad line"}
10493 set s [lindex $line 0]
10494 set arcstart($a) $s
10495 lappend arcout($s) $a
10496 if {![info exists arcnos($s)]} {
10497 lappend possible_seeds $s
10498 set arcnos($s) {}
10499 }
10500 set e [lindex $line 1]
10501 if {$e eq {}} {
10502 set growing($a) 1
10503 } else {
10504 set arcend($a) $e
10505 if {![info exists arcout($e)]} {
10506 set arcout($e) {}
10507 }
10508 }
10509 set arcids($a) [lindex $line 2]
10510 foreach id $arcids($a) {
10511 lappend allparents($s) $id
10512 set s $id
10513 lappend arcnos($id) $a
10514 }
10515 if {![info exists allparents($s)]} {
10516 set allparents($s) {}
10517 }
10518 set arctags($a) {}
10519 set archeads($a) {}
10520 }
10521 set nextarc [expr {$a - 1}]
10522 }
10523 } err]} {
10524 dropcache $err
10525 return 0
10526 }
10527 if {!$allcwait} {
10528 getallcommits
10529 }
10530 return $allcwait
10531}
10532
10533proc getcache {f} {
10534 global nextarc cachedarcs possible_seeds
10535
10536 if {[catch {
10537 set line [gets $f]
10538 if {[llength $line] != 2 || [lindex $line 0] ne "1"} {error "bad version"}
10539 # make sure it's an integer
10540 set cachedarcs [expr {int([lindex $line 1])}]
10541 if {$cachedarcs < 0} {error "bad number of arcs"}
10542 set nextarc 0
10543 set possible_seeds {}
10544 run readcache $f
10545 } err]} {
10546 dropcache $err
10547 }
10548 return 0
10549}
10550
10551proc dropcache {err} {
10552 global allcwait nextarc cachedarcs seeds
10553
10554 #puts "dropping cache ($err)"
10555 foreach v {arcnos arcout arcids arcstart arcend growing \
10556 arctags archeads allparents allchildren} {
10557 global $v
Paul Mackerras009409f2015-05-02 20:53:36 +100010558 unset -nocomplain $v
Paul Mackerras5cd15b62007-08-30 21:54:17 +100010559 }
10560 set allcwait 0
10561 set nextarc 0
10562 set cachedarcs 0
10563 set seeds {}
10564 getallcommits
10565}
10566
10567proc writecache {f} {
10568 global cachearc cachedarcs allccache
10569 global arcstart arcend arcnos arcids arcout
10570
10571 set a $cachearc
10572 set lim $cachedarcs
10573 if {$lim - $a > 1000} {
10574 set lim [expr {$a + 1000}]
10575 }
10576 if {[catch {
10577 while {[incr a] <= $lim} {
10578 if {[info exists arcend($a)]} {
10579 puts $f [list $arcstart($a) $arcend($a) $arcids($a)]
10580 } else {
10581 puts $f [list $arcstart($a) {} $arcids($a)]
10582 }
10583 }
10584 } err]} {
10585 catch {close $f}
10586 catch {file delete $allccache}
10587 #puts "writing cache failed ($err)"
10588 return 0
10589 }
10590 set cachearc [expr {$a - 1}]
10591 if {$a > $cachedarcs} {
10592 puts $f "1"
10593 close $f
10594 return 0
10595 }
10596 return 1
10597}
10598
10599proc savecache {} {
10600 global nextarc cachedarcs cachearc allccache
10601
10602 if {$nextarc == $cachedarcs} return
10603 set cachearc 0
10604 set cachedarcs $nextarc
10605 catch {
10606 set f [open $allccache w]
10607 puts $f [list 1 $cachedarcs]
10608 run writecache $f
10609 }
10610}
10611
Paul Mackerrase11f1232007-06-16 20:29:25 +100010612# Returns 1 if a is an ancestor of b, -1 if b is an ancestor of a,
10613# or 0 if neither is true.
10614proc anc_or_desc {a b} {
10615 global arcout arcstart arcend arcnos cached_isanc
10616
10617 if {$arcnos($a) eq $arcnos($b)} {
10618 # Both are on the same arc(s); either both are the same BMP,
10619 # or if one is not a BMP, the other is also not a BMP or is
10620 # the BMP at end of the arc (and it only has 1 incoming arc).
Paul Mackerras69c0b5d2007-07-04 21:57:04 +100010621 # Or both can be BMPs with no incoming arcs.
10622 if {$a eq $b || $arcnos($a) eq {}} {
Paul Mackerrase11f1232007-06-16 20:29:25 +100010623 return 0
10624 }
10625 # assert {[llength $arcnos($a)] == 1}
10626 set arc [lindex $arcnos($a) 0]
10627 set i [lsearch -exact $arcids($arc) $a]
10628 set j [lsearch -exact $arcids($arc) $b]
10629 if {$i < 0 || $i > $j} {
10630 return 1
10631 } else {
10632 return -1
10633 }
10634 }
10635
10636 if {![info exists arcout($a)]} {
10637 set arc [lindex $arcnos($a) 0]
10638 if {[info exists arcend($arc)]} {
10639 set aend $arcend($arc)
10640 } else {
10641 set aend {}
10642 }
10643 set a $arcstart($arc)
10644 } else {
10645 set aend $a
10646 }
10647 if {![info exists arcout($b)]} {
10648 set arc [lindex $arcnos($b) 0]
10649 if {[info exists arcend($arc)]} {
10650 set bend $arcend($arc)
10651 } else {
10652 set bend {}
10653 }
10654 set b $arcstart($arc)
10655 } else {
10656 set bend $b
10657 }
10658 if {$a eq $bend} {
10659 return 1
10660 }
10661 if {$b eq $aend} {
10662 return -1
10663 }
10664 if {[info exists cached_isanc($a,$bend)]} {
10665 if {$cached_isanc($a,$bend)} {
10666 return 1
10667 }
10668 }
10669 if {[info exists cached_isanc($b,$aend)]} {
10670 if {$cached_isanc($b,$aend)} {
10671 return -1
10672 }
10673 if {[info exists cached_isanc($a,$bend)]} {
10674 return 0
10675 }
10676 }
10677
10678 set todo [list $a $b]
10679 set anc($a) a
10680 set anc($b) b
10681 for {set i 0} {$i < [llength $todo]} {incr i} {
10682 set x [lindex $todo $i]
10683 if {$anc($x) eq {}} {
10684 continue
10685 }
10686 foreach arc $arcnos($x) {
10687 set xd $arcstart($arc)
10688 if {$xd eq $bend} {
10689 set cached_isanc($a,$bend) 1
10690 set cached_isanc($b,$aend) 0
10691 return 1
10692 } elseif {$xd eq $aend} {
10693 set cached_isanc($b,$aend) 1
10694 set cached_isanc($a,$bend) 0
10695 return -1
10696 }
10697 if {![info exists anc($xd)]} {
10698 set anc($xd) $anc($x)
10699 lappend todo $xd
10700 } elseif {$anc($xd) ne $anc($x)} {
10701 set anc($xd) {}
10702 }
10703 }
10704 }
10705 set cached_isanc($a,$bend) 0
10706 set cached_isanc($b,$aend) 0
10707 return 0
10708}
10709
10710# This identifies whether $desc has an ancestor that is
10711# a growing tip of the graph and which is not an ancestor of $anc
10712# and returns 0 if so and 1 if not.
10713# If we subsequently discover a tag on such a growing tip, and that
10714# turns out to be a descendent of $anc (which it could, since we
10715# don't necessarily see children before parents), then $desc
10716# isn't a good choice to display as a descendent tag of
10717# $anc (since it is the descendent of another tag which is
10718# a descendent of $anc). Similarly, $anc isn't a good choice to
10719# display as a ancestor tag of $desc.
10720#
10721proc is_certain {desc anc} {
10722 global arcnos arcout arcstart arcend growing problems
10723
10724 set certain {}
10725 if {[llength $arcnos($anc)] == 1} {
10726 # tags on the same arc are certain
10727 if {$arcnos($desc) eq $arcnos($anc)} {
10728 return 1
10729 }
10730 if {![info exists arcout($anc)]} {
10731 # if $anc is partway along an arc, use the start of the arc instead
10732 set a [lindex $arcnos($anc) 0]
10733 set anc $arcstart($a)
10734 }
10735 }
10736 if {[llength $arcnos($desc)] > 1 || [info exists arcout($desc)]} {
10737 set x $desc
10738 } else {
10739 set a [lindex $arcnos($desc) 0]
10740 set x $arcend($a)
10741 }
10742 if {$x == $anc} {
10743 return 1
10744 }
10745 set anclist [list $x]
10746 set dl($x) 1
10747 set nnh 1
10748 set ngrowanc 0
10749 for {set i 0} {$i < [llength $anclist] && ($nnh > 0 || $ngrowanc > 0)} {incr i} {
10750 set x [lindex $anclist $i]
10751 if {$dl($x)} {
10752 incr nnh -1
10753 }
10754 set done($x) 1
10755 foreach a $arcout($x) {
10756 if {[info exists growing($a)]} {
10757 if {![info exists growanc($x)] && $dl($x)} {
10758 set growanc($x) 1
10759 incr ngrowanc
10760 }
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +100010761 } else {
Paul Mackerrase11f1232007-06-16 20:29:25 +100010762 set y $arcend($a)
10763 if {[info exists dl($y)]} {
10764 if {$dl($y)} {
10765 if {!$dl($x)} {
10766 set dl($y) 0
10767 if {![info exists done($y)]} {
10768 incr nnh -1
10769 }
10770 if {[info exists growanc($x)]} {
10771 incr ngrowanc -1
10772 }
10773 set xl [list $y]
10774 for {set k 0} {$k < [llength $xl]} {incr k} {
10775 set z [lindex $xl $k]
10776 foreach c $arcout($z) {
10777 if {[info exists arcend($c)]} {
10778 set v $arcend($c)
10779 if {[info exists dl($v)] && $dl($v)} {
10780 set dl($v) 0
10781 if {![info exists done($v)]} {
10782 incr nnh -1
10783 }
10784 if {[info exists growanc($v)]} {
10785 incr ngrowanc -1
10786 }
10787 lappend xl $v
10788 }
10789 }
10790 }
10791 }
10792 }
10793 }
10794 } elseif {$y eq $anc || !$dl($x)} {
10795 set dl($y) 0
10796 lappend anclist $y
10797 } else {
10798 set dl($y) 1
10799 lappend anclist $y
10800 incr nnh
10801 }
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +100010802 }
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +100010803 }
10804 }
Paul Mackerrase11f1232007-06-16 20:29:25 +100010805 foreach x [array names growanc] {
10806 if {$dl($x)} {
10807 return 0
10808 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +100010809 return 0
Paul Mackerrase11f1232007-06-16 20:29:25 +100010810 }
10811 return 1
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +100010812}
10813
Paul Mackerrase11f1232007-06-16 20:29:25 +100010814proc validate_arctags {a} {
10815 global arctags idtags
10816
10817 set i -1
10818 set na $arctags($a)
10819 foreach id $arctags($a) {
10820 incr i
10821 if {![info exists idtags($id)]} {
10822 set na [lreplace $na $i $i]
10823 incr i -1
10824 }
10825 }
10826 set arctags($a) $na
10827}
10828
10829proc validate_archeads {a} {
10830 global archeads idheads
10831
10832 set i -1
10833 set na $archeads($a)
10834 foreach id $archeads($a) {
10835 incr i
10836 if {![info exists idheads($id)]} {
10837 set na [lreplace $na $i $i]
10838 incr i -1
10839 }
10840 }
10841 set archeads($a) $na
10842}
10843
10844# Return the list of IDs that have tags that are descendents of id,
10845# ignoring IDs that are descendents of IDs already reported.
10846proc desctags {id} {
10847 global arcnos arcstart arcids arctags idtags allparents
10848 global growing cached_dtags
10849
10850 if {![info exists allparents($id)]} {
10851 return {}
10852 }
10853 set t1 [clock clicks -milliseconds]
10854 set argid $id
10855 if {[llength $arcnos($id)] == 1 && [llength $allparents($id)] == 1} {
10856 # part-way along an arc; check that arc first
10857 set a [lindex $arcnos($id) 0]
10858 if {$arctags($a) ne {}} {
10859 validate_arctags $a
10860 set i [lsearch -exact $arcids($a) $id]
10861 set tid {}
10862 foreach t $arctags($a) {
10863 set j [lsearch -exact $arcids($a) $t]
10864 if {$j >= $i} break
10865 set tid $t
10866 }
10867 if {$tid ne {}} {
10868 return $tid
10869 }
10870 }
10871 set id $arcstart($a)
10872 if {[info exists idtags($id)]} {
10873 return $id
10874 }
10875 }
10876 if {[info exists cached_dtags($id)]} {
10877 return $cached_dtags($id)
10878 }
10879
10880 set origid $id
10881 set todo [list $id]
10882 set queued($id) 1
10883 set nc 1
10884 for {set i 0} {$i < [llength $todo] && $nc > 0} {incr i} {
10885 set id [lindex $todo $i]
10886 set done($id) 1
10887 set ta [info exists hastaggedancestor($id)]
10888 if {!$ta} {
10889 incr nc -1
10890 }
10891 # ignore tags on starting node
10892 if {!$ta && $i > 0} {
10893 if {[info exists idtags($id)]} {
10894 set tagloc($id) $id
10895 set ta 1
10896 } elseif {[info exists cached_dtags($id)]} {
10897 set tagloc($id) $cached_dtags($id)
10898 set ta 1
10899 }
10900 }
10901 foreach a $arcnos($id) {
10902 set d $arcstart($a)
10903 if {!$ta && $arctags($a) ne {}} {
10904 validate_arctags $a
10905 if {$arctags($a) ne {}} {
10906 lappend tagloc($id) [lindex $arctags($a) end]
10907 }
10908 }
10909 if {$ta || $arctags($a) ne {}} {
10910 set tomark [list $d]
10911 for {set j 0} {$j < [llength $tomark]} {incr j} {
10912 set dd [lindex $tomark $j]
10913 if {![info exists hastaggedancestor($dd)]} {
10914 if {[info exists done($dd)]} {
10915 foreach b $arcnos($dd) {
10916 lappend tomark $arcstart($b)
10917 }
10918 if {[info exists tagloc($dd)]} {
10919 unset tagloc($dd)
10920 }
10921 } elseif {[info exists queued($dd)]} {
10922 incr nc -1
10923 }
10924 set hastaggedancestor($dd) 1
10925 }
10926 }
10927 }
10928 if {![info exists queued($d)]} {
10929 lappend todo $d
10930 set queued($d) 1
10931 if {![info exists hastaggedancestor($d)]} {
10932 incr nc
10933 }
10934 }
10935 }
10936 }
10937 set tags {}
10938 foreach id [array names tagloc] {
10939 if {![info exists hastaggedancestor($id)]} {
10940 foreach t $tagloc($id) {
10941 if {[lsearch -exact $tags $t] < 0} {
10942 lappend tags $t
10943 }
10944 }
10945 }
10946 }
10947 set t2 [clock clicks -milliseconds]
10948 set loopix $i
10949
10950 # remove tags that are descendents of other tags
10951 for {set i 0} {$i < [llength $tags]} {incr i} {
10952 set a [lindex $tags $i]
10953 for {set j 0} {$j < $i} {incr j} {
10954 set b [lindex $tags $j]
10955 set r [anc_or_desc $a $b]
10956 if {$r == 1} {
10957 set tags [lreplace $tags $j $j]
10958 incr j -1
10959 incr i -1
10960 } elseif {$r == -1} {
10961 set tags [lreplace $tags $i $i]
10962 incr i -1
10963 break
10964 }
10965 }
10966 }
10967
10968 if {[array names growing] ne {}} {
10969 # graph isn't finished, need to check if any tag could get
10970 # eclipsed by another tag coming later. Simply ignore any
10971 # tags that could later get eclipsed.
10972 set ctags {}
10973 foreach t $tags {
10974 if {[is_certain $t $origid]} {
10975 lappend ctags $t
10976 }
10977 }
10978 if {$tags eq $ctags} {
10979 set cached_dtags($origid) $tags
10980 } else {
10981 set tags $ctags
10982 }
10983 } else {
10984 set cached_dtags($origid) $tags
10985 }
10986 set t3 [clock clicks -milliseconds]
10987 if {0 && $t3 - $t1 >= 100} {
10988 puts "iterating descendents ($loopix/[llength $todo] nodes) took\
10989 [expr {$t2-$t1}]+[expr {$t3-$t2}]ms, $nc candidates left"
10990 }
10991 return $tags
10992}
10993
10994proc anctags {id} {
10995 global arcnos arcids arcout arcend arctags idtags allparents
10996 global growing cached_atags
10997
10998 if {![info exists allparents($id)]} {
10999 return {}
11000 }
11001 set t1 [clock clicks -milliseconds]
11002 set argid $id
11003 if {[llength $arcnos($id)] == 1 && [llength $allparents($id)] == 1} {
11004 # part-way along an arc; check that arc first
11005 set a [lindex $arcnos($id) 0]
11006 if {$arctags($a) ne {}} {
11007 validate_arctags $a
11008 set i [lsearch -exact $arcids($a) $id]
11009 foreach t $arctags($a) {
11010 set j [lsearch -exact $arcids($a) $t]
11011 if {$j > $i} {
11012 return $t
11013 }
11014 }
11015 }
11016 if {![info exists arcend($a)]} {
11017 return {}
11018 }
11019 set id $arcend($a)
11020 if {[info exists idtags($id)]} {
11021 return $id
11022 }
11023 }
11024 if {[info exists cached_atags($id)]} {
11025 return $cached_atags($id)
11026 }
11027
11028 set origid $id
11029 set todo [list $id]
11030 set queued($id) 1
11031 set taglist {}
11032 set nc 1
11033 for {set i 0} {$i < [llength $todo] && $nc > 0} {incr i} {
11034 set id [lindex $todo $i]
11035 set done($id) 1
11036 set td [info exists hastaggeddescendent($id)]
11037 if {!$td} {
11038 incr nc -1
11039 }
11040 # ignore tags on starting node
11041 if {!$td && $i > 0} {
11042 if {[info exists idtags($id)]} {
11043 set tagloc($id) $id
11044 set td 1
11045 } elseif {[info exists cached_atags($id)]} {
11046 set tagloc($id) $cached_atags($id)
11047 set td 1
11048 }
11049 }
11050 foreach a $arcout($id) {
11051 if {!$td && $arctags($a) ne {}} {
11052 validate_arctags $a
11053 if {$arctags($a) ne {}} {
11054 lappend tagloc($id) [lindex $arctags($a) 0]
11055 }
11056 }
11057 if {![info exists arcend($a)]} continue
11058 set d $arcend($a)
11059 if {$td || $arctags($a) ne {}} {
11060 set tomark [list $d]
11061 for {set j 0} {$j < [llength $tomark]} {incr j} {
11062 set dd [lindex $tomark $j]
11063 if {![info exists hastaggeddescendent($dd)]} {
11064 if {[info exists done($dd)]} {
11065 foreach b $arcout($dd) {
11066 if {[info exists arcend($b)]} {
11067 lappend tomark $arcend($b)
11068 }
11069 }
11070 if {[info exists tagloc($dd)]} {
11071 unset tagloc($dd)
11072 }
11073 } elseif {[info exists queued($dd)]} {
11074 incr nc -1
11075 }
11076 set hastaggeddescendent($dd) 1
11077 }
11078 }
11079 }
11080 if {![info exists queued($d)]} {
11081 lappend todo $d
11082 set queued($d) 1
11083 if {![info exists hastaggeddescendent($d)]} {
11084 incr nc
11085 }
11086 }
11087 }
11088 }
11089 set t2 [clock clicks -milliseconds]
11090 set loopix $i
11091 set tags {}
11092 foreach id [array names tagloc] {
11093 if {![info exists hastaggeddescendent($id)]} {
11094 foreach t $tagloc($id) {
11095 if {[lsearch -exact $tags $t] < 0} {
11096 lappend tags $t
11097 }
11098 }
11099 }
11100 }
11101
11102 # remove tags that are ancestors of other tags
11103 for {set i 0} {$i < [llength $tags]} {incr i} {
11104 set a [lindex $tags $i]
11105 for {set j 0} {$j < $i} {incr j} {
11106 set b [lindex $tags $j]
11107 set r [anc_or_desc $a $b]
11108 if {$r == -1} {
11109 set tags [lreplace $tags $j $j]
11110 incr j -1
11111 incr i -1
11112 } elseif {$r == 1} {
11113 set tags [lreplace $tags $i $i]
11114 incr i -1
11115 break
11116 }
11117 }
11118 }
11119
11120 if {[array names growing] ne {}} {
11121 # graph isn't finished, need to check if any tag could get
11122 # eclipsed by another tag coming later. Simply ignore any
11123 # tags that could later get eclipsed.
11124 set ctags {}
11125 foreach t $tags {
11126 if {[is_certain $origid $t]} {
11127 lappend ctags $t
11128 }
11129 }
11130 if {$tags eq $ctags} {
11131 set cached_atags($origid) $tags
11132 } else {
11133 set tags $ctags
11134 }
11135 } else {
11136 set cached_atags($origid) $tags
11137 }
11138 set t3 [clock clicks -milliseconds]
11139 if {0 && $t3 - $t1 >= 100} {
11140 puts "iterating ancestors ($loopix/[llength $todo] nodes) took\
11141 [expr {$t2-$t1}]+[expr {$t3-$t2}]ms, $nc candidates left"
11142 }
11143 return $tags
11144}
11145
11146# Return the list of IDs that have heads that are descendents of id,
11147# including id itself if it has a head.
11148proc descheads {id} {
11149 global arcnos arcstart arcids archeads idheads cached_dheads
Paul Mackerrasd809fb12013-01-01 16:51:03 +110011150 global allparents arcout
Paul Mackerrase11f1232007-06-16 20:29:25 +100011151
11152 if {![info exists allparents($id)]} {
11153 return {}
11154 }
Paul Mackerrasf3326b62007-06-18 22:39:21 +100011155 set aret {}
Paul Mackerrasd809fb12013-01-01 16:51:03 +110011156 if {![info exists arcout($id)]} {
Paul Mackerrase11f1232007-06-16 20:29:25 +100011157 # part-way along an arc; check it first
11158 set a [lindex $arcnos($id) 0]
11159 if {$archeads($a) ne {}} {
11160 validate_archeads $a
11161 set i [lsearch -exact $arcids($a) $id]
11162 foreach t $archeads($a) {
11163 set j [lsearch -exact $arcids($a) $t]
11164 if {$j > $i} break
Paul Mackerrasf3326b62007-06-18 22:39:21 +100011165 lappend aret $t
Paul Mackerrase11f1232007-06-16 20:29:25 +100011166 }
11167 }
11168 set id $arcstart($a)
11169 }
11170 set origid $id
11171 set todo [list $id]
11172 set seen($id) 1
Paul Mackerrasf3326b62007-06-18 22:39:21 +100011173 set ret {}
Paul Mackerrase11f1232007-06-16 20:29:25 +100011174 for {set i 0} {$i < [llength $todo]} {incr i} {
11175 set id [lindex $todo $i]
11176 if {[info exists cached_dheads($id)]} {
11177 set ret [concat $ret $cached_dheads($id)]
11178 } else {
11179 if {[info exists idheads($id)]} {
11180 lappend ret $id
11181 }
11182 foreach a $arcnos($id) {
11183 if {$archeads($a) ne {}} {
Paul Mackerras706d6c32007-06-26 11:09:49 +100011184 validate_archeads $a
11185 if {$archeads($a) ne {}} {
11186 set ret [concat $ret $archeads($a)]
11187 }
Paul Mackerrase11f1232007-06-16 20:29:25 +100011188 }
11189 set d $arcstart($a)
11190 if {![info exists seen($d)]} {
11191 lappend todo $d
11192 set seen($d) 1
11193 }
11194 }
11195 }
11196 }
11197 set ret [lsort -unique $ret]
11198 set cached_dheads($origid) $ret
Paul Mackerrasf3326b62007-06-18 22:39:21 +100011199 return [concat $ret $aret]
Paul Mackerrase11f1232007-06-16 20:29:25 +100011200}
11201
Paul Mackerrasceadfe92006-08-08 20:55:36 +100011202proc addedtag {id} {
Paul Mackerrase11f1232007-06-16 20:29:25 +100011203 global arcnos arcout cached_dtags cached_atags
Paul Mackerrasceadfe92006-08-08 20:55:36 +100011204
Paul Mackerrase11f1232007-06-16 20:29:25 +100011205 if {![info exists arcnos($id)]} return
11206 if {![info exists arcout($id)]} {
11207 recalcarc [lindex $arcnos($id) 0]
Paul Mackerrasceadfe92006-08-08 20:55:36 +100011208 }
Paul Mackerras009409f2015-05-02 20:53:36 +100011209 unset -nocomplain cached_dtags
11210 unset -nocomplain cached_atags
Paul Mackerrasceadfe92006-08-08 20:55:36 +100011211}
11212
Paul Mackerrasca6d8f52006-08-06 21:08:05 +100011213proc addedhead {hid head} {
Paul Mackerrase11f1232007-06-16 20:29:25 +100011214 global arcnos arcout cached_dheads
Paul Mackerrasca6d8f52006-08-06 21:08:05 +100011215
Paul Mackerrase11f1232007-06-16 20:29:25 +100011216 if {![info exists arcnos($hid)]} return
11217 if {![info exists arcout($hid)]} {
11218 recalcarc [lindex $arcnos($hid) 0]
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +100011219 }
Paul Mackerras009409f2015-05-02 20:53:36 +100011220 unset -nocomplain cached_dheads
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +100011221}
11222
Paul Mackerrasca6d8f52006-08-06 21:08:05 +100011223proc removedhead {hid head} {
Paul Mackerrase11f1232007-06-16 20:29:25 +100011224 global cached_dheads
Paul Mackerrasca6d8f52006-08-06 21:08:05 +100011225
Paul Mackerras009409f2015-05-02 20:53:36 +100011226 unset -nocomplain cached_dheads
Paul Mackerras10299152006-08-02 09:52:01 +100011227}
11228
Paul Mackerrase11f1232007-06-16 20:29:25 +100011229proc movedhead {hid head} {
11230 global arcnos arcout cached_dheads
Paul Mackerrasca6d8f52006-08-06 21:08:05 +100011231
Paul Mackerrase11f1232007-06-16 20:29:25 +100011232 if {![info exists arcnos($hid)]} return
11233 if {![info exists arcout($hid)]} {
11234 recalcarc [lindex $arcnos($hid) 0]
Paul Mackerrasca6d8f52006-08-06 21:08:05 +100011235 }
Paul Mackerras009409f2015-05-02 20:53:36 +100011236 unset -nocomplain cached_dheads
Paul Mackerrasca6d8f52006-08-06 21:08:05 +100011237}
11238
Paul Mackerrascec7bec2006-08-02 09:38:10 +100011239proc changedrefs {} {
David Aguilar587277f2012-09-08 12:53:16 -070011240 global cached_dheads cached_dtags cached_atags cached_tagcontent
Paul Mackerrase11f1232007-06-16 20:29:25 +100011241 global arctags archeads arcnos arcout idheads idtags
Paul Mackerrascec7bec2006-08-02 09:38:10 +100011242
Paul Mackerrase11f1232007-06-16 20:29:25 +100011243 foreach id [concat [array names idheads] [array names idtags]] {
11244 if {[info exists arcnos($id)] && ![info exists arcout($id)]} {
11245 set a [lindex $arcnos($id) 0]
11246 if {![info exists donearc($a)]} {
11247 recalcarc $a
11248 set donearc($a) 1
11249 }
Paul Mackerrascec7bec2006-08-02 09:38:10 +100011250 }
11251 }
Paul Mackerras009409f2015-05-02 20:53:36 +100011252 unset -nocomplain cached_tagcontent
11253 unset -nocomplain cached_dtags
11254 unset -nocomplain cached_atags
11255 unset -nocomplain cached_dheads
Paul Mackerrascec7bec2006-08-02 09:38:10 +100011256}
11257
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +100011258proc rereadrefs {} {
Paul Mackerrasfc2a2562007-12-26 23:03:43 +110011259 global idtags idheads idotherrefs mainheadid
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +100011260
11261 set refids [concat [array names idtags] \
11262 [array names idheads] [array names idotherrefs]]
11263 foreach id $refids {
11264 if {![info exists ref($id)]} {
11265 set ref($id) [listrefs $id]
11266 }
11267 }
Paul Mackerrasfc2a2562007-12-26 23:03:43 +110011268 set oldmainhead $mainheadid
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +100011269 readrefs
Paul Mackerrascec7bec2006-08-02 09:38:10 +100011270 changedrefs
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +100011271 set refids [lsort -unique [concat $refids [array names idtags] \
11272 [array names idheads] [array names idotherrefs]]]
11273 foreach id $refids {
11274 set v [listrefs $id]
Paul Mackerrasc11ff122008-05-26 10:11:33 +100011275 if {![info exists ref($id)] || $ref($id) != $v} {
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +100011276 redrawtags $id
11277 }
11278 }
Paul Mackerrasc11ff122008-05-26 10:11:33 +100011279 if {$oldmainhead ne $mainheadid} {
11280 redrawtags $oldmainhead
11281 redrawtags $mainheadid
11282 }
Paul Mackerras887c9962007-08-20 19:36:20 +100011283 run refill_reflist
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +100011284}
11285
Junio C Hamano2e1ded42006-06-11 09:50:47 -070011286proc listrefs {id} {
11287 global idtags idheads idotherrefs
11288
11289 set x {}
11290 if {[info exists idtags($id)]} {
11291 set x $idtags($id)
11292 }
11293 set y {}
11294 if {[info exists idheads($id)]} {
11295 set y $idheads($id)
11296 }
11297 set z {}
11298 if {[info exists idotherrefs($id)]} {
11299 set z $idotherrefs($id)
11300 }
11301 return [list $x $y $z]
11302}
11303
Paul Mackerras4399fe32013-01-03 10:10:31 +110011304proc add_tag_ctext {tag} {
11305 global ctext cached_tagcontent tagids
11306
11307 if {![info exists cached_tagcontent($tag)]} {
11308 catch {
11309 set cached_tagcontent($tag) [exec git cat-file -p $tag]
11310 }
11311 }
11312 $ctext insert end "[mc "Tag"]: $tag\n" bold
11313 if {[info exists cached_tagcontent($tag)]} {
11314 set text $cached_tagcontent($tag)
11315 } else {
11316 set text "[mc "Id"]: $tagids($tag)"
11317 }
11318 appendwithlinks $text {}
11319}
11320
Paul Mackerras106288c2005-08-19 23:11:39 +100011321proc showtag {tag isnew} {
David Aguilar587277f2012-09-08 12:53:16 -070011322 global ctext cached_tagcontent tagids linknum tagobjid
Paul Mackerras106288c2005-08-19 23:11:39 +100011323
11324 if {$isnew} {
Paul Mackerras354af6b2008-11-23 13:14:23 +110011325 addtohistory [list showtag $tag 0] savectextpos
Paul Mackerras106288c2005-08-19 23:11:39 +100011326 }
11327 $ctext conf -state normal
Paul Mackerras3ea06f92006-05-24 10:16:03 +100011328 clear_ctext
Paul Mackerras32f1b3e2007-09-28 21:27:39 +100011329 settabs 0
Paul Mackerras106288c2005-08-19 23:11:39 +100011330 set linknum 0
Paul Mackerras4399fe32013-01-03 10:10:31 +110011331 add_tag_ctext $tag
11332 maybe_scroll_ctext 1
11333 $ctext conf -state disabled
11334 init_flist {}
11335}
11336
11337proc showtags {id isnew} {
11338 global idtags ctext linknum
11339
11340 if {$isnew} {
11341 addtohistory [list showtags $id 0] savectextpos
Paul Mackerras62d3ea62006-09-11 10:36:53 +100011342 }
Paul Mackerras4399fe32013-01-03 10:10:31 +110011343 $ctext conf -state normal
11344 clear_ctext
11345 settabs 0
11346 set linknum 0
11347 set sep {}
11348 foreach tag $idtags($id) {
11349 $ctext insert end $sep
11350 add_tag_ctext $tag
11351 set sep "\n\n"
Paul Mackerras106288c2005-08-19 23:11:39 +100011352 }
Pat Thoytsa80e82f2009-11-14 13:21:09 +000011353 maybe_scroll_ctext 1
Paul Mackerras106288c2005-08-19 23:11:39 +100011354 $ctext conf -state disabled
Paul Mackerras7fcceed2006-04-27 19:21:49 +100011355 init_flist {}
Paul Mackerras106288c2005-08-19 23:11:39 +100011356}
11357
Paul Mackerras1d10f362005-05-15 12:55:47 +000011358proc doquit {} {
11359 global stopped
Thomas Arcila314f5de2008-03-24 12:55:36 +010011360 global gitktmpdir
11361
Paul Mackerras1d10f362005-05-15 12:55:47 +000011362 set stopped 100
Mark Levedahlb6047c52007-02-08 22:22:24 -050011363 savestuff .
Paul Mackerras1d10f362005-05-15 12:55:47 +000011364 destroy .
Thomas Arcila314f5de2008-03-24 12:55:36 +010011365
11366 if {[info exists gitktmpdir]} {
11367 catch {file delete -force $gitktmpdir}
11368 }
Paul Mackerras1d10f362005-05-15 12:55:47 +000011369}
11370
Paul Mackerras9a7558f2007-10-06 20:16:06 +100011371proc mkfontdisp {font top which} {
Pat Thoytsd93f1712009-04-17 01:24:35 +010011372 global fontattr fontpref $font NS use_ttk
Paul Mackerras9a7558f2007-10-06 20:16:06 +100011373
11374 set fontpref($font) [set $font]
Pat Thoytsd93f1712009-04-17 01:24:35 +010011375 ${NS}::button $top.${font}but -text $which \
Paul Mackerras9a7558f2007-10-06 20:16:06 +100011376 -command [list choosefont $font $which]
Pat Thoytsd93f1712009-04-17 01:24:35 +010011377 ${NS}::label $top.$font -relief flat -font $font \
Paul Mackerras9a7558f2007-10-06 20:16:06 +100011378 -text $fontattr($font,family) -justify left
11379 grid x $top.${font}but $top.$font -sticky w
11380}
11381
11382proc choosefont {font which} {
11383 global fontparam fontlist fonttop fontattr
Pat Thoytsd93f1712009-04-17 01:24:35 +010011384 global prefstop NS
Paul Mackerras9a7558f2007-10-06 20:16:06 +100011385
11386 set fontparam(which) $which
11387 set fontparam(font) $font
11388 set fontparam(family) [font actual $font -family]
11389 set fontparam(size) $fontattr($font,size)
11390 set fontparam(weight) $fontattr($font,weight)
11391 set fontparam(slant) $fontattr($font,slant)
11392 set top .gitkfont
11393 set fonttop $top
11394 if {![winfo exists $top]} {
11395 font create sample
11396 eval font config sample [font actual $font]
Pat Thoytsd93f1712009-04-17 01:24:35 +010011397 ttk_toplevel $top
Alexander Gavrilove7d64002008-11-11 23:55:42 +030011398 make_transient $top $prefstop
Christian Stimmingd990ced2007-11-07 18:42:55 +010011399 wm title $top [mc "Gitk font chooser"]
Pat Thoytsd93f1712009-04-17 01:24:35 +010011400 ${NS}::label $top.l -textvariable fontparam(which)
Paul Mackerras9a7558f2007-10-06 20:16:06 +100011401 pack $top.l -side top
11402 set fontlist [lsort [font families]]
Pat Thoytsd93f1712009-04-17 01:24:35 +010011403 ${NS}::frame $top.f
Paul Mackerras9a7558f2007-10-06 20:16:06 +100011404 listbox $top.f.fam -listvariable fontlist \
11405 -yscrollcommand [list $top.f.sb set]
11406 bind $top.f.fam <<ListboxSelect>> selfontfam
Pat Thoytsd93f1712009-04-17 01:24:35 +010011407 ${NS}::scrollbar $top.f.sb -command [list $top.f.fam yview]
Paul Mackerras9a7558f2007-10-06 20:16:06 +100011408 pack $top.f.sb -side right -fill y
11409 pack $top.f.fam -side left -fill both -expand 1
11410 pack $top.f -side top -fill both -expand 1
Pat Thoytsd93f1712009-04-17 01:24:35 +010011411 ${NS}::frame $top.g
Paul Mackerras9a7558f2007-10-06 20:16:06 +100011412 spinbox $top.g.size -from 4 -to 40 -width 4 \
11413 -textvariable fontparam(size) \
11414 -validatecommand {string is integer -strict %s}
11415 checkbutton $top.g.bold -padx 5 \
Christian Stimmingd990ced2007-11-07 18:42:55 +010011416 -font {{Times New Roman} 12 bold} -text [mc "B"] -indicatoron 0 \
Paul Mackerras9a7558f2007-10-06 20:16:06 +100011417 -variable fontparam(weight) -onvalue bold -offvalue normal
11418 checkbutton $top.g.ital -padx 5 \
Christian Stimmingd990ced2007-11-07 18:42:55 +010011419 -font {{Times New Roman} 12 italic} -text [mc "I"] -indicatoron 0 \
Paul Mackerras9a7558f2007-10-06 20:16:06 +100011420 -variable fontparam(slant) -onvalue italic -offvalue roman
11421 pack $top.g.size $top.g.bold $top.g.ital -side left
11422 pack $top.g -side top
11423 canvas $top.c -width 150 -height 50 -border 2 -relief sunk \
11424 -background white
11425 $top.c create text 100 25 -anchor center -text $which -font sample \
11426 -fill black -tags text
11427 bind $top.c <Configure> [list centertext $top.c]
11428 pack $top.c -side top -fill x
Pat Thoytsd93f1712009-04-17 01:24:35 +010011429 ${NS}::frame $top.buts
11430 ${NS}::button $top.buts.ok -text [mc "OK"] -command fontok -default active
11431 ${NS}::button $top.buts.can -text [mc "Cancel"] -command fontcan -default normal
Alexander Gavrilov76f15942008-11-02 21:59:44 +030011432 bind $top <Key-Return> fontok
11433 bind $top <Key-Escape> fontcan
Paul Mackerras9a7558f2007-10-06 20:16:06 +100011434 grid $top.buts.ok $top.buts.can
11435 grid columnconfigure $top.buts 0 -weight 1 -uniform a
11436 grid columnconfigure $top.buts 1 -weight 1 -uniform a
11437 pack $top.buts -side bottom -fill x
11438 trace add variable fontparam write chg_fontparam
11439 } else {
11440 raise $top
11441 $top.c itemconf text -text $which
11442 }
11443 set i [lsearch -exact $fontlist $fontparam(family)]
11444 if {$i >= 0} {
11445 $top.f.fam selection set $i
11446 $top.f.fam see $i
11447 }
11448}
11449
11450proc centertext {w} {
11451 $w coords text [expr {[winfo width $w] / 2}] [expr {[winfo height $w] / 2}]
11452}
11453
11454proc fontok {} {
11455 global fontparam fontpref prefstop
11456
11457 set f $fontparam(font)
11458 set fontpref($f) [list $fontparam(family) $fontparam(size)]
11459 if {$fontparam(weight) eq "bold"} {
11460 lappend fontpref($f) "bold"
11461 }
11462 if {$fontparam(slant) eq "italic"} {
11463 lappend fontpref($f) "italic"
11464 }
Pat Thoyts39ddf992012-04-01 23:00:52 +010011465 set w $prefstop.notebook.fonts.$f
Paul Mackerras9a7558f2007-10-06 20:16:06 +100011466 $w conf -text $fontparam(family) -font $fontpref($f)
Pat Thoytsd93f1712009-04-17 01:24:35 +010011467
Paul Mackerras9a7558f2007-10-06 20:16:06 +100011468 fontcan
11469}
11470
11471proc fontcan {} {
11472 global fonttop fontparam
11473
11474 if {[info exists fonttop]} {
11475 catch {destroy $fonttop}
11476 catch {font delete sample}
11477 unset fonttop
11478 unset fontparam
11479 }
11480}
11481
Pat Thoytsd93f1712009-04-17 01:24:35 +010011482if {[package vsatisfies [package provide Tk] 8.6]} {
11483 # In Tk 8.6 we have a native font chooser dialog. Overwrite the above
11484 # function to make use of it.
11485 proc choosefont {font which} {
11486 tk fontchooser configure -title $which -font $font \
11487 -command [list on_choosefont $font $which]
11488 tk fontchooser show
11489 }
11490 proc on_choosefont {font which newfont} {
11491 global fontparam
11492 puts stderr "$font $newfont"
11493 array set f [font actual $newfont]
11494 set fontparam(which) $which
11495 set fontparam(font) $font
11496 set fontparam(family) $f(-family)
11497 set fontparam(size) $f(-size)
11498 set fontparam(weight) $f(-weight)
11499 set fontparam(slant) $f(-slant)
11500 fontok
11501 }
11502}
11503
Paul Mackerras9a7558f2007-10-06 20:16:06 +100011504proc selfontfam {} {
11505 global fonttop fontparam
11506
11507 set i [$fonttop.f.fam curselection]
11508 if {$i ne {}} {
11509 set fontparam(family) [$fonttop.f.fam get $i]
11510 }
11511}
11512
11513proc chg_fontparam {v sub op} {
11514 global fontparam
11515
11516 font config sample -$sub $fontparam($sub)
11517}
11518
Pat Thoyts44acce02011-12-13 14:56:49 +000011519# Create a property sheet tab page
11520proc create_prefs_page {w} {
11521 global NS
11522 set parent [join [lrange [split $w .] 0 end-1] .]
11523 if {[winfo class $parent] eq "TNotebook"} {
11524 ${NS}::frame $w
11525 } else {
11526 ${NS}::labelframe $w
11527 }
11528}
11529
11530proc prefspage_general {notebook} {
11531 global NS maxwidth maxgraphpct showneartags showlocalchanges
11532 global tabstop limitdiffs autoselect autosellen extdifftool perfile_attrs
Paul Mackerras3441de52019-08-27 08:12:34 +100011533 global hideremotes want_ttk have_ttk maxrefs web_browser
Pat Thoyts44acce02011-12-13 14:56:49 +000011534
11535 set page [create_prefs_page $notebook.general]
11536
11537 ${NS}::label $page.ldisp -text [mc "Commit list display options"]
11538 grid $page.ldisp - -sticky w -pady 10
11539 ${NS}::label $page.spacer -text " "
11540 ${NS}::label $page.maxwidthl -text [mc "Maximum graph width (lines)"]
11541 spinbox $page.maxwidth -from 0 -to 100 -width 4 -textvariable maxwidth
11542 grid $page.spacer $page.maxwidthl $page.maxwidth -sticky w
Alex Henrie8a1692f2015-01-22 01:19:39 -070011543 #xgettext:no-tcl-format
Pat Thoyts44acce02011-12-13 14:56:49 +000011544 ${NS}::label $page.maxpctl -text [mc "Maximum graph width (% of pane)"]
11545 spinbox $page.maxpct -from 1 -to 100 -width 4 -textvariable maxgraphpct
11546 grid x $page.maxpctl $page.maxpct -sticky w
11547 ${NS}::checkbutton $page.showlocal -text [mc "Show local changes"] \
11548 -variable showlocalchanges
11549 grid x $page.showlocal -sticky w
11550 ${NS}::checkbutton $page.autoselect -text [mc "Auto-select SHA1 (length)"] \
11551 -variable autoselect
11552 spinbox $page.autosellen -from 1 -to 40 -width 4 -textvariable autosellen
11553 grid x $page.autoselect $page.autosellen -sticky w
11554 ${NS}::checkbutton $page.hideremotes -text [mc "Hide remote refs"] \
11555 -variable hideremotes
11556 grid x $page.hideremotes -sticky w
11557
11558 ${NS}::label $page.ddisp -text [mc "Diff display options"]
11559 grid $page.ddisp - -sticky w -pady 10
11560 ${NS}::label $page.tabstopl -text [mc "Tab spacing"]
11561 spinbox $page.tabstop -from 1 -to 20 -width 4 -textvariable tabstop
11562 grid x $page.tabstopl $page.tabstop -sticky w
Paul Mackerrasd34835c2013-01-01 23:08:12 +110011563 ${NS}::checkbutton $page.ntag -text [mc "Display nearby tags/heads"] \
Pat Thoyts44acce02011-12-13 14:56:49 +000011564 -variable showneartags
11565 grid x $page.ntag -sticky w
Paul Mackerrasd34835c2013-01-01 23:08:12 +110011566 ${NS}::label $page.maxrefsl -text [mc "Maximum # tags/heads to show"]
11567 spinbox $page.maxrefs -from 1 -to 1000 -width 4 -textvariable maxrefs
11568 grid x $page.maxrefsl $page.maxrefs -sticky w
Pat Thoyts44acce02011-12-13 14:56:49 +000011569 ${NS}::checkbutton $page.ldiff -text [mc "Limit diffs to listed paths"] \
11570 -variable limitdiffs
11571 grid x $page.ldiff -sticky w
11572 ${NS}::checkbutton $page.lattr -text [mc "Support per-file encodings"] \
11573 -variable perfile_attrs
11574 grid x $page.lattr -sticky w
11575
11576 ${NS}::entry $page.extdifft -textvariable extdifftool
11577 ${NS}::frame $page.extdifff
11578 ${NS}::label $page.extdifff.l -text [mc "External diff tool" ]
11579 ${NS}::button $page.extdifff.b -text [mc "Choose..."] -command choose_extdiff
11580 pack $page.extdifff.l $page.extdifff.b -side left
11581 pack configure $page.extdifff.l -padx 10
11582 grid x $page.extdifff $page.extdifft -sticky ew
11583
Paul Mackerras3441de52019-08-27 08:12:34 +100011584 ${NS}::entry $page.webbrowser -textvariable web_browser
11585 ${NS}::frame $page.webbrowserf
11586 ${NS}::label $page.webbrowserf.l -text [mc "Web browser" ]
11587 pack $page.webbrowserf.l -side left
11588 pack configure $page.webbrowserf.l -padx 10
11589 grid x $page.webbrowserf $page.webbrowser -sticky ew
11590
Pat Thoyts44acce02011-12-13 14:56:49 +000011591 ${NS}::label $page.lgen -text [mc "General options"]
11592 grid $page.lgen - -sticky w -pady 10
11593 ${NS}::checkbutton $page.want_ttk -variable want_ttk \
11594 -text [mc "Use themed widgets"]
11595 if {$have_ttk} {
11596 ${NS}::label $page.ttk_note -text [mc "(change requires restart)"]
11597 } else {
11598 ${NS}::label $page.ttk_note -text [mc "(currently unavailable)"]
11599 }
11600 grid x $page.want_ttk $page.ttk_note -sticky w
11601 return $page
11602}
11603
11604proc prefspage_colors {notebook} {
11605 global NS uicolor bgcolor fgcolor ctext diffcolors selectbgcolor markbgcolor
11606
11607 set page [create_prefs_page $notebook.colors]
11608
11609 ${NS}::label $page.cdisp -text [mc "Colors: press to choose"]
11610 grid $page.cdisp - -sticky w -pady 10
11611 label $page.ui -padx 40 -relief sunk -background $uicolor
11612 ${NS}::button $page.uibut -text [mc "Interface"] \
11613 -command [list choosecolor uicolor {} $page.ui [mc "interface"] setui]
11614 grid x $page.uibut $page.ui -sticky w
11615 label $page.bg -padx 40 -relief sunk -background $bgcolor
11616 ${NS}::button $page.bgbut -text [mc "Background"] \
11617 -command [list choosecolor bgcolor {} $page.bg [mc "background"] setbg]
11618 grid x $page.bgbut $page.bg -sticky w
11619 label $page.fg -padx 40 -relief sunk -background $fgcolor
11620 ${NS}::button $page.fgbut -text [mc "Foreground"] \
11621 -command [list choosecolor fgcolor {} $page.fg [mc "foreground"] setfg]
11622 grid x $page.fgbut $page.fg -sticky w
11623 label $page.diffold -padx 40 -relief sunk -background [lindex $diffcolors 0]
11624 ${NS}::button $page.diffoldbut -text [mc "Diff: old lines"] \
11625 -command [list choosecolor diffcolors 0 $page.diffold [mc "diff old lines"] \
11626 [list $ctext tag conf d0 -foreground]]
11627 grid x $page.diffoldbut $page.diffold -sticky w
11628 label $page.diffnew -padx 40 -relief sunk -background [lindex $diffcolors 1]
11629 ${NS}::button $page.diffnewbut -text [mc "Diff: new lines"] \
11630 -command [list choosecolor diffcolors 1 $page.diffnew [mc "diff new lines"] \
11631 [list $ctext tag conf dresult -foreground]]
11632 grid x $page.diffnewbut $page.diffnew -sticky w
11633 label $page.hunksep -padx 40 -relief sunk -background [lindex $diffcolors 2]
11634 ${NS}::button $page.hunksepbut -text [mc "Diff: hunk header"] \
11635 -command [list choosecolor diffcolors 2 $page.hunksep \
11636 [mc "diff hunk header"] \
11637 [list $ctext tag conf hunksep -foreground]]
11638 grid x $page.hunksepbut $page.hunksep -sticky w
11639 label $page.markbgsep -padx 40 -relief sunk -background $markbgcolor
11640 ${NS}::button $page.markbgbut -text [mc "Marked line bg"] \
11641 -command [list choosecolor markbgcolor {} $page.markbgsep \
11642 [mc "marked line background"] \
11643 [list $ctext tag conf omark -background]]
11644 grid x $page.markbgbut $page.markbgsep -sticky w
11645 label $page.selbgsep -padx 40 -relief sunk -background $selectbgcolor
11646 ${NS}::button $page.selbgbut -text [mc "Select bg"] \
11647 -command [list choosecolor selectbgcolor {} $page.selbgsep [mc "background"] setselbg]
11648 grid x $page.selbgbut $page.selbgsep -sticky w
11649 return $page
11650}
11651
11652proc prefspage_fonts {notebook} {
11653 global NS
11654 set page [create_prefs_page $notebook.fonts]
11655 ${NS}::label $page.cfont -text [mc "Fonts: press to choose"]
11656 grid $page.cfont - -sticky w -pady 10
11657 mkfontdisp mainfont $page [mc "Main font"]
11658 mkfontdisp textfont $page [mc "Diff display font"]
11659 mkfontdisp uifont $page [mc "User interface font"]
11660 return $page
11661}
11662
Paul Mackerras712fcc02005-11-30 09:28:16 +110011663proc doprefs {} {
Pat Thoytsd93f1712009-04-17 01:24:35 +010011664 global maxwidth maxgraphpct use_ttk NS
Paul Mackerras219ea3a2006-09-07 10:21:39 +100011665 global oldprefs prefstop showneartags showlocalchanges
Guillermo S. Romero5497f7a2009-10-15 18:51:49 +020011666 global uicolor bgcolor fgcolor ctext diffcolors selectbgcolor markbgcolor
Paul Mackerras21ac8a82011-03-09 20:52:38 +110011667 global tabstop limitdiffs autoselect autosellen extdifftool perfile_attrs
Paul Mackerras0cc08ff2009-09-05 22:06:46 +100011668 global hideremotes want_ttk have_ttk
Paul Mackerras232475d2005-11-15 10:34:03 +110011669
Paul Mackerras712fcc02005-11-30 09:28:16 +110011670 set top .gitkprefs
11671 set prefstop $top
11672 if {[winfo exists $top]} {
11673 raise $top
11674 return
Paul Mackerras757f17b2005-11-21 09:56:07 +110011675 }
Paul Mackerras3de07112007-10-23 22:40:50 +100011676 foreach v {maxwidth maxgraphpct showneartags showlocalchanges \
Paul Mackerras0cc08ff2009-09-05 22:06:46 +100011677 limitdiffs tabstop perfile_attrs hideremotes want_ttk} {
Paul Mackerras712fcc02005-11-30 09:28:16 +110011678 set oldprefs($v) [set $v]
Paul Mackerras232475d2005-11-15 10:34:03 +110011679 }
Pat Thoytsd93f1712009-04-17 01:24:35 +010011680 ttk_toplevel $top
Christian Stimmingd990ced2007-11-07 18:42:55 +010011681 wm title $top [mc "Gitk preferences"]
Alexander Gavrilove7d64002008-11-11 23:55:42 +030011682 make_transient $top .
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +100011683
Pat Thoyts44acce02011-12-13 14:56:49 +000011684 if {[set use_notebook [expr {$use_ttk && [info command ::ttk::notebook] ne ""}]]} {
11685 set notebook [ttk::notebook $top.notebook]
Paul Mackerras0cc08ff2009-09-05 22:06:46 +100011686 } else {
Pat Thoyts44acce02011-12-13 14:56:49 +000011687 set notebook [${NS}::frame $top.notebook -borderwidth 0 -relief flat]
Paul Mackerras0cc08ff2009-09-05 22:06:46 +100011688 }
Paul Mackerras0cc08ff2009-09-05 22:06:46 +100011689
Pat Thoyts44acce02011-12-13 14:56:49 +000011690 lappend pages [prefspage_general $notebook] [mc "General"]
11691 lappend pages [prefspage_colors $notebook] [mc "Colors"]
11692 lappend pages [prefspage_fonts $notebook] [mc "Fonts"]
Pat Thoyts28cb7072012-04-01 23:00:51 +010011693 set col 0
Pat Thoyts44acce02011-12-13 14:56:49 +000011694 foreach {page title} $pages {
11695 if {$use_notebook} {
11696 $notebook add $page -text $title
11697 } else {
11698 set btn [${NS}::button $notebook.b_[string map {. X} $page] \
11699 -text $title -command [list raise $page]]
11700 $page configure -text $title
11701 grid $btn -row 0 -column [incr col] -sticky w
11702 grid $page -row 1 -column 0 -sticky news -columnspan 100
11703 }
11704 }
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +100011705
Pat Thoyts44acce02011-12-13 14:56:49 +000011706 if {!$use_notebook} {
11707 grid columnconfigure $notebook 0 -weight 1
11708 grid rowconfigure $notebook 1 -weight 1
11709 raise [lindex $pages 0]
11710 }
11711
11712 grid $notebook -sticky news -padx 2 -pady 2
11713 grid rowconfigure $top 0 -weight 1
11714 grid columnconfigure $top 0 -weight 1
Paul Mackerras9a7558f2007-10-06 20:16:06 +100011715
Pat Thoytsd93f1712009-04-17 01:24:35 +010011716 ${NS}::frame $top.buts
11717 ${NS}::button $top.buts.ok -text [mc "OK"] -command prefsok -default active
11718 ${NS}::button $top.buts.can -text [mc "Cancel"] -command prefscan -default normal
Alexander Gavrilov76f15942008-11-02 21:59:44 +030011719 bind $top <Key-Return> prefsok
11720 bind $top <Key-Escape> prefscan
Paul Mackerras712fcc02005-11-30 09:28:16 +110011721 grid $top.buts.ok $top.buts.can
11722 grid columnconfigure $top.buts 0 -weight 1 -uniform a
11723 grid columnconfigure $top.buts 1 -weight 1 -uniform a
11724 grid $top.buts - - -pady 10 -sticky ew
Pat Thoytsd93f1712009-04-17 01:24:35 +010011725 grid columnconfigure $top 2 -weight 1
Pat Thoyts44acce02011-12-13 14:56:49 +000011726 bind $top <Visibility> [list focus $top.buts.ok]
Paul Mackerras712fcc02005-11-30 09:28:16 +110011727}
11728
Thomas Arcila314f5de2008-03-24 12:55:36 +010011729proc choose_extdiff {} {
11730 global extdifftool
11731
Michele Ballabiob56e0a92009-03-30 21:17:25 +020011732 set prog [tk_getOpenFile -title [mc "External diff tool"] -multiple false]
Thomas Arcila314f5de2008-03-24 12:55:36 +010011733 if {$prog ne {}} {
11734 set extdifftool $prog
11735 }
11736}
11737
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +100011738proc choosecolor {v vi w x cmd} {
11739 global $v
11740
11741 set c [tk_chooseColor -initialcolor [lindex [set $v] $vi] \
Christian Stimmingd990ced2007-11-07 18:42:55 +010011742 -title [mc "Gitk: choose color for %s" $x]]
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +100011743 if {$c eq {}} return
11744 $w conf -background $c
11745 lset $v $vi $c
11746 eval $cmd $c
11747}
11748
Mark Levedahl60378c02007-05-20 12:12:48 -040011749proc setselbg {c} {
11750 global bglist cflist
11751 foreach w $bglist {
Paul Mackerraseb859df2015-05-03 15:11:29 +100011752 if {[winfo exists $w]} {
11753 $w configure -selectbackground $c
11754 }
Mark Levedahl60378c02007-05-20 12:12:48 -040011755 }
11756 $cflist tag configure highlight \
11757 -background [$cflist cget -selectbackground]
11758 allcanvs itemconf secsel -fill $c
11759}
11760
Paul Mackerras51a7e8b2009-11-14 21:15:01 +110011761# This sets the background color and the color scheme for the whole UI.
11762# For some reason, tk_setPalette chooses a nasty dark red for selectColor
11763# if we don't specify one ourselves, which makes the checkbuttons and
11764# radiobuttons look bad. This chooses white for selectColor if the
11765# background color is light, or black if it is dark.
Guillermo S. Romero5497f7a2009-10-15 18:51:49 +020011766proc setui {c} {
Pat Thoyts2e58c942010-03-12 18:31:47 +000011767 if {[tk windowingsystem] eq "win32"} { return }
Paul Mackerras51a7e8b2009-11-14 21:15:01 +110011768 set bg [winfo rgb . $c]
11769 set selc black
11770 if {[lindex $bg 0] + 1.5 * [lindex $bg 1] + 0.5 * [lindex $bg 2] > 100000} {
11771 set selc white
11772 }
11773 tk_setPalette background $c selectColor $selc
Guillermo S. Romero5497f7a2009-10-15 18:51:49 +020011774}
11775
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +100011776proc setbg {c} {
11777 global bglist
11778
11779 foreach w $bglist {
Paul Mackerraseb859df2015-05-03 15:11:29 +100011780 if {[winfo exists $w]} {
11781 $w conf -background $c
11782 }
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +100011783 }
11784}
11785
11786proc setfg {c} {
11787 global fglist canv
11788
11789 foreach w $fglist {
Paul Mackerraseb859df2015-05-03 15:11:29 +100011790 if {[winfo exists $w]} {
11791 $w conf -foreground $c
11792 }
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +100011793 }
11794 allcanvs itemconf text -fill $c
11795 $canv itemconf circle -outline $c
Paul Mackerrasb9fdba72009-04-09 09:34:46 +100011796 $canv itemconf markid -outline $c
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +100011797}
11798
Paul Mackerras712fcc02005-11-30 09:28:16 +110011799proc prefscan {} {
Paul Mackerras94503912007-10-23 10:33:38 +100011800 global oldprefs prefstop
Paul Mackerras712fcc02005-11-30 09:28:16 +110011801
Paul Mackerras3de07112007-10-23 22:40:50 +100011802 foreach v {maxwidth maxgraphpct showneartags showlocalchanges \
Paul Mackerras0cc08ff2009-09-05 22:06:46 +100011803 limitdiffs tabstop perfile_attrs hideremotes want_ttk} {
Paul Mackerras94503912007-10-23 10:33:38 +100011804 global $v
Paul Mackerras712fcc02005-11-30 09:28:16 +110011805 set $v $oldprefs($v)
11806 }
11807 catch {destroy $prefstop}
11808 unset prefstop
Paul Mackerras9a7558f2007-10-06 20:16:06 +100011809 fontcan
Paul Mackerras712fcc02005-11-30 09:28:16 +110011810}
11811
11812proc prefsok {} {
11813 global maxwidth maxgraphpct
Paul Mackerras219ea3a2006-09-07 10:21:39 +100011814 global oldprefs prefstop showneartags showlocalchanges
Paul Mackerras9a7558f2007-10-06 20:16:06 +100011815 global fontpref mainfont textfont uifont
Paul Mackerras39ee47e2008-10-15 22:23:03 +110011816 global limitdiffs treediffs perfile_attrs
Thomas Rastffe15292009-08-03 23:53:36 +020011817 global hideremotes
Paul Mackerras712fcc02005-11-30 09:28:16 +110011818
11819 catch {destroy $prefstop}
11820 unset prefstop
Paul Mackerras9a7558f2007-10-06 20:16:06 +100011821 fontcan
11822 set fontchanged 0
11823 if {$mainfont ne $fontpref(mainfont)} {
11824 set mainfont $fontpref(mainfont)
11825 parsefont mainfont $mainfont
11826 eval font configure mainfont [fontflags mainfont]
11827 eval font configure mainfontbold [fontflags mainfont 1]
11828 setcoords
11829 set fontchanged 1
11830 }
11831 if {$textfont ne $fontpref(textfont)} {
11832 set textfont $fontpref(textfont)
11833 parsefont textfont $textfont
11834 eval font configure textfont [fontflags textfont]
11835 eval font configure textfontbold [fontflags textfont 1]
11836 }
11837 if {$uifont ne $fontpref(uifont)} {
11838 set uifont $fontpref(uifont)
11839 parsefont uifont $uifont
11840 eval font configure uifont [fontflags uifont]
11841 }
Paul Mackerras32f1b3e2007-09-28 21:27:39 +100011842 settabs
Paul Mackerras219ea3a2006-09-07 10:21:39 +100011843 if {$showlocalchanges != $oldprefs(showlocalchanges)} {
11844 if {$showlocalchanges} {
11845 doshowlocalchanges
11846 } else {
11847 dohidelocalchanges
11848 }
11849 }
Paul Mackerras39ee47e2008-10-15 22:23:03 +110011850 if {$limitdiffs != $oldprefs(limitdiffs) ||
11851 ($perfile_attrs && !$oldprefs(perfile_attrs))} {
11852 # treediffs elements are limited by path;
11853 # won't have encodings cached if perfile_attrs was just turned on
Paul Mackerras009409f2015-05-02 20:53:36 +100011854 unset -nocomplain treediffs
Paul Mackerras74a40c72007-10-24 10:16:56 +100011855 }
Paul Mackerras9a7558f2007-10-06 20:16:06 +100011856 if {$fontchanged || $maxwidth != $oldprefs(maxwidth)
Paul Mackerras712fcc02005-11-30 09:28:16 +110011857 || $maxgraphpct != $oldprefs(maxgraphpct)} {
11858 redisplay
Paul Mackerras7a39a172007-10-23 10:15:11 +100011859 } elseif {$showneartags != $oldprefs(showneartags) ||
11860 $limitdiffs != $oldprefs(limitdiffs)} {
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +100011861 reselectline
Paul Mackerras712fcc02005-11-30 09:28:16 +110011862 }
Thomas Rastffe15292009-08-03 23:53:36 +020011863 if {$hideremotes != $oldprefs(hideremotes)} {
11864 rereadrefs
11865 }
Paul Mackerras712fcc02005-11-30 09:28:16 +110011866}
11867
11868proc formatdate {d} {
Arjen Laarhovene8b5f4b2007-08-14 22:02:04 +020011869 global datetimeformat
Paul Mackerras219ea3a2006-09-07 10:21:39 +100011870 if {$d ne {}} {
Anders Kaseorg019e1632014-05-12 07:25:58 -040011871 # If $datetimeformat includes a timezone, display in the
11872 # timezone of the argument. Otherwise, display in local time.
11873 if {[string match {*%[zZ]*} $datetimeformat]} {
11874 if {[catch {set d [clock format [lindex $d 0] -timezone [lindex $d 1] -format $datetimeformat]}]} {
11875 # Tcl < 8.5 does not support -timezone. Emulate it by
11876 # setting TZ (e.g. TZ=<-0430>+04:30).
11877 global env
11878 if {[info exists env(TZ)]} {
11879 set savedTZ $env(TZ)
11880 }
11881 set zone [lindex $d 1]
11882 set sign [string map {+ - - +} [string index $zone 0]]
11883 set env(TZ) <$zone>$sign[string range $zone 1 2]:[string range $zone 3 4]
11884 set d [clock format [lindex $d 0] -format $datetimeformat]
11885 if {[info exists savedTZ]} {
11886 set env(TZ) $savedTZ
11887 } else {
11888 unset env(TZ)
11889 }
11890 }
11891 } else {
11892 set d [clock format [lindex $d 0] -format $datetimeformat]
11893 }
Paul Mackerras219ea3a2006-09-07 10:21:39 +100011894 }
11895 return $d
Paul Mackerras232475d2005-11-15 10:34:03 +110011896}
11897
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +110011898# This list of encoding names and aliases is distilled from
11899# http://www.iana.org/assignments/character-sets.
11900# Not all of them are supported by Tcl.
11901set encoding_aliases {
11902 { ANSI_X3.4-1968 iso-ir-6 ANSI_X3.4-1986 ISO_646.irv:1991 ASCII
11903 ISO646-US US-ASCII us IBM367 cp367 csASCII }
11904 { ISO-10646-UTF-1 csISO10646UTF1 }
11905 { ISO_646.basic:1983 ref csISO646basic1983 }
11906 { INVARIANT csINVARIANT }
11907 { ISO_646.irv:1983 iso-ir-2 irv csISO2IntlRefVersion }
11908 { BS_4730 iso-ir-4 ISO646-GB gb uk csISO4UnitedKingdom }
11909 { NATS-SEFI iso-ir-8-1 csNATSSEFI }
11910 { NATS-SEFI-ADD iso-ir-8-2 csNATSSEFIADD }
11911 { NATS-DANO iso-ir-9-1 csNATSDANO }
11912 { NATS-DANO-ADD iso-ir-9-2 csNATSDANOADD }
11913 { SEN_850200_B iso-ir-10 FI ISO646-FI ISO646-SE se csISO10Swedish }
11914 { SEN_850200_C iso-ir-11 ISO646-SE2 se2 csISO11SwedishForNames }
11915 { KS_C_5601-1987 iso-ir-149 KS_C_5601-1989 KSC_5601 korean csKSC56011987 }
11916 { ISO-2022-KR csISO2022KR }
11917 { EUC-KR csEUCKR }
11918 { ISO-2022-JP csISO2022JP }
11919 { ISO-2022-JP-2 csISO2022JP2 }
11920 { JIS_C6220-1969-jp JIS_C6220-1969 iso-ir-13 katakana x0201-7
11921 csISO13JISC6220jp }
11922 { JIS_C6220-1969-ro iso-ir-14 jp ISO646-JP csISO14JISC6220ro }
11923 { IT iso-ir-15 ISO646-IT csISO15Italian }
11924 { PT iso-ir-16 ISO646-PT csISO16Portuguese }
11925 { ES iso-ir-17 ISO646-ES csISO17Spanish }
11926 { greek7-old iso-ir-18 csISO18Greek7Old }
11927 { latin-greek iso-ir-19 csISO19LatinGreek }
11928 { DIN_66003 iso-ir-21 de ISO646-DE csISO21German }
11929 { NF_Z_62-010_(1973) iso-ir-25 ISO646-FR1 csISO25French }
11930 { Latin-greek-1 iso-ir-27 csISO27LatinGreek1 }
11931 { ISO_5427 iso-ir-37 csISO5427Cyrillic }
11932 { JIS_C6226-1978 iso-ir-42 csISO42JISC62261978 }
11933 { BS_viewdata iso-ir-47 csISO47BSViewdata }
11934 { INIS iso-ir-49 csISO49INIS }
11935 { INIS-8 iso-ir-50 csISO50INIS8 }
11936 { INIS-cyrillic iso-ir-51 csISO51INISCyrillic }
11937 { ISO_5427:1981 iso-ir-54 ISO5427Cyrillic1981 }
11938 { ISO_5428:1980 iso-ir-55 csISO5428Greek }
11939 { GB_1988-80 iso-ir-57 cn ISO646-CN csISO57GB1988 }
11940 { GB_2312-80 iso-ir-58 chinese csISO58GB231280 }
11941 { NS_4551-1 iso-ir-60 ISO646-NO no csISO60DanishNorwegian
11942 csISO60Norwegian1 }
11943 { NS_4551-2 ISO646-NO2 iso-ir-61 no2 csISO61Norwegian2 }
11944 { NF_Z_62-010 iso-ir-69 ISO646-FR fr csISO69French }
11945 { videotex-suppl iso-ir-70 csISO70VideotexSupp1 }
11946 { PT2 iso-ir-84 ISO646-PT2 csISO84Portuguese2 }
11947 { ES2 iso-ir-85 ISO646-ES2 csISO85Spanish2 }
11948 { MSZ_7795.3 iso-ir-86 ISO646-HU hu csISO86Hungarian }
11949 { JIS_C6226-1983 iso-ir-87 x0208 JIS_X0208-1983 csISO87JISX0208 }
11950 { greek7 iso-ir-88 csISO88Greek7 }
11951 { ASMO_449 ISO_9036 arabic7 iso-ir-89 csISO89ASMO449 }
11952 { iso-ir-90 csISO90 }
11953 { JIS_C6229-1984-a iso-ir-91 jp-ocr-a csISO91JISC62291984a }
11954 { JIS_C6229-1984-b iso-ir-92 ISO646-JP-OCR-B jp-ocr-b
11955 csISO92JISC62991984b }
11956 { JIS_C6229-1984-b-add iso-ir-93 jp-ocr-b-add csISO93JIS62291984badd }
11957 { JIS_C6229-1984-hand iso-ir-94 jp-ocr-hand csISO94JIS62291984hand }
11958 { JIS_C6229-1984-hand-add iso-ir-95 jp-ocr-hand-add
11959 csISO95JIS62291984handadd }
11960 { JIS_C6229-1984-kana iso-ir-96 csISO96JISC62291984kana }
11961 { ISO_2033-1983 iso-ir-98 e13b csISO2033 }
11962 { ANSI_X3.110-1983 iso-ir-99 CSA_T500-1983 NAPLPS csISO99NAPLPS }
11963 { ISO_8859-1:1987 iso-ir-100 ISO_8859-1 ISO-8859-1 latin1 l1 IBM819
11964 CP819 csISOLatin1 }
11965 { ISO_8859-2:1987 iso-ir-101 ISO_8859-2 ISO-8859-2 latin2 l2 csISOLatin2 }
11966 { T.61-7bit iso-ir-102 csISO102T617bit }
11967 { T.61-8bit T.61 iso-ir-103 csISO103T618bit }
11968 { ISO_8859-3:1988 iso-ir-109 ISO_8859-3 ISO-8859-3 latin3 l3 csISOLatin3 }
11969 { ISO_8859-4:1988 iso-ir-110 ISO_8859-4 ISO-8859-4 latin4 l4 csISOLatin4 }
11970 { ECMA-cyrillic iso-ir-111 KOI8-E csISO111ECMACyrillic }
11971 { CSA_Z243.4-1985-1 iso-ir-121 ISO646-CA csa7-1 ca csISO121Canadian1 }
11972 { CSA_Z243.4-1985-2 iso-ir-122 ISO646-CA2 csa7-2 csISO122Canadian2 }
11973 { CSA_Z243.4-1985-gr iso-ir-123 csISO123CSAZ24341985gr }
11974 { ISO_8859-6:1987 iso-ir-127 ISO_8859-6 ISO-8859-6 ECMA-114 ASMO-708
11975 arabic csISOLatinArabic }
11976 { ISO_8859-6-E csISO88596E ISO-8859-6-E }
11977 { ISO_8859-6-I csISO88596I ISO-8859-6-I }
11978 { ISO_8859-7:1987 iso-ir-126 ISO_8859-7 ISO-8859-7 ELOT_928 ECMA-118
11979 greek greek8 csISOLatinGreek }
11980 { T.101-G2 iso-ir-128 csISO128T101G2 }
11981 { ISO_8859-8:1988 iso-ir-138 ISO_8859-8 ISO-8859-8 hebrew
11982 csISOLatinHebrew }
11983 { ISO_8859-8-E csISO88598E ISO-8859-8-E }
11984 { ISO_8859-8-I csISO88598I ISO-8859-8-I }
11985 { CSN_369103 iso-ir-139 csISO139CSN369103 }
11986 { JUS_I.B1.002 iso-ir-141 ISO646-YU js yu csISO141JUSIB1002 }
11987 { ISO_6937-2-add iso-ir-142 csISOTextComm }
11988 { IEC_P27-1 iso-ir-143 csISO143IECP271 }
11989 { ISO_8859-5:1988 iso-ir-144 ISO_8859-5 ISO-8859-5 cyrillic
11990 csISOLatinCyrillic }
11991 { JUS_I.B1.003-serb iso-ir-146 serbian csISO146Serbian }
11992 { JUS_I.B1.003-mac macedonian iso-ir-147 csISO147Macedonian }
11993 { ISO_8859-9:1989 iso-ir-148 ISO_8859-9 ISO-8859-9 latin5 l5 csISOLatin5 }
11994 { greek-ccitt iso-ir-150 csISO150 csISO150GreekCCITT }
11995 { NC_NC00-10:81 cuba iso-ir-151 ISO646-CU csISO151Cuba }
11996 { ISO_6937-2-25 iso-ir-152 csISO6937Add }
11997 { GOST_19768-74 ST_SEV_358-88 iso-ir-153 csISO153GOST1976874 }
11998 { ISO_8859-supp iso-ir-154 latin1-2-5 csISO8859Supp }
11999 { ISO_10367-box iso-ir-155 csISO10367Box }
12000 { ISO-8859-10 iso-ir-157 l6 ISO_8859-10:1992 csISOLatin6 latin6 }
12001 { latin-lap lap iso-ir-158 csISO158Lap }
12002 { JIS_X0212-1990 x0212 iso-ir-159 csISO159JISX02121990 }
12003 { DS_2089 DS2089 ISO646-DK dk csISO646Danish }
12004 { us-dk csUSDK }
12005 { dk-us csDKUS }
12006 { JIS_X0201 X0201 csHalfWidthKatakana }
12007 { KSC5636 ISO646-KR csKSC5636 }
12008 { ISO-10646-UCS-2 csUnicode }
12009 { ISO-10646-UCS-4 csUCS4 }
12010 { DEC-MCS dec csDECMCS }
12011 { hp-roman8 roman8 r8 csHPRoman8 }
12012 { macintosh mac csMacintosh }
12013 { IBM037 cp037 ebcdic-cp-us ebcdic-cp-ca ebcdic-cp-wt ebcdic-cp-nl
12014 csIBM037 }
12015 { IBM038 EBCDIC-INT cp038 csIBM038 }
12016 { IBM273 CP273 csIBM273 }
12017 { IBM274 EBCDIC-BE CP274 csIBM274 }
12018 { IBM275 EBCDIC-BR cp275 csIBM275 }
12019 { IBM277 EBCDIC-CP-DK EBCDIC-CP-NO csIBM277 }
12020 { IBM278 CP278 ebcdic-cp-fi ebcdic-cp-se csIBM278 }
12021 { IBM280 CP280 ebcdic-cp-it csIBM280 }
12022 { IBM281 EBCDIC-JP-E cp281 csIBM281 }
12023 { IBM284 CP284 ebcdic-cp-es csIBM284 }
12024 { IBM285 CP285 ebcdic-cp-gb csIBM285 }
12025 { IBM290 cp290 EBCDIC-JP-kana csIBM290 }
12026 { IBM297 cp297 ebcdic-cp-fr csIBM297 }
12027 { IBM420 cp420 ebcdic-cp-ar1 csIBM420 }
12028 { IBM423 cp423 ebcdic-cp-gr csIBM423 }
12029 { IBM424 cp424 ebcdic-cp-he csIBM424 }
12030 { IBM437 cp437 437 csPC8CodePage437 }
12031 { IBM500 CP500 ebcdic-cp-be ebcdic-cp-ch csIBM500 }
12032 { IBM775 cp775 csPC775Baltic }
12033 { IBM850 cp850 850 csPC850Multilingual }
12034 { IBM851 cp851 851 csIBM851 }
12035 { IBM852 cp852 852 csPCp852 }
12036 { IBM855 cp855 855 csIBM855 }
12037 { IBM857 cp857 857 csIBM857 }
12038 { IBM860 cp860 860 csIBM860 }
12039 { IBM861 cp861 861 cp-is csIBM861 }
12040 { IBM862 cp862 862 csPC862LatinHebrew }
12041 { IBM863 cp863 863 csIBM863 }
12042 { IBM864 cp864 csIBM864 }
12043 { IBM865 cp865 865 csIBM865 }
12044 { IBM866 cp866 866 csIBM866 }
12045 { IBM868 CP868 cp-ar csIBM868 }
12046 { IBM869 cp869 869 cp-gr csIBM869 }
12047 { IBM870 CP870 ebcdic-cp-roece ebcdic-cp-yu csIBM870 }
12048 { IBM871 CP871 ebcdic-cp-is csIBM871 }
12049 { IBM880 cp880 EBCDIC-Cyrillic csIBM880 }
12050 { IBM891 cp891 csIBM891 }
12051 { IBM903 cp903 csIBM903 }
12052 { IBM904 cp904 904 csIBBM904 }
12053 { IBM905 CP905 ebcdic-cp-tr csIBM905 }
12054 { IBM918 CP918 ebcdic-cp-ar2 csIBM918 }
12055 { IBM1026 CP1026 csIBM1026 }
12056 { EBCDIC-AT-DE csIBMEBCDICATDE }
12057 { EBCDIC-AT-DE-A csEBCDICATDEA }
12058 { EBCDIC-CA-FR csEBCDICCAFR }
12059 { EBCDIC-DK-NO csEBCDICDKNO }
12060 { EBCDIC-DK-NO-A csEBCDICDKNOA }
12061 { EBCDIC-FI-SE csEBCDICFISE }
12062 { EBCDIC-FI-SE-A csEBCDICFISEA }
12063 { EBCDIC-FR csEBCDICFR }
12064 { EBCDIC-IT csEBCDICIT }
12065 { EBCDIC-PT csEBCDICPT }
12066 { EBCDIC-ES csEBCDICES }
12067 { EBCDIC-ES-A csEBCDICESA }
12068 { EBCDIC-ES-S csEBCDICESS }
12069 { EBCDIC-UK csEBCDICUK }
12070 { EBCDIC-US csEBCDICUS }
12071 { UNKNOWN-8BIT csUnknown8BiT }
12072 { MNEMONIC csMnemonic }
12073 { MNEM csMnem }
12074 { VISCII csVISCII }
12075 { VIQR csVIQR }
12076 { KOI8-R csKOI8R }
12077 { IBM00858 CCSID00858 CP00858 PC-Multilingual-850+euro }
12078 { IBM00924 CCSID00924 CP00924 ebcdic-Latin9--euro }
12079 { IBM01140 CCSID01140 CP01140 ebcdic-us-37+euro }
12080 { IBM01141 CCSID01141 CP01141 ebcdic-de-273+euro }
12081 { IBM01142 CCSID01142 CP01142 ebcdic-dk-277+euro ebcdic-no-277+euro }
12082 { IBM01143 CCSID01143 CP01143 ebcdic-fi-278+euro ebcdic-se-278+euro }
12083 { IBM01144 CCSID01144 CP01144 ebcdic-it-280+euro }
12084 { IBM01145 CCSID01145 CP01145 ebcdic-es-284+euro }
12085 { IBM01146 CCSID01146 CP01146 ebcdic-gb-285+euro }
12086 { IBM01147 CCSID01147 CP01147 ebcdic-fr-297+euro }
12087 { IBM01148 CCSID01148 CP01148 ebcdic-international-500+euro }
12088 { IBM01149 CCSID01149 CP01149 ebcdic-is-871+euro }
12089 { IBM1047 IBM-1047 }
12090 { PTCP154 csPTCP154 PT154 CP154 Cyrillic-Asian }
12091 { Amiga-1251 Ami1251 Amiga1251 Ami-1251 }
12092 { UNICODE-1-1 csUnicode11 }
12093 { CESU-8 csCESU-8 }
12094 { BOCU-1 csBOCU-1 }
12095 { UNICODE-1-1-UTF-7 csUnicode11UTF7 }
12096 { ISO-8859-14 iso-ir-199 ISO_8859-14:1998 ISO_8859-14 latin8 iso-celtic
12097 l8 }
12098 { ISO-8859-15 ISO_8859-15 Latin-9 }
12099 { ISO-8859-16 iso-ir-226 ISO_8859-16:2001 ISO_8859-16 latin10 l10 }
12100 { GBK CP936 MS936 windows-936 }
12101 { JIS_Encoding csJISEncoding }
Alexander Gavrilov09c70292008-10-13 12:12:31 +040012102 { Shift_JIS MS_Kanji csShiftJIS ShiftJIS Shift-JIS }
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +110012103 { Extended_UNIX_Code_Packed_Format_for_Japanese csEUCPkdFmtJapanese
12104 EUC-JP }
12105 { Extended_UNIX_Code_Fixed_Width_for_Japanese csEUCFixWidJapanese }
12106 { ISO-10646-UCS-Basic csUnicodeASCII }
12107 { ISO-10646-Unicode-Latin1 csUnicodeLatin1 ISO-10646 }
12108 { ISO-Unicode-IBM-1261 csUnicodeIBM1261 }
12109 { ISO-Unicode-IBM-1268 csUnicodeIBM1268 }
12110 { ISO-Unicode-IBM-1276 csUnicodeIBM1276 }
12111 { ISO-Unicode-IBM-1264 csUnicodeIBM1264 }
12112 { ISO-Unicode-IBM-1265 csUnicodeIBM1265 }
12113 { ISO-8859-1-Windows-3.0-Latin-1 csWindows30Latin1 }
12114 { ISO-8859-1-Windows-3.1-Latin-1 csWindows31Latin1 }
12115 { ISO-8859-2-Windows-Latin-2 csWindows31Latin2 }
12116 { ISO-8859-9-Windows-Latin-5 csWindows31Latin5 }
12117 { Adobe-Standard-Encoding csAdobeStandardEncoding }
12118 { Ventura-US csVenturaUS }
12119 { Ventura-International csVenturaInternational }
12120 { PC8-Danish-Norwegian csPC8DanishNorwegian }
12121 { PC8-Turkish csPC8Turkish }
12122 { IBM-Symbols csIBMSymbols }
12123 { IBM-Thai csIBMThai }
12124 { HP-Legal csHPLegal }
12125 { HP-Pi-font csHPPiFont }
12126 { HP-Math8 csHPMath8 }
12127 { Adobe-Symbol-Encoding csHPPSMath }
12128 { HP-DeskTop csHPDesktop }
12129 { Ventura-Math csVenturaMath }
12130 { Microsoft-Publishing csMicrosoftPublishing }
12131 { Windows-31J csWindows31J }
12132 { GB2312 csGB2312 }
12133 { Big5 csBig5 }
12134}
12135
12136proc tcl_encoding {enc} {
Paul Mackerras39ee47e2008-10-15 22:23:03 +110012137 global encoding_aliases tcl_encoding_cache
12138 if {[info exists tcl_encoding_cache($enc)]} {
12139 return $tcl_encoding_cache($enc)
12140 }
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +110012141 set names [encoding names]
12142 set lcnames [string tolower $names]
12143 set enc [string tolower $enc]
12144 set i [lsearch -exact $lcnames $enc]
12145 if {$i < 0} {
12146 # look for "isonnn" instead of "iso-nnn" or "iso_nnn"
Alexander Gavrilov09c70292008-10-13 12:12:31 +040012147 if {[regsub {^(iso|cp|ibm|jis)[-_]} $enc {\1} encx]} {
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +110012148 set i [lsearch -exact $lcnames $encx]
12149 }
12150 }
12151 if {$i < 0} {
12152 foreach l $encoding_aliases {
12153 set ll [string tolower $l]
12154 if {[lsearch -exact $ll $enc] < 0} continue
12155 # look through the aliases for one that tcl knows about
12156 foreach e $ll {
12157 set i [lsearch -exact $lcnames $e]
12158 if {$i < 0} {
Alexander Gavrilov09c70292008-10-13 12:12:31 +040012159 if {[regsub {^(iso|cp|ibm|jis)[-_]} $e {\1} ex]} {
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +110012160 set i [lsearch -exact $lcnames $ex]
12161 }
12162 }
12163 if {$i >= 0} break
12164 }
12165 break
12166 }
12167 }
Paul Mackerras39ee47e2008-10-15 22:23:03 +110012168 set tclenc {}
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +110012169 if {$i >= 0} {
Paul Mackerras39ee47e2008-10-15 22:23:03 +110012170 set tclenc [lindex $names $i]
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +110012171 }
Paul Mackerras39ee47e2008-10-15 22:23:03 +110012172 set tcl_encoding_cache($enc) $tclenc
12173 return $tclenc
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +110012174}
12175
Alexander Gavrilov09c70292008-10-13 12:12:31 +040012176proc gitattr {path attr default} {
Paul Mackerras39ee47e2008-10-15 22:23:03 +110012177 global path_attr_cache
12178 if {[info exists path_attr_cache($attr,$path)]} {
12179 set r $path_attr_cache($attr,$path)
12180 } else {
12181 set r "unspecified"
12182 if {![catch {set line [exec git check-attr $attr -- $path]}]} {
Johannes Sixt097e1112009-07-21 10:09:48 +020012183 regexp "(.*): $attr: (.*)" $line m f r
Alexander Gavrilov09c70292008-10-13 12:12:31 +040012184 }
Alexander Gavrilov4db09302008-10-13 12:12:33 +040012185 set path_attr_cache($attr,$path) $r
Paul Mackerras39ee47e2008-10-15 22:23:03 +110012186 }
12187 if {$r eq "unspecified"} {
12188 return $default
12189 }
12190 return $r
Alexander Gavrilov09c70292008-10-13 12:12:31 +040012191}
12192
Alexander Gavrilov4db09302008-10-13 12:12:33 +040012193proc cache_gitattr {attr pathlist} {
Paul Mackerras39ee47e2008-10-15 22:23:03 +110012194 global path_attr_cache
12195 set newlist {}
12196 foreach path $pathlist {
12197 if {![info exists path_attr_cache($attr,$path)]} {
12198 lappend newlist $path
Alexander Gavrilov4db09302008-10-13 12:12:33 +040012199 }
Paul Mackerras39ee47e2008-10-15 22:23:03 +110012200 }
12201 set lim 1000
12202 if {[tk windowingsystem] == "win32"} {
12203 # windows has a 32k limit on the arguments to a command...
12204 set lim 30
12205 }
12206 while {$newlist ne {}} {
12207 set head [lrange $newlist 0 [expr {$lim - 1}]]
12208 set newlist [lrange $newlist $lim end]
12209 if {![catch {set rlist [eval exec git check-attr $attr -- $head]}]} {
12210 foreach row [split $rlist "\n"] {
Johannes Sixt097e1112009-07-21 10:09:48 +020012211 if {[regexp "(.*): $attr: (.*)" $row m path value]} {
Paul Mackerras39ee47e2008-10-15 22:23:03 +110012212 if {[string index $path 0] eq "\""} {
12213 set path [encoding convertfrom [lindex $path 0]]
12214 }
12215 set path_attr_cache($attr,$path) $value
Alexander Gavrilov4db09302008-10-13 12:12:33 +040012216 }
Paul Mackerras39ee47e2008-10-15 22:23:03 +110012217 }
Alexander Gavrilov4db09302008-10-13 12:12:33 +040012218 }
Paul Mackerras39ee47e2008-10-15 22:23:03 +110012219 }
Alexander Gavrilov4db09302008-10-13 12:12:33 +040012220}
12221
Alexander Gavrilov09c70292008-10-13 12:12:31 +040012222proc get_path_encoding {path} {
Paul Mackerras39ee47e2008-10-15 22:23:03 +110012223 global gui_encoding perfile_attrs
12224 set tcl_enc $gui_encoding
12225 if {$path ne {} && $perfile_attrs} {
12226 set enc2 [tcl_encoding [gitattr $path encoding $tcl_enc]]
12227 if {$enc2 ne {}} {
12228 set tcl_enc $enc2
Alexander Gavrilov09c70292008-10-13 12:12:31 +040012229 }
Paul Mackerras39ee47e2008-10-15 22:23:03 +110012230 }
12231 return $tcl_enc
Alexander Gavrilov09c70292008-10-13 12:12:31 +040012232}
12233
Alex Henrieef87a482015-05-11 13:26:41 -060012234## For msgcat loading, first locate the installation location.
12235if { [info exists ::env(GITK_MSGSDIR)] } {
12236 ## Msgsdir was manually set in the environment.
12237 set gitk_msgsdir $::env(GITK_MSGSDIR)
12238} else {
12239 ## Let's guess the prefix from argv0.
12240 set gitk_prefix [file dirname [file dirname [file normalize $argv0]]]
12241 set gitk_libdir [file join $gitk_prefix share gitk lib]
12242 set gitk_msgsdir [file join $gitk_libdir msgs]
12243 unset gitk_prefix
12244}
12245
12246## Internationalization (i18n) through msgcat and gettext. See
12247## http://www.gnu.org/software/gettext/manual/html_node/Tcl.html
12248package require msgcat
12249namespace import ::msgcat::mc
12250## And eventually load the actual message catalog
12251::msgcat::mcload $gitk_msgsdir
12252
Paul Mackerras5d7589d2007-10-20 21:21:03 +100012253# First check that Tcl/Tk is recent enough
12254if {[catch {package require Tk 8.4} err]} {
Alex Henrieef87a482015-05-11 13:26:41 -060012255 show_error {} . [mc "Sorry, gitk cannot run with this version of Tcl/Tk.\n\
12256 Gitk requires at least Tcl/Tk 8.4."]
Paul Mackerras5d7589d2007-10-20 21:21:03 +100012257 exit 1
12258}
12259
Tair Sabirgaliev76bf6ff2013-04-24 15:48:27 +060012260# on OSX bring the current Wish process window to front
12261if {[tk windowingsystem] eq "aqua"} {
12262 exec osascript -e [format {
12263 tell application "System Events"
12264 set frontmost of processes whose unix id is %d to true
12265 end tell
12266 } [pid] ]
12267}
12268
Aske Olsson0ae10352012-05-10 12:13:43 +020012269# Unset GIT_TRACE var if set
12270if { [info exists ::env(GIT_TRACE)] } {
12271 unset ::env(GIT_TRACE)
12272}
12273
Paul Mackerras1d10f362005-05-15 12:55:47 +000012274# defaults...
Chris Packhame203d1d2014-11-02 21:37:50 +130012275set wrcomcmd "git diff-tree --stdin -p --pretty=email"
Junio C Hamano671bc152005-11-27 16:12:51 -080012276
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +110012277set gitencoding {}
Junio C Hamano671bc152005-11-27 16:12:51 -080012278catch {
Paul Mackerras27cb61c2007-02-15 08:54:34 +110012279 set gitencoding [exec git config --get i18n.commitencoding]
Junio C Hamano671bc152005-11-27 16:12:51 -080012280}
Alexander Gavrilov590915d2008-11-09 18:06:07 +030012281catch {
12282 set gitencoding [exec git config --get i18n.logoutputencoding]
12283}
Junio C Hamano671bc152005-11-27 16:12:51 -080012284if {$gitencoding == ""} {
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +110012285 set gitencoding "utf-8"
12286}
12287set tclencoding [tcl_encoding $gitencoding]
12288if {$tclencoding == {}} {
12289 puts stderr "Warning: encoding $gitencoding is not supported by Tcl/Tk"
Junio C Hamano671bc152005-11-27 16:12:51 -080012290}
Paul Mackerras1d10f362005-05-15 12:55:47 +000012291
Alexander Gavrilov09c70292008-10-13 12:12:31 +040012292set gui_encoding [encoding system]
12293catch {
Paul Mackerras39ee47e2008-10-15 22:23:03 +110012294 set enc [exec git config --get gui.encoding]
12295 if {$enc ne {}} {
12296 set tclenc [tcl_encoding $enc]
12297 if {$tclenc ne {}} {
12298 set gui_encoding $tclenc
12299 } else {
12300 puts stderr "Warning: encoding $enc is not supported by Tcl/Tk"
12301 }
12302 }
Alexander Gavrilov09c70292008-10-13 12:12:31 +040012303}
12304
Marcus Karlssonb2b76d12011-10-04 22:08:13 +020012305set log_showroot true
12306catch {
12307 set log_showroot [exec git config --bool --get log.showroot]
12308}
12309
Daniel A. Steffen5fdcbb12009-03-23 12:17:38 +010012310if {[tk windowingsystem] eq "aqua"} {
12311 set mainfont {{Lucida Grande} 9}
12312 set textfont {Monaco 9}
12313 set uifont {{Lucida Grande} 9 bold}
Jonathan Nieder5c9096f2012-03-08 06:30:11 -060012314} elseif {![catch {::tk::pkgconfig get fontsystem} xft] && $xft eq "xft"} {
12315 # fontconfig!
12316 set mainfont {sans 9}
12317 set textfont {monospace 9}
12318 set uifont {sans 9 bold}
Daniel A. Steffen5fdcbb12009-03-23 12:17:38 +010012319} else {
12320 set mainfont {Helvetica 9}
12321 set textfont {Courier 9}
12322 set uifont {Helvetica 9 bold}
12323}
Mark Levedahl7e12f1a2007-05-20 11:45:50 -040012324set tabstop 8
Paul Mackerrasb74fd572005-07-16 07:46:13 -040012325set findmergefiles 0
Paul Mackerras8d858d12005-08-05 09:52:16 +100012326set maxgraphpct 50
Paul Mackerrasf6075eb2005-08-18 09:30:10 +100012327set maxwidth 16
Paul Mackerras232475d2005-11-15 10:34:03 +110012328set revlistorder 0
Paul Mackerras757f17b2005-11-21 09:56:07 +110012329set fastdate 0
Paul Mackerras6e8c8702007-07-31 21:03:06 +100012330set uparrowlen 5
12331set downarrowlen 5
12332set mingaplen 100
Paul Mackerrasf8b28a42006-05-01 09:50:57 +100012333set cmitmode "patch"
Sergey Vlasovf1b86292006-05-15 19:13:14 +040012334set wrapcomment "none"
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +100012335set showneartags 1
Thomas Rastffe15292009-08-03 23:53:36 +020012336set hideremotes 0
Paul Mackerras0a4dd8b2007-06-16 21:21:57 +100012337set maxrefs 20
Max Kirillovbde4a0f2014-06-24 08:19:44 +030012338set visiblerefs {"master"}
Paul Mackerras322a8cc2006-10-15 18:03:46 +100012339set maxlinelen 200
Paul Mackerras219ea3a2006-09-07 10:21:39 +100012340set showlocalchanges 1
Paul Mackerras7a39a172007-10-23 10:15:11 +100012341set limitdiffs 1
Arjen Laarhovene8b5f4b2007-08-14 22:02:04 +020012342set datetimeformat "%Y-%m-%d %H:%M:%S"
Jeff King95293b52008-03-06 06:49:25 -050012343set autoselect 1
Paul Mackerras21ac8a82011-03-09 20:52:38 +110012344set autosellen 40
Paul Mackerras39ee47e2008-10-15 22:23:03 +110012345set perfile_attrs 0
Paul Mackerras0cc08ff2009-09-05 22:06:46 +100012346set want_ttk 1
Paul Mackerras1d10f362005-05-15 12:55:47 +000012347
Daniel A. Steffen5fdcbb12009-03-23 12:17:38 +010012348if {[tk windowingsystem] eq "aqua"} {
12349 set extdifftool "opendiff"
12350} else {
12351 set extdifftool "meld"
12352}
Thomas Arcila314f5de2008-03-24 12:55:36 +010012353
Paul Mackerras6e8fda52016-12-12 11:29:21 +110012354set colors {"#00ff00" red blue magenta darkgrey brown orange}
Pat Thoyts1924d1b2009-11-06 23:28:01 +000012355if {[tk windowingsystem] eq "win32"} {
12356 set uicolor SystemButtonFace
Gauthier Östervall252c52d2013-03-27 14:40:51 +010012357 set uifgcolor SystemButtonText
12358 set uifgdisabledcolor SystemDisabledText
Pat Thoyts1924d1b2009-11-06 23:28:01 +000012359 set bgcolor SystemWindow
Gauthier Östervall252c52d2013-03-27 14:40:51 +010012360 set fgcolor SystemWindowText
Pat Thoyts1924d1b2009-11-06 23:28:01 +000012361 set selectbgcolor SystemHighlight
Paul Mackerras3441de52019-08-27 08:12:34 +100012362 set web_browser "cmd /c start"
Pat Thoyts1924d1b2009-11-06 23:28:01 +000012363} else {
12364 set uicolor grey85
Gauthier Östervall252c52d2013-03-27 14:40:51 +010012365 set uifgcolor black
12366 set uifgdisabledcolor "#999"
Pat Thoyts1924d1b2009-11-06 23:28:01 +000012367 set bgcolor white
12368 set fgcolor black
12369 set selectbgcolor gray85
Paul Mackerras3441de52019-08-27 08:12:34 +100012370 if {[tk windowingsystem] eq "aqua"} {
12371 set web_browser "open"
12372 } else {
12373 set web_browser "xdg-open"
12374 }
Pat Thoyts1924d1b2009-11-06 23:28:01 +000012375}
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +100012376set diffcolors {red "#00a000" blue}
Steffen Prohaska890fae72007-08-12 12:05:46 +020012377set diffcontext 3
Paul Mackerras6e8fda52016-12-12 11:29:21 +110012378set mergecolors {red blue "#00ff00" purple brown "#009090" magenta "#808000" "#009000" "#ff0080" cyan "#b07070" "#70b0f0" "#70f0b0" "#f0b070" "#ff70b0"}
Steffen Prohaskab9b86002008-01-17 23:42:55 +010012379set ignorespace 0
Thomas Rastae4e3ff2010-10-16 12:15:10 +020012380set worddiff ""
Paul Mackerrase3e901b2008-10-27 22:37:21 +110012381set markbgcolor "#e0e0ff"
Paul Mackerras1d10f362005-05-15 12:55:47 +000012382
Paul Mackerras6e8fda52016-12-12 11:29:21 +110012383set headbgcolor "#00ff00"
Gauthier Östervall252c52d2013-03-27 14:40:51 +010012384set headfgcolor black
12385set headoutlinecolor black
12386set remotebgcolor #ffddaa
12387set tagbgcolor yellow
12388set tagfgcolor black
12389set tagoutlinecolor black
12390set reflinecolor black
12391set filesepbgcolor #aaaaaa
12392set filesepfgcolor black
12393set linehoverbgcolor #ffff80
12394set linehoverfgcolor black
12395set linehoveroutlinecolor black
12396set mainheadcirclecolor yellow
12397set workingfilescirclecolor red
Paul Mackerras6e8fda52016-12-12 11:29:21 +110012398set indexcirclecolor "#00ff00"
Paul Mackerrasc11ff122008-05-26 10:11:33 +100012399set circlecolors {white blue gray blue blue}
Gauthier Östervall252c52d2013-03-27 14:40:51 +010012400set linkfgcolor blue
12401set circleoutlinecolor $fgcolor
12402set foundbgcolor yellow
12403set currentsearchhitbgcolor orange
Paul Mackerrasc11ff122008-05-26 10:11:33 +100012404
Paul Mackerrasd277e892008-09-21 18:11:37 -050012405# button for popping up context menus
12406if {[tk windowingsystem] eq "aqua"} {
12407 set ctxbut <Button-2>
12408} else {
12409 set ctxbut <Button-3>
12410}
12411
Astril Hayato8f863392014-01-21 19:10:16 +000012412catch {
12413 # follow the XDG base directory specification by default. See
12414 # http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html
12415 if {[info exists env(XDG_CONFIG_HOME)] && $env(XDG_CONFIG_HOME) ne ""} {
12416 # XDG_CONFIG_HOME environment variable is set
12417 set config_file [file join $env(XDG_CONFIG_HOME) git gitk]
12418 set config_file_tmp [file join $env(XDG_CONFIG_HOME) git gitk-tmp]
12419 } else {
12420 # default XDG_CONFIG_HOME
12421 set config_file "~/.config/git/gitk"
12422 set config_file_tmp "~/.config/git/gitk-tmp"
12423 }
12424 if {![file exists $config_file]} {
12425 # for backward compatibility use the old config file if it exists
12426 if {[file exists "~/.gitk"]} {
12427 set config_file "~/.gitk"
12428 set config_file_tmp "~/.gitk-tmp"
12429 } elseif {![file exists [file dirname $config_file]]} {
12430 file mkdir [file dirname $config_file]
12431 }
12432 }
12433 source $config_file
12434}
Max Kirilloveaf7e832015-03-04 05:58:18 +020012435config_check_tmp_exists 50
Paul Mackerras1d10f362005-05-15 12:55:47 +000012436
Max Kirillov9fabefb2014-09-14 23:35:57 +030012437set config_variables {
12438 mainfont textfont uifont tabstop findmergefiles maxgraphpct maxwidth
12439 cmitmode wrapcomment autoselect autosellen showneartags maxrefs visiblerefs
12440 hideremotes showlocalchanges datetimeformat limitdiffs uicolor want_ttk
12441 bgcolor fgcolor uifgcolor uifgdisabledcolor colors diffcolors mergecolors
12442 markbgcolor diffcontext selectbgcolor foundbgcolor currentsearchhitbgcolor
12443 extdifftool perfile_attrs headbgcolor headfgcolor headoutlinecolor
12444 remotebgcolor tagbgcolor tagfgcolor tagoutlinecolor reflinecolor
12445 filesepbgcolor filesepfgcolor linehoverbgcolor linehoverfgcolor
12446 linehoveroutlinecolor mainheadcirclecolor workingfilescirclecolor
12447 indexcirclecolor circlecolors linkfgcolor circleoutlinecolor
Paul Mackerras3441de52019-08-27 08:12:34 +100012448 web_browser
Max Kirillov9fabefb2014-09-14 23:35:57 +030012449}
Max Kirillov995f7922015-03-04 05:58:16 +020012450foreach var $config_variables {
12451 config_init_trace $var
12452 trace add variable $var write config_variable_change_cb
12453}
Max Kirillov9fabefb2014-09-14 23:35:57 +030012454
Paul Mackerras0ed1dd32007-10-06 18:27:37 +100012455parsefont mainfont $mainfont
12456eval font create mainfont [fontflags mainfont]
12457eval font create mainfontbold [fontflags mainfont 1]
12458
12459parsefont textfont $textfont
12460eval font create textfont [fontflags textfont]
12461eval font create textfontbold [fontflags textfont 1]
12462
12463parsefont uifont $uifont
12464eval font create uifont [fontflags uifont]
Paul Mackerras17386062005-05-18 22:51:00 +000012465
Paul Mackerras51a7e8b2009-11-14 21:15:01 +110012466setui $uicolor
Guillermo S. Romero5497f7a2009-10-15 18:51:49 +020012467
Paul Mackerrasb039f0a2008-01-06 15:54:46 +110012468setoptions
12469
Paul Mackerrasaa81d972006-02-28 11:27:12 +110012470# check that we can find a .git directory somewhere...
Martin von Zweigbergk86e847b2011-04-04 22:14:18 -040012471if {[catch {set gitdir [exec git rev-parse --git-dir]}]} {
Christian Stimmingd990ced2007-11-07 18:42:55 +010012472 show_error {} . [mc "Cannot find a git repository here."]
Alex Riesen6c87d602007-07-29 22:29:45 +020012473 exit 1
12474}
Paul Mackerrasaa81d972006-02-28 11:27:12 +110012475
Alexander Gavrilov39816d62008-08-23 12:27:44 +040012476set selecthead {}
12477set selectheadid {}
12478
Paul Mackerrascdaee5d2007-07-12 22:29:49 +100012479set revtreeargs {}
Paul Mackerras098dd8a2006-05-03 09:32:53 +100012480set cmdline_files {}
Paul Mackerrascdaee5d2007-07-12 22:29:49 +100012481set i 0
Yann Dirson2d480852008-02-21 21:23:31 +010012482set revtreeargscmd {}
Paul Mackerrascdaee5d2007-07-12 22:29:49 +100012483foreach arg $argv {
Yann Dirson2d480852008-02-21 21:23:31 +010012484 switch -glob -- $arg {
Paul Mackerras6ebedab2007-07-13 13:45:55 +100012485 "" { }
Paul Mackerrascdaee5d2007-07-12 22:29:49 +100012486 "--" {
12487 set cmdline_files [lrange $argv [expr {$i + 1}] end]
12488 break
12489 }
Alexander Gavrilov39816d62008-08-23 12:27:44 +040012490 "--select-commit=*" {
12491 set selecthead [string range $arg 16 end]
12492 }
Yann Dirson2d480852008-02-21 21:23:31 +010012493 "--argscmd=*" {
12494 set revtreeargscmd [string range $arg 10 end]
12495 }
Paul Mackerrascdaee5d2007-07-12 22:29:49 +100012496 default {
12497 lappend revtreeargs $arg
12498 }
12499 }
12500 incr i
12501}
12502
Alexander Gavrilov39816d62008-08-23 12:27:44 +040012503if {$selecthead eq "HEAD"} {
12504 set selecthead {}
12505}
12506
Paul Mackerrascdaee5d2007-07-12 22:29:49 +100012507if {$i >= [llength $argv] && $revtreeargs ne {}} {
Paul Mackerras3ed31a82008-04-26 16:00:00 +100012508 # no -- on command line, but some arguments (other than --argscmd)
Paul Mackerras098dd8a2006-05-03 09:32:53 +100012509 if {[catch {
Timo Hirvonen8974c6f2006-05-24 10:57:40 +030012510 set f [eval exec git rev-parse --no-revs --no-flags $revtreeargs]
Paul Mackerras098dd8a2006-05-03 09:32:53 +100012511 set cmdline_files [split $f "\n"]
12512 set n [llength $cmdline_files]
12513 set revtreeargs [lrange $revtreeargs 0 end-$n]
Paul Mackerrascdaee5d2007-07-12 22:29:49 +100012514 # Unfortunately git rev-parse doesn't produce an error when
12515 # something is both a revision and a filename. To be consistent
12516 # with git log and git rev-list, check revtreeargs for filenames.
12517 foreach arg $revtreeargs {
12518 if {[file exists $arg]} {
Christian Stimmingd990ced2007-11-07 18:42:55 +010012519 show_error {} . [mc "Ambiguous argument '%s': both revision\
12520 and filename" $arg]
Paul Mackerrascdaee5d2007-07-12 22:29:49 +100012521 exit 1
12522 }
12523 }
Paul Mackerras098dd8a2006-05-03 09:32:53 +100012524 } err]} {
12525 # unfortunately we get both stdout and stderr in $err,
12526 # so look for "fatal:".
12527 set i [string first "fatal:" $err]
12528 if {$i > 0} {
Junio C Hamanob5e09632006-05-26 00:07:15 -070012529 set err [string range $err [expr {$i + 6}] end]
Paul Mackerras098dd8a2006-05-03 09:32:53 +100012530 }
Christian Stimmingd990ced2007-11-07 18:42:55 +010012531 show_error {} . "[mc "Bad arguments to gitk:"]\n$err"
Paul Mackerras098dd8a2006-05-03 09:32:53 +100012532 exit 1
12533 }
12534}
12535
Paul Mackerras219ea3a2006-09-07 10:21:39 +100012536set nullid "0000000000000000000000000000000000000000"
Paul Mackerras8f489362007-07-13 19:49:37 +100012537set nullid2 "0000000000000000000000000000000000000001"
Thomas Arcila314f5de2008-03-24 12:55:36 +010012538set nullfile "/dev/null"
Paul Mackerras8f489362007-07-13 19:49:37 +100012539
Paul Mackerras32f1b3e2007-09-28 21:27:39 +100012540set have_tk85 [expr {[package vcompare $tk_version "8.5"] >= 0}]
Paul Mackerras0cc08ff2009-09-05 22:06:46 +100012541if {![info exists have_ttk]} {
12542 set have_ttk [llength [info commands ::ttk::style]]
Pat Thoytsd93f1712009-04-17 01:24:35 +010012543}
Paul Mackerras0cc08ff2009-09-05 22:06:46 +100012544set use_ttk [expr {$have_ttk && $want_ttk}]
Pat Thoytsd93f1712009-04-17 01:24:35 +010012545set NS [expr {$use_ttk ? "ttk" : ""}]
Paul Mackerras0cc08ff2009-09-05 22:06:46 +100012546
Giuseppe Bilotta6cb73c82015-12-08 08:05:50 +010012547if {$use_ttk} {
12548 setttkstyle
12549}
12550
Anders Kaseorg7add5af2011-01-06 17:42:33 -070012551regexp {^git version ([\d.]*\d)} [exec git version] _ git_version
Paul Mackerras219ea3a2006-09-07 10:21:39 +100012552
Kirill Smelkov7defefb2010-05-20 13:50:41 +040012553set show_notes {}
12554if {[package vcompare $git_version "1.6.6.2"] >= 0} {
12555 set show_notes "--show-notes"
12556}
12557
Zbigniew Jędrzejewski-Szmek3878e632011-11-09 17:28:28 +010012558set appname "gitk"
12559
Paul Mackerras7eb3cb92007-06-17 14:45:00 +100012560set runq {}
Paul Mackerrasd6982062005-08-06 22:06:06 +100012561set history {}
12562set historyindex 0
Paul Mackerras908c3582006-05-20 09:38:11 +100012563set fh_serial 0
Paul Mackerras908c3582006-05-20 09:38:11 +100012564set nhl_names {}
Paul Mackerras63b79192006-05-20 21:31:52 +100012565set highlight_paths {}
Paul Mackerras687c8762007-09-22 12:49:33 +100012566set findpattern {}
Paul Mackerras1902c272006-05-25 21:25:13 +100012567set searchdirn -forwards
Paul Mackerras28593d32008-11-13 23:01:46 +110012568set boldids {}
12569set boldnameids {}
Paul Mackerrasa8d610a2007-04-19 11:39:12 +100012570set diffelide {0 0}
Paul Mackerras4fb0fa12007-07-04 19:43:51 +100012571set markingmatches 0
Paul Mackerras97645682007-08-23 22:24:38 +100012572set linkentercount 0
Paul Mackerras03800812007-08-29 21:45:21 +100012573set need_redisplay 0
12574set nrows_drawn 0
Paul Mackerras32f1b3e2007-09-28 21:27:39 +100012575set firsttabstop 0
Paul Mackerras9f1afe02006-02-19 22:44:47 +110012576
Paul Mackerras50b44ec2006-04-04 10:16:22 +100012577set nextviewnum 1
12578set curview 0
Paul Mackerrasa90a6d22006-04-25 17:12:46 +100012579set selectedview 0
Christian Stimmingb007ee22007-11-07 18:44:35 +010012580set selectedhlview [mc "None"]
12581set highlight_related [mc "None"]
Paul Mackerras687c8762007-09-22 12:49:33 +100012582set highlight_files {}
Paul Mackerras50b44ec2006-04-04 10:16:22 +100012583set viewfiles(0) {}
Paul Mackerrasa90a6d22006-04-25 17:12:46 +100012584set viewperm(0) 0
Max Kirillov995f7922015-03-04 05:58:16 +020012585set viewchanged(0) 0
Paul Mackerras098dd8a2006-05-03 09:32:53 +100012586set viewargs(0) {}
Yann Dirson2d480852008-02-21 21:23:31 +010012587set viewargscmd(0) {}
Paul Mackerras50b44ec2006-04-04 10:16:22 +100012588
Paul Mackerras94b4a692008-05-20 20:51:06 +100012589set selectedline {}
Paul Mackerras6df74032008-05-11 22:13:02 +100012590set numcommits 0
Paul Mackerras7fcc92b2007-12-03 10:33:01 +110012591set loginstance 0
Paul Mackerras098dd8a2006-05-03 09:32:53 +100012592set cmdlineok 0
Paul Mackerras1d10f362005-05-15 12:55:47 +000012593set stopped 0
Paul Mackerras0fba86b2005-05-16 23:54:58 +000012594set stuffsaved 0
Paul Mackerras74daedb2005-06-27 19:27:32 +100012595set patchnum 0
Paul Mackerras219ea3a2006-09-07 10:21:39 +100012596set lserial 0
Martin von Zweigbergk74cb8842011-05-23 22:44:08 -040012597set hasworktree [hasworktree]
Martin von Zweigbergkc332f442011-04-04 22:14:12 -040012598set cdup {}
Martin von Zweigbergk74cb8842011-05-23 22:44:08 -040012599if {[expr {[exec git rev-parse --is-inside-work-tree] == "true"}]} {
Martin von Zweigbergkc332f442011-04-04 22:14:12 -040012600 set cdup [exec git rev-parse --show-cdup]
12601}
Martin von Zweigbergk784b7e22011-04-04 22:14:15 -040012602set worktree [exec git rev-parse --show-toplevel]
Paul Mackerras1d10f362005-05-15 12:55:47 +000012603setcoords
Paul Mackerrasd94f8cd2006-04-06 10:18:23 +100012604makewindow
Giuseppe Bilotta37871b72009-03-19 01:54:17 -070012605catch {
12606 image create photo gitlogo -width 16 -height 16
12607
12608 image create photo gitlogominus -width 4 -height 2
12609 gitlogominus put #C00000 -to 0 0 4 2
12610 gitlogo copy gitlogominus -to 1 5
12611 gitlogo copy gitlogominus -to 6 5
12612 gitlogo copy gitlogominus -to 11 5
12613 image delete gitlogominus
12614
12615 image create photo gitlogoplus -width 4 -height 4
12616 gitlogoplus put #008000 -to 1 0 3 4
12617 gitlogoplus put #008000 -to 0 1 4 3
12618 gitlogo copy gitlogoplus -to 1 9
12619 gitlogo copy gitlogoplus -to 6 9
12620 gitlogo copy gitlogoplus -to 11 9
12621 image delete gitlogoplus
12622
Stephen Boydd38d7d42009-03-19 01:54:18 -070012623 image create photo gitlogo32 -width 32 -height 32
12624 gitlogo32 copy gitlogo -zoom 2 2
12625
12626 wm iconphoto . -default gitlogo gitlogo32
Giuseppe Bilotta37871b72009-03-19 01:54:17 -070012627}
Paul Mackerras0eafba12007-07-23 21:35:03 +100012628# wait for the window to become visible
12629tkwait visibility .
Marc Branchaud9922c5a2015-04-07 11:51:51 -040012630set_window_title
Pat Thoyts478afad2009-04-15 17:14:03 +010012631update
Paul Mackerras887fe3c2005-05-21 07:35:37 +000012632readrefs
Paul Mackerrasa8aaf192006-04-23 22:45:55 +100012633
Yann Dirson2d480852008-02-21 21:23:31 +010012634if {$cmdline_files ne {} || $revtreeargs ne {} || $revtreeargscmd ne {}} {
Paul Mackerras50b44ec2006-04-04 10:16:22 +100012635 # create a view for the files/dirs specified on the command line
12636 set curview 1
Paul Mackerrasa90a6d22006-04-25 17:12:46 +100012637 set selectedview 1
Paul Mackerras50b44ec2006-04-04 10:16:22 +100012638 set nextviewnum 2
Christian Stimmingd990ced2007-11-07 18:42:55 +010012639 set viewname(1) [mc "Command line"]
Paul Mackerras50b44ec2006-04-04 10:16:22 +100012640 set viewfiles(1) $cmdline_files
Paul Mackerras098dd8a2006-05-03 09:32:53 +100012641 set viewargs(1) $revtreeargs
Yann Dirson2d480852008-02-21 21:23:31 +010012642 set viewargscmd(1) $revtreeargscmd
Paul Mackerrasa90a6d22006-04-25 17:12:46 +100012643 set viewperm(1) 0
Max Kirillov995f7922015-03-04 05:58:16 +020012644 set viewchanged(1) 0
Paul Mackerras3ed31a82008-04-26 16:00:00 +100012645 set vdatemode(1) 0
Paul Mackerrasda7c24d2006-05-02 11:15:29 +100012646 addviewmenu 1
Beat Bolli28de5682015-09-30 21:50:11 +020012647 .bar.view entryconf [mca "&Edit view..."] -state normal
12648 .bar.view entryconf [mca "&Delete view"] -state normal
Paul Mackerras50b44ec2006-04-04 10:16:22 +100012649}
Paul Mackerrasa90a6d22006-04-25 17:12:46 +100012650
12651if {[info exists permviews]} {
12652 foreach v $permviews {
12653 set n $nextviewnum
12654 incr nextviewnum
12655 set viewname($n) [lindex $v 0]
12656 set viewfiles($n) [lindex $v 1]
Paul Mackerras098dd8a2006-05-03 09:32:53 +100012657 set viewargs($n) [lindex $v 2]
Yann Dirson2d480852008-02-21 21:23:31 +010012658 set viewargscmd($n) [lindex $v 3]
Paul Mackerrasa90a6d22006-04-25 17:12:46 +100012659 set viewperm($n) 1
Max Kirillov995f7922015-03-04 05:58:16 +020012660 set viewchanged($n) 0
Paul Mackerrasda7c24d2006-05-02 11:15:29 +100012661 addviewmenu $n
Paul Mackerrasa90a6d22006-04-25 17:12:46 +100012662 }
12663}
Johannes Sixte4df5192008-12-18 08:30:49 +010012664
12665if {[tk windowingsystem] eq "win32"} {
12666 focus -force .
12667}
12668
Alexander Gavrilov567c34e2008-07-26 20:13:45 +040012669getcommits {}
Pat Thoytsadab0da2010-03-12 18:31:48 +000012670
12671# Local variables:
12672# mode: tcl
12673# indent-tabs-mode: t
12674# tab-width: 8
12675# End: