blob: 9a2daf3c55b2292239ec9667a919b5121a7e965e [file] [log] [blame]
Paul Mackerras1db95b02005-05-09 04:08:39 +00001#!/bin/sh
2# Tcl ignores the next line -*- tcl -*- \
Paul Mackerras9e026d32005-09-27 10:29:41 +10003exec wish "$0" -- "$@"
Paul Mackerras1db95b02005-05-09 04:08:39 +00004
Paul Mackerras6c626a02014-01-21 22:02:27 +11005# Copyright © 2005-2014 Paul Mackerras. All rights reserved.
Paul Mackerras1db95b02005-05-09 04:08:39 +00006# This program is free software; it may be used, copied, modified
7# and distributed under the terms of the GNU General Public Licence,
8# either version 2, or (at your option) any later version.
9
Pat Thoytsd93f1712009-04-17 01:24:35 +010010package require Tk
11
Martin von Zweigbergk74cb8842011-05-23 22:44:08 -040012proc hasworktree {} {
13 return [expr {[exec git rev-parse --is-bare-repository] == "false" &&
14 [exec git rev-parse --is-inside-git-dir] == "false"}]
15}
16
Zbigniew Jędrzejewski-Szmek3878e632011-11-09 17:28:28 +010017proc reponame {} {
18 global gitdir
19 set n [file normalize $gitdir]
20 if {[string match "*/.git" $n]} {
21 set n [string range $n 0 end-5]
22 }
23 return [file tail $n]
24}
25
Pat Thoyts65bb0bd2011-12-13 16:50:50 +000026proc gitworktree {} {
27 variable _gitworktree
28 if {[info exists _gitworktree]} {
29 return $_gitworktree
30 }
31 # v1.7.0 introduced --show-toplevel to return the canonical work-tree
32 if {[catch {set _gitworktree [exec git rev-parse --show-toplevel]}]} {
33 # try to set work tree from environment, core.worktree or use
34 # cdup to obtain a relative path to the top of the worktree. If
35 # run from the top, the ./ prefix ensures normalize expands pwd.
36 if {[catch { set _gitworktree $env(GIT_WORK_TREE) }]} {
37 catch {set _gitworktree [exec git config --get core.worktree]}
38 if {$_gitworktree eq ""} {
39 set _gitworktree [file normalize ./[exec git rev-parse --show-cdup]]
40 }
41 }
42 }
43 return $_gitworktree
44}
45
Paul Mackerras7eb3cb92007-06-17 14:45:00 +100046# A simple scheduler for compute-intensive stuff.
47# The aim is to make sure that event handlers for GUI actions can
48# run at least every 50-100 ms. Unfortunately fileevent handlers are
49# run before X event handlers, so reading from a fast source can
50# make the GUI completely unresponsive.
51proc run args {
Alexander Gavrilovdf75e862008-08-09 14:41:50 +040052 global isonrunq runq currunq
Paul Mackerras7eb3cb92007-06-17 14:45:00 +100053
54 set script $args
55 if {[info exists isonrunq($script)]} return
Alexander Gavrilovdf75e862008-08-09 14:41:50 +040056 if {$runq eq {} && ![info exists currunq]} {
Paul Mackerras7eb3cb92007-06-17 14:45:00 +100057 after idle dorunq
58 }
59 lappend runq [list {} $script]
60 set isonrunq($script) 1
61}
62
63proc filerun {fd script} {
64 fileevent $fd readable [list filereadable $fd $script]
65}
66
67proc filereadable {fd script} {
Alexander Gavrilovdf75e862008-08-09 14:41:50 +040068 global runq currunq
Paul Mackerras7eb3cb92007-06-17 14:45:00 +100069
70 fileevent $fd readable {}
Alexander Gavrilovdf75e862008-08-09 14:41:50 +040071 if {$runq eq {} && ![info exists currunq]} {
Paul Mackerras7eb3cb92007-06-17 14:45:00 +100072 after idle dorunq
73 }
74 lappend runq [list $fd $script]
75}
76
Paul Mackerras7fcc92b2007-12-03 10:33:01 +110077proc nukefile {fd} {
78 global runq
79
80 for {set i 0} {$i < [llength $runq]} {} {
81 if {[lindex $runq $i 0] eq $fd} {
82 set runq [lreplace $runq $i $i]
83 } else {
84 incr i
85 }
86 }
87}
88
Paul Mackerras7eb3cb92007-06-17 14:45:00 +100089proc dorunq {} {
Alexander Gavrilovdf75e862008-08-09 14:41:50 +040090 global isonrunq runq currunq
Paul Mackerras7eb3cb92007-06-17 14:45:00 +100091
92 set tstart [clock clicks -milliseconds]
93 set t0 $tstart
Paul Mackerras7fcc92b2007-12-03 10:33:01 +110094 while {[llength $runq] > 0} {
Paul Mackerras7eb3cb92007-06-17 14:45:00 +100095 set fd [lindex $runq 0 0]
96 set script [lindex $runq 0 1]
Alexander Gavrilovdf75e862008-08-09 14:41:50 +040097 set currunq [lindex $runq 0]
98 set runq [lrange $runq 1 end]
Paul Mackerras7eb3cb92007-06-17 14:45:00 +100099 set repeat [eval $script]
Alexander Gavrilovdf75e862008-08-09 14:41:50 +0400100 unset currunq
Paul Mackerras7eb3cb92007-06-17 14:45:00 +1000101 set t1 [clock clicks -milliseconds]
102 set t [expr {$t1 - $t0}]
Paul Mackerras7eb3cb92007-06-17 14:45:00 +1000103 if {$repeat ne {} && $repeat} {
104 if {$fd eq {} || $repeat == 2} {
105 # script returns 1 if it wants to be readded
106 # file readers return 2 if they could do more straight away
107 lappend runq [list $fd $script]
108 } else {
109 fileevent $fd readable [list filereadable $fd $script]
110 }
111 } elseif {$fd eq {}} {
112 unset isonrunq($script)
113 }
114 set t0 $t1
115 if {$t1 - $tstart >= 80} break
116 }
117 if {$runq ne {}} {
118 after idle dorunq
119 }
120}
121
Alexander Gavrilove439e092008-07-13 16:40:47 +0400122proc reg_instance {fd} {
123 global commfd leftover loginstance
124
125 set i [incr loginstance]
126 set commfd($i) $fd
127 set leftover($i) {}
128 return $i
129}
130
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000131proc unmerged_files {files} {
132 global nr_unmerged
133
134 # find the list of unmerged files
135 set mlist {}
136 set nr_unmerged 0
137 if {[catch {
138 set fd [open "| git ls-files -u" r]
139 } err]} {
140 show_error {} . "[mc "Couldn't get list of unmerged files:"] $err"
141 exit 1
142 }
143 while {[gets $fd line] >= 0} {
144 set i [string first "\t" $line]
145 if {$i < 0} continue
146 set fname [string range $line [expr {$i+1}] end]
147 if {[lsearch -exact $mlist $fname] >= 0} continue
148 incr nr_unmerged
149 if {$files eq {} || [path_filter $files $fname]} {
150 lappend mlist $fname
151 }
152 }
153 catch {close $fd}
154 return $mlist
155}
156
157proc parseviewargs {n arglist} {
Christian Couderc2f2dab2009-12-12 05:52:39 +0100158 global vdatemode vmergeonly vflags vdflags vrevs vfiltered vorigargs env
Thomas Rast9403bd02013-11-16 18:37:43 +0100159 global vinlinediff
Thomas Rastae4e3ff2010-10-16 12:15:10 +0200160 global worddiff git_version
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000161
162 set vdatemode($n) 0
163 set vmergeonly($n) 0
Thomas Rast9403bd02013-11-16 18:37:43 +0100164 set vinlinediff($n) 0
Paul Mackerrasee66e082008-05-09 10:14:07 +1000165 set glflags {}
166 set diffargs {}
167 set nextisval 0
168 set revargs {}
169 set origargs $arglist
170 set allknown 1
171 set filtered 0
172 set i -1
173 foreach arg $arglist {
174 incr i
175 if {$nextisval} {
176 lappend glflags $arg
177 set nextisval 0
178 continue
179 }
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000180 switch -glob -- $arg {
181 "-d" -
182 "--date-order" {
183 set vdatemode($n) 1
Paul Mackerrasee66e082008-05-09 10:14:07 +1000184 # remove from origargs in case we hit an unknown option
185 set origargs [lreplace $origargs $i $i]
186 incr i -1
187 }
Paul Mackerrasee66e082008-05-09 10:14:07 +1000188 "-[puabwcrRBMC]" -
189 "--no-renames" - "--full-index" - "--binary" - "--abbrev=*" -
190 "--find-copies-harder" - "-l*" - "--ext-diff" - "--no-ext-diff" -
191 "--src-prefix=*" - "--dst-prefix=*" - "--no-prefix" -
192 "-O*" - "--text" - "--full-diff" - "--ignore-space-at-eol" -
193 "--ignore-space-change" - "-U*" - "--unified=*" {
Paul Mackerras29582282008-11-18 19:44:20 +1100194 # These request or affect diff output, which we don't want.
195 # Some could be used to set our defaults for diff display.
Paul Mackerrasee66e082008-05-09 10:14:07 +1000196 lappend diffargs $arg
197 }
Paul Mackerrasee66e082008-05-09 10:14:07 +1000198 "--raw" - "--patch-with-raw" - "--patch-with-stat" -
Thomas Rastae4e3ff2010-10-16 12:15:10 +0200199 "--name-only" - "--name-status" - "--color" -
Paul Mackerrasee66e082008-05-09 10:14:07 +1000200 "--log-size" - "--pretty=*" - "--decorate" - "--abbrev-commit" -
201 "--cc" - "-z" - "--header" - "--parents" - "--boundary" -
202 "--no-color" - "-g" - "--walk-reflogs" - "--no-walk" -
203 "--timestamp" - "relative-date" - "--date=*" - "--stdin" -
204 "--objects" - "--objects-edge" - "--reverse" {
Paul Mackerras29582282008-11-18 19:44:20 +1100205 # These cause our parsing of git log's output to fail, or else
206 # they're options we want to set ourselves, so ignore them.
Paul Mackerrasee66e082008-05-09 10:14:07 +1000207 }
Thomas Rastae4e3ff2010-10-16 12:15:10 +0200208 "--color-words*" - "--word-diff=color" {
209 # These trigger a word diff in the console interface,
210 # so help the user by enabling our own support
211 if {[package vcompare $git_version "1.7.2"] >= 0} {
212 set worddiff [mc "Color words"]
213 }
214 }
215 "--word-diff*" {
216 if {[package vcompare $git_version "1.7.2"] >= 0} {
217 set worddiff [mc "Markup words"]
218 }
219 }
Paul Mackerrasee66e082008-05-09 10:14:07 +1000220 "--stat=*" - "--numstat" - "--shortstat" - "--summary" -
221 "--check" - "--exit-code" - "--quiet" - "--topo-order" -
222 "--full-history" - "--dense" - "--sparse" -
223 "--follow" - "--left-right" - "--encoding=*" {
Paul Mackerras29582282008-11-18 19:44:20 +1100224 # These are harmless, and some are even useful
Paul Mackerrasee66e082008-05-09 10:14:07 +1000225 lappend glflags $arg
226 }
Paul Mackerrasee66e082008-05-09 10:14:07 +1000227 "--diff-filter=*" - "--no-merges" - "--unpacked" -
228 "--max-count=*" - "--skip=*" - "--since=*" - "--after=*" -
229 "--until=*" - "--before=*" - "--max-age=*" - "--min-age=*" -
230 "--author=*" - "--committer=*" - "--grep=*" - "-[iE]" -
231 "--remove-empty" - "--first-parent" - "--cherry-pick" -
Thomas Rast71846c52013-11-16 18:37:40 +0100232 "-S*" - "-G*" - "--pickaxe-all" - "--pickaxe-regex" -
Dirk Suesserottf687aaa2009-05-21 15:35:40 +0200233 "--simplify-by-decoration" {
Paul Mackerras29582282008-11-18 19:44:20 +1100234 # These mean that we get a subset of the commits
Paul Mackerrasee66e082008-05-09 10:14:07 +1000235 set filtered 1
236 lappend glflags $arg
237 }
Thomas Rastce2c58c2013-11-16 18:37:44 +0100238 "-L*" {
239 # Line-log with 'stuck' argument (unstuck form is
240 # not supported)
241 set filtered 1
242 set vinlinediff($n) 1
243 set allknown 0
244 lappend glflags $arg
245 }
Paul Mackerrasee66e082008-05-09 10:14:07 +1000246 "-n" {
Paul Mackerras29582282008-11-18 19:44:20 +1100247 # This appears to be the only one that has a value as a
248 # separate word following it
Paul Mackerrasee66e082008-05-09 10:14:07 +1000249 set filtered 1
250 set nextisval 1
251 lappend glflags $arg
252 }
Paul Mackerras6e7e87c2008-12-02 09:17:46 +1100253 "--not" - "--all" {
Paul Mackerrasee66e082008-05-09 10:14:07 +1000254 lappend revargs $arg
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000255 }
256 "--merge" {
257 set vmergeonly($n) 1
Paul Mackerrasee66e082008-05-09 10:14:07 +1000258 # git rev-parse doesn't understand --merge
259 lappend revargs --gitk-symmetric-diff-marker MERGE_HEAD...HEAD
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000260 }
Christian Couderc2f2dab2009-12-12 05:52:39 +0100261 "--no-replace-objects" {
262 set env(GIT_NO_REPLACE_OBJECTS) "1"
263 }
Paul Mackerrasee66e082008-05-09 10:14:07 +1000264 "-*" {
Paul Mackerras29582282008-11-18 19:44:20 +1100265 # Other flag arguments including -<n>
Paul Mackerrasee66e082008-05-09 10:14:07 +1000266 if {[string is digit -strict [string range $arg 1 end]]} {
267 set filtered 1
268 } else {
269 # a flag argument that we don't recognize;
270 # that means we can't optimize
271 set allknown 0
272 }
273 lappend glflags $arg
274 }
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000275 default {
Paul Mackerras29582282008-11-18 19:44:20 +1100276 # Non-flag arguments specify commits or ranges of commits
Paul Mackerrasee66e082008-05-09 10:14:07 +1000277 if {[string match "*...*" $arg]} {
278 lappend revargs --gitk-symmetric-diff-marker
279 }
280 lappend revargs $arg
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000281 }
282 }
283 }
Paul Mackerrasee66e082008-05-09 10:14:07 +1000284 set vdflags($n) $diffargs
285 set vflags($n) $glflags
286 set vrevs($n) $revargs
287 set vfiltered($n) $filtered
288 set vorigargs($n) $origargs
289 return $allknown
290}
291
292proc parseviewrevs {view revs} {
293 global vposids vnegids
294
295 if {$revs eq {}} {
296 set revs HEAD
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
Paul Mackerras6df74032008-05-11 22:13:02 +1000591 global targetid
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 Mackerras7fcc92b2007-12-03 10:33:01 +1100603 catch {unset currentid}
604 catch {unset thickerline}
605 catch {unset treediffs}
606 readrefs
607 changedrefs
608 if {$showneartags} {
609 getallcommits
610 }
611 clear_display
612 catch {unset commitinterest}
613 catch {unset cached_commitrow}
Paul Mackerras42a671f2008-01-02 09:59:39 +1100614 catch {unset targetid}
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100615 setcanvscroll
Alexander Gavrilov567c34e2008-07-26 20:13:45 +0400616 getcommits $selid
Paul Mackerrase7297a12008-01-15 22:30:40 +1100617 return 0
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100618}
619
Paul Mackerras6e8c8702007-07-31 21:03:06 +1000620# This makes a string representation of a positive integer which
621# sorts as a string in numerical order
622proc strrep {n} {
623 if {$n < 16} {
624 return [format "%x" $n]
625 } elseif {$n < 256} {
626 return [format "x%.2x" $n]
627 } elseif {$n < 65536} {
628 return [format "y%.4x" $n]
629 }
630 return [format "z%.8x" $n]
631}
632
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100633# Procedures used in reordering commits from git log (without
634# --topo-order) into the order for display.
635
636proc varcinit {view} {
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100637 global varcstart vupptr vdownptr vleftptr vbackptr varctok varcrow
638 global vtokmod varcmod vrowmod varcix vlastins
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100639
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100640 set varcstart($view) {{}}
641 set vupptr($view) {0}
642 set vdownptr($view) {0}
643 set vleftptr($view) {0}
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100644 set vbackptr($view) {0}
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100645 set varctok($view) {{}}
646 set varcrow($view) {{}}
647 set vtokmod($view) {}
648 set varcmod($view) 0
Paul Mackerrase5b37ac2007-12-12 18:13:51 +1100649 set vrowmod($view) 0
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100650 set varcix($view) {{}}
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100651 set vlastins($view) {0}
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100652}
653
654proc resetvarcs {view} {
655 global varcid varccommits parents children vseedcount ordertok
Paul Mackerras22387f22012-03-19 11:21:08 +1100656 global vshortids
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100657
658 foreach vid [array names varcid $view,*] {
659 unset varcid($vid)
660 unset children($vid)
661 unset parents($vid)
662 }
Paul Mackerras22387f22012-03-19 11:21:08 +1100663 foreach vid [array names vshortids $view,*] {
664 unset vshortids($vid)
665 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100666 # some commits might have children but haven't been seen yet
667 foreach vid [array names children $view,*] {
668 unset children($vid)
669 }
670 foreach va [array names varccommits $view,*] {
671 unset varccommits($va)
672 }
673 foreach vd [array names vseedcount $view,*] {
674 unset vseedcount($vd)
675 }
Paul Mackerras9257d8f2007-12-11 10:45:38 +1100676 catch {unset ordertok}
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100677}
678
Paul Mackerras468bcae2008-03-03 10:19:35 +1100679# returns a list of the commits with no children
680proc seeds {v} {
681 global vdownptr vleftptr varcstart
682
683 set ret {}
684 set a [lindex $vdownptr($v) 0]
685 while {$a != 0} {
686 lappend ret [lindex $varcstart($v) $a]
687 set a [lindex $vleftptr($v) $a]
688 }
689 return $ret
690}
691
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100692proc newvarc {view id} {
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000693 global varcid varctok parents children vdatemode
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100694 global vupptr vdownptr vleftptr vbackptr varcrow varcix varcstart
695 global commitdata commitinfo vseedcount varccommits vlastins
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100696
697 set a [llength $varctok($view)]
698 set vid $view,$id
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000699 if {[llength $children($vid)] == 0 || $vdatemode($view)} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100700 if {![info exists commitinfo($id)]} {
701 parsecommit $id $commitdata($id) 1
702 }
Anders Kaseorgf5974d92011-01-19 14:47:25 -0500703 set cdate [lindex [lindex $commitinfo($id) 4] 0]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100704 if {![string is integer -strict $cdate]} {
705 set cdate 0
706 }
707 if {![info exists vseedcount($view,$cdate)]} {
708 set vseedcount($view,$cdate) -1
709 }
710 set c [incr vseedcount($view,$cdate)]
711 set cdate [expr {$cdate ^ 0xffffffff}]
712 set tok "s[strrep $cdate][strrep $c]"
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100713 } else {
714 set tok {}
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100715 }
716 set ka 0
717 if {[llength $children($vid)] > 0} {
718 set kid [lindex $children($vid) end]
719 set k $varcid($view,$kid)
720 if {[string compare [lindex $varctok($view) $k] $tok] > 0} {
721 set ki $kid
722 set ka $k
723 set tok [lindex $varctok($view) $k]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100724 }
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100725 }
726 if {$ka != 0} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100727 set i [lsearch -exact $parents($view,$ki) $id]
728 set j [expr {[llength $parents($view,$ki)] - 1 - $i}]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100729 append tok [strrep $j]
730 }
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100731 set c [lindex $vlastins($view) $ka]
732 if {$c == 0 || [string compare $tok [lindex $varctok($view) $c]] < 0} {
733 set c $ka
734 set b [lindex $vdownptr($view) $ka]
735 } else {
736 set b [lindex $vleftptr($view) $c]
737 }
738 while {$b != 0 && [string compare $tok [lindex $varctok($view) $b]] >= 0} {
739 set c $b
740 set b [lindex $vleftptr($view) $c]
741 }
742 if {$c == $ka} {
743 lset vdownptr($view) $ka $a
744 lappend vbackptr($view) 0
745 } else {
746 lset vleftptr($view) $c $a
747 lappend vbackptr($view) $c
748 }
749 lset vlastins($view) $ka $a
750 lappend vupptr($view) $ka
751 lappend vleftptr($view) $b
752 if {$b != 0} {
753 lset vbackptr($view) $b $a
754 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100755 lappend varctok($view) $tok
756 lappend varcstart($view) $id
757 lappend vdownptr($view) 0
758 lappend varcrow($view) {}
759 lappend varcix($view) {}
Paul Mackerrase5b37ac2007-12-12 18:13:51 +1100760 set varccommits($view,$a) {}
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100761 lappend vlastins($view) 0
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100762 return $a
763}
764
765proc splitvarc {p v} {
Paul Mackerras52b8ea92009-03-02 09:38:17 +1100766 global varcid varcstart varccommits varctok vtokmod
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100767 global vupptr vdownptr vleftptr vbackptr varcix varcrow vlastins
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100768
769 set oa $varcid($v,$p)
Paul Mackerras52b8ea92009-03-02 09:38:17 +1100770 set otok [lindex $varctok($v) $oa]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100771 set ac $varccommits($v,$oa)
772 set i [lsearch -exact $varccommits($v,$oa) $p]
773 if {$i <= 0} return
774 set na [llength $varctok($v)]
775 # "%" sorts before "0"...
Paul Mackerras52b8ea92009-03-02 09:38:17 +1100776 set tok "$otok%[strrep $i]"
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100777 lappend varctok($v) $tok
778 lappend varcrow($v) {}
779 lappend varcix($v) {}
780 set varccommits($v,$oa) [lrange $ac 0 [expr {$i - 1}]]
781 set varccommits($v,$na) [lrange $ac $i end]
782 lappend varcstart($v) $p
783 foreach id $varccommits($v,$na) {
784 set varcid($v,$id) $na
785 }
786 lappend vdownptr($v) [lindex $vdownptr($v) $oa]
Paul Mackerras841ea822008-02-18 10:44:33 +1100787 lappend vlastins($v) [lindex $vlastins($v) $oa]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100788 lset vdownptr($v) $oa $na
Paul Mackerras841ea822008-02-18 10:44:33 +1100789 lset vlastins($v) $oa 0
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100790 lappend vupptr($v) $oa
791 lappend vleftptr($v) 0
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100792 lappend vbackptr($v) 0
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100793 for {set b [lindex $vdownptr($v) $na]} {$b != 0} {set b [lindex $vleftptr($v) $b]} {
794 lset vupptr($v) $b $na
795 }
Paul Mackerras52b8ea92009-03-02 09:38:17 +1100796 if {[string compare $otok $vtokmod($v)] <= 0} {
797 modify_arc $v $oa
798 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100799}
800
801proc renumbervarc {a v} {
802 global parents children varctok varcstart varccommits
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000803 global vupptr vdownptr vleftptr vbackptr vlastins varcid vtokmod vdatemode
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100804
805 set t1 [clock clicks -milliseconds]
806 set todo {}
807 set isrelated($a) 1
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100808 set kidchanged($a) 1
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100809 set ntot 0
810 while {$a != 0} {
811 if {[info exists isrelated($a)]} {
812 lappend todo $a
813 set id [lindex $varccommits($v,$a) end]
814 foreach p $parents($v,$id) {
815 if {[info exists varcid($v,$p)]} {
816 set isrelated($varcid($v,$p)) 1
817 }
818 }
819 }
820 incr ntot
821 set b [lindex $vdownptr($v) $a]
822 if {$b == 0} {
823 while {$a != 0} {
824 set b [lindex $vleftptr($v) $a]
825 if {$b != 0} break
826 set a [lindex $vupptr($v) $a]
827 }
828 }
829 set a $b
830 }
831 foreach a $todo {
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100832 if {![info exists kidchanged($a)]} continue
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100833 set id [lindex $varcstart($v) $a]
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100834 if {[llength $children($v,$id)] > 1} {
835 set children($v,$id) [lsort -command [list vtokcmp $v] \
836 $children($v,$id)]
837 }
838 set oldtok [lindex $varctok($v) $a]
Paul Mackerras3ed31a82008-04-26 16:00:00 +1000839 if {!$vdatemode($v)} {
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100840 set tok {}
841 } else {
842 set tok $oldtok
843 }
844 set ka 0
Paul Mackerrasc8c9f3d2008-01-06 13:54:58 +1100845 set kid [last_real_child $v,$id]
846 if {$kid ne {}} {
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100847 set k $varcid($v,$kid)
848 if {[string compare [lindex $varctok($v) $k] $tok] > 0} {
849 set ki $kid
850 set ka $k
851 set tok [lindex $varctok($v) $k]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100852 }
853 }
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100854 if {$ka != 0} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100855 set i [lsearch -exact $parents($v,$ki) $id]
856 set j [expr {[llength $parents($v,$ki)] - 1 - $i}]
857 append tok [strrep $j]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100858 }
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100859 if {$tok eq $oldtok} {
860 continue
861 }
862 set id [lindex $varccommits($v,$a) end]
863 foreach p $parents($v,$id) {
864 if {[info exists varcid($v,$p)]} {
865 set kidchanged($varcid($v,$p)) 1
866 } else {
867 set sortkids($p) 1
868 }
869 }
870 lset varctok($v) $a $tok
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100871 set b [lindex $vupptr($v) $a]
872 if {$b != $ka} {
Paul Mackerras9257d8f2007-12-11 10:45:38 +1100873 if {[string compare [lindex $varctok($v) $ka] $vtokmod($v)] < 0} {
874 modify_arc $v $ka
Paul Mackerras38dfe932007-12-06 20:50:31 +1100875 }
Paul Mackerras9257d8f2007-12-11 10:45:38 +1100876 if {[string compare [lindex $varctok($v) $b] $vtokmod($v)] < 0} {
877 modify_arc $v $b
Paul Mackerras38dfe932007-12-06 20:50:31 +1100878 }
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100879 set c [lindex $vbackptr($v) $a]
880 set d [lindex $vleftptr($v) $a]
881 if {$c == 0} {
882 lset vdownptr($v) $b $d
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100883 } else {
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100884 lset vleftptr($v) $c $d
885 }
886 if {$d != 0} {
887 lset vbackptr($v) $d $c
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100888 }
Paul Mackerras841ea822008-02-18 10:44:33 +1100889 if {[lindex $vlastins($v) $b] == $a} {
890 lset vlastins($v) $b $c
891 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100892 lset vupptr($v) $a $ka
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100893 set c [lindex $vlastins($v) $ka]
894 if {$c == 0 || \
895 [string compare $tok [lindex $varctok($v) $c]] < 0} {
896 set c $ka
897 set b [lindex $vdownptr($v) $ka]
898 } else {
899 set b [lindex $vleftptr($v) $c]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100900 }
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100901 while {$b != 0 && \
902 [string compare $tok [lindex $varctok($v) $b]] >= 0} {
903 set c $b
904 set b [lindex $vleftptr($v) $c]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100905 }
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +1100906 if {$c == $ka} {
907 lset vdownptr($v) $ka $a
908 lset vbackptr($v) $a 0
909 } else {
910 lset vleftptr($v) $c $a
911 lset vbackptr($v) $a $c
912 }
913 lset vleftptr($v) $a $b
914 if {$b != 0} {
915 lset vbackptr($v) $b $a
916 }
917 lset vlastins($v) $ka $a
918 }
919 }
920 foreach id [array names sortkids] {
921 if {[llength $children($v,$id)] > 1} {
922 set children($v,$id) [lsort -command [list vtokcmp $v] \
923 $children($v,$id)]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100924 }
925 }
926 set t2 [clock clicks -milliseconds]
927 #puts "renumbervarc did [llength $todo] of $ntot arcs in [expr {$t2-$t1}]ms"
928}
929
Paul Mackerrasf806f0f2008-02-24 12:16:56 +1100930# Fix up the graph after we have found out that in view $v,
931# $p (a commit that we have already seen) is actually the parent
932# of the last commit in arc $a.
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100933proc fix_reversal {p a v} {
Paul Mackerras24f7a662007-12-19 09:35:33 +1100934 global varcid varcstart varctok vupptr
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100935
936 set pa $varcid($v,$p)
937 if {$p ne [lindex $varcstart($v) $pa]} {
938 splitvarc $p $v
939 set pa $varcid($v,$p)
940 }
Paul Mackerras24f7a662007-12-19 09:35:33 +1100941 # seeds always need to be renumbered
942 if {[lindex $vupptr($v) $pa] == 0 ||
943 [string compare [lindex $varctok($v) $a] \
944 [lindex $varctok($v) $pa]] > 0} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100945 renumbervarc $pa $v
946 }
947}
948
949proc insertrow {id p v} {
Paul Mackerrasb8a938c2008-02-13 22:12:31 +1100950 global cmitlisted children parents varcid varctok vtokmod
951 global varccommits ordertok commitidx numcommits curview
Paul Mackerras22387f22012-03-19 11:21:08 +1100952 global targetid targetrow vshortids
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100953
Paul Mackerrasb8a938c2008-02-13 22:12:31 +1100954 readcommit $id
955 set vid $v,$id
956 set cmitlisted($vid) 1
957 set children($vid) {}
958 set parents($vid) [list $p]
959 set a [newvarc $v $id]
960 set varcid($vid) $a
Paul Mackerras22387f22012-03-19 11:21:08 +1100961 lappend vshortids($v,[string range $id 0 3]) $id
Paul Mackerrasb8a938c2008-02-13 22:12:31 +1100962 if {[string compare [lindex $varctok($v) $a] $vtokmod($v)] < 0} {
963 modify_arc $v $a
964 }
965 lappend varccommits($v,$a) $id
966 set vp $v,$p
967 if {[llength [lappend children($vp) $id]] > 1} {
968 set children($vp) [lsort -command [list vtokcmp $v] $children($vp)]
969 catch {unset ordertok}
970 }
971 fix_reversal $p $a $v
972 incr commitidx($v)
973 if {$v == $curview} {
974 set numcommits $commitidx($v)
975 setcanvscroll
976 if {[info exists targetid]} {
977 if {![comes_before $targetid $p]} {
978 incr targetrow
979 }
980 }
981 }
982}
983
984proc insertfakerow {id p} {
985 global varcid varccommits parents children cmitlisted
986 global commitidx varctok vtokmod targetid targetrow curview numcommits
987
988 set v $curview
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100989 set a $varcid($v,$p)
990 set i [lsearch -exact $varccommits($v,$a) $p]
991 if {$i < 0} {
Paul Mackerrasb8a938c2008-02-13 22:12:31 +1100992 puts "oops: insertfakerow can't find [shortids $p] on arc $a"
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100993 return
994 }
995 set children($v,$id) {}
996 set parents($v,$id) [list $p]
997 set varcid($v,$id) $a
Paul Mackerras9257d8f2007-12-11 10:45:38 +1100998 lappend children($v,$p) $id
Paul Mackerras7fcc92b2007-12-03 10:33:01 +1100999 set cmitlisted($v,$id) 1
Paul Mackerrasb8a938c2008-02-13 22:12:31 +11001000 set numcommits [incr commitidx($v)]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001001 # note we deliberately don't update varcstart($v) even if $i == 0
1002 set varccommits($v,$a) [linsert $varccommits($v,$a) $i $id]
Paul Mackerrasc9cfdc92008-03-04 21:32:38 +11001003 modify_arc $v $a $i
Paul Mackerras42a671f2008-01-02 09:59:39 +11001004 if {[info exists targetid]} {
1005 if {![comes_before $targetid $p]} {
1006 incr targetrow
1007 }
1008 }
Paul Mackerrasb8a938c2008-02-13 22:12:31 +11001009 setcanvscroll
Paul Mackerras9257d8f2007-12-11 10:45:38 +11001010 drawvisible
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001011}
1012
Paul Mackerrasb8a938c2008-02-13 22:12:31 +11001013proc removefakerow {id} {
Paul Mackerras9257d8f2007-12-11 10:45:38 +11001014 global varcid varccommits parents children commitidx
Paul Mackerrasfc2a2562007-12-26 23:03:43 +11001015 global varctok vtokmod cmitlisted currentid selectedline
Paul Mackerrasb8a938c2008-02-13 22:12:31 +11001016 global targetid curview numcommits
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001017
Paul Mackerrasb8a938c2008-02-13 22:12:31 +11001018 set v $curview
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001019 if {[llength $parents($v,$id)] != 1} {
Paul Mackerrasb8a938c2008-02-13 22:12:31 +11001020 puts "oops: removefakerow [shortids $id] has [llength $parents($v,$id)] parents"
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001021 return
1022 }
1023 set p [lindex $parents($v,$id) 0]
1024 set a $varcid($v,$id)
1025 set i [lsearch -exact $varccommits($v,$a) $id]
1026 if {$i < 0} {
Paul Mackerrasb8a938c2008-02-13 22:12:31 +11001027 puts "oops: removefakerow can't find [shortids $id] on arc $a"
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001028 return
1029 }
1030 unset varcid($v,$id)
1031 set varccommits($v,$a) [lreplace $varccommits($v,$a) $i $i]
1032 unset parents($v,$id)
1033 unset children($v,$id)
1034 unset cmitlisted($v,$id)
Paul Mackerrasb8a938c2008-02-13 22:12:31 +11001035 set numcommits [incr commitidx($v) -1]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001036 set j [lsearch -exact $children($v,$p) $id]
1037 if {$j >= 0} {
1038 set children($v,$p) [lreplace $children($v,$p) $j $j]
1039 }
Paul Mackerrasc9cfdc92008-03-04 21:32:38 +11001040 modify_arc $v $a $i
Paul Mackerrasfc2a2562007-12-26 23:03:43 +11001041 if {[info exist currentid] && $id eq $currentid} {
1042 unset currentid
Paul Mackerras94b4a692008-05-20 20:51:06 +10001043 set selectedline {}
Paul Mackerrasfc2a2562007-12-26 23:03:43 +11001044 }
Paul Mackerras42a671f2008-01-02 09:59:39 +11001045 if {[info exists targetid] && $targetid eq $id} {
1046 set targetid $p
1047 }
Paul Mackerrasb8a938c2008-02-13 22:12:31 +11001048 setcanvscroll
Paul Mackerras9257d8f2007-12-11 10:45:38 +11001049 drawvisible
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001050}
1051
Paul Mackerrasaa435612009-09-10 21:58:40 +10001052proc real_children {vp} {
1053 global children nullid nullid2
1054
1055 set kids {}
1056 foreach id $children($vp) {
1057 if {$id ne $nullid && $id ne $nullid2} {
1058 lappend kids $id
1059 }
1060 }
1061 return $kids
1062}
1063
Paul Mackerrasc8c9f3d2008-01-06 13:54:58 +11001064proc first_real_child {vp} {
1065 global children nullid nullid2
1066
1067 foreach id $children($vp) {
1068 if {$id ne $nullid && $id ne $nullid2} {
1069 return $id
1070 }
1071 }
1072 return {}
1073}
1074
1075proc last_real_child {vp} {
1076 global children nullid nullid2
1077
1078 set kids $children($vp)
1079 for {set i [llength $kids]} {[incr i -1] >= 0} {} {
1080 set id [lindex $kids $i]
1081 if {$id ne $nullid && $id ne $nullid2} {
1082 return $id
1083 }
1084 }
1085 return {}
1086}
1087
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001088proc vtokcmp {v a b} {
1089 global varctok varcid
1090
1091 return [string compare [lindex $varctok($v) $varcid($v,$a)] \
1092 [lindex $varctok($v) $varcid($v,$b)]]
1093}
1094
Paul Mackerrasc9cfdc92008-03-04 21:32:38 +11001095# This assumes that if lim is not given, the caller has checked that
1096# arc a's token is less than $vtokmod($v)
Paul Mackerrase5b37ac2007-12-12 18:13:51 +11001097proc modify_arc {v a {lim {}}} {
1098 global varctok vtokmod varcmod varcrow vupptr curview vrowmod varccommits
Paul Mackerras9257d8f2007-12-11 10:45:38 +11001099
Paul Mackerrasc9cfdc92008-03-04 21:32:38 +11001100 if {$lim ne {}} {
1101 set c [string compare [lindex $varctok($v) $a] $vtokmod($v)]
1102 if {$c > 0} return
1103 if {$c == 0} {
1104 set r [lindex $varcrow($v) $a]
1105 if {$r ne {} && $vrowmod($v) <= $r + $lim} return
1106 }
1107 }
Paul Mackerras9257d8f2007-12-11 10:45:38 +11001108 set vtokmod($v) [lindex $varctok($v) $a]
1109 set varcmod($v) $a
1110 if {$v == $curview} {
1111 while {$a != 0 && [lindex $varcrow($v) $a] eq {}} {
1112 set a [lindex $vupptr($v) $a]
Paul Mackerrase5b37ac2007-12-12 18:13:51 +11001113 set lim {}
Paul Mackerras9257d8f2007-12-11 10:45:38 +11001114 }
Paul Mackerrase5b37ac2007-12-12 18:13:51 +11001115 set r 0
1116 if {$a != 0} {
1117 if {$lim eq {}} {
1118 set lim [llength $varccommits($v,$a)]
1119 }
1120 set r [expr {[lindex $varcrow($v) $a] + $lim}]
1121 }
1122 set vrowmod($v) $r
Paul Mackerras0c278862007-12-11 20:09:53 +11001123 undolayout $r
Paul Mackerras9257d8f2007-12-11 10:45:38 +11001124 }
1125}
1126
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001127proc update_arcrows {v} {
Paul Mackerrase5b37ac2007-12-12 18:13:51 +11001128 global vtokmod varcmod vrowmod varcrow commitidx currentid selectedline
Paul Mackerras24f7a662007-12-19 09:35:33 +11001129 global varcid vrownum varcorder varcix varccommits
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001130 global vupptr vdownptr vleftptr varctok
Paul Mackerras24f7a662007-12-19 09:35:33 +11001131 global displayorder parentlist curview cached_commitrow
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001132
Paul Mackerrasc9cfdc92008-03-04 21:32:38 +11001133 if {$vrowmod($v) == $commitidx($v)} return
1134 if {$v == $curview} {
1135 if {[llength $displayorder] > $vrowmod($v)} {
1136 set displayorder [lrange $displayorder 0 [expr {$vrowmod($v) - 1}]]
1137 set parentlist [lrange $parentlist 0 [expr {$vrowmod($v) - 1}]]
1138 }
1139 catch {unset cached_commitrow}
1140 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001141 set narctot [expr {[llength $varctok($v)] - 1}]
1142 set a $varcmod($v)
1143 while {$a != 0 && [lindex $varcix($v) $a] eq {}} {
1144 # go up the tree until we find something that has a row number,
1145 # or we get to a seed
1146 set a [lindex $vupptr($v) $a]
1147 }
1148 if {$a == 0} {
1149 set a [lindex $vdownptr($v) 0]
1150 if {$a == 0} return
1151 set vrownum($v) {0}
1152 set varcorder($v) [list $a]
1153 lset varcix($v) $a 0
1154 lset varcrow($v) $a 0
1155 set arcn 0
1156 set row 0
1157 } else {
1158 set arcn [lindex $varcix($v) $a]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001159 if {[llength $vrownum($v)] > $arcn + 1} {
1160 set vrownum($v) [lrange $vrownum($v) 0 $arcn]
1161 set varcorder($v) [lrange $varcorder($v) 0 $arcn]
1162 }
1163 set row [lindex $varcrow($v) $a]
1164 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001165 while {1} {
1166 set p $a
1167 incr row [llength $varccommits($v,$a)]
1168 # go down if possible
1169 set b [lindex $vdownptr($v) $a]
1170 if {$b == 0} {
1171 # if not, go left, or go up until we can go left
1172 while {$a != 0} {
1173 set b [lindex $vleftptr($v) $a]
1174 if {$b != 0} break
1175 set a [lindex $vupptr($v) $a]
1176 }
1177 if {$a == 0} break
1178 }
1179 set a $b
1180 incr arcn
1181 lappend vrownum($v) $row
1182 lappend varcorder($v) $a
1183 lset varcix($v) $a $arcn
1184 lset varcrow($v) $a $row
1185 }
Paul Mackerrase5b37ac2007-12-12 18:13:51 +11001186 set vtokmod($v) [lindex $varctok($v) $p]
1187 set varcmod($v) $p
1188 set vrowmod($v) $row
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001189 if {[info exists currentid]} {
1190 set selectedline [rowofcommit $currentid]
1191 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001192}
1193
1194# Test whether view $v contains commit $id
1195proc commitinview {id v} {
1196 global varcid
1197
1198 return [info exists varcid($v,$id)]
1199}
1200
1201# Return the row number for commit $id in the current view
1202proc rowofcommit {id} {
1203 global varcid varccommits varcrow curview cached_commitrow
Paul Mackerras9257d8f2007-12-11 10:45:38 +11001204 global varctok vtokmod
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001205
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001206 set v $curview
1207 if {![info exists varcid($v,$id)]} {
1208 puts "oops rowofcommit no arc for [shortids $id]"
1209 return {}
1210 }
1211 set a $varcid($v,$id)
Paul Mackerrasfc2a2562007-12-26 23:03:43 +11001212 if {[string compare [lindex $varctok($v) $a] $vtokmod($v)] >= 0} {
Paul Mackerras9257d8f2007-12-11 10:45:38 +11001213 update_arcrows $v
1214 }
Paul Mackerras31c0eaa2007-12-30 22:41:14 +11001215 if {[info exists cached_commitrow($id)]} {
1216 return $cached_commitrow($id)
1217 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001218 set i [lsearch -exact $varccommits($v,$a) $id]
1219 if {$i < 0} {
1220 puts "oops didn't find commit [shortids $id] in arc $a"
1221 return {}
1222 }
1223 incr i [lindex $varcrow($v) $a]
1224 set cached_commitrow($id) $i
1225 return $i
1226}
1227
Paul Mackerras42a671f2008-01-02 09:59:39 +11001228# Returns 1 if a is on an earlier row than b, otherwise 0
1229proc comes_before {a b} {
1230 global varcid varctok curview
1231
1232 set v $curview
1233 if {$a eq $b || ![info exists varcid($v,$a)] || \
1234 ![info exists varcid($v,$b)]} {
1235 return 0
1236 }
1237 if {$varcid($v,$a) != $varcid($v,$b)} {
1238 return [expr {[string compare [lindex $varctok($v) $varcid($v,$a)] \
1239 [lindex $varctok($v) $varcid($v,$b)]] < 0}]
1240 }
1241 return [expr {[rowofcommit $a] < [rowofcommit $b]}]
1242}
1243
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001244proc bsearch {l elt} {
1245 if {[llength $l] == 0 || $elt <= [lindex $l 0]} {
1246 return 0
1247 }
1248 set lo 0
1249 set hi [llength $l]
1250 while {$hi - $lo > 1} {
1251 set mid [expr {int(($lo + $hi) / 2)}]
1252 set t [lindex $l $mid]
1253 if {$elt < $t} {
1254 set hi $mid
1255 } elseif {$elt > $t} {
1256 set lo $mid
1257 } else {
1258 return $mid
1259 }
1260 }
1261 return $lo
1262}
1263
1264# Make sure rows $start..$end-1 are valid in displayorder and parentlist
1265proc make_disporder {start end} {
1266 global vrownum curview commitidx displayorder parentlist
Paul Mackerrase5b37ac2007-12-12 18:13:51 +11001267 global varccommits varcorder parents vrowmod varcrow
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001268 global d_valid_start d_valid_end
1269
Paul Mackerrase5b37ac2007-12-12 18:13:51 +11001270 if {$end > $vrowmod($curview)} {
Paul Mackerras9257d8f2007-12-11 10:45:38 +11001271 update_arcrows $curview
1272 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001273 set ai [bsearch $vrownum($curview) $start]
1274 set start [lindex $vrownum($curview) $ai]
1275 set narc [llength $vrownum($curview)]
1276 for {set r $start} {$ai < $narc && $r < $end} {incr ai} {
1277 set a [lindex $varcorder($curview) $ai]
1278 set l [llength $displayorder]
1279 set al [llength $varccommits($curview,$a)]
1280 if {$l < $r + $al} {
1281 if {$l < $r} {
1282 set pad [ntimes [expr {$r - $l}] {}]
1283 set displayorder [concat $displayorder $pad]
1284 set parentlist [concat $parentlist $pad]
1285 } elseif {$l > $r} {
1286 set displayorder [lrange $displayorder 0 [expr {$r - 1}]]
1287 set parentlist [lrange $parentlist 0 [expr {$r - 1}]]
1288 }
1289 foreach id $varccommits($curview,$a) {
1290 lappend displayorder $id
1291 lappend parentlist $parents($curview,$id)
1292 }
Paul Mackerras17529cf92008-01-12 21:46:31 +11001293 } elseif {[lindex $displayorder [expr {$r + $al - 1}]] eq {}} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001294 set i $r
1295 foreach id $varccommits($curview,$a) {
1296 lset displayorder $i $id
1297 lset parentlist $i $parents($curview,$id)
1298 incr i
1299 }
1300 }
1301 incr r $al
1302 }
1303}
1304
1305proc commitonrow {row} {
1306 global displayorder
1307
1308 set id [lindex $displayorder $row]
1309 if {$id eq {}} {
1310 make_disporder $row [expr {$row + 1}]
1311 set id [lindex $displayorder $row]
1312 }
1313 return $id
1314}
1315
1316proc closevarcs {v} {
1317 global varctok varccommits varcid parents children
Paul Mackerrasd375ef92008-10-21 10:18:12 +11001318 global cmitlisted commitidx vtokmod
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001319
1320 set missing_parents 0
1321 set scripts {}
1322 set narcs [llength $varctok($v)]
1323 for {set a 1} {$a < $narcs} {incr a} {
1324 set id [lindex $varccommits($v,$a) end]
1325 foreach p $parents($v,$id) {
1326 if {[info exists varcid($v,$p)]} continue
1327 # add p as a new commit
1328 incr missing_parents
1329 set cmitlisted($v,$p) 0
1330 set parents($v,$p) {}
1331 if {[llength $children($v,$p)] == 1 &&
1332 [llength $parents($v,$id)] == 1} {
1333 set b $a
1334 } else {
1335 set b [newvarc $v $p]
1336 }
1337 set varcid($v,$p) $b
Paul Mackerras9257d8f2007-12-11 10:45:38 +11001338 if {[string compare [lindex $varctok($v) $b] $vtokmod($v)] < 0} {
1339 modify_arc $v $b
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001340 }
Paul Mackerrase5b37ac2007-12-12 18:13:51 +11001341 lappend varccommits($v,$b) $p
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001342 incr commitidx($v)
Paul Mackerrasd375ef92008-10-21 10:18:12 +11001343 set scripts [check_interest $p $scripts]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001344 }
1345 }
1346 if {$missing_parents > 0} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001347 foreach s $scripts {
1348 eval $s
1349 }
1350 }
1351}
1352
Paul Mackerrasf806f0f2008-02-24 12:16:56 +11001353# Use $rwid as a substitute for $id, i.e. reparent $id's children to $rwid
1354# Assumes we already have an arc for $rwid.
1355proc rewrite_commit {v id rwid} {
1356 global children parents varcid varctok vtokmod varccommits
1357
1358 foreach ch $children($v,$id) {
1359 # make $rwid be $ch's parent in place of $id
1360 set i [lsearch -exact $parents($v,$ch) $id]
1361 if {$i < 0} {
1362 puts "oops rewrite_commit didn't find $id in parent list for $ch"
1363 }
1364 set parents($v,$ch) [lreplace $parents($v,$ch) $i $i $rwid]
1365 # add $ch to $rwid's children and sort the list if necessary
1366 if {[llength [lappend children($v,$rwid) $ch]] > 1} {
1367 set children($v,$rwid) [lsort -command [list vtokcmp $v] \
1368 $children($v,$rwid)]
1369 }
1370 # fix the graph after joining $id to $rwid
1371 set a $varcid($v,$ch)
1372 fix_reversal $rwid $a $v
Paul Mackerrasc9cfdc92008-03-04 21:32:38 +11001373 # parentlist is wrong for the last element of arc $a
1374 # even if displayorder is right, hence the 3rd arg here
1375 modify_arc $v $a [expr {[llength $varccommits($v,$a)] - 1}]
Paul Mackerrasf806f0f2008-02-24 12:16:56 +11001376 }
1377}
1378
Paul Mackerrasd375ef92008-10-21 10:18:12 +11001379# Mechanism for registering a command to be executed when we come
1380# across a particular commit. To handle the case when only the
1381# prefix of the commit is known, the commitinterest array is now
1382# indexed by the first 4 characters of the ID. Each element is a
1383# list of id, cmd pairs.
1384proc interestedin {id cmd} {
1385 global commitinterest
1386
1387 lappend commitinterest([string range $id 0 3]) $id $cmd
1388}
1389
1390proc check_interest {id scripts} {
1391 global commitinterest
1392
1393 set prefix [string range $id 0 3]
1394 if {[info exists commitinterest($prefix)]} {
1395 set newlist {}
1396 foreach {i script} $commitinterest($prefix) {
1397 if {[string match "$i*" $id]} {
1398 lappend scripts [string map [list "%I" $id "%P" $i] $script]
1399 } else {
1400 lappend newlist $i $script
1401 }
1402 }
1403 if {$newlist ne {}} {
1404 set commitinterest($prefix) $newlist
1405 } else {
1406 unset commitinterest($prefix)
1407 }
1408 }
1409 return $scripts
1410}
1411
Paul Mackerrasf806f0f2008-02-24 12:16:56 +11001412proc getcommitlines {fd inst view updating} {
Paul Mackerrasd375ef92008-10-21 10:18:12 +11001413 global cmitlisted leftover
Paul Mackerras3ed31a82008-04-26 16:00:00 +10001414 global commitidx commitdata vdatemode
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001415 global parents children curview hlview
Paul Mackerras468bcae2008-03-03 10:19:35 +11001416 global idpending ordertok
Paul Mackerras22387f22012-03-19 11:21:08 +11001417 global varccommits varcid varctok vtokmod vfilelimit vshortids
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +00001418
Paul Mackerrasd1e46752006-08-16 20:02:32 +10001419 set stuff [read $fd 500000]
Paul Mackerras005a2f42007-07-26 22:36:39 +10001420 # git log doesn't terminate the last commit with a null...
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001421 if {$stuff == {} && $leftover($inst) ne {} && [eof $fd]} {
Paul Mackerras005a2f42007-07-26 22:36:39 +10001422 set stuff "\0"
1423 }
Paul Mackerrasb490a992005-06-22 10:25:38 +10001424 if {$stuff == {}} {
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10001425 if {![eof $fd]} {
1426 return 1
1427 }
Paul Mackerras6df74032008-05-11 22:13:02 +10001428 global commfd viewcomplete viewactive viewname
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001429 global viewinstances
1430 unset commfd($inst)
1431 set i [lsearch -exact $viewinstances($view) $inst]
1432 if {$i >= 0} {
1433 set viewinstances($view) [lreplace $viewinstances($view) $i $i]
Paul Mackerrasb0cdca92007-08-23 19:35:51 +10001434 }
Paul Mackerrasf0654862005-07-18 14:29:03 -04001435 # set it blocking so we wait for the process to terminate
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10001436 fconfigure $fd -blocking 1
Paul Mackerras098dd8a2006-05-03 09:32:53 +10001437 if {[catch {close $fd} err]} {
1438 set fv {}
1439 if {$view != $curview} {
1440 set fv " for the \"$viewname($view)\" view"
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10001441 }
Paul Mackerras098dd8a2006-05-03 09:32:53 +10001442 if {[string range $err 0 4] == "usage"} {
1443 set err "Gitk: error reading commits$fv:\
Paul Mackerrasf9e0b6f2008-03-04 21:14:17 +11001444 bad arguments to git log."
Paul Mackerras098dd8a2006-05-03 09:32:53 +10001445 if {$viewname($view) eq "Command line"} {
1446 append err \
Paul Mackerrasf9e0b6f2008-03-04 21:14:17 +11001447 " (Note: arguments to gitk are passed to git log\
Paul Mackerras098dd8a2006-05-03 09:32:53 +10001448 to allow selection of commits to be displayed.)"
1449 }
1450 } else {
1451 set err "Error reading commits$fv: $err"
1452 }
1453 error_popup $err
Paul Mackerras1d10f362005-05-15 12:55:47 +00001454 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001455 if {[incr viewactive($view) -1] <= 0} {
1456 set viewcomplete($view) 1
1457 # Check if we have seen any ids listed as parents that haven't
1458 # appeared in the list
1459 closevarcs $view
1460 notbusy $view
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001461 }
Paul Mackerras098dd8a2006-05-03 09:32:53 +10001462 if {$view == $curview} {
Paul Mackerrasac1276a2008-03-03 10:11:08 +11001463 run chewcommits
Paul Mackerras9a40c502005-05-12 23:46:16 +00001464 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10001465 return 0
Paul Mackerras9a40c502005-05-12 23:46:16 +00001466 }
Paul Mackerrasb490a992005-06-22 10:25:38 +10001467 set start 0
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11001468 set gotsome 0
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001469 set scripts {}
Paul Mackerrasb490a992005-06-22 10:25:38 +10001470 while 1 {
1471 set i [string first "\0" $stuff $start]
1472 if {$i < 0} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001473 append leftover($inst) [string range $stuff $start end]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11001474 break
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +00001475 }
Paul Mackerrasb490a992005-06-22 10:25:38 +10001476 if {$start == 0} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001477 set cmit $leftover($inst)
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11001478 append cmit [string range $stuff 0 [expr {$i - 1}]]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001479 set leftover($inst) {}
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11001480 } else {
1481 set cmit [string range $stuff $start [expr {$i - 1}]]
Paul Mackerrasb490a992005-06-22 10:25:38 +10001482 }
1483 set start [expr {$i + 1}]
Paul Mackerrase5ea7012005-08-18 20:40:39 +10001484 set j [string first "\n" $cmit]
1485 set ok 0
Paul Mackerras16c1ff92006-03-30 18:43:51 +11001486 set listed 1
Paul Mackerrasc961b222007-07-09 22:45:47 +10001487 if {$j >= 0 && [string match "commit *" $cmit]} {
1488 set ids [string range $cmit 7 [expr {$j - 1}]]
Linus Torvalds1407ade2008-02-09 14:02:07 -08001489 if {[string match {[-^<>]*} $ids]} {
Paul Mackerrasc961b222007-07-09 22:45:47 +10001490 switch -- [string index $ids 0] {
1491 "-" {set listed 0}
Linus Torvalds1407ade2008-02-09 14:02:07 -08001492 "^" {set listed 2}
1493 "<" {set listed 3}
1494 ">" {set listed 4}
Paul Mackerrasc961b222007-07-09 22:45:47 +10001495 }
Paul Mackerras16c1ff92006-03-30 18:43:51 +11001496 set ids [string range $ids 1 end]
1497 }
Paul Mackerrase5ea7012005-08-18 20:40:39 +10001498 set ok 1
1499 foreach id $ids {
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11001500 if {[string length $id] != 40} {
Paul Mackerrase5ea7012005-08-18 20:40:39 +10001501 set ok 0
1502 break
1503 }
1504 }
1505 }
1506 if {!$ok} {
Paul Mackerras7e952e72005-06-27 20:04:26 +10001507 set shortcmit $cmit
1508 if {[string length $shortcmit] > 80} {
1509 set shortcmit "[string range $shortcmit 0 80]..."
1510 }
Christian Stimmingd990ced2007-11-07 18:42:55 +01001511 error_popup "[mc "Can't parse git log output:"] {$shortcmit}"
Paul Mackerrasb490a992005-06-22 10:25:38 +10001512 exit 1
1513 }
Paul Mackerrase5ea7012005-08-18 20:40:39 +10001514 set id [lindex $ids 0]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001515 set vid $view,$id
Paul Mackerrasf806f0f2008-02-24 12:16:56 +11001516
Paul Mackerras22387f22012-03-19 11:21:08 +11001517 lappend vshortids($view,[string range $id 0 3]) $id
1518
Paul Mackerrasf806f0f2008-02-24 12:16:56 +11001519 if {!$listed && $updating && ![info exists varcid($vid)] &&
Paul Mackerras3ed31a82008-04-26 16:00:00 +10001520 $vfilelimit($view) ne {}} {
Paul Mackerrasf806f0f2008-02-24 12:16:56 +11001521 # git log doesn't rewrite parents for unlisted commits
1522 # when doing path limiting, so work around that here
1523 # by working out the rewritten parent with git rev-list
1524 # and if we already know about it, using the rewritten
1525 # parent as a substitute parent for $id's children.
1526 if {![catch {
1527 set rwid [exec git rev-list --first-parent --max-count=1 \
Paul Mackerras3ed31a82008-04-26 16:00:00 +10001528 $id -- $vfilelimit($view)]
Paul Mackerrasf806f0f2008-02-24 12:16:56 +11001529 }]} {
1530 if {$rwid ne {} && [info exists varcid($view,$rwid)]} {
1531 # use $rwid in place of $id
1532 rewrite_commit $view $id $rwid
1533 continue
1534 }
1535 }
1536 }
1537
Paul Mackerrasf1bf4ee2008-02-16 17:47:31 +11001538 set a 0
1539 if {[info exists varcid($vid)]} {
1540 if {$cmitlisted($vid) || !$listed} continue
1541 set a $varcid($vid)
1542 }
Paul Mackerras16c1ff92006-03-30 18:43:51 +11001543 if {$listed} {
1544 set olds [lrange $ids 1 end]
Paul Mackerras16c1ff92006-03-30 18:43:51 +11001545 } else {
1546 set olds {}
1547 }
Paul Mackerrasf7a3e8d2006-03-18 10:04:48 +11001548 set commitdata($id) [string range $cmit [expr {$j + 1}] end]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001549 set cmitlisted($vid) $listed
1550 set parents($vid) $olds
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001551 if {![info exists children($vid)]} {
1552 set children($vid) {}
Paul Mackerrasf1bf4ee2008-02-16 17:47:31 +11001553 } elseif {$a == 0 && [llength $children($vid)] == 1} {
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +11001554 set k [lindex $children($vid) 0]
1555 if {[llength $parents($view,$k)] == 1 &&
Paul Mackerras3ed31a82008-04-26 16:00:00 +10001556 (!$vdatemode($view) ||
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +11001557 $varcid($view,$k) == [llength $varctok($view)] - 1)} {
1558 set a $varcid($view,$k)
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001559 }
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10001560 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001561 if {$a == 0} {
1562 # new arc
1563 set a [newvarc $view $id]
1564 }
Paul Mackerrase5b37ac2007-12-12 18:13:51 +11001565 if {[string compare [lindex $varctok($view) $a] $vtokmod($view)] < 0} {
1566 modify_arc $view $a
1567 }
Paul Mackerrasf1bf4ee2008-02-16 17:47:31 +11001568 if {![info exists varcid($vid)]} {
1569 set varcid($vid) $a
1570 lappend varccommits($view,$a) $id
1571 incr commitidx($view)
1572 }
Paul Mackerrase5b37ac2007-12-12 18:13:51 +11001573
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001574 set i 0
1575 foreach p $olds {
1576 if {$i == 0 || [lsearch -exact $olds $p] >= $i} {
1577 set vp $view,$p
1578 if {[llength [lappend children($vp) $id]] > 1 &&
1579 [vtokcmp $view [lindex $children($vp) end-1] $id] > 0} {
1580 set children($vp) [lsort -command [list vtokcmp $view] \
1581 $children($vp)]
Paul Mackerras9257d8f2007-12-11 10:45:38 +11001582 catch {unset ordertok}
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001583 }
Paul Mackerrasf3ea5ed2007-12-20 10:03:35 +11001584 if {[info exists varcid($view,$p)]} {
1585 fix_reversal $p $a $view
1586 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001587 }
1588 incr i
1589 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001590
Paul Mackerrasd375ef92008-10-21 10:18:12 +11001591 set scripts [check_interest $id $scripts]
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11001592 set gotsome 1
Paul Mackerras9f1afe02006-02-19 22:44:47 +11001593 }
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11001594 if {$gotsome} {
Paul Mackerrasac1276a2008-03-03 10:11:08 +11001595 global numcommits hlview
1596
1597 if {$view == $curview} {
1598 set numcommits $commitidx($view)
1599 run chewcommits
1600 }
1601 if {[info exists hlview] && $view == $hlview} {
1602 # we never actually get here...
1603 run vhighlightmore
1604 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001605 foreach s $scripts {
1606 eval $s
1607 }
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11001608 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10001609 return 2
Paul Mackerrascfb45632005-05-31 12:14:42 +00001610}
1611
Paul Mackerrasac1276a2008-03-03 10:11:08 +11001612proc chewcommits {} {
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10001613 global curview hlview viewcomplete
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001614 global pending_select
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +00001615
Paul Mackerrasac1276a2008-03-03 10:11:08 +11001616 layoutmore
1617 if {$viewcomplete($curview)} {
1618 global commitidx varctok
1619 global numcommits startmsecs
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10001620
Paul Mackerrasac1276a2008-03-03 10:11:08 +11001621 if {[info exists pending_select]} {
Alexander Gavrilov835e62a2008-07-26 20:15:54 +04001622 update
1623 reset_pending_select {}
1624
1625 if {[commitinview $pending_select $curview]} {
1626 selectline [rowofcommit $pending_select] 1
1627 } else {
1628 set row [first_real_row]
1629 selectline $row 1
1630 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10001631 }
Paul Mackerrasac1276a2008-03-03 10:11:08 +11001632 if {$commitidx($curview) > 0} {
1633 #set ms [expr {[clock clicks -milliseconds] - $startmsecs}]
1634 #puts "overall $ms ms for $numcommits commits"
1635 #puts "[llength $varctok($view)] arcs, $commitidx($view) commits"
1636 } else {
1637 show_status [mc "No commits selected"]
1638 }
1639 notbusy layout
Paul Mackerrasb6645502005-08-11 09:56:23 +10001640 }
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10001641 return 0
Paul Mackerras1db95b02005-05-09 04:08:39 +00001642}
1643
Alexander Gavrilov590915d2008-11-09 18:06:07 +03001644proc do_readcommit {id} {
1645 global tclencoding
1646
1647 # Invoke git-log to handle automatic encoding conversion
1648 set fd [open [concat | git log --no-color --pretty=raw -1 $id] r]
1649 # Read the results using i18n.logoutputencoding
1650 fconfigure $fd -translation lf -eofchar {}
1651 if {$tclencoding != {}} {
1652 fconfigure $fd -encoding $tclencoding
1653 }
1654 set contents [read $fd]
1655 close $fd
1656 # Remove the heading line
1657 regsub {^commit [0-9a-f]+\n} $contents {} contents
1658
1659 return $contents
1660}
1661
Paul Mackerras1db95b02005-05-09 04:08:39 +00001662proc readcommit {id} {
Alexander Gavrilov590915d2008-11-09 18:06:07 +03001663 if {[catch {set contents [do_readcommit $id]}]} return
1664 parsecommit $id $contents 1
Paul Mackerrasb490a992005-06-22 10:25:38 +10001665}
1666
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11001667proc parsecommit {id contents listed} {
Anders Kaseorgef738962011-01-19 14:46:59 -05001668 global commitinfo
Sven Verdoolaegeb5c2f302005-11-29 22:15:51 +01001669
1670 set inhdr 1
1671 set comment {}
1672 set headline {}
1673 set auname {}
1674 set audate {}
1675 set comname {}
1676 set comdate {}
Paul Mackerras232475d2005-11-15 10:34:03 +11001677 set hdrend [string first "\n\n" $contents]
1678 if {$hdrend < 0} {
1679 # should never happen...
1680 set hdrend [string length $contents]
1681 }
1682 set header [string range $contents 0 [expr {$hdrend - 1}]]
1683 set comment [string range $contents [expr {$hdrend + 2}] end]
1684 foreach line [split $header "\n"] {
Kevin Ballard61f57cb2008-12-18 01:26:48 -08001685 set line [split $line " "]
Paul Mackerras232475d2005-11-15 10:34:03 +11001686 set tag [lindex $line 0]
1687 if {$tag == "author"} {
Anders Kaseorgf5974d92011-01-19 14:47:25 -05001688 set audate [lrange $line end-1 end]
Kevin Ballard61f57cb2008-12-18 01:26:48 -08001689 set auname [join [lrange $line 1 end-2] " "]
Paul Mackerras232475d2005-11-15 10:34:03 +11001690 } elseif {$tag == "committer"} {
Anders Kaseorgf5974d92011-01-19 14:47:25 -05001691 set comdate [lrange $line end-1 end]
Kevin Ballard61f57cb2008-12-18 01:26:48 -08001692 set comname [join [lrange $line 1 end-2] " "]
Paul Mackerras1db95b02005-05-09 04:08:39 +00001693 }
1694 }
Paul Mackerras232475d2005-11-15 10:34:03 +11001695 set headline {}
Paul Mackerras43c25072006-09-27 10:56:02 +10001696 # take the first non-blank line of the comment as the headline
1697 set headline [string trimleft $comment]
1698 set i [string first "\n" $headline]
Paul Mackerras232475d2005-11-15 10:34:03 +11001699 if {$i >= 0} {
Paul Mackerras43c25072006-09-27 10:56:02 +10001700 set headline [string range $headline 0 $i]
1701 }
1702 set headline [string trimright $headline]
1703 set i [string first "\r" $headline]
1704 if {$i >= 0} {
1705 set headline [string trimright [string range $headline 0 $i]]
Paul Mackerras232475d2005-11-15 10:34:03 +11001706 }
1707 if {!$listed} {
Paul Mackerrasf9e0b6f2008-03-04 21:14:17 +11001708 # git log indents the comment by 4 spaces;
Timo Hirvonen8974c6f2006-05-24 10:57:40 +03001709 # if we got this via git cat-file, add the indentation
Paul Mackerras232475d2005-11-15 10:34:03 +11001710 set newcomment {}
1711 foreach line [split $comment "\n"] {
1712 append newcomment " "
1713 append newcomment $line
Paul Mackerrasf6e28692005-11-20 23:08:22 +11001714 append newcomment "\n"
Paul Mackerras232475d2005-11-15 10:34:03 +11001715 }
1716 set comment $newcomment
Paul Mackerras1db95b02005-05-09 04:08:39 +00001717 }
Raphael Zimmerer36242492011-04-19 22:37:09 +02001718 set hasnote [string first "\nNotes:\n" $contents]
Thomas Rastb449eb22013-11-16 18:37:42 +01001719 set diff ""
1720 # If there is diff output shown in the git-log stream, split it
1721 # out. But get rid of the empty line that always precedes the
1722 # diff.
1723 set i [string first "\n\ndiff" $comment]
1724 if {$i >= 0} {
1725 set diff [string range $comment $i+1 end]
1726 set comment [string range $comment 0 $i-1]
1727 }
Paul Mackerrase5c2d852005-05-11 23:44:54 +00001728 set commitinfo($id) [list $headline $auname $audate \
Thomas Rastb449eb22013-11-16 18:37:42 +01001729 $comname $comdate $comment $hasnote $diff]
Paul Mackerras1db95b02005-05-09 04:08:39 +00001730}
1731
Paul Mackerrasf7a3e8d2006-03-18 10:04:48 +11001732proc getcommit {id} {
Paul Mackerras79b2c752006-04-02 20:47:40 +10001733 global commitdata commitinfo
Paul Mackerras8ed16482006-03-02 22:56:44 +11001734
Paul Mackerrasf7a3e8d2006-03-18 10:04:48 +11001735 if {[info exists commitdata($id)]} {
1736 parsecommit $id $commitdata($id) 1
Paul Mackerras8ed16482006-03-02 22:56:44 +11001737 } else {
1738 readcommit $id
1739 if {![info exists commitinfo($id)]} {
Christian Stimmingd990ced2007-11-07 18:42:55 +01001740 set commitinfo($id) [list [mc "No commit information available"]]
Paul Mackerras8ed16482006-03-02 22:56:44 +11001741 }
1742 }
1743 return 1
1744}
1745
Paul Mackerrasd375ef92008-10-21 10:18:12 +11001746# Expand an abbreviated commit ID to a list of full 40-char IDs that match
1747# and are present in the current view.
1748# This is fairly slow...
1749proc longid {prefix} {
Paul Mackerras22387f22012-03-19 11:21:08 +11001750 global varcid curview vshortids
Paul Mackerrasd375ef92008-10-21 10:18:12 +11001751
1752 set ids {}
Paul Mackerras22387f22012-03-19 11:21:08 +11001753 if {[string length $prefix] >= 4} {
1754 set vshortid $curview,[string range $prefix 0 3]
1755 if {[info exists vshortids($vshortid)]} {
1756 foreach id $vshortids($vshortid) {
1757 if {[string match "$prefix*" $id]} {
1758 if {[lsearch -exact $ids $id] < 0} {
1759 lappend ids $id
1760 if {[llength $ids] >= 2} break
1761 }
1762 }
1763 }
1764 }
1765 } else {
1766 foreach match [array names varcid "$curview,$prefix*"] {
1767 lappend ids [lindex [split $match ","] 1]
1768 if {[llength $ids] >= 2} break
1769 }
Paul Mackerrasd375ef92008-10-21 10:18:12 +11001770 }
1771 return $ids
1772}
1773
Paul Mackerras887fe3c2005-05-21 07:35:37 +00001774proc readrefs {} {
Paul Mackerras62d3ea62006-09-11 10:36:53 +10001775 global tagids idtags headids idheads tagobjid
Paul Mackerras219ea3a2006-09-07 10:21:39 +10001776 global otherrefids idotherrefs mainhead mainheadid
Alexander Gavrilov39816d62008-08-23 12:27:44 +04001777 global selecthead selectheadid
Thomas Rastffe15292009-08-03 23:53:36 +02001778 global hideremotes
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10001779
Sven Verdoolaegeb5c2f302005-11-29 22:15:51 +01001780 foreach v {tagids idtags headids idheads otherrefids idotherrefs} {
1781 catch {unset $v}
1782 }
Paul Mackerras62d3ea62006-09-11 10:36:53 +10001783 set refd [open [list | git show-ref -d] r]
1784 while {[gets $refd line] >= 0} {
1785 if {[string index $line 40] ne " "} continue
1786 set id [string range $line 0 39]
1787 set ref [string range $line 41 end]
1788 if {![string match "refs/*" $ref]} continue
1789 set name [string range $ref 5 end]
1790 if {[string match "remotes/*" $name]} {
Thomas Rastffe15292009-08-03 23:53:36 +02001791 if {![string match "*/HEAD" $name] && !$hideremotes} {
Paul Mackerras62d3ea62006-09-11 10:36:53 +10001792 set headids($name) $id
1793 lappend idheads($id) $name
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10001794 }
Paul Mackerras62d3ea62006-09-11 10:36:53 +10001795 } elseif {[string match "heads/*" $name]} {
1796 set name [string range $name 6 end]
Junio C Hamano36a7cad2005-11-18 23:54:17 -08001797 set headids($name) $id
1798 lappend idheads($id) $name
Paul Mackerras62d3ea62006-09-11 10:36:53 +10001799 } elseif {[string match "tags/*" $name]} {
1800 # this lets refs/tags/foo^{} overwrite refs/tags/foo,
1801 # which is what we want since the former is the commit ID
1802 set name [string range $name 5 end]
1803 if {[string match "*^{}" $name]} {
1804 set name [string range $name 0 end-3]
1805 } else {
1806 set tagobjid($name) $id
1807 }
1808 set tagids($name) $id
1809 lappend idtags($id) $name
Junio C Hamano36a7cad2005-11-18 23:54:17 -08001810 } else {
1811 set otherrefids($name) $id
1812 lappend idotherrefs($id) $name
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10001813 }
1814 }
Alex Riesen062d6712007-07-29 22:28:40 +02001815 catch {close $refd}
Paul Mackerras8a485712006-07-06 10:21:23 +10001816 set mainhead {}
Paul Mackerras219ea3a2006-09-07 10:21:39 +10001817 set mainheadid {}
Paul Mackerras8a485712006-07-06 10:21:23 +10001818 catch {
Paul Mackerrasc11ff122008-05-26 10:11:33 +10001819 set mainheadid [exec git rev-parse HEAD]
Paul Mackerras8a485712006-07-06 10:21:23 +10001820 set thehead [exec git symbolic-ref HEAD]
1821 if {[string match "refs/heads/*" $thehead]} {
1822 set mainhead [string range $thehead 11 end]
1823 }
1824 }
Alexander Gavrilov39816d62008-08-23 12:27:44 +04001825 set selectheadid {}
1826 if {$selecthead ne {}} {
1827 catch {
1828 set selectheadid [exec git rev-parse --verify $selecthead]
1829 }
1830 }
Paul Mackerras887fe3c2005-05-21 07:35:37 +00001831}
1832
Paul Mackerras8f489362007-07-13 19:49:37 +10001833# skip over fake commits
1834proc first_real_row {} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001835 global nullid nullid2 numcommits
Paul Mackerras8f489362007-07-13 19:49:37 +10001836
1837 for {set row 0} {$row < $numcommits} {incr row} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11001838 set id [commitonrow $row]
Paul Mackerras8f489362007-07-13 19:49:37 +10001839 if {$id ne $nullid && $id ne $nullid2} {
1840 break
1841 }
1842 }
1843 return $row
1844}
1845
Paul Mackerrase11f1232007-06-16 20:29:25 +10001846# update things for a head moved to a child of its previous location
1847proc movehead {id name} {
1848 global headids idheads
1849
1850 removehead $headids($name) $name
1851 set headids($name) $id
1852 lappend idheads($id) $name
1853}
1854
1855# update things when a head has been removed
1856proc removehead {id name} {
1857 global headids idheads
1858
1859 if {$idheads($id) eq $name} {
1860 unset idheads($id)
1861 } else {
1862 set i [lsearch -exact $idheads($id) $name]
1863 if {$i >= 0} {
1864 set idheads($id) [lreplace $idheads($id) $i $i]
1865 }
1866 }
1867 unset headids($name)
1868}
1869
Pat Thoytsd93f1712009-04-17 01:24:35 +01001870proc ttk_toplevel {w args} {
1871 global use_ttk
1872 eval [linsert $args 0 ::toplevel $w]
1873 if {$use_ttk} {
1874 place [ttk::frame $w._toplevel_background] -x 0 -y 0 -relwidth 1 -relheight 1
1875 }
1876 return $w
1877}
1878
Alexander Gavrilove7d64002008-11-11 23:55:42 +03001879proc make_transient {window origin} {
1880 global have_tk85
1881
1882 # In MacOS Tk 8.4 transient appears to work by setting
1883 # overrideredirect, which is utterly useless, since the
1884 # windows get no border, and are not even kept above
1885 # the parent.
1886 if {!$have_tk85 && [tk windowingsystem] eq {aqua}} return
1887
1888 wm transient $window $origin
1889
1890 # Windows fails to place transient windows normally, so
1891 # schedule a callback to center them on the parent.
1892 if {[tk windowingsystem] eq {win32}} {
1893 after idle [list tk::PlaceWindow $window widget $origin]
1894 }
1895}
1896
Bernt Hansen8d849952009-11-02 07:41:00 -05001897proc show_error {w top msg {mc mc}} {
Pat Thoytsd93f1712009-04-17 01:24:35 +01001898 global NS
Pat Thoyts3cb1f9c2009-05-12 15:45:06 +01001899 if {![info exists NS]} {set NS ""}
Pat Thoytsd93f1712009-04-17 01:24:35 +01001900 if {[wm state $top] eq "withdrawn"} { wm deiconify $top }
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00001901 message $w.m -text $msg -justify center -aspect 400
1902 pack $w.m -side top -fill x -padx 20 -pady 20
Paul Mackerras7a0ebbf2009-11-14 21:26:31 +11001903 ${NS}::button $w.ok -default active -text [$mc OK] -command "destroy $top"
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00001904 pack $w.ok -side bottom -fill x
Paul Mackerrase54be9e2006-05-26 22:34:30 +10001905 bind $top <Visibility> "grab $top; focus $top"
1906 bind $top <Key-Return> "destroy $top"
Alexander Gavrilov76f15942008-11-02 21:59:44 +03001907 bind $top <Key-space> "destroy $top"
1908 bind $top <Key-Escape> "destroy $top"
Paul Mackerrase54be9e2006-05-26 22:34:30 +10001909 tkwait window $top
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00001910}
1911
Alexander Gavrilov84a76f12008-11-02 21:59:45 +03001912proc error_popup {msg {owner .}} {
Pat Thoytsd93f1712009-04-17 01:24:35 +01001913 if {[tk windowingsystem] eq "win32"} {
1914 tk_messageBox -icon error -type ok -title [wm title .] \
1915 -parent $owner -message $msg
1916 } else {
1917 set w .error
1918 ttk_toplevel $w
1919 make_transient $w $owner
1920 show_error $w $w $msg
1921 }
Paul Mackerras098dd8a2006-05-03 09:32:53 +10001922}
1923
Alexander Gavrilov84a76f12008-11-02 21:59:45 +03001924proc confirm_popup {msg {owner .}} {
Pat Thoytsd93f1712009-04-17 01:24:35 +01001925 global confirm_ok NS
Paul Mackerras10299152006-08-02 09:52:01 +10001926 set confirm_ok 0
1927 set w .confirm
Pat Thoytsd93f1712009-04-17 01:24:35 +01001928 ttk_toplevel $w
Alexander Gavrilove7d64002008-11-11 23:55:42 +03001929 make_transient $w $owner
Paul Mackerras10299152006-08-02 09:52:01 +10001930 message $w.m -text $msg -justify center -aspect 400
1931 pack $w.m -side top -fill x -padx 20 -pady 20
Pat Thoytsd93f1712009-04-17 01:24:35 +01001932 ${NS}::button $w.ok -text [mc OK] -command "set confirm_ok 1; destroy $w"
Paul Mackerras10299152006-08-02 09:52:01 +10001933 pack $w.ok -side left -fill x
Pat Thoytsd93f1712009-04-17 01:24:35 +01001934 ${NS}::button $w.cancel -text [mc Cancel] -command "destroy $w"
Paul Mackerras10299152006-08-02 09:52:01 +10001935 pack $w.cancel -side right -fill x
1936 bind $w <Visibility> "grab $w; focus $w"
Alexander Gavrilov76f15942008-11-02 21:59:44 +03001937 bind $w <Key-Return> "set confirm_ok 1; destroy $w"
1938 bind $w <Key-space> "set confirm_ok 1; destroy $w"
1939 bind $w <Key-Escape> "destroy $w"
Pat Thoytsd93f1712009-04-17 01:24:35 +01001940 tk::PlaceWindow $w widget $owner
Paul Mackerras10299152006-08-02 09:52:01 +10001941 tkwait window $w
1942 return $confirm_ok
1943}
1944
Paul Mackerrasb039f0a2008-01-06 15:54:46 +11001945proc setoptions {} {
Pat Thoytsd93f1712009-04-17 01:24:35 +01001946 if {[tk windowingsystem] ne "win32"} {
1947 option add *Panedwindow.showHandle 1 startupFile
1948 option add *Panedwindow.sashRelief raised startupFile
1949 if {[tk windowingsystem] ne "aqua"} {
1950 option add *Menu.font uifont startupFile
1951 }
1952 } else {
1953 option add *Menu.TearOff 0 startupFile
1954 }
Paul Mackerrasb039f0a2008-01-06 15:54:46 +11001955 option add *Button.font uifont startupFile
1956 option add *Checkbutton.font uifont startupFile
1957 option add *Radiobutton.font uifont startupFile
Paul Mackerrasb039f0a2008-01-06 15:54:46 +11001958 option add *Menubutton.font uifont startupFile
1959 option add *Label.font uifont startupFile
1960 option add *Message.font uifont startupFile
Mark Hillsb9b142f2010-01-13 20:40:22 +00001961 option add *Entry.font textfont startupFile
1962 option add *Text.font textfont startupFile
Pat Thoytsd93f1712009-04-17 01:24:35 +01001963 option add *Labelframe.font uifont startupFile
Mark Hills0933b042010-01-13 20:40:19 +00001964 option add *Spinbox.font textfont startupFile
Mark Hills207ad7b2010-01-13 20:40:20 +00001965 option add *Listbox.font mainfont startupFile
Paul Mackerrasb039f0a2008-01-06 15:54:46 +11001966}
1967
Paul Mackerras79056032008-10-18 16:24:46 +11001968# Make a menu and submenus.
1969# m is the window name for the menu, items is the list of menu items to add.
1970# Each item is a list {mc label type description options...}
1971# mc is ignored; it's so we can put mc there to alert xgettext
1972# label is the string that appears in the menu
1973# type is cascade, command or radiobutton (should add checkbutton)
1974# description depends on type; it's the sublist for cascade, the
1975# command to invoke for command, or {variable value} for radiobutton
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11001976proc makemenu {m items} {
1977 menu $m
Alexander Gavrilovcea07cf2008-11-09 13:00:45 +03001978 if {[tk windowingsystem] eq {aqua}} {
1979 set Meta1 Cmd
1980 } else {
1981 set Meta1 Ctrl
1982 }
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11001983 foreach i $items {
Paul Mackerras79056032008-10-18 16:24:46 +11001984 set name [mc [lindex $i 1]]
1985 set type [lindex $i 2]
1986 set thing [lindex $i 3]
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11001987 set params [list $type]
1988 if {$name ne {}} {
1989 set u [string first "&" [string map {&& x} $name]]
1990 lappend params -label [string map {&& & & {}} $name]
1991 if {$u >= 0} {
1992 lappend params -underline $u
1993 }
1994 }
1995 switch -- $type {
1996 "cascade" {
Paul Mackerras79056032008-10-18 16:24:46 +11001997 set submenu [string tolower [string map {& ""} [lindex $i 1]]]
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11001998 lappend params -menu $m.$submenu
1999 }
2000 "command" {
2001 lappend params -command $thing
2002 }
2003 "radiobutton" {
2004 lappend params -variable [lindex $thing 0] \
2005 -value [lindex $thing 1]
2006 }
2007 }
Alexander Gavrilovcea07cf2008-11-09 13:00:45 +03002008 set tail [lrange $i 4 end]
2009 regsub -all {\yMeta1\y} $tail $Meta1 tail
2010 eval $m add $params $tail
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11002011 if {$type eq "cascade"} {
2012 makemenu $m.$submenu $thing
2013 }
2014 }
2015}
2016
2017# translate string and remove ampersands
2018proc mca {str} {
2019 return [string map {&& & & {}} [mc $str]]
2020}
2021
Paul Mackerras39c12692013-05-11 17:08:41 +10002022proc cleardropsel {w} {
2023 $w selection clear
2024}
Pat Thoytsd93f1712009-04-17 01:24:35 +01002025proc makedroplist {w varname args} {
2026 global use_ttk
2027 if {$use_ttk} {
Pat Thoyts3cb1f9c2009-05-12 15:45:06 +01002028 set width 0
2029 foreach label $args {
2030 set cx [string length $label]
2031 if {$cx > $width} {set width $cx}
2032 }
2033 set gm [ttk::combobox $w -width $width -state readonly\
Paul Mackerras39c12692013-05-11 17:08:41 +10002034 -textvariable $varname -values $args \
2035 -exportselection false]
2036 bind $gm <<ComboboxSelected>> [list $gm selection clear]
Pat Thoytsd93f1712009-04-17 01:24:35 +01002037 } else {
2038 set gm [eval [linsert $args 0 tk_optionMenu $w $varname]]
2039 }
2040 return $gm
2041}
2042
Paul Mackerrasd94f8cd2006-04-06 10:18:23 +10002043proc makewindow {} {
Paul Mackerras31c0eaa2007-12-30 22:41:14 +11002044 global canv canv2 canv3 linespc charspc ctext cflist cscroll
Paul Mackerras9c311b32007-10-04 22:27:13 +10002045 global tabstop
Paul Mackerrasb74fd572005-07-16 07:46:13 -04002046 global findtype findtypemenu findloc findstring fstring geometry
Paul Mackerras887fe3c2005-05-21 07:35:37 +00002047 global entries sha1entry sha1string sha1but
Steffen Prohaska890fae72007-08-12 12:05:46 +02002048 global diffcontextstring diffcontext
Steffen Prohaskab9b86002008-01-17 23:42:55 +01002049 global ignorespace
Paul Mackerras94a2eed2005-08-07 15:27:57 +10002050 global maincursor textcursor curtextcursor
Paul Mackerras219ea3a2006-09-07 10:21:39 +10002051 global rowctxmenu fakerowmenu mergemax wrapcomment
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10002052 global highlight_files gdttype
Paul Mackerras3ea06f92006-05-24 10:16:03 +10002053 global searchstring sstring
Mark Levedahl60378c02007-05-20 12:12:48 -04002054 global bgcolor fgcolor bglist fglist diffcolors selectbgcolor
Gauthier Östervall252c52d2013-03-27 14:40:51 +01002055 global uifgcolor uifgdisabledcolor
2056 global filesepbgcolor filesepfgcolor
2057 global mergecolors foundbgcolor currentsearchhitbgcolor
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10002058 global headctxmenu progresscanv progressitem progresscoords statusw
2059 global fprogitem fprogcoord lastprogupdate progupdatepending
Paul Mackerras6df74032008-05-11 22:13:02 +10002060 global rprogitem rprogcoord rownumsel numcommits
Pat Thoytsd93f1712009-04-17 01:24:35 +01002061 global have_tk85 use_ttk NS
Thomas Rastae4e3ff2010-10-16 12:15:10 +02002062 global git_version
2063 global worddiff
Paul Mackerras9a40c502005-05-12 23:46:16 +00002064
Paul Mackerras79056032008-10-18 16:24:46 +11002065 # The "mc" arguments here are purely so that xgettext
2066 # sees the following string as needing to be translated
Daniel A. Steffen5fdcbb12009-03-23 12:17:38 +01002067 set file {
2068 mc "File" cascade {
Paul Mackerras79056032008-10-18 16:24:46 +11002069 {mc "Update" command updatecommits -accelerator F5}
Felipe Contrerasa135f212012-04-07 03:29:38 +03002070 {mc "Reload" command reloadcommits -accelerator Shift-F5}
Paul Mackerras79056032008-10-18 16:24:46 +11002071 {mc "Reread references" command rereadrefs}
Alexander Gavrilovcea07cf2008-11-09 13:00:45 +03002072 {mc "List references" command showrefs -accelerator F2}
Alexander Gavrilov7fb0abb2008-11-13 23:12:42 +03002073 {xx "" separator}
2074 {mc "Start git gui" command {exec git gui &}}
2075 {xx "" separator}
Alexander Gavrilovcea07cf2008-11-09 13:00:45 +03002076 {mc "Quit" command doquit -accelerator Meta1-Q}
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11002077 }}
Daniel A. Steffen5fdcbb12009-03-23 12:17:38 +01002078 set edit {
2079 mc "Edit" cascade {
Paul Mackerras79056032008-10-18 16:24:46 +11002080 {mc "Preferences" command doprefs}
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11002081 }}
Daniel A. Steffen5fdcbb12009-03-23 12:17:38 +01002082 set view {
2083 mc "View" cascade {
Alexander Gavrilovcea07cf2008-11-09 13:00:45 +03002084 {mc "New view..." command {newview 0} -accelerator Shift-F4}
2085 {mc "Edit view..." command editview -state disabled -accelerator F4}
Paul Mackerras79056032008-10-18 16:24:46 +11002086 {mc "Delete view" command delview -state disabled}
2087 {xx "" separator}
2088 {mc "All files" radiobutton {selectedview 0} -command {showview 0}}
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11002089 }}
Daniel A. Steffen5fdcbb12009-03-23 12:17:38 +01002090 if {[tk windowingsystem] ne "aqua"} {
2091 set help {
2092 mc "Help" cascade {
Paul Mackerras79056032008-10-18 16:24:46 +11002093 {mc "About gitk" command about}
2094 {mc "Key bindings" command keys}
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11002095 }}
Daniel A. Steffen5fdcbb12009-03-23 12:17:38 +01002096 set bar [list $file $edit $view $help]
2097 } else {
2098 proc ::tk::mac::ShowPreferences {} {doprefs}
2099 proc ::tk::mac::Quit {} {doquit}
2100 lset file end [lreplace [lindex $file end] end-1 end]
2101 set apple {
2102 xx "Apple" cascade {
2103 {mc "About gitk" command about}
2104 {xx "" separator}
2105 }}
2106 set help {
2107 mc "Help" cascade {
2108 {mc "Key bindings" command keys}
2109 }}
2110 set bar [list $apple $file $view $help]
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11002111 }
Daniel A. Steffen5fdcbb12009-03-23 12:17:38 +01002112 makemenu .bar $bar
Paul Mackerras9a40c502005-05-12 23:46:16 +00002113 . configure -menu .bar
2114
Pat Thoytsd93f1712009-04-17 01:24:35 +01002115 if {$use_ttk} {
2116 # cover the non-themed toplevel with a themed frame.
2117 place [ttk::frame ._main_background] -x 0 -y 0 -relwidth 1 -relheight 1
2118 }
2119
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002120 # the gui has upper and lower half, parts of a paned window.
Pat Thoytsd93f1712009-04-17 01:24:35 +01002121 ${NS}::panedwindow .ctop -orient vertical
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002122
2123 # possibly use assumed geometry
Mark Levedahl9ca72f42007-02-12 19:19:34 -05002124 if {![info exists geometry(pwsash0)]} {
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002125 set geometry(topheight) [expr {15 * $linespc}]
2126 set geometry(topwidth) [expr {80 * $charspc}]
2127 set geometry(botheight) [expr {15 * $linespc}]
2128 set geometry(botwidth) [expr {50 * $charspc}]
Pat Thoytsd93f1712009-04-17 01:24:35 +01002129 set geometry(pwsash0) [list [expr {40 * $charspc}] 2]
2130 set geometry(pwsash1) [list [expr {60 * $charspc}] 2]
Paul Mackerras0fba86b2005-05-16 23:54:58 +00002131 }
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002132
2133 # 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 +01002134 ${NS}::frame .tf -height $geometry(topheight) -width $geometry(topwidth)
2135 ${NS}::frame .tf.histframe
2136 ${NS}::panedwindow .tf.histframe.pwclist -orient horizontal
2137 if {!$use_ttk} {
2138 .tf.histframe.pwclist configure -sashpad 0 -handlesize 4
2139 }
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002140
2141 # create three canvases
2142 set cscroll .tf.histframe.csb
2143 set canv .tf.histframe.pwclist.canv
Mark Levedahl9ca72f42007-02-12 19:19:34 -05002144 canvas $canv \
Mark Levedahl60378c02007-05-20 12:12:48 -04002145 -selectbackground $selectbgcolor \
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10002146 -background $bgcolor -bd 0 \
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002147 -yscrollincr $linespc -yscrollcommand "scrollcanv $cscroll"
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002148 .tf.histframe.pwclist add $canv
2149 set canv2 .tf.histframe.pwclist.canv2
Mark Levedahl9ca72f42007-02-12 19:19:34 -05002150 canvas $canv2 \
Mark Levedahl60378c02007-05-20 12:12:48 -04002151 -selectbackground $selectbgcolor \
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10002152 -background $bgcolor -bd 0 -yscrollincr $linespc
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002153 .tf.histframe.pwclist add $canv2
2154 set canv3 .tf.histframe.pwclist.canv3
Mark Levedahl9ca72f42007-02-12 19:19:34 -05002155 canvas $canv3 \
Mark Levedahl60378c02007-05-20 12:12:48 -04002156 -selectbackground $selectbgcolor \
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10002157 -background $bgcolor -bd 0 -yscrollincr $linespc
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002158 .tf.histframe.pwclist add $canv3
Pat Thoytsd93f1712009-04-17 01:24:35 +01002159 if {$use_ttk} {
2160 bind .tf.histframe.pwclist <Map> {
2161 bind %W <Map> {}
2162 .tf.histframe.pwclist sashpos 1 [lindex $::geometry(pwsash1) 0]
2163 .tf.histframe.pwclist sashpos 0 [lindex $::geometry(pwsash0) 0]
2164 }
2165 } else {
2166 eval .tf.histframe.pwclist sash place 0 $geometry(pwsash0)
2167 eval .tf.histframe.pwclist sash place 1 $geometry(pwsash1)
2168 }
Paul Mackerras98f350e2005-05-15 05:56:51 +00002169
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002170 # a scroll bar to rule them
Pat Thoytsd93f1712009-04-17 01:24:35 +01002171 ${NS}::scrollbar $cscroll -command {allcanvs yview}
2172 if {!$use_ttk} {$cscroll configure -highlightthickness 0}
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002173 pack $cscroll -side right -fill y
2174 bind .tf.histframe.pwclist <Configure> {resizeclistpanes %W %w}
2175 lappend bglist $canv $canv2 $canv3
2176 pack .tf.histframe.pwclist -fill both -expand 1 -side left
2177
2178 # we have two button bars at bottom of top frame. Bar 1
Pat Thoytsd93f1712009-04-17 01:24:35 +01002179 ${NS}::frame .tf.bar
2180 ${NS}::frame .tf.lbar -height 15
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002181
2182 set sha1entry .tf.bar.sha1
Paul Mackerras887fe3c2005-05-21 07:35:37 +00002183 set entries $sha1entry
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002184 set sha1but .tf.bar.sha1label
Markus Heidelberg0359ba72010-01-09 23:11:12 +01002185 button $sha1but -text "[mc "SHA1 ID:"] " -state disabled -relief flat \
Paul Mackerrasb039f0a2008-01-06 15:54:46 +11002186 -command gotocommit -width 8
Paul Mackerras887fe3c2005-05-21 07:35:37 +00002187 $sha1but conf -disabledforeground [$sha1but cget -foreground]
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002188 pack .tf.bar.sha1label -side left
Pat Thoytsd93f1712009-04-17 01:24:35 +01002189 ${NS}::entry $sha1entry -width 40 -font textfont -textvariable sha1string
Paul Mackerras887fe3c2005-05-21 07:35:37 +00002190 trace add variable sha1string write sha1change
Paul Mackerras98f350e2005-05-15 05:56:51 +00002191 pack $sha1entry -side left -pady 2
Paul Mackerrasd6982062005-08-06 22:06:06 +10002192
Stefan Hallerf062e502012-09-22 09:46:48 +02002193 set bm_left_data {
Paul Mackerrasd6982062005-08-06 22:06:06 +10002194 #define left_width 16
2195 #define left_height 16
2196 static unsigned char left_bits[] = {
2197 0x00, 0x00, 0xc0, 0x01, 0xe0, 0x00, 0x70, 0x00, 0x38, 0x00, 0x1c, 0x00,
2198 0x0e, 0x00, 0xff, 0x7f, 0xff, 0x7f, 0xff, 0x7f, 0x0e, 0x00, 0x1c, 0x00,
2199 0x38, 0x00, 0x70, 0x00, 0xe0, 0x00, 0xc0, 0x01};
2200 }
Stefan Hallerf062e502012-09-22 09:46:48 +02002201 set bm_right_data {
Paul Mackerrasd6982062005-08-06 22:06:06 +10002202 #define right_width 16
2203 #define right_height 16
2204 static unsigned char right_bits[] = {
2205 0x00, 0x00, 0xc0, 0x01, 0x80, 0x03, 0x00, 0x07, 0x00, 0x0e, 0x00, 0x1c,
2206 0x00, 0x38, 0xff, 0x7f, 0xff, 0x7f, 0xff, 0x7f, 0x00, 0x38, 0x00, 0x1c,
2207 0x00, 0x0e, 0x00, 0x07, 0x80, 0x03, 0xc0, 0x01};
2208 }
Gauthier Östervall252c52d2013-03-27 14:40:51 +01002209 image create bitmap bm-left -data $bm_left_data -foreground $uifgcolor
2210 image create bitmap bm-left-gray -data $bm_left_data -foreground $uifgdisabledcolor
2211 image create bitmap bm-right -data $bm_right_data -foreground $uifgcolor
2212 image create bitmap bm-right-gray -data $bm_right_data -foreground $uifgdisabledcolor
Stefan Hallerf062e502012-09-22 09:46:48 +02002213
Marcus Karlsson62e9ac52012-10-07 23:21:14 +02002214 ${NS}::button .tf.bar.leftbut -command goback -state disabled -width 26
2215 if {$use_ttk} {
2216 .tf.bar.leftbut configure -image [list bm-left disabled bm-left-gray]
2217 } else {
2218 .tf.bar.leftbut configure -image bm-left
2219 }
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002220 pack .tf.bar.leftbut -side left -fill y
Marcus Karlsson62e9ac52012-10-07 23:21:14 +02002221 ${NS}::button .tf.bar.rightbut -command goforw -state disabled -width 26
2222 if {$use_ttk} {
2223 .tf.bar.rightbut configure -image [list bm-right disabled bm-right-gray]
2224 } else {
2225 .tf.bar.rightbut configure -image bm-right
2226 }
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002227 pack .tf.bar.rightbut -side left -fill y
Paul Mackerrasd6982062005-08-06 22:06:06 +10002228
Pat Thoytsd93f1712009-04-17 01:24:35 +01002229 ${NS}::label .tf.bar.rowlabel -text [mc "Row"]
Paul Mackerras6df74032008-05-11 22:13:02 +10002230 set rownumsel {}
Pat Thoytsd93f1712009-04-17 01:24:35 +01002231 ${NS}::label .tf.bar.rownum -width 7 -textvariable rownumsel \
Paul Mackerras6df74032008-05-11 22:13:02 +10002232 -relief sunken -anchor e
Pat Thoytsd93f1712009-04-17 01:24:35 +01002233 ${NS}::label .tf.bar.rowlabel2 -text "/"
2234 ${NS}::label .tf.bar.numcommits -width 7 -textvariable numcommits \
Paul Mackerras6df74032008-05-11 22:13:02 +10002235 -relief sunken -anchor e
2236 pack .tf.bar.rowlabel .tf.bar.rownum .tf.bar.rowlabel2 .tf.bar.numcommits \
2237 -side left
Pat Thoytsd93f1712009-04-17 01:24:35 +01002238 if {!$use_ttk} {
2239 foreach w {rownum numcommits} {.tf.bar.$w configure -font textfont}
2240 }
Paul Mackerras6df74032008-05-11 22:13:02 +10002241 global selectedline
Paul Mackerras94b4a692008-05-20 20:51:06 +10002242 trace add variable selectedline write selectedline_change
Paul Mackerras6df74032008-05-11 22:13:02 +10002243
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10002244 # Status label and progress bar
2245 set statusw .tf.bar.status
Pat Thoytsd93f1712009-04-17 01:24:35 +01002246 ${NS}::label $statusw -width 15 -relief sunken
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10002247 pack $statusw -side left -padx 5
Pat Thoytsd93f1712009-04-17 01:24:35 +01002248 if {$use_ttk} {
2249 set progresscanv [ttk::progressbar .tf.bar.progress]
2250 } else {
2251 set h [expr {[font metrics uifont -linespace] + 2}]
2252 set progresscanv .tf.bar.progress
2253 canvas $progresscanv -relief sunken -height $h -borderwidth 2
2254 set progressitem [$progresscanv create rect -1 0 0 $h -fill green]
2255 set fprogitem [$progresscanv create rect -1 0 0 $h -fill yellow]
2256 set rprogitem [$progresscanv create rect -1 0 0 $h -fill red]
2257 }
2258 pack $progresscanv -side right -expand 1 -fill x -padx {0 2}
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10002259 set progresscoords {0 0}
2260 set fprogcoord 0
Paul Mackerrasa137a902007-10-23 21:12:49 +10002261 set rprogcoord 0
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10002262 bind $progresscanv <Configure> adjustprogress
2263 set lastprogupdate [clock clicks -milliseconds]
2264 set progupdatepending 0
Paul Mackerrasb5721c72005-05-10 12:08:22 +00002265
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002266 # build up the bottom bar of upper window
Pat Thoytsd93f1712009-04-17 01:24:35 +01002267 ${NS}::label .tf.lbar.flabel -text "[mc "Find"] "
Marc Branchaud786f15c2013-12-18 11:04:13 -05002268
2269 set bm_down_data {
2270 #define down_width 16
2271 #define down_height 16
2272 static unsigned char down_bits[] = {
2273 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01,
2274 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01,
2275 0x87, 0xe1, 0x8e, 0x71, 0x9c, 0x39, 0xb8, 0x1d,
2276 0xf0, 0x0f, 0xe0, 0x07, 0xc0, 0x03, 0x80, 0x01};
2277 }
2278 image create bitmap bm-down -data $bm_down_data -foreground $uifgcolor
2279 ${NS}::button .tf.lbar.fnext -width 26 -command {dofind 1 1}
2280 .tf.lbar.fnext configure -image bm-down
2281
2282 set bm_up_data {
2283 #define up_width 16
2284 #define up_height 16
2285 static unsigned char up_bits[] = {
2286 0x80, 0x01, 0xc0, 0x03, 0xe0, 0x07, 0xf0, 0x0f,
2287 0xb8, 0x1d, 0x9c, 0x39, 0x8e, 0x71, 0x87, 0xe1,
2288 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01,
2289 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01};
2290 }
2291 image create bitmap bm-up -data $bm_up_data -foreground $uifgcolor
2292 ${NS}::button .tf.lbar.fprev -width 26 -command {dofind -1 1}
2293 .tf.lbar.fprev configure -image bm-up
2294
Pat Thoytsd93f1712009-04-17 01:24:35 +01002295 ${NS}::label .tf.lbar.flab2 -text " [mc "commit"] "
Marc Branchaud786f15c2013-12-18 11:04:13 -05002296
Paul Mackerras687c8762007-09-22 12:49:33 +10002297 pack .tf.lbar.flabel .tf.lbar.fnext .tf.lbar.fprev .tf.lbar.flab2 \
2298 -side left -fill y
Christian Stimmingb007ee22007-11-07 18:44:35 +01002299 set gdttype [mc "containing:"]
Pat Thoyts3cb1f9c2009-05-12 15:45:06 +01002300 set gm [makedroplist .tf.lbar.gdttype gdttype \
Christian Stimmingb007ee22007-11-07 18:44:35 +01002301 [mc "containing:"] \
2302 [mc "touching paths:"] \
Martin Langhoffc33cb902012-06-14 20:34:11 +02002303 [mc "adding/removing string:"] \
2304 [mc "changing lines matching:"]]
Paul Mackerras687c8762007-09-22 12:49:33 +10002305 trace add variable gdttype write gdttype_change
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002306 pack .tf.lbar.gdttype -side left -fill y
Paul Mackerras687c8762007-09-22 12:49:33 +10002307
2308 set findstring {}
2309 set fstring .tf.lbar.findstring
2310 lappend entries $fstring
Mark Hillsb9b142f2010-01-13 20:40:22 +00002311 ${NS}::entry $fstring -width 30 -textvariable findstring
Paul Mackerras687c8762007-09-22 12:49:33 +10002312 trace add variable findstring write find_change
Christian Stimmingb007ee22007-11-07 18:44:35 +01002313 set findtype [mc "Exact"]
Pat Thoytsd93f1712009-04-17 01:24:35 +01002314 set findtypemenu [makedroplist .tf.lbar.findtype \
2315 findtype [mc "Exact"] [mc "IgnCase"] [mc "Regexp"]]
Paul Mackerras687c8762007-09-22 12:49:33 +10002316 trace add variable findtype write findcom_change
Christian Stimmingb007ee22007-11-07 18:44:35 +01002317 set findloc [mc "All fields"]
Pat Thoytsd93f1712009-04-17 01:24:35 +01002318 makedroplist .tf.lbar.findloc findloc [mc "All fields"] [mc "Headline"] \
Christian Stimmingb007ee22007-11-07 18:44:35 +01002319 [mc "Comments"] [mc "Author"] [mc "Committer"]
Paul Mackerras687c8762007-09-22 12:49:33 +10002320 trace add variable findloc write find_change
Paul Mackerras687c8762007-09-22 12:49:33 +10002321 pack .tf.lbar.findloc -side right
2322 pack .tf.lbar.findtype -side right
2323 pack $fstring -side left -expand 1 -fill x
Paul Mackerras908c3582006-05-20 09:38:11 +10002324
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002325 # Finish putting the upper half of the viewer together
2326 pack .tf.lbar -in .tf -side bottom -fill x
2327 pack .tf.bar -in .tf -side bottom -fill x
2328 pack .tf.histframe -fill both -side top -expand 1
2329 .ctop add .tf
Pat Thoytsd93f1712009-04-17 01:24:35 +01002330 if {!$use_ttk} {
2331 .ctop paneconfigure .tf -height $geometry(topheight)
2332 .ctop paneconfigure .tf -width $geometry(topwidth)
2333 }
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002334
2335 # now build up the bottom
Pat Thoytsd93f1712009-04-17 01:24:35 +01002336 ${NS}::panedwindow .pwbottom -orient horizontal
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002337
2338 # lower left, a text box over search bar, scroll bar to the right
2339 # if we know window height, then that will set the lower text height, otherwise
2340 # we set lower text height which will drive window height
2341 if {[info exists geometry(main)]} {
Pat Thoytsd93f1712009-04-17 01:24:35 +01002342 ${NS}::frame .bleft -width $geometry(botwidth)
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002343 } else {
Pat Thoytsd93f1712009-04-17 01:24:35 +01002344 ${NS}::frame .bleft -width $geometry(botwidth) -height $geometry(botheight)
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002345 }
Pat Thoytsd93f1712009-04-17 01:24:35 +01002346 ${NS}::frame .bleft.top
2347 ${NS}::frame .bleft.mid
2348 ${NS}::frame .bleft.bottom
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002349
Pat Thoytsd93f1712009-04-17 01:24:35 +01002350 ${NS}::button .bleft.top.search -text [mc "Search"] -command dosearch
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002351 pack .bleft.top.search -side left -padx 5
2352 set sstring .bleft.top.sstring
Pat Thoytsd93f1712009-04-17 01:24:35 +01002353 set searchstring ""
Mark Hillsb9b142f2010-01-13 20:40:22 +00002354 ${NS}::entry $sstring -width 20 -textvariable searchstring
Paul Mackerras3ea06f92006-05-24 10:16:03 +10002355 lappend entries $sstring
2356 trace add variable searchstring write incrsearch
2357 pack $sstring -side left -expand 1 -fill x
Pat Thoytsd93f1712009-04-17 01:24:35 +01002358 ${NS}::radiobutton .bleft.mid.diff -text [mc "Diff"] \
Paul Mackerrasa8d610a2007-04-19 11:39:12 +10002359 -command changediffdisp -variable diffelide -value {0 0}
Pat Thoytsd93f1712009-04-17 01:24:35 +01002360 ${NS}::radiobutton .bleft.mid.old -text [mc "Old version"] \
Paul Mackerrasa8d610a2007-04-19 11:39:12 +10002361 -command changediffdisp -variable diffelide -value {0 1}
Pat Thoytsd93f1712009-04-17 01:24:35 +01002362 ${NS}::radiobutton .bleft.mid.new -text [mc "New version"] \
Paul Mackerrasa8d610a2007-04-19 11:39:12 +10002363 -command changediffdisp -variable diffelide -value {1 0}
Pat Thoytsd93f1712009-04-17 01:24:35 +01002364 ${NS}::label .bleft.mid.labeldiffcontext -text " [mc "Lines of context"]: "
Paul Mackerrasa8d610a2007-04-19 11:39:12 +10002365 pack .bleft.mid.diff .bleft.mid.old .bleft.mid.new -side left
Mark Hills0933b042010-01-13 20:40:19 +00002366 spinbox .bleft.mid.diffcontext -width 5 \
Markus Heidelberga41ddbb2009-05-23 19:31:37 +02002367 -from 0 -increment 1 -to 10000000 \
Steffen Prohaska890fae72007-08-12 12:05:46 +02002368 -validate all -validatecommand "diffcontextvalidate %P" \
2369 -textvariable diffcontextstring
2370 .bleft.mid.diffcontext set $diffcontext
2371 trace add variable diffcontextstring write diffcontextchange
2372 lappend entries .bleft.mid.diffcontext
2373 pack .bleft.mid.labeldiffcontext .bleft.mid.diffcontext -side left
Pat Thoytsd93f1712009-04-17 01:24:35 +01002374 ${NS}::checkbutton .bleft.mid.ignspace -text [mc "Ignore space change"] \
Steffen Prohaskab9b86002008-01-17 23:42:55 +01002375 -command changeignorespace -variable ignorespace
2376 pack .bleft.mid.ignspace -side left -padx 5
Thomas Rastae4e3ff2010-10-16 12:15:10 +02002377
2378 set worddiff [mc "Line diff"]
2379 if {[package vcompare $git_version "1.7.2"] >= 0} {
2380 makedroplist .bleft.mid.worddiff worddiff [mc "Line diff"] \
2381 [mc "Markup words"] [mc "Color words"]
2382 trace add variable worddiff write changeworddiff
2383 pack .bleft.mid.worddiff -side left -padx 5
2384 }
2385
Pekka Kaitaniemi8809d692008-03-08 14:27:23 +02002386 set ctext .bleft.bottom.ctext
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10002387 text $ctext -background $bgcolor -foreground $fgcolor \
Paul Mackerras9c311b32007-10-04 22:27:13 +10002388 -state disabled -font textfont \
Pekka Kaitaniemi8809d692008-03-08 14:27:23 +02002389 -yscrollcommand scrolltext -wrap none \
2390 -xscrollcommand ".bleft.bottom.sbhorizontal set"
Paul Mackerras32f1b3e2007-09-28 21:27:39 +10002391 if {$have_tk85} {
2392 $ctext conf -tabstyle wordprocessor
2393 }
Pat Thoytsd93f1712009-04-17 01:24:35 +01002394 ${NS}::scrollbar .bleft.bottom.sb -command "$ctext yview"
2395 ${NS}::scrollbar .bleft.bottom.sbhorizontal -command "$ctext xview" -orient h
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002396 pack .bleft.top -side top -fill x
Paul Mackerrasa8d610a2007-04-19 11:39:12 +10002397 pack .bleft.mid -side top -fill x
Pekka Kaitaniemi8809d692008-03-08 14:27:23 +02002398 grid $ctext .bleft.bottom.sb -sticky nsew
2399 grid .bleft.bottom.sbhorizontal -sticky ew
2400 grid columnconfigure .bleft.bottom 0 -weight 1
2401 grid rowconfigure .bleft.bottom 0 -weight 1
2402 grid rowconfigure .bleft.bottom 1 -weight 0
2403 pack .bleft.bottom -side top -fill both -expand 1
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10002404 lappend bglist $ctext
2405 lappend fglist $ctext
Paul Mackerrasd2610d12005-05-11 00:45:38 +00002406
Sergey Vlasovf1b86292006-05-15 19:13:14 +04002407 $ctext tag conf comment -wrap $wrapcomment
Gauthier Östervall252c52d2013-03-27 14:40:51 +01002408 $ctext tag conf filesep -font textfontbold -fore $filesepfgcolor -back $filesepbgcolor
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10002409 $ctext tag conf hunksep -fore [lindex $diffcolors 2]
2410 $ctext tag conf d0 -fore [lindex $diffcolors 0]
Paul Mackerras8b07dca2008-11-02 22:34:47 +11002411 $ctext tag conf dresult -fore [lindex $diffcolors 1]
Gauthier Östervall252c52d2013-03-27 14:40:51 +01002412 $ctext tag conf m0 -fore [lindex $mergecolors 0]
2413 $ctext tag conf m1 -fore [lindex $mergecolors 1]
2414 $ctext tag conf m2 -fore [lindex $mergecolors 2]
2415 $ctext tag conf m3 -fore [lindex $mergecolors 3]
2416 $ctext tag conf m4 -fore [lindex $mergecolors 4]
2417 $ctext tag conf m5 -fore [lindex $mergecolors 5]
2418 $ctext tag conf m6 -fore [lindex $mergecolors 6]
2419 $ctext tag conf m7 -fore [lindex $mergecolors 7]
2420 $ctext tag conf m8 -fore [lindex $mergecolors 8]
2421 $ctext tag conf m9 -fore [lindex $mergecolors 9]
2422 $ctext tag conf m10 -fore [lindex $mergecolors 10]
2423 $ctext tag conf m11 -fore [lindex $mergecolors 11]
2424 $ctext tag conf m12 -fore [lindex $mergecolors 12]
2425 $ctext tag conf m13 -fore [lindex $mergecolors 13]
2426 $ctext tag conf m14 -fore [lindex $mergecolors 14]
2427 $ctext tag conf m15 -fore [lindex $mergecolors 15]
Paul Mackerras712fcc02005-11-30 09:28:16 +11002428 $ctext tag conf mmax -fore darkgrey
Paul Mackerrasb77b0272006-02-07 09:13:52 +11002429 set mergemax 16
Paul Mackerras9c311b32007-10-04 22:27:13 +10002430 $ctext tag conf mresult -font textfontbold
2431 $ctext tag conf msep -font textfontbold
Gauthier Östervall252c52d2013-03-27 14:40:51 +01002432 $ctext tag conf found -back $foundbgcolor
2433 $ctext tag conf currentsearchhit -back $currentsearchhitbgcolor
Paul Mackerras76d64ca2014-01-23 22:06:22 +11002434 $ctext tag conf wwrap -wrap word -lmargin2 1c
Paul Mackerras4399fe32013-01-03 10:10:31 +11002435 $ctext tag conf bold -font textfontbold
Paul Mackerrase5c2d852005-05-11 23:44:54 +00002436
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002437 .pwbottom add .bleft
Pat Thoytsd93f1712009-04-17 01:24:35 +01002438 if {!$use_ttk} {
2439 .pwbottom paneconfigure .bleft -width $geometry(botwidth)
2440 }
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002441
2442 # lower right
Pat Thoytsd93f1712009-04-17 01:24:35 +01002443 ${NS}::frame .bright
2444 ${NS}::frame .bright.mode
2445 ${NS}::radiobutton .bright.mode.patch -text [mc "Patch"] \
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10002446 -command reselectline -variable cmitmode -value "patch"
Pat Thoytsd93f1712009-04-17 01:24:35 +01002447 ${NS}::radiobutton .bright.mode.tree -text [mc "Tree"] \
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10002448 -command reselectline -variable cmitmode -value "tree"
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002449 grid .bright.mode.patch .bright.mode.tree -sticky ew
2450 pack .bright.mode -side top -fill x
2451 set cflist .bright.cfiles
Paul Mackerras9c311b32007-10-04 22:27:13 +10002452 set indent [font measure mainfont "nn"]
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002453 text $cflist \
Mark Levedahl60378c02007-05-20 12:12:48 -04002454 -selectbackground $selectbgcolor \
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10002455 -background $bgcolor -foreground $fgcolor \
Paul Mackerras9c311b32007-10-04 22:27:13 +10002456 -font mainfont \
Paul Mackerras7fcceed2006-04-27 19:21:49 +10002457 -tabs [list $indent [expr {2 * $indent}]] \
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002458 -yscrollcommand ".bright.sb set" \
Paul Mackerras7fcceed2006-04-27 19:21:49 +10002459 -cursor [. cget -cursor] \
2460 -spacing1 1 -spacing3 1
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10002461 lappend bglist $cflist
2462 lappend fglist $cflist
Pat Thoytsd93f1712009-04-17 01:24:35 +01002463 ${NS}::scrollbar .bright.sb -command "$cflist yview"
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002464 pack .bright.sb -side right -fill y
Paul Mackerrasd2610d12005-05-11 00:45:38 +00002465 pack $cflist -side left -fill both -expand 1
Paul Mackerras89b11d32006-05-02 19:55:31 +10002466 $cflist tag configure highlight \
2467 -background [$cflist cget -selectbackground]
Paul Mackerras9c311b32007-10-04 22:27:13 +10002468 $cflist tag configure bold -font mainfontbold
Paul Mackerrasd2610d12005-05-11 00:45:38 +00002469
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002470 .pwbottom add .bright
2471 .ctop add .pwbottom
Paul Mackerras1db95b02005-05-09 04:08:39 +00002472
Paul Mackerrasb9bee112008-03-10 16:50:34 +11002473 # restore window width & height if known
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002474 if {[info exists geometry(main)]} {
Paul Mackerrasb9bee112008-03-10 16:50:34 +11002475 if {[scan $geometry(main) "%dx%d" w h] >= 2} {
2476 if {$w > [winfo screenwidth .]} {
2477 set w [winfo screenwidth .]
2478 }
2479 if {$h > [winfo screenheight .]} {
2480 set h [winfo screenheight .]
2481 }
2482 wm geometry . "${w}x$h"
2483 }
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002484 }
2485
Pat Thoytsc876dba2009-04-14 22:09:53 +01002486 if {[info exists geometry(state)] && $geometry(state) eq "zoomed"} {
2487 wm state . $geometry(state)
2488 }
2489
Shawn O. Pearced23d98d2007-07-19 00:37:58 -04002490 if {[tk windowingsystem] eq {aqua}} {
2491 set M1B M1
Daniel A. Steffen5fdcbb12009-03-23 12:17:38 +01002492 set ::BM "3"
Shawn O. Pearced23d98d2007-07-19 00:37:58 -04002493 } else {
2494 set M1B Control
Daniel A. Steffen5fdcbb12009-03-23 12:17:38 +01002495 set ::BM "2"
Shawn O. Pearced23d98d2007-07-19 00:37:58 -04002496 }
2497
Pat Thoytsd93f1712009-04-17 01:24:35 +01002498 if {$use_ttk} {
2499 bind .ctop <Map> {
2500 bind %W <Map> {}
2501 %W sashpos 0 $::geometry(topheight)
2502 }
2503 bind .pwbottom <Map> {
2504 bind %W <Map> {}
2505 %W sashpos 0 $::geometry(botwidth)
2506 }
2507 }
2508
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002509 bind .pwbottom <Configure> {resizecdetpanes %W %w}
2510 pack .ctop -fill both -expand 1
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10002511 bindall <1> {selcanvline %W %x %y}
2512 #bindall <B1-Motion> {selcanvline %W %x %y}
Mark Levedahl314c3092007-08-07 21:40:35 -04002513 if {[tk windowingsystem] == "win32"} {
2514 bind . <MouseWheel> { windows_mousewheel_redirector %W %X %Y %D }
2515 bind $ctext <MouseWheel> { windows_mousewheel_redirector %W %X %Y %D ; break }
2516 } else {
2517 bindall <ButtonRelease-4> "allcanvs yview scroll -5 units"
2518 bindall <ButtonRelease-5> "allcanvs yview scroll 5 units"
Gabriele Mazzotta122b8072014-11-15 15:05:06 +01002519 bind $ctext <Button> {
2520 if {"%b" eq 6} {
2521 $ctext xview scroll -5 units
2522 } elseif {"%b" eq 7} {
2523 $ctext xview scroll 5 units
2524 }
2525 }
Jonathan del Strother5dd57d52007-10-15 10:33:07 +01002526 if {[tk windowingsystem] eq "aqua"} {
2527 bindall <MouseWheel> {
2528 set delta [expr {- (%D)}]
2529 allcanvs yview scroll $delta units
2530 }
Daniel A. Steffen5fdcbb12009-03-23 12:17:38 +01002531 bindall <Shift-MouseWheel> {
2532 set delta [expr {- (%D)}]
2533 $canv xview scroll $delta units
2534 }
Jonathan del Strother5dd57d52007-10-15 10:33:07 +01002535 }
Mark Levedahl314c3092007-08-07 21:40:35 -04002536 }
Daniel A. Steffen5fdcbb12009-03-23 12:17:38 +01002537 bindall <$::BM> "canvscan mark %W %x %y"
2538 bindall <B$::BM-Motion> "canvscan dragto %W %x %y"
Jens Lehmanndecd0a12010-02-02 23:11:28 +01002539 bind all <$M1B-Key-w> {destroy [winfo toplevel %W]}
2540 bind . <$M1B-Key-w> doquit
Rutger Nijlunsing6e5f7202006-04-05 10:24:03 +10002541 bindkey <Home> selfirstline
2542 bindkey <End> sellastline
Paul Mackerras17386062005-05-18 22:51:00 +00002543 bind . <Key-Up> "selnextline -1"
2544 bind . <Key-Down> "selnextline 1"
Paul Mackerrascca5d942007-10-27 21:16:56 +10002545 bind . <Shift-Key-Up> "dofind -1 0"
2546 bind . <Shift-Key-Down> "dofind 1 0"
Rutger Nijlunsing6e5f7202006-04-05 10:24:03 +10002547 bindkey <Key-Right> "goforw"
2548 bindkey <Key-Left> "goback"
2549 bind . <Key-Prior> "selnextpage -1"
2550 bind . <Key-Next> "selnextpage 1"
Shawn O. Pearced23d98d2007-07-19 00:37:58 -04002551 bind . <$M1B-Home> "allcanvs yview moveto 0.0"
2552 bind . <$M1B-End> "allcanvs yview moveto 1.0"
2553 bind . <$M1B-Key-Up> "allcanvs yview scroll -1 units"
2554 bind . <$M1B-Key-Down> "allcanvs yview scroll 1 units"
2555 bind . <$M1B-Key-Prior> "allcanvs yview scroll -1 pages"
2556 bind . <$M1B-Key-Next> "allcanvs yview scroll 1 pages"
Paul Mackerrascfb45632005-05-31 12:14:42 +00002557 bindkey <Key-Delete> "$ctext yview scroll -1 pages"
2558 bindkey <Key-BackSpace> "$ctext yview scroll -1 pages"
2559 bindkey <Key-space> "$ctext yview scroll 1 pages"
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00002560 bindkey p "selnextline -1"
2561 bindkey n "selnextline 1"
Robert Suetterlin6e2dda32005-09-22 10:07:36 +10002562 bindkey z "goback"
2563 bindkey x "goforw"
Jonathan Nieder811c70f2011-09-19 11:49:50 -05002564 bindkey k "selnextline -1"
2565 bindkey j "selnextline 1"
2566 bindkey h "goback"
Robert Suetterlin6e2dda32005-09-22 10:07:36 +10002567 bindkey l "goforw"
Paul Mackerrasf4c54b32008-05-10 13:15:36 +10002568 bindkey b prevfile
Paul Mackerrascfb45632005-05-31 12:14:42 +00002569 bindkey d "$ctext yview scroll 18 units"
2570 bindkey u "$ctext yview scroll -18 units"
Giuseppe Bilotta97bed032008-12-02 02:19:22 +01002571 bindkey / {focus $fstring}
Michele Ballabiob6e192d2009-03-30 14:55:21 +02002572 bindkey <Key-KP_Divide> {focus $fstring}
Paul Mackerrascca5d942007-10-27 21:16:56 +10002573 bindkey <Key-Return> {dofind 1 1}
2574 bindkey ? {dofind -1 1}
Paul Mackerras39ad8572005-05-19 12:35:53 +00002575 bindkey f nextfile
Alexander Gavrilovcea07cf2008-11-09 13:00:45 +03002576 bind . <F5> updatecommits
Andrew Wongebb91db2012-10-02 11:04:45 -04002577 bindmodfunctionkey Shift 5 reloadcommits
Alexander Gavrilovcea07cf2008-11-09 13:00:45 +03002578 bind . <F2> showrefs
Andrew Wong69ecfcd2012-10-02 11:04:44 -04002579 bindmodfunctionkey Shift 4 {newview 0}
Alexander Gavrilovcea07cf2008-11-09 13:00:45 +03002580 bind . <F4> edit_or_newview
Shawn O. Pearced23d98d2007-07-19 00:37:58 -04002581 bind . <$M1B-q> doquit
Paul Mackerrascca5d942007-10-27 21:16:56 +10002582 bind . <$M1B-f> {dofind 1 1}
2583 bind . <$M1B-g> {dofind 1 0}
Shawn O. Pearced23d98d2007-07-19 00:37:58 -04002584 bind . <$M1B-r> dosearchback
2585 bind . <$M1B-s> dosearch
2586 bind . <$M1B-equal> {incrfont 1}
Johannes Schindelin646f3a12008-01-11 12:39:33 +00002587 bind . <$M1B-plus> {incrfont 1}
Shawn O. Pearced23d98d2007-07-19 00:37:58 -04002588 bind . <$M1B-KP_Add> {incrfont 1}
2589 bind . <$M1B-minus> {incrfont -1}
2590 bind . <$M1B-KP_Subtract> {incrfont -1}
Mark Levedahlb6047c52007-02-08 22:22:24 -05002591 wm protocol . WM_DELETE_WINDOW doquit
Alexander Gavrilove2f90ee2008-07-12 16:09:28 +04002592 bind . <Destroy> {stop_backends}
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00002593 bind . <Button-1> "click %W"
Paul Mackerrascca5d942007-10-27 21:16:56 +10002594 bind $fstring <Key-Return> {dofind 1 1}
Paul Mackerras968ce452008-10-16 09:57:02 +11002595 bind $sha1entry <Key-Return> {gotocommit; break}
Paul Mackerrasee3dc722005-06-25 16:37:13 +10002596 bind $sha1entry <<PasteSelection>> clearsha1
Ilya Bobyrada2ea12014-03-20 01:58:51 -07002597 bind $sha1entry <<Paste>> clearsha1
Paul Mackerras7fcceed2006-04-27 19:21:49 +10002598 bind $cflist <1> {sel_flist %W %x %y; break}
2599 bind $cflist <B1-Motion> {sel_flist %W %x %y; break}
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10002600 bind $cflist <ButtonRelease-1> {treeclick %W %x %y}
Paul Mackerrasd277e892008-09-21 18:11:37 -05002601 global ctxbut
2602 bind $cflist $ctxbut {pop_flist_menu %W %X %Y %x %y}
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04002603 bind $ctext $ctxbut {pop_diff_menu %W %X %Y %x %y}
Stefan Haller4adcbea2010-11-14 13:22:56 +01002604 bind $ctext <Button-1> {focus %W}
Stefan Hallerc4614992012-09-22 09:40:24 +02002605 bind $ctext <<Selection>> rehighlight_search_results
Max Kirillovd4ec30b2014-07-08 23:45:35 +03002606 for {set i 1} {$i < 10} {incr i} {
2607 bind . <$M1B-Key-$i> [list go_to_parent $i]
2608 }
Paul Mackerrasea13cba2005-06-16 10:54:04 +00002609
2610 set maincursor [. cget -cursor]
2611 set textcursor [$ctext cget -cursor]
Paul Mackerras94a2eed2005-08-07 15:27:57 +10002612 set curtextcursor $textcursor
Paul Mackerras84ba7342005-06-17 00:12:26 +00002613
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10002614 set rowctxmenu .rowctxmenu
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11002615 makemenu $rowctxmenu {
Paul Mackerras79056032008-10-18 16:24:46 +11002616 {mc "Diff this -> selected" command {diffvssel 0}}
2617 {mc "Diff selected -> this" command {diffvssel 1}}
2618 {mc "Make patch" command mkpatch}
2619 {mc "Create tag" command mktag}
2620 {mc "Write commit to file" command writecommit}
2621 {mc "Create new branch" command mkbranch}
2622 {mc "Cherry-pick this commit" command cherrypick}
2623 {mc "Reset HEAD branch to here" command resethead}
Paul Mackerrasb9fdba72009-04-09 09:34:46 +10002624 {mc "Mark this commit" command markhere}
2625 {mc "Return to mark" command gotomark}
2626 {mc "Find descendant of this and mark" command find_common_desc}
Paul Mackerras010509f2009-04-09 22:10:20 +10002627 {mc "Compare with marked commit" command compare_commits}
Paul Mackerras6febded2012-03-23 22:07:27 +11002628 {mc "Diff this -> marked commit" command {diffvsmark 0}}
2629 {mc "Diff marked commit -> this" command {diffvsmark 1}}
Knut Franke8f3ff932013-04-27 16:36:13 +02002630 {mc "Revert this commit" command revert}
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11002631 }
2632 $rowctxmenu configure -tearoff 0
Paul Mackerras10299152006-08-02 09:52:01 +10002633
Paul Mackerras219ea3a2006-09-07 10:21:39 +10002634 set fakerowmenu .fakerowmenu
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11002635 makemenu $fakerowmenu {
Paul Mackerras79056032008-10-18 16:24:46 +11002636 {mc "Diff this -> selected" command {diffvssel 0}}
2637 {mc "Diff selected -> this" command {diffvssel 1}}
2638 {mc "Make patch" command mkpatch}
Paul Mackerras6febded2012-03-23 22:07:27 +11002639 {mc "Diff this -> marked commit" command {diffvsmark 0}}
2640 {mc "Diff marked commit -> this" command {diffvsmark 1}}
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11002641 }
2642 $fakerowmenu configure -tearoff 0
Paul Mackerras219ea3a2006-09-07 10:21:39 +10002643
Paul Mackerras10299152006-08-02 09:52:01 +10002644 set headctxmenu .headctxmenu
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11002645 makemenu $headctxmenu {
Paul Mackerras79056032008-10-18 16:24:46 +11002646 {mc "Check out this branch" command cobranch}
2647 {mc "Remove this branch" command rmbranch}
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11002648 }
2649 $headctxmenu configure -tearoff 0
Paul Mackerras32447292007-07-27 22:30:15 +10002650
2651 global flist_menu
2652 set flist_menu .flistctxmenu
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11002653 makemenu $flist_menu {
Paul Mackerras79056032008-10-18 16:24:46 +11002654 {mc "Highlight this too" command {flist_hl 0}}
2655 {mc "Highlight this only" command {flist_hl 1}}
2656 {mc "External diff" command {external_diff}}
2657 {mc "Blame parent commit" command {external_blame 1}}
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11002658 }
2659 $flist_menu configure -tearoff 0
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04002660
2661 global diff_menu
2662 set diff_menu .diffctxmenu
2663 makemenu $diff_menu {
Paul Mackerras8a897742008-10-27 21:36:25 +11002664 {mc "Show origin of this line" command show_line_source}
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04002665 {mc "Run git gui blame on this line" command {external_blame_diff}}
2666 }
2667 $diff_menu configure -tearoff 0
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00002668}
2669
Mark Levedahl314c3092007-08-07 21:40:35 -04002670# Windows sends all mouse wheel events to the current focused window, not
2671# the one where the mouse hovers, so bind those events here and redirect
2672# to the correct window
2673proc windows_mousewheel_redirector {W X Y D} {
2674 global canv canv2 canv3
2675 set w [winfo containing -displayof $W $X $Y]
2676 if {$w ne ""} {
2677 set u [expr {$D < 0 ? 5 : -5}]
2678 if {$w == $canv || $w == $canv2 || $w == $canv3} {
2679 allcanvs yview scroll $u units
2680 } else {
2681 catch {
2682 $w yview scroll $u units
2683 }
2684 }
2685 }
2686}
2687
Paul Mackerras6df74032008-05-11 22:13:02 +10002688# Update row number label when selectedline changes
2689proc selectedline_change {n1 n2 op} {
2690 global selectedline rownumsel
2691
Paul Mackerras94b4a692008-05-20 20:51:06 +10002692 if {$selectedline eq {}} {
Paul Mackerras6df74032008-05-11 22:13:02 +10002693 set rownumsel {}
2694 } else {
2695 set rownumsel [expr {$selectedline + 1}]
2696 }
2697}
2698
Paul Mackerrasbe0cd092006-03-31 09:55:11 +11002699# mouse-2 makes all windows scan vertically, but only the one
2700# the cursor is in scans horizontally
2701proc canvscan {op w x y} {
2702 global canv canv2 canv3
2703 foreach c [list $canv $canv2 $canv3] {
2704 if {$c == $w} {
2705 $c scan $op $x $y
2706 } else {
2707 $c scan $op 0 $y
2708 }
2709 }
2710}
2711
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002712proc scrollcanv {cscroll f0 f1} {
2713 $cscroll set $f0 $f1
Paul Mackerras31c0eaa2007-12-30 22:41:14 +11002714 drawvisible
Paul Mackerras908c3582006-05-20 09:38:11 +10002715 flushhighlights
Paul Mackerras9f1afe02006-02-19 22:44:47 +11002716}
2717
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00002718# when we make a key binding for the toplevel, make sure
2719# it doesn't get triggered when that key is pressed in the
2720# find string entry widget.
2721proc bindkey {ev script} {
Paul Mackerras887fe3c2005-05-21 07:35:37 +00002722 global entries
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00002723 bind . $ev $script
2724 set escript [bind Entry $ev]
2725 if {$escript == {}} {
2726 set escript [bind Entry <Key>]
2727 }
Paul Mackerras887fe3c2005-05-21 07:35:37 +00002728 foreach e $entries {
2729 bind $e $ev "$escript; break"
2730 }
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00002731}
2732
Andrew Wong69ecfcd2012-10-02 11:04:44 -04002733proc bindmodfunctionkey {mod n script} {
2734 bind . <$mod-F$n> $script
2735 catch { bind . <$mod-XF86_Switch_VT_$n> $script }
2736}
2737
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00002738# set the focus back to the toplevel for any click outside
Paul Mackerras887fe3c2005-05-21 07:35:37 +00002739# the entry widgets
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00002740proc click {w} {
Mark Levedahlbd441de2007-08-07 21:40:34 -04002741 global ctext entries
2742 foreach e [concat $entries $ctext] {
Paul Mackerras887fe3c2005-05-21 07:35:37 +00002743 if {$w == $e} return
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00002744 }
Paul Mackerras887fe3c2005-05-21 07:35:37 +00002745 focus .
Paul Mackerras0fba86b2005-05-16 23:54:58 +00002746}
2747
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10002748# Adjust the progress bar for a change in requested extent or canvas size
2749proc adjustprogress {} {
2750 global progresscanv progressitem progresscoords
2751 global fprogitem fprogcoord lastprogupdate progupdatepending
Pat Thoytsd93f1712009-04-17 01:24:35 +01002752 global rprogitem rprogcoord use_ttk
2753
2754 if {$use_ttk} {
2755 $progresscanv configure -value [expr {int($fprogcoord * 100)}]
2756 return
2757 }
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10002758
2759 set w [expr {[winfo width $progresscanv] - 4}]
2760 set x0 [expr {$w * [lindex $progresscoords 0]}]
2761 set x1 [expr {$w * [lindex $progresscoords 1]}]
2762 set h [winfo height $progresscanv]
2763 $progresscanv coords $progressitem $x0 0 $x1 $h
2764 $progresscanv coords $fprogitem 0 0 [expr {$w * $fprogcoord}] $h
Paul Mackerrasa137a902007-10-23 21:12:49 +10002765 $progresscanv coords $rprogitem 0 0 [expr {$w * $rprogcoord}] $h
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10002766 set now [clock clicks -milliseconds]
2767 if {$now >= $lastprogupdate + 100} {
2768 set progupdatepending 0
2769 update
2770 } elseif {!$progupdatepending} {
2771 set progupdatepending 1
2772 after [expr {$lastprogupdate + 100 - $now}] doprogupdate
2773 }
2774}
2775
2776proc doprogupdate {} {
2777 global lastprogupdate progupdatepending
2778
2779 if {$progupdatepending} {
2780 set progupdatepending 0
2781 set lastprogupdate [clock clicks -milliseconds]
2782 update
2783 }
2784}
2785
Max Kirilloveaf7e832015-03-04 05:58:18 +02002786proc config_check_tmp_exists {tries_left} {
2787 global config_file_tmp
2788
2789 if {[file exists $config_file_tmp]} {
2790 incr tries_left -1
2791 if {$tries_left > 0} {
2792 after 100 [list config_check_tmp_exists $tries_left]
2793 } else {
2794 error_popup "There appears to be a stale $config_file_tmp\
2795 file, which will prevent gitk from saving its configuration on exit.\
2796 Please remove it if it is not being used by any existing gitk process."
2797 }
2798 }
2799}
2800
Max Kirillov995f7922015-03-04 05:58:16 +02002801proc config_init_trace {name} {
2802 global config_variable_changed config_variable_original
2803
2804 upvar #0 $name var
2805 set config_variable_changed($name) 0
2806 set config_variable_original($name) $var
2807}
2808
2809proc config_variable_change_cb {name name2 op} {
2810 global config_variable_changed config_variable_original
2811
2812 upvar #0 $name var
2813 if {$op eq "write" &&
2814 (![info exists config_variable_original($name)] ||
2815 $config_variable_original($name) ne $var)} {
2816 set config_variable_changed($name) 1
2817 }
2818}
2819
Paul Mackerras0fba86b2005-05-16 23:54:58 +00002820proc savestuff {w} {
Max Kirillov9fabefb2014-09-14 23:35:57 +03002821 global stuffsaved
Astril Hayato8f863392014-01-21 19:10:16 +00002822 global config_file config_file_tmp
Max Kirillov995f7922015-03-04 05:58:16 +02002823 global config_variables config_variable_changed
2824 global viewchanged
2825
2826 upvar #0 viewname current_viewname
2827 upvar #0 viewfiles current_viewfiles
2828 upvar #0 viewargs current_viewargs
2829 upvar #0 viewargscmd current_viewargscmd
2830 upvar #0 viewperm current_viewperm
2831 upvar #0 nextviewnum current_nextviewnum
2832 upvar #0 use_ttk current_use_ttk
Paul Mackerras4ef17532005-07-27 22:16:51 -05002833
Paul Mackerras0fba86b2005-05-16 23:54:58 +00002834 if {$stuffsaved} return
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00002835 if {![winfo viewable .]} return
Max Kirilloveaf7e832015-03-04 05:58:18 +02002836 set remove_tmp 0
Max Kirillov1dd29602015-03-04 05:58:17 +02002837 if {[catch {
Max Kirilloveaf7e832015-03-04 05:58:18 +02002838 set try_count 0
2839 while {[catch {set f [open $config_file_tmp {WRONLY CREAT EXCL}]}]} {
2840 if {[incr try_count] > 50} {
2841 error "Unable to write config file: $config_file_tmp exists"
2842 }
2843 after 100
Astril Hayato8f863392014-01-21 19:10:16 +00002844 }
Max Kirilloveaf7e832015-03-04 05:58:18 +02002845 set remove_tmp 1
Paul Mackerras9832e4f2009-03-23 21:37:51 +11002846 if {$::tcl_platform(platform) eq {windows}} {
Astril Hayato8f863392014-01-21 19:10:16 +00002847 file attributes $config_file_tmp -hidden true
Paul Mackerras9832e4f2009-03-23 21:37:51 +11002848 }
Max Kirillov995f7922015-03-04 05:58:16 +02002849 if {[file exists $config_file]} {
2850 source $config_file
2851 }
Max Kirillov9fabefb2014-09-14 23:35:57 +03002852 foreach var_name $config_variables {
2853 upvar #0 $var_name var
Max Kirillov995f7922015-03-04 05:58:16 +02002854 upvar 0 $var_name old_var
2855 if {!$config_variable_changed($var_name) && [info exists old_var]} {
2856 puts $f [list set $var_name $old_var]
2857 } else {
2858 puts $f [list set $var_name $var]
2859 }
Max Kirillov9fabefb2014-09-14 23:35:57 +03002860 }
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002861
Mark Levedahlb6047c52007-02-08 22:22:24 -05002862 puts $f "set geometry(main) [wm geometry .]"
Pat Thoytsc876dba2009-04-14 22:09:53 +01002863 puts $f "set geometry(state) [wm state .]"
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002864 puts $f "set geometry(topwidth) [winfo width .tf]"
2865 puts $f "set geometry(topheight) [winfo height .tf]"
Max Kirillov995f7922015-03-04 05:58:16 +02002866 if {$current_use_ttk} {
Pat Thoytsd93f1712009-04-17 01:24:35 +01002867 puts $f "set geometry(pwsash0) \"[.tf.histframe.pwclist sashpos 0] 1\""
2868 puts $f "set geometry(pwsash1) \"[.tf.histframe.pwclist sashpos 1] 1\""
2869 } else {
2870 puts $f "set geometry(pwsash0) \"[.tf.histframe.pwclist sash coord 0]\""
2871 puts $f "set geometry(pwsash1) \"[.tf.histframe.pwclist sash coord 1]\""
2872 }
Junio C Hamanoe9937d22007-02-01 08:46:38 -05002873 puts $f "set geometry(botwidth) [winfo width .bleft]"
2874 puts $f "set geometry(botheight) [winfo height .bleft]"
2875
Max Kirillov995f7922015-03-04 05:58:16 +02002876 array set view_save {}
2877 array set views {}
2878 if {![info exists permviews]} { set permviews {} }
2879 foreach view $permviews {
2880 set view_save([lindex $view 0]) 1
2881 set views([lindex $view 0]) $view
2882 }
Paul Mackerrasa90a6d22006-04-25 17:12:46 +10002883 puts -nonewline $f "set permviews {"
Max Kirillov995f7922015-03-04 05:58:16 +02002884 for {set v 1} {$v < $current_nextviewnum} {incr v} {
2885 if {$viewchanged($v)} {
2886 if {$current_viewperm($v)} {
2887 set views($current_viewname($v)) [list $current_viewname($v) $current_viewfiles($v) $current_viewargs($v) $current_viewargscmd($v)]
2888 } else {
2889 set view_save($current_viewname($v)) 0
2890 }
Paul Mackerrasa90a6d22006-04-25 17:12:46 +10002891 }
2892 }
Max Kirillov995f7922015-03-04 05:58:16 +02002893 # write old and updated view to their places and append remaining to the end
2894 foreach view $permviews {
2895 set view_name [lindex $view 0]
2896 if {$view_save($view_name)} {
2897 puts $f "{$views($view_name)}"
2898 }
2899 unset views($view_name)
2900 }
2901 foreach view_name [array names views] {
2902 puts $f "{$views($view_name)}"
2903 }
Paul Mackerrasa90a6d22006-04-25 17:12:46 +10002904 puts $f "}"
Paul Mackerras0fba86b2005-05-16 23:54:58 +00002905 close $f
Astril Hayato8f863392014-01-21 19:10:16 +00002906 file rename -force $config_file_tmp $config_file
Max Kirilloveaf7e832015-03-04 05:58:18 +02002907 set remove_tmp 0
Max Kirillov1dd29602015-03-04 05:58:17 +02002908 } err]} {
2909 puts "Error saving config: $err"
Paul Mackerras0fba86b2005-05-16 23:54:58 +00002910 }
Max Kirilloveaf7e832015-03-04 05:58:18 +02002911 if {$remove_tmp} {
2912 file delete -force $config_file_tmp
2913 }
Paul Mackerras0fba86b2005-05-16 23:54:58 +00002914 set stuffsaved 1
Paul Mackerras1db95b02005-05-09 04:08:39 +00002915}
2916
Paul Mackerras43bddeb2005-05-15 23:19:18 +00002917proc resizeclistpanes {win w} {
Pat Thoytsd93f1712009-04-17 01:24:35 +01002918 global oldwidth use_ttk
Paul Mackerras418c4c72006-02-07 09:10:18 +11002919 if {[info exists oldwidth($win)]} {
Pat Thoytsd93f1712009-04-17 01:24:35 +01002920 if {$use_ttk} {
2921 set s0 [$win sashpos 0]
2922 set s1 [$win sashpos 1]
2923 } else {
2924 set s0 [$win sash coord 0]
2925 set s1 [$win sash coord 1]
2926 }
Paul Mackerras43bddeb2005-05-15 23:19:18 +00002927 if {$w < 60} {
2928 set sash0 [expr {int($w/2 - 2)}]
2929 set sash1 [expr {int($w*5/6 - 2)}]
2930 } else {
2931 set factor [expr {1.0 * $w / $oldwidth($win)}]
2932 set sash0 [expr {int($factor * [lindex $s0 0])}]
2933 set sash1 [expr {int($factor * [lindex $s1 0])}]
2934 if {$sash0 < 30} {
2935 set sash0 30
2936 }
2937 if {$sash1 < $sash0 + 20} {
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08002938 set sash1 [expr {$sash0 + 20}]
Paul Mackerras43bddeb2005-05-15 23:19:18 +00002939 }
2940 if {$sash1 > $w - 10} {
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08002941 set sash1 [expr {$w - 10}]
Paul Mackerras43bddeb2005-05-15 23:19:18 +00002942 if {$sash0 > $sash1 - 20} {
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08002943 set sash0 [expr {$sash1 - 20}]
Paul Mackerras43bddeb2005-05-15 23:19:18 +00002944 }
2945 }
2946 }
Pat Thoytsd93f1712009-04-17 01:24:35 +01002947 if {$use_ttk} {
2948 $win sashpos 0 $sash0
2949 $win sashpos 1 $sash1
2950 } else {
2951 $win sash place 0 $sash0 [lindex $s0 1]
2952 $win sash place 1 $sash1 [lindex $s1 1]
2953 }
Paul Mackerras43bddeb2005-05-15 23:19:18 +00002954 }
2955 set oldwidth($win) $w
2956}
2957
2958proc resizecdetpanes {win w} {
Pat Thoytsd93f1712009-04-17 01:24:35 +01002959 global oldwidth use_ttk
Paul Mackerras418c4c72006-02-07 09:10:18 +11002960 if {[info exists oldwidth($win)]} {
Pat Thoytsd93f1712009-04-17 01:24:35 +01002961 if {$use_ttk} {
2962 set s0 [$win sashpos 0]
2963 } else {
2964 set s0 [$win sash coord 0]
2965 }
Paul Mackerras43bddeb2005-05-15 23:19:18 +00002966 if {$w < 60} {
2967 set sash0 [expr {int($w*3/4 - 2)}]
2968 } else {
2969 set factor [expr {1.0 * $w / $oldwidth($win)}]
2970 set sash0 [expr {int($factor * [lindex $s0 0])}]
2971 if {$sash0 < 45} {
2972 set sash0 45
2973 }
2974 if {$sash0 > $w - 15} {
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08002975 set sash0 [expr {$w - 15}]
Paul Mackerras43bddeb2005-05-15 23:19:18 +00002976 }
2977 }
Pat Thoytsd93f1712009-04-17 01:24:35 +01002978 if {$use_ttk} {
2979 $win sashpos 0 $sash0
2980 } else {
2981 $win sash place 0 $sash0 [lindex $s0 1]
2982 }
Paul Mackerras43bddeb2005-05-15 23:19:18 +00002983 }
2984 set oldwidth($win) $w
2985}
2986
Paul Mackerrasb5721c72005-05-10 12:08:22 +00002987proc allcanvs args {
2988 global canv canv2 canv3
2989 eval $canv $args
2990 eval $canv2 $args
2991 eval $canv3 $args
2992}
2993
2994proc bindall {event action} {
2995 global canv canv2 canv3
2996 bind $canv $event $action
2997 bind $canv2 $event $action
2998 bind $canv3 $event $action
2999}
3000
Paul Mackerras9a40c502005-05-12 23:46:16 +00003001proc about {} {
Pat Thoytsd93f1712009-04-17 01:24:35 +01003002 global uifont NS
Paul Mackerras9a40c502005-05-12 23:46:16 +00003003 set w .about
3004 if {[winfo exists $w]} {
3005 raise $w
3006 return
3007 }
Pat Thoytsd93f1712009-04-17 01:24:35 +01003008 ttk_toplevel $w
Christian Stimmingd990ced2007-11-07 18:42:55 +01003009 wm title $w [mc "About gitk"]
Alexander Gavrilove7d64002008-11-11 23:55:42 +03003010 make_transient $w .
Christian Stimmingd990ced2007-11-07 18:42:55 +01003011 message $w.m -text [mc "
Paul Mackerras9f1afe02006-02-19 22:44:47 +11003012Gitk - a commit viewer for git
Paul Mackerras9a40c502005-05-12 23:46:16 +00003013
Paul Mackerras6c626a02014-01-21 22:02:27 +11003014Copyright \u00a9 2005-2014 Paul Mackerras
Paul Mackerras9a40c502005-05-12 23:46:16 +00003015
Christian Stimmingd990ced2007-11-07 18:42:55 +01003016Use and redistribute under the terms of the GNU General Public License"] \
Eygene Ryabinkin3a950e92007-03-27 14:36:59 +04003017 -justify center -aspect 400 -border 2 -bg white -relief groove
3018 pack $w.m -side top -fill x -padx 2 -pady 2
Pat Thoytsd93f1712009-04-17 01:24:35 +01003019 ${NS}::button $w.ok -text [mc "Close"] -command "destroy $w" -default active
Paul Mackerras9a40c502005-05-12 23:46:16 +00003020 pack $w.ok -side bottom
Eygene Ryabinkin3a950e92007-03-27 14:36:59 +04003021 bind $w <Visibility> "focus $w.ok"
3022 bind $w <Key-Escape> "destroy $w"
3023 bind $w <Key-Return> "destroy $w"
Pat Thoytsd93f1712009-04-17 01:24:35 +01003024 tk::PlaceWindow $w widget .
Paul Mackerras9a40c502005-05-12 23:46:16 +00003025}
3026
Paul Mackerras4e95e1f2006-04-05 09:39:51 +10003027proc keys {} {
Pat Thoytsd93f1712009-04-17 01:24:35 +01003028 global NS
Paul Mackerras4e95e1f2006-04-05 09:39:51 +10003029 set w .keys
3030 if {[winfo exists $w]} {
3031 raise $w
3032 return
3033 }
Shawn O. Pearced23d98d2007-07-19 00:37:58 -04003034 if {[tk windowingsystem] eq {aqua}} {
3035 set M1T Cmd
3036 } else {
3037 set M1T Ctrl
3038 }
Pat Thoytsd93f1712009-04-17 01:24:35 +01003039 ttk_toplevel $w
Christian Stimmingd990ced2007-11-07 18:42:55 +01003040 wm title $w [mc "Gitk key bindings"]
Alexander Gavrilove7d64002008-11-11 23:55:42 +03003041 make_transient $w .
Michele Ballabio3d2c9982008-01-15 23:31:49 +01003042 message $w.m -text "
3043[mc "Gitk key bindings:"]
Paul Mackerras4e95e1f2006-04-05 09:39:51 +10003044
Michele Ballabio3d2c9982008-01-15 23:31:49 +01003045[mc "<%s-Q> Quit" $M1T]
Jens Lehmanndecd0a12010-02-02 23:11:28 +01003046[mc "<%s-W> Close window" $M1T]
Michele Ballabio3d2c9982008-01-15 23:31:49 +01003047[mc "<Home> Move to first commit"]
3048[mc "<End> Move to last commit"]
Jonathan Nieder811c70f2011-09-19 11:49:50 -05003049[mc "<Up>, p, k Move up one commit"]
3050[mc "<Down>, n, j Move down one commit"]
3051[mc "<Left>, z, h Go back in history list"]
Michele Ballabio3d2c9982008-01-15 23:31:49 +01003052[mc "<Right>, x, l Go forward in history list"]
Max Kirillovd4ec30b2014-07-08 23:45:35 +03003053[mc "<%s-n> Go to n-th parent of current commit in history list" $M1T]
Michele Ballabio3d2c9982008-01-15 23:31:49 +01003054[mc "<PageUp> Move up one page in commit list"]
3055[mc "<PageDown> Move down one page in commit list"]
3056[mc "<%s-Home> Scroll to top of commit list" $M1T]
3057[mc "<%s-End> Scroll to bottom of commit list" $M1T]
3058[mc "<%s-Up> Scroll commit list up one line" $M1T]
3059[mc "<%s-Down> Scroll commit list down one line" $M1T]
3060[mc "<%s-PageUp> Scroll commit list up one page" $M1T]
3061[mc "<%s-PageDown> Scroll commit list down one page" $M1T]
3062[mc "<Shift-Up> Find backwards (upwards, later commits)"]
3063[mc "<Shift-Down> Find forwards (downwards, earlier commits)"]
3064[mc "<Delete>, b Scroll diff view up one page"]
3065[mc "<Backspace> Scroll diff view up one page"]
3066[mc "<Space> Scroll diff view down one page"]
3067[mc "u Scroll diff view up 18 lines"]
3068[mc "d Scroll diff view down 18 lines"]
3069[mc "<%s-F> Find" $M1T]
3070[mc "<%s-G> Move to next find hit" $M1T]
3071[mc "<Return> Move to next find hit"]
Giuseppe Bilotta97bed032008-12-02 02:19:22 +01003072[mc "/ Focus the search box"]
Michele Ballabio3d2c9982008-01-15 23:31:49 +01003073[mc "? Move to previous find hit"]
3074[mc "f Scroll diff view to next file"]
3075[mc "<%s-S> Search for next hit in diff view" $M1T]
3076[mc "<%s-R> Search for previous hit in diff view" $M1T]
3077[mc "<%s-KP+> Increase font size" $M1T]
3078[mc "<%s-plus> Increase font size" $M1T]
3079[mc "<%s-KP-> Decrease font size" $M1T]
3080[mc "<%s-minus> Decrease font size" $M1T]
3081[mc "<F5> Update"]
3082" \
Eygene Ryabinkin3a950e92007-03-27 14:36:59 +04003083 -justify left -bg white -border 2 -relief groove
3084 pack $w.m -side top -fill both -padx 2 -pady 2
Pat Thoytsd93f1712009-04-17 01:24:35 +01003085 ${NS}::button $w.ok -text [mc "Close"] -command "destroy $w" -default active
Alexander Gavrilov76f15942008-11-02 21:59:44 +03003086 bind $w <Key-Escape> [list destroy $w]
Paul Mackerras4e95e1f2006-04-05 09:39:51 +10003087 pack $w.ok -side bottom
Eygene Ryabinkin3a950e92007-03-27 14:36:59 +04003088 bind $w <Visibility> "focus $w.ok"
3089 bind $w <Key-Escape> "destroy $w"
3090 bind $w <Key-Return> "destroy $w"
Paul Mackerras4e95e1f2006-04-05 09:39:51 +10003091}
3092
Paul Mackerras7fcceed2006-04-27 19:21:49 +10003093# Procedures for manipulating the file list window at the
3094# bottom right of the overall window.
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10003095
3096proc treeview {w l openlevs} {
3097 global treecontents treediropen treeheight treeparent treeindex
3098
3099 set ix 0
3100 set treeindex() 0
3101 set lev 0
3102 set prefix {}
3103 set prefixend -1
3104 set prefendstack {}
3105 set htstack {}
3106 set ht 0
3107 set treecontents() {}
3108 $w conf -state normal
3109 foreach f $l {
3110 while {[string range $f 0 $prefixend] ne $prefix} {
3111 if {$lev <= $openlevs} {
3112 $w mark set e:$treeindex($prefix) "end -1c"
3113 $w mark gravity e:$treeindex($prefix) left
3114 }
3115 set treeheight($prefix) $ht
3116 incr ht [lindex $htstack end]
3117 set htstack [lreplace $htstack end end]
3118 set prefixend [lindex $prefendstack end]
3119 set prefendstack [lreplace $prefendstack end end]
3120 set prefix [string range $prefix 0 $prefixend]
3121 incr lev -1
3122 }
3123 set tail [string range $f [expr {$prefixend+1}] end]
3124 while {[set slash [string first "/" $tail]] >= 0} {
3125 lappend htstack $ht
3126 set ht 0
3127 lappend prefendstack $prefixend
3128 incr prefixend [expr {$slash + 1}]
3129 set d [string range $tail 0 $slash]
3130 lappend treecontents($prefix) $d
3131 set oldprefix $prefix
3132 append prefix $d
3133 set treecontents($prefix) {}
3134 set treeindex($prefix) [incr ix]
3135 set treeparent($prefix) $oldprefix
3136 set tail [string range $tail [expr {$slash+1}] end]
3137 if {$lev <= $openlevs} {
3138 set ht 1
3139 set treediropen($prefix) [expr {$lev < $openlevs}]
3140 set bm [expr {$lev == $openlevs? "tri-rt": "tri-dn"}]
3141 $w mark set d:$ix "end -1c"
3142 $w mark gravity d:$ix left
3143 set str "\n"
3144 for {set i 0} {$i < $lev} {incr i} {append str "\t"}
3145 $w insert end $str
3146 $w image create end -align center -image $bm -padx 1 \
3147 -name a:$ix
Paul Mackerras45a9d502006-05-20 22:56:27 +10003148 $w insert end $d [highlight_tag $prefix]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10003149 $w mark set s:$ix "end -1c"
3150 $w mark gravity s:$ix left
3151 }
3152 incr lev
3153 }
3154 if {$tail ne {}} {
3155 if {$lev <= $openlevs} {
3156 incr ht
3157 set str "\n"
3158 for {set i 0} {$i < $lev} {incr i} {append str "\t"}
3159 $w insert end $str
Paul Mackerras45a9d502006-05-20 22:56:27 +10003160 $w insert end $tail [highlight_tag $f]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10003161 }
3162 lappend treecontents($prefix) $tail
3163 }
3164 }
3165 while {$htstack ne {}} {
3166 set treeheight($prefix) $ht
3167 incr ht [lindex $htstack end]
3168 set htstack [lreplace $htstack end end]
Brian Downing096e96b2007-07-05 06:33:02 -05003169 set prefixend [lindex $prefendstack end]
3170 set prefendstack [lreplace $prefendstack end end]
3171 set prefix [string range $prefix 0 $prefixend]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10003172 }
3173 $w conf -state disabled
3174}
3175
3176proc linetoelt {l} {
3177 global treeheight treecontents
3178
3179 set y 2
3180 set prefix {}
3181 while {1} {
3182 foreach e $treecontents($prefix) {
3183 if {$y == $l} {
3184 return "$prefix$e"
3185 }
3186 set n 1
3187 if {[string index $e end] eq "/"} {
3188 set n $treeheight($prefix$e)
3189 if {$y + $n > $l} {
3190 append prefix $e
3191 incr y
3192 break
3193 }
3194 }
3195 incr y $n
3196 }
3197 }
3198}
3199
Paul Mackerras45a9d502006-05-20 22:56:27 +10003200proc highlight_tree {y prefix} {
3201 global treeheight treecontents cflist
3202
3203 foreach e $treecontents($prefix) {
3204 set path $prefix$e
3205 if {[highlight_tag $path] ne {}} {
3206 $cflist tag add bold $y.0 "$y.0 lineend"
3207 }
3208 incr y
3209 if {[string index $e end] eq "/" && $treeheight($path) > 1} {
3210 set y [highlight_tree $y $path]
3211 }
3212 }
3213 return $y
3214}
3215
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10003216proc treeclosedir {w dir} {
3217 global treediropen treeheight treeparent treeindex
3218
3219 set ix $treeindex($dir)
3220 $w conf -state normal
3221 $w delete s:$ix e:$ix
3222 set treediropen($dir) 0
3223 $w image configure a:$ix -image tri-rt
3224 $w conf -state disabled
3225 set n [expr {1 - $treeheight($dir)}]
3226 while {$dir ne {}} {
3227 incr treeheight($dir) $n
3228 set dir $treeparent($dir)
3229 }
3230}
3231
3232proc treeopendir {w dir} {
3233 global treediropen treeheight treeparent treecontents treeindex
3234
3235 set ix $treeindex($dir)
3236 $w conf -state normal
3237 $w image configure a:$ix -image tri-dn
3238 $w mark set e:$ix s:$ix
3239 $w mark gravity e:$ix right
3240 set lev 0
3241 set str "\n"
3242 set n [llength $treecontents($dir)]
3243 for {set x $dir} {$x ne {}} {set x $treeparent($x)} {
3244 incr lev
3245 append str "\t"
3246 incr treeheight($x) $n
3247 }
3248 foreach e $treecontents($dir) {
Paul Mackerras45a9d502006-05-20 22:56:27 +10003249 set de $dir$e
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10003250 if {[string index $e end] eq "/"} {
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10003251 set iy $treeindex($de)
3252 $w mark set d:$iy e:$ix
3253 $w mark gravity d:$iy left
3254 $w insert e:$ix $str
3255 set treediropen($de) 0
3256 $w image create e:$ix -align center -image tri-rt -padx 1 \
3257 -name a:$iy
Paul Mackerras45a9d502006-05-20 22:56:27 +10003258 $w insert e:$ix $e [highlight_tag $de]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10003259 $w mark set s:$iy e:$ix
3260 $w mark gravity s:$iy left
3261 set treeheight($de) 1
3262 } else {
3263 $w insert e:$ix $str
Paul Mackerras45a9d502006-05-20 22:56:27 +10003264 $w insert e:$ix $e [highlight_tag $de]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10003265 }
3266 }
Alexander Gavrilovb8a640e2008-09-08 11:28:16 +04003267 $w mark gravity e:$ix right
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10003268 $w conf -state disabled
3269 set treediropen($dir) 1
3270 set top [lindex [split [$w index @0,0] .] 0]
3271 set ht [$w cget -height]
3272 set l [lindex [split [$w index s:$ix] .] 0]
3273 if {$l < $top} {
3274 $w yview $l.0
3275 } elseif {$l + $n + 1 > $top + $ht} {
3276 set top [expr {$l + $n + 2 - $ht}]
3277 if {$l < $top} {
3278 set top $l
3279 }
3280 $w yview $top.0
3281 }
3282}
3283
3284proc treeclick {w x y} {
3285 global treediropen cmitmode ctext cflist cflist_top
3286
3287 if {$cmitmode ne "tree"} return
3288 if {![info exists cflist_top]} return
3289 set l [lindex [split [$w index "@$x,$y"] "."] 0]
3290 $cflist tag remove highlight $cflist_top.0 "$cflist_top.0 lineend"
3291 $cflist tag add highlight $l.0 "$l.0 lineend"
3292 set cflist_top $l
3293 if {$l == 1} {
3294 $ctext yview 1.0
3295 return
3296 }
3297 set e [linetoelt $l]
3298 if {[string index $e end] ne "/"} {
3299 showfile $e
3300 } elseif {$treediropen($e)} {
3301 treeclosedir $w $e
3302 } else {
3303 treeopendir $w $e
3304 }
3305}
3306
3307proc setfilelist {id} {
Paul Mackerras8a897742008-10-27 21:36:25 +11003308 global treefilelist cflist jump_to_here
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10003309
3310 treeview $cflist $treefilelist($id) 0
Paul Mackerras8a897742008-10-27 21:36:25 +11003311 if {$jump_to_here ne {}} {
3312 set f [lindex $jump_to_here 0]
3313 if {[lsearch -exact $treefilelist($id) $f] >= 0} {
3314 showfile $f
3315 }
3316 }
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10003317}
3318
3319image create bitmap tri-rt -background black -foreground blue -data {
3320 #define tri-rt_width 13
3321 #define tri-rt_height 13
3322 static unsigned char tri-rt_bits[] = {
3323 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x30, 0x00, 0x70, 0x00, 0xf0, 0x00,
3324 0xf0, 0x01, 0xf0, 0x00, 0x70, 0x00, 0x30, 0x00, 0x10, 0x00, 0x00, 0x00,
3325 0x00, 0x00};
3326} -maskdata {
3327 #define tri-rt-mask_width 13
3328 #define tri-rt-mask_height 13
3329 static unsigned char tri-rt-mask_bits[] = {
3330 0x08, 0x00, 0x18, 0x00, 0x38, 0x00, 0x78, 0x00, 0xf8, 0x00, 0xf8, 0x01,
3331 0xf8, 0x03, 0xf8, 0x01, 0xf8, 0x00, 0x78, 0x00, 0x38, 0x00, 0x18, 0x00,
3332 0x08, 0x00};
3333}
3334image create bitmap tri-dn -background black -foreground blue -data {
3335 #define tri-dn_width 13
3336 #define tri-dn_height 13
3337 static unsigned char tri-dn_bits[] = {
3338 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x07, 0xf8, 0x03,
3339 0xf0, 0x01, 0xe0, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3340 0x00, 0x00};
3341} -maskdata {
3342 #define tri-dn-mask_width 13
3343 #define tri-dn-mask_height 13
3344 static unsigned char tri-dn-mask_bits[] = {
3345 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x1f, 0xfe, 0x0f, 0xfc, 0x07,
3346 0xf8, 0x03, 0xf0, 0x01, 0xe0, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00,
3347 0x00, 0x00};
3348}
3349
Paul Mackerras887c9962007-08-20 19:36:20 +10003350image create bitmap reficon-T -background black -foreground yellow -data {
3351 #define tagicon_width 13
3352 #define tagicon_height 9
3353 static unsigned char tagicon_bits[] = {
3354 0x00, 0x00, 0x00, 0x00, 0xf0, 0x07, 0xf8, 0x07,
3355 0xfc, 0x07, 0xf8, 0x07, 0xf0, 0x07, 0x00, 0x00, 0x00, 0x00};
3356} -maskdata {
3357 #define tagicon-mask_width 13
3358 #define tagicon-mask_height 9
3359 static unsigned char tagicon-mask_bits[] = {
3360 0x00, 0x00, 0xf0, 0x0f, 0xf8, 0x0f, 0xfc, 0x0f,
3361 0xfe, 0x0f, 0xfc, 0x0f, 0xf8, 0x0f, 0xf0, 0x0f, 0x00, 0x00};
3362}
3363set rectdata {
3364 #define headicon_width 13
3365 #define headicon_height 9
3366 static unsigned char headicon_bits[] = {
3367 0x00, 0x00, 0x00, 0x00, 0xf8, 0x07, 0xf8, 0x07,
3368 0xf8, 0x07, 0xf8, 0x07, 0xf8, 0x07, 0x00, 0x00, 0x00, 0x00};
3369}
3370set rectmask {
3371 #define headicon-mask_width 13
3372 #define headicon-mask_height 9
3373 static unsigned char headicon-mask_bits[] = {
3374 0x00, 0x00, 0xfc, 0x0f, 0xfc, 0x0f, 0xfc, 0x0f,
3375 0xfc, 0x0f, 0xfc, 0x0f, 0xfc, 0x0f, 0xfc, 0x0f, 0x00, 0x00};
3376}
3377image create bitmap reficon-H -background black -foreground green \
3378 -data $rectdata -maskdata $rectmask
3379image create bitmap reficon-o -background black -foreground "#ddddff" \
3380 -data $rectdata -maskdata $rectmask
3381
Paul Mackerras7fcceed2006-04-27 19:21:49 +10003382proc init_flist {first} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11003383 global cflist cflist_top difffilestart
Paul Mackerras7fcceed2006-04-27 19:21:49 +10003384
3385 $cflist conf -state normal
3386 $cflist delete 0.0 end
3387 if {$first ne {}} {
3388 $cflist insert end $first
3389 set cflist_top 1
Paul Mackerras7fcceed2006-04-27 19:21:49 +10003390 $cflist tag add highlight 1.0 "1.0 lineend"
3391 } else {
3392 catch {unset cflist_top}
3393 }
3394 $cflist conf -state disabled
3395 set difffilestart {}
3396}
3397
Paul Mackerras63b79192006-05-20 21:31:52 +10003398proc highlight_tag {f} {
3399 global highlight_paths
3400
3401 foreach p $highlight_paths {
3402 if {[string match $p $f]} {
3403 return "bold"
3404 }
3405 }
3406 return {}
3407}
3408
3409proc highlight_filelist {} {
Paul Mackerras45a9d502006-05-20 22:56:27 +10003410 global cmitmode cflist
Paul Mackerras63b79192006-05-20 21:31:52 +10003411
Paul Mackerras45a9d502006-05-20 22:56:27 +10003412 $cflist conf -state normal
3413 if {$cmitmode ne "tree"} {
Paul Mackerras63b79192006-05-20 21:31:52 +10003414 set end [lindex [split [$cflist index end] .] 0]
3415 for {set l 2} {$l < $end} {incr l} {
3416 set line [$cflist get $l.0 "$l.0 lineend"]
3417 if {[highlight_tag $line] ne {}} {
3418 $cflist tag add bold $l.0 "$l.0 lineend"
3419 }
3420 }
Paul Mackerras45a9d502006-05-20 22:56:27 +10003421 } else {
3422 highlight_tree 2 {}
Paul Mackerras63b79192006-05-20 21:31:52 +10003423 }
Paul Mackerras45a9d502006-05-20 22:56:27 +10003424 $cflist conf -state disabled
Paul Mackerras63b79192006-05-20 21:31:52 +10003425}
3426
3427proc unhighlight_filelist {} {
Paul Mackerras45a9d502006-05-20 22:56:27 +10003428 global cflist
Paul Mackerras63b79192006-05-20 21:31:52 +10003429
Paul Mackerras45a9d502006-05-20 22:56:27 +10003430 $cflist conf -state normal
3431 $cflist tag remove bold 1.0 end
3432 $cflist conf -state disabled
Paul Mackerras63b79192006-05-20 21:31:52 +10003433}
3434
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10003435proc add_flist {fl} {
Paul Mackerras45a9d502006-05-20 22:56:27 +10003436 global cflist
Paul Mackerras7fcceed2006-04-27 19:21:49 +10003437
Paul Mackerras45a9d502006-05-20 22:56:27 +10003438 $cflist conf -state normal
3439 foreach f $fl {
3440 $cflist insert end "\n"
3441 $cflist insert end $f [highlight_tag $f]
Paul Mackerras7fcceed2006-04-27 19:21:49 +10003442 }
Paul Mackerras45a9d502006-05-20 22:56:27 +10003443 $cflist conf -state disabled
Paul Mackerras7fcceed2006-04-27 19:21:49 +10003444}
3445
3446proc sel_flist {w x y} {
Paul Mackerras45a9d502006-05-20 22:56:27 +10003447 global ctext difffilestart cflist cflist_top cmitmode
Paul Mackerras7fcceed2006-04-27 19:21:49 +10003448
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10003449 if {$cmitmode eq "tree"} return
Paul Mackerras7fcceed2006-04-27 19:21:49 +10003450 if {![info exists cflist_top]} return
3451 set l [lindex [split [$w index "@$x,$y"] "."] 0]
Paul Mackerras89b11d32006-05-02 19:55:31 +10003452 $cflist tag remove highlight $cflist_top.0 "$cflist_top.0 lineend"
3453 $cflist tag add highlight $l.0 "$l.0 lineend"
3454 set cflist_top $l
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10003455 if {$l == 1} {
3456 $ctext yview 1.0
3457 } else {
3458 catch {$ctext yview [lindex $difffilestart [expr {$l - 2}]]}
Paul Mackerras7fcceed2006-04-27 19:21:49 +10003459 }
Stefan Hallerb9671352012-09-19 20:17:27 +02003460 suppress_highlighting_file_for_current_scrollpos
Paul Mackerras7fcceed2006-04-27 19:21:49 +10003461}
3462
Paul Mackerras32447292007-07-27 22:30:15 +10003463proc pop_flist_menu {w X Y x y} {
3464 global ctext cflist cmitmode flist_menu flist_menu_file
3465 global treediffs diffids
3466
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10003467 stopfinding
Paul Mackerras32447292007-07-27 22:30:15 +10003468 set l [lindex [split [$w index "@$x,$y"] "."] 0]
3469 if {$l <= 1} return
3470 if {$cmitmode eq "tree"} {
3471 set e [linetoelt $l]
3472 if {[string index $e end] eq "/"} return
3473 } else {
3474 set e [lindex $treediffs($diffids) [expr {$l-2}]]
3475 }
3476 set flist_menu_file $e
Thomas Arcila314f5de2008-03-24 12:55:36 +01003477 set xdiffstate "normal"
3478 if {$cmitmode eq "tree"} {
3479 set xdiffstate "disabled"
3480 }
3481 # Disable "External diff" item in tree mode
3482 $flist_menu entryconf 2 -state $xdiffstate
Paul Mackerras32447292007-07-27 22:30:15 +10003483 tk_popup $flist_menu $X $Y
3484}
3485
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003486proc find_ctext_fileinfo {line} {
3487 global ctext_file_names ctext_file_lines
3488
3489 set ok [bsearch $ctext_file_lines $line]
3490 set tline [lindex $ctext_file_lines $ok]
3491
3492 if {$ok >= [llength $ctext_file_lines] || $line < $tline} {
3493 return {}
3494 } else {
3495 return [list [lindex $ctext_file_names $ok] $tline]
3496 }
3497}
3498
3499proc pop_diff_menu {w X Y x y} {
3500 global ctext diff_menu flist_menu_file
3501 global diff_menu_txtpos diff_menu_line
3502 global diff_menu_filebase
3503
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003504 set diff_menu_txtpos [split [$w index "@$x,$y"] "."]
3505 set diff_menu_line [lindex $diff_menu_txtpos 0]
Paul Mackerras190ec522008-10-27 21:13:37 +11003506 # don't pop up the menu on hunk-separator or file-separator lines
3507 if {[lsearch -glob [$ctext tag names $diff_menu_line.0] "*sep"] >= 0} {
3508 return
3509 }
3510 stopfinding
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003511 set f [find_ctext_fileinfo $diff_menu_line]
3512 if {$f eq {}} return
3513 set flist_menu_file [lindex $f 0]
3514 set diff_menu_filebase [lindex $f 1]
3515 tk_popup $diff_menu $X $Y
3516}
3517
Paul Mackerras32447292007-07-27 22:30:15 +10003518proc flist_hl {only} {
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10003519 global flist_menu_file findstring gdttype
Paul Mackerras32447292007-07-27 22:30:15 +10003520
3521 set x [shellquote $flist_menu_file]
Christian Stimmingb007ee22007-11-07 18:44:35 +01003522 if {$only || $findstring eq {} || $gdttype ne [mc "touching paths:"]} {
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10003523 set findstring $x
Paul Mackerras32447292007-07-27 22:30:15 +10003524 } else {
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10003525 append findstring " " $x
Paul Mackerras32447292007-07-27 22:30:15 +10003526 }
Christian Stimmingb007ee22007-11-07 18:44:35 +01003527 set gdttype [mc "touching paths:"]
Paul Mackerras32447292007-07-27 22:30:15 +10003528}
3529
Paul Mackerrasc21398b2009-09-07 10:08:21 +10003530proc gitknewtmpdir {} {
David Aguilarc7664f12014-06-13 14:13:37 -07003531 global diffnum gitktmpdir gitdir env
Paul Mackerrasc21398b2009-09-07 10:08:21 +10003532
3533 if {![info exists gitktmpdir]} {
David Aguilarc7664f12014-06-13 14:13:37 -07003534 if {[info exists env(GITK_TMPDIR)]} {
3535 set tmpdir $env(GITK_TMPDIR)
3536 } elseif {[info exists env(TMPDIR)]} {
3537 set tmpdir $env(TMPDIR)
3538 } else {
3539 set tmpdir $gitdir
3540 }
David Aguilar105b5d32014-06-13 14:43:48 -07003541 set gitktmpformat [file join $tmpdir ".gitk-tmp.XXXXXX"]
David Aguilarac54a4b2014-06-18 19:53:14 -07003542 if {[catch {set gitktmpdir [exec mktemp -d $gitktmpformat]}]} {
3543 set gitktmpdir [file join $gitdir [format ".gitk-tmp.%s" [pid]]]
3544 }
Paul Mackerrasc21398b2009-09-07 10:08:21 +10003545 if {[catch {file mkdir $gitktmpdir} err]} {
3546 error_popup "[mc "Error creating temporary directory %s:" $gitktmpdir] $err"
3547 unset gitktmpdir
3548 return {}
3549 }
3550 set diffnum 0
3551 }
3552 incr diffnum
3553 set diffdir [file join $gitktmpdir $diffnum]
3554 if {[catch {file mkdir $diffdir} err]} {
3555 error_popup "[mc "Error creating temporary directory %s:" $diffdir] $err"
3556 return {}
3557 }
3558 return $diffdir
3559}
3560
Thomas Arcila314f5de2008-03-24 12:55:36 +01003561proc save_file_from_commit {filename output what} {
3562 global nullfile
3563
3564 if {[catch {exec git show $filename -- > $output} err]} {
3565 if {[string match "fatal: bad revision *" $err]} {
3566 return $nullfile
3567 }
Christian Stimming3945d2c2008-09-12 11:39:43 +02003568 error_popup "[mc "Error getting \"%s\" from %s:" $filename $what] $err"
Thomas Arcila314f5de2008-03-24 12:55:36 +01003569 return {}
3570 }
3571 return $output
3572}
3573
3574proc external_diff_get_one_file {diffid filename diffdir} {
3575 global nullid nullid2 nullfile
Martin von Zweigbergk784b7e22011-04-04 22:14:15 -04003576 global worktree
Thomas Arcila314f5de2008-03-24 12:55:36 +01003577
3578 if {$diffid == $nullid} {
Martin von Zweigbergk784b7e22011-04-04 22:14:15 -04003579 set difffile [file join $worktree $filename]
Thomas Arcila314f5de2008-03-24 12:55:36 +01003580 if {[file exists $difffile]} {
3581 return $difffile
3582 }
3583 return $nullfile
3584 }
3585 if {$diffid == $nullid2} {
3586 set difffile [file join $diffdir "\[index\] [file tail $filename]"]
3587 return [save_file_from_commit :$filename $difffile index]
3588 }
3589 set difffile [file join $diffdir "\[$diffid\] [file tail $filename]"]
3590 return [save_file_from_commit $diffid:$filename $difffile \
3591 "revision $diffid"]
3592}
3593
3594proc external_diff {} {
Paul Mackerrasc21398b2009-09-07 10:08:21 +10003595 global nullid nullid2
Thomas Arcila314f5de2008-03-24 12:55:36 +01003596 global flist_menu_file
3597 global diffids
Paul Mackerrasc21398b2009-09-07 10:08:21 +10003598 global extdifftool
Thomas Arcila314f5de2008-03-24 12:55:36 +01003599
3600 if {[llength $diffids] == 1} {
3601 # no reference commit given
3602 set diffidto [lindex $diffids 0]
3603 if {$diffidto eq $nullid} {
3604 # diffing working copy with index
3605 set diffidfrom $nullid2
3606 } elseif {$diffidto eq $nullid2} {
3607 # diffing index with HEAD
3608 set diffidfrom "HEAD"
3609 } else {
3610 # use first parent commit
3611 global parentlist selectedline
3612 set diffidfrom [lindex $parentlist $selectedline 0]
3613 }
3614 } else {
3615 set diffidfrom [lindex $diffids 0]
3616 set diffidto [lindex $diffids 1]
3617 }
3618
3619 # make sure that several diffs wont collide
Paul Mackerrasc21398b2009-09-07 10:08:21 +10003620 set diffdir [gitknewtmpdir]
3621 if {$diffdir eq {}} return
Thomas Arcila314f5de2008-03-24 12:55:36 +01003622
3623 # gather files to diff
3624 set difffromfile [external_diff_get_one_file $diffidfrom $flist_menu_file $diffdir]
3625 set difftofile [external_diff_get_one_file $diffidto $flist_menu_file $diffdir]
3626
3627 if {$difffromfile ne {} && $difftofile ne {}} {
Pat Thoytsb575b2f2009-04-15 16:54:19 +01003628 set cmd [list [shellsplit $extdifftool] $difffromfile $difftofile]
3629 if {[catch {set fl [open |$cmd r]} err]} {
Thomas Arcila314f5de2008-03-24 12:55:36 +01003630 file delete -force $diffdir
Christian Stimming3945d2c2008-09-12 11:39:43 +02003631 error_popup "$extdifftool: [mc "command failed:"] $err"
Thomas Arcila314f5de2008-03-24 12:55:36 +01003632 } else {
3633 fconfigure $fl -blocking 0
3634 filerun $fl [list delete_at_eof $fl $diffdir]
3635 }
3636 }
3637}
3638
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003639proc find_hunk_blamespec {base line} {
3640 global ctext
3641
3642 # Find and parse the hunk header
3643 set s_lix [$ctext search -backwards -regexp ^@@ "$line.0 lineend" $base.0]
3644 if {$s_lix eq {}} return
3645
3646 set s_line [$ctext get $s_lix "$s_lix + 1 lines"]
3647 if {![regexp {^@@@*(( -\d+(,\d+)?)+) \+(\d+)(,\d+)? @@} $s_line \
3648 s_line old_specs osz osz1 new_line nsz]} {
3649 return
3650 }
3651
3652 # base lines for the parents
3653 set base_lines [list $new_line]
3654 foreach old_spec [lrange [split $old_specs " "] 1 end] {
3655 if {![regexp -- {-(\d+)(,\d+)?} $old_spec \
3656 old_spec old_line osz]} {
3657 return
3658 }
3659 lappend base_lines $old_line
3660 }
3661
3662 # Now scan the lines to determine offset within the hunk
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003663 set max_parent [expr {[llength $base_lines]-2}]
3664 set dline 0
3665 set s_lno [lindex [split $s_lix "."] 0]
3666
Paul Mackerras190ec522008-10-27 21:13:37 +11003667 # Determine if the line is removed
3668 set chunk [$ctext get $line.0 "$line.1 + $max_parent chars"]
3669 if {[string match {[-+ ]*} $chunk]} {
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003670 set removed_idx [string first "-" $chunk]
3671 # Choose a parent index
Paul Mackerras190ec522008-10-27 21:13:37 +11003672 if {$removed_idx >= 0} {
3673 set parent $removed_idx
3674 } else {
3675 set unchanged_idx [string first " " $chunk]
3676 if {$unchanged_idx >= 0} {
3677 set parent $unchanged_idx
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003678 } else {
Paul Mackerras190ec522008-10-27 21:13:37 +11003679 # blame the current commit
3680 set parent -1
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003681 }
3682 }
3683 # then count other lines that belong to it
Paul Mackerras190ec522008-10-27 21:13:37 +11003684 for {set i $line} {[incr i -1] > $s_lno} {} {
3685 set chunk [$ctext get $i.0 "$i.1 + $max_parent chars"]
3686 # Determine if the line is removed
3687 set removed_idx [string first "-" $chunk]
3688 if {$parent >= 0} {
3689 set code [string index $chunk $parent]
3690 if {$code eq "-" || ($removed_idx < 0 && $code ne "+")} {
3691 incr dline
3692 }
3693 } else {
3694 if {$removed_idx < 0} {
3695 incr dline
3696 }
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003697 }
3698 }
Paul Mackerras190ec522008-10-27 21:13:37 +11003699 incr parent
3700 } else {
3701 set parent 0
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003702 }
3703
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003704 incr dline [lindex $base_lines $parent]
3705 return [list $parent $dline]
3706}
3707
3708proc external_blame_diff {} {
Paul Mackerras8b07dca2008-11-02 22:34:47 +11003709 global currentid cmitmode
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003710 global diff_menu_txtpos diff_menu_line
3711 global diff_menu_filebase flist_menu_file
3712
3713 if {$cmitmode eq "tree"} {
3714 set parent_idx 0
Paul Mackerras190ec522008-10-27 21:13:37 +11003715 set line [expr {$diff_menu_line - $diff_menu_filebase}]
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003716 } else {
3717 set hinfo [find_hunk_blamespec $diff_menu_filebase $diff_menu_line]
3718 if {$hinfo ne {}} {
3719 set parent_idx [lindex $hinfo 0]
3720 set line [lindex $hinfo 1]
3721 } else {
3722 set parent_idx 0
3723 set line 0
3724 }
3725 }
3726
3727 external_blame $parent_idx $line
3728}
3729
Paul Mackerrasfc4977e2008-11-04 12:57:44 +11003730# Find the SHA1 ID of the blob for file $fname in the index
3731# at stage 0 or 2
3732proc index_sha1 {fname} {
3733 set f [open [list | git ls-files -s $fname] r]
3734 while {[gets $f line] >= 0} {
3735 set info [lindex [split $line "\t"] 0]
3736 set stage [lindex $info 2]
3737 if {$stage eq "0" || $stage eq "2"} {
3738 close $f
3739 return [lindex $info 1]
3740 }
3741 }
3742 close $f
3743 return {}
3744}
3745
Paul Mackerras9712b812008-12-06 21:44:05 +11003746# Turn an absolute path into one relative to the current directory
3747proc make_relative {f} {
Markus Heidelberga4390ac2009-11-04 00:21:41 +01003748 if {[file pathtype $f] eq "relative"} {
3749 return $f
3750 }
Paul Mackerras9712b812008-12-06 21:44:05 +11003751 set elts [file split $f]
3752 set here [file split [pwd]]
3753 set ei 0
3754 set hi 0
3755 set res {}
3756 foreach d $here {
3757 if {$ei < $hi || $ei >= [llength $elts] || [lindex $elts $ei] ne $d} {
3758 lappend res ".."
3759 } else {
3760 incr ei
3761 }
3762 incr hi
3763 }
3764 set elts [concat $res [lrange $elts $ei end]]
3765 return [eval file join $elts]
3766}
3767
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003768proc external_blame {parent_idx {line {}}} {
Martin von Zweigbergk0a2a9792011-04-04 22:14:14 -04003769 global flist_menu_file cdup
Alexander Gavrilov77aa0ae2008-08-23 12:29:08 +04003770 global nullid nullid2
3771 global parentlist selectedline currentid
3772
3773 if {$parent_idx > 0} {
3774 set base_commit [lindex $parentlist $selectedline [expr {$parent_idx-1}]]
3775 } else {
3776 set base_commit $currentid
3777 }
3778
3779 if {$base_commit eq {} || $base_commit eq $nullid || $base_commit eq $nullid2} {
3780 error_popup [mc "No such commit"]
3781 return
3782 }
3783
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003784 set cmdline [list git gui blame]
3785 if {$line ne {} && $line > 1} {
3786 lappend cmdline "--line=$line"
3787 }
Martin von Zweigbergk0a2a9792011-04-04 22:14:14 -04003788 set f [file join $cdup $flist_menu_file]
Paul Mackerras9712b812008-12-06 21:44:05 +11003789 # Unfortunately it seems git gui blame doesn't like
3790 # being given an absolute path...
3791 set f [make_relative $f]
3792 lappend cmdline $base_commit $f
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04003793 if {[catch {eval exec $cmdline &} err]} {
Christian Stimming3945d2c2008-09-12 11:39:43 +02003794 error_popup "[mc "git gui blame: command failed:"] $err"
Alexander Gavrilov77aa0ae2008-08-23 12:29:08 +04003795 }
3796}
3797
Paul Mackerras8a897742008-10-27 21:36:25 +11003798proc show_line_source {} {
3799 global cmitmode currentid parents curview blamestuff blameinst
3800 global diff_menu_line diff_menu_filebase flist_menu_file
Martin von Zweigbergk9b6adf32011-04-04 22:14:13 -04003801 global nullid nullid2 gitdir cdup
Paul Mackerras8a897742008-10-27 21:36:25 +11003802
Paul Mackerrasfc4977e2008-11-04 12:57:44 +11003803 set from_index {}
Paul Mackerras8a897742008-10-27 21:36:25 +11003804 if {$cmitmode eq "tree"} {
3805 set id $currentid
3806 set line [expr {$diff_menu_line - $diff_menu_filebase}]
3807 } else {
3808 set h [find_hunk_blamespec $diff_menu_filebase $diff_menu_line]
3809 if {$h eq {}} return
3810 set pi [lindex $h 0]
3811 if {$pi == 0} {
3812 mark_ctext_line $diff_menu_line
3813 return
3814 }
Paul Mackerrasfc4977e2008-11-04 12:57:44 +11003815 incr pi -1
3816 if {$currentid eq $nullid} {
3817 if {$pi > 0} {
3818 # must be a merge in progress...
3819 if {[catch {
3820 # get the last line from .git/MERGE_HEAD
3821 set f [open [file join $gitdir MERGE_HEAD] r]
3822 set id [lindex [split [read $f] "\n"] end-1]
3823 close $f
3824 } err]} {
3825 error_popup [mc "Couldn't read merge head: %s" $err]
3826 return
3827 }
3828 } elseif {$parents($curview,$currentid) eq $nullid2} {
3829 # need to do the blame from the index
3830 if {[catch {
3831 set from_index [index_sha1 $flist_menu_file]
3832 } err]} {
3833 error_popup [mc "Error reading index: %s" $err]
3834 return
3835 }
Paul Mackerras9712b812008-12-06 21:44:05 +11003836 } else {
3837 set id $parents($curview,$currentid)
Paul Mackerrasfc4977e2008-11-04 12:57:44 +11003838 }
3839 } else {
3840 set id [lindex $parents($curview,$currentid) $pi]
3841 }
Paul Mackerras8a897742008-10-27 21:36:25 +11003842 set line [lindex $h 1]
3843 }
Paul Mackerrasfc4977e2008-11-04 12:57:44 +11003844 set blameargs {}
3845 if {$from_index ne {}} {
3846 lappend blameargs | git cat-file blob $from_index
3847 }
3848 lappend blameargs | git blame -p -L$line,+1
3849 if {$from_index ne {}} {
3850 lappend blameargs --contents -
3851 } else {
3852 lappend blameargs $id
3853 }
Martin von Zweigbergk9b6adf32011-04-04 22:14:13 -04003854 lappend blameargs -- [file join $cdup $flist_menu_file]
Paul Mackerras8a897742008-10-27 21:36:25 +11003855 if {[catch {
Paul Mackerrasfc4977e2008-11-04 12:57:44 +11003856 set f [open $blameargs r]
Paul Mackerras8a897742008-10-27 21:36:25 +11003857 } err]} {
3858 error_popup [mc "Couldn't start git blame: %s" $err]
3859 return
3860 }
Alexander Gavrilovf3413072008-12-01 20:30:09 +03003861 nowbusy blaming [mc "Searching"]
Paul Mackerras8a897742008-10-27 21:36:25 +11003862 fconfigure $f -blocking 0
3863 set i [reg_instance $f]
3864 set blamestuff($i) {}
3865 set blameinst $i
3866 filerun $f [list read_line_source $f $i]
3867}
3868
3869proc stopblaming {} {
3870 global blameinst
3871
3872 if {[info exists blameinst]} {
3873 stop_instance $blameinst
3874 unset blameinst
Alexander Gavrilovf3413072008-12-01 20:30:09 +03003875 notbusy blaming
Paul Mackerras8a897742008-10-27 21:36:25 +11003876 }
3877}
3878
3879proc read_line_source {fd inst} {
Paul Mackerrasfc4977e2008-11-04 12:57:44 +11003880 global blamestuff curview commfd blameinst nullid nullid2
Paul Mackerras8a897742008-10-27 21:36:25 +11003881
3882 while {[gets $fd line] >= 0} {
3883 lappend blamestuff($inst) $line
3884 }
3885 if {![eof $fd]} {
3886 return 1
3887 }
3888 unset commfd($inst)
3889 unset blameinst
Alexander Gavrilovf3413072008-12-01 20:30:09 +03003890 notbusy blaming
Paul Mackerras8a897742008-10-27 21:36:25 +11003891 fconfigure $fd -blocking 1
3892 if {[catch {close $fd} err]} {
3893 error_popup [mc "Error running git blame: %s" $err]
3894 return 0
3895 }
3896
3897 set fname {}
3898 set line [split [lindex $blamestuff($inst) 0] " "]
3899 set id [lindex $line 0]
3900 set lnum [lindex $line 1]
3901 if {[string length $id] == 40 && [string is xdigit $id] &&
3902 [string is digit -strict $lnum]} {
3903 # look for "filename" line
3904 foreach l $blamestuff($inst) {
3905 if {[string match "filename *" $l]} {
3906 set fname [string range $l 9 end]
3907 break
3908 }
3909 }
3910 }
3911 if {$fname ne {}} {
3912 # all looks good, select it
Paul Mackerrasfc4977e2008-11-04 12:57:44 +11003913 if {$id eq $nullid} {
3914 # blame uses all-zeroes to mean not committed,
3915 # which would mean a change in the index
3916 set id $nullid2
3917 }
Paul Mackerras8a897742008-10-27 21:36:25 +11003918 if {[commitinview $id $curview]} {
Max Kirillov4135d362014-04-05 23:38:50 +03003919 selectline [rowofcommit $id] 1 [list $fname $lnum] 1
Paul Mackerras8a897742008-10-27 21:36:25 +11003920 } else {
3921 error_popup [mc "That line comes from commit %s, \
3922 which is not in this view" [shortids $id]]
3923 }
3924 } else {
3925 puts "oops couldn't parse git blame output"
3926 }
3927 return 0
3928}
3929
Thomas Arcila314f5de2008-03-24 12:55:36 +01003930# delete $dir when we see eof on $f (presumably because the child has exited)
3931proc delete_at_eof {f dir} {
3932 while {[gets $f line] >= 0} {}
3933 if {[eof $f]} {
3934 if {[catch {close $f} err]} {
Christian Stimming3945d2c2008-09-12 11:39:43 +02003935 error_popup "[mc "External diff viewer failed:"] $err"
Thomas Arcila314f5de2008-03-24 12:55:36 +01003936 }
3937 file delete -force $dir
3938 return 0
3939 }
3940 return 1
3941}
3942
Paul Mackerras098dd8a2006-05-03 09:32:53 +10003943# Functions for adding and removing shell-type quoting
3944
3945proc shellquote {str} {
3946 if {![string match "*\['\"\\ \t]*" $str]} {
3947 return $str
3948 }
3949 if {![string match "*\['\"\\]*" $str]} {
3950 return "\"$str\""
3951 }
3952 if {![string match "*'*" $str]} {
3953 return "'$str'"
3954 }
3955 return "\"[string map {\" \\\" \\ \\\\} $str]\""
3956}
3957
3958proc shellarglist {l} {
3959 set str {}
3960 foreach a $l {
3961 if {$str ne {}} {
3962 append str " "
3963 }
3964 append str [shellquote $a]
3965 }
3966 return $str
3967}
3968
3969proc shelldequote {str} {
3970 set ret {}
3971 set used -1
3972 while {1} {
3973 incr used
3974 if {![regexp -start $used -indices "\['\"\\\\ \t]" $str first]} {
3975 append ret [string range $str $used end]
3976 set used [string length $str]
3977 break
3978 }
3979 set first [lindex $first 0]
3980 set ch [string index $str $first]
3981 if {$first > $used} {
3982 append ret [string range $str $used [expr {$first - 1}]]
3983 set used $first
3984 }
3985 if {$ch eq " " || $ch eq "\t"} break
3986 incr used
3987 if {$ch eq "'"} {
3988 set first [string first "'" $str $used]
3989 if {$first < 0} {
3990 error "unmatched single-quote"
3991 }
3992 append ret [string range $str $used [expr {$first - 1}]]
3993 set used $first
3994 continue
3995 }
3996 if {$ch eq "\\"} {
3997 if {$used >= [string length $str]} {
3998 error "trailing backslash"
3999 }
4000 append ret [string index $str $used]
4001 continue
4002 }
4003 # here ch == "\""
4004 while {1} {
4005 if {![regexp -start $used -indices "\[\"\\\\]" $str first]} {
4006 error "unmatched double-quote"
4007 }
4008 set first [lindex $first 0]
4009 set ch [string index $str $first]
4010 if {$first > $used} {
4011 append ret [string range $str $used [expr {$first - 1}]]
4012 set used $first
4013 }
4014 if {$ch eq "\""} break
4015 incr used
4016 append ret [string index $str $used]
4017 incr used
4018 }
4019 }
4020 return [list $used $ret]
4021}
4022
4023proc shellsplit {str} {
4024 set l {}
4025 while {1} {
4026 set str [string trimleft $str]
4027 if {$str eq {}} break
4028 set dq [shelldequote $str]
4029 set n [lindex $dq 0]
4030 set word [lindex $dq 1]
4031 set str [string range $str $n end]
4032 lappend l $word
4033 }
4034 return $l
4035}
4036
Paul Mackerras7fcceed2006-04-27 19:21:49 +10004037# Code to implement multiple views
4038
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004039proc newview {ishighlight} {
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004040 global nextviewnum newviewname newishighlight
4041 global revtreeargs viewargscmd newviewopts curview
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004042
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004043 set newishighlight $ishighlight
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004044 set top .gitkview
4045 if {[winfo exists $top]} {
4046 raise $top
4047 return
4048 }
Jonathan Nieder5d11f792010-03-06 16:58:42 -06004049 decode_view_opts $nextviewnum $revtreeargs
Michele Ballabioa3a1f572008-03-03 21:12:47 +01004050 set newviewname($nextviewnum) "[mc "View"] $nextviewnum"
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004051 set newviewopts($nextviewnum,perm) 0
4052 set newviewopts($nextviewnum,cmd) $viewargscmd($curview)
Christian Stimmingd990ced2007-11-07 18:42:55 +01004053 vieweditor $top $nextviewnum [mc "Gitk view definition"]
Paul Mackerrasd16c0812006-04-25 21:21:10 +10004054}
4055
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004056set known_view_options {
Elijah Newren13d40b62009-03-23 11:57:46 -06004057 {perm b . {} {mc "Remember this view"}}
4058 {reflabel l + {} {mc "References (space separated list):"}}
4059 {refs t15 .. {} {mc "Branches & tags:"}}
4060 {allrefs b *. "--all" {mc "All refs"}}
4061 {branches b . "--branches" {mc "All (local) branches"}}
4062 {tags b . "--tags" {mc "All tags"}}
4063 {remotes b . "--remotes" {mc "All remote-tracking branches"}}
4064 {commitlbl l + {} {mc "Commit Info (regular expressions):"}}
4065 {author t15 .. "--author=*" {mc "Author:"}}
4066 {committer t15 . "--committer=*" {mc "Committer:"}}
4067 {loginfo t15 .. "--grep=*" {mc "Commit Message:"}}
4068 {allmatch b .. "--all-match" {mc "Matches all Commit Info criteria"}}
Christoph Junghansce232c32015-01-12 18:33:32 -07004069 {igrep b .. "--invert-grep" {mc "Matches none Commit Info criteria"}}
Elijah Newren13d40b62009-03-23 11:57:46 -06004070 {changes_l l + {} {mc "Changes to Files:"}}
4071 {pickaxe_s r0 . {} {mc "Fixed String"}}
4072 {pickaxe_t r1 . "--pickaxe-regex" {mc "Regular Expression"}}
4073 {pickaxe t15 .. "-S*" {mc "Search string:"}}
4074 {datelabel l + {} {mc "Commit Dates (\"2 weeks ago\", \"2009-03-17 15:27:38\", \"March 17, 2009 15:27:38\"):"}}
4075 {since t15 .. {"--since=*" "--after=*"} {mc "Since:"}}
4076 {until t15 . {"--until=*" "--before=*"} {mc "Until:"}}
4077 {limit_lbl l + {} {mc "Limit and/or skip a number of revisions (positive integer):"}}
4078 {limit t10 *. "--max-count=*" {mc "Number to show:"}}
4079 {skip t10 . "--skip=*" {mc "Number to skip:"}}
4080 {misc_lbl l + {} {mc "Miscellaneous options:"}}
4081 {dorder b *. {"--date-order" "-d"} {mc "Strictly sort by date"}}
4082 {lright b . "--left-right" {mc "Mark branch sides"}}
4083 {first b . "--first-parent" {mc "Limit to first parent"}}
Dirk Suesserottf687aaa2009-05-21 15:35:40 +02004084 {smplhst b . "--simplify-by-decoration" {mc "Simple history"}}
Elijah Newren13d40b62009-03-23 11:57:46 -06004085 {args t50 *. {} {mc "Additional arguments to git log:"}}
4086 {allpaths path + {} {mc "Enter files and directories to include, one per line:"}}
4087 {cmd t50= + {} {mc "Command to generate more commits to include:"}}
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004088 }
4089
Jonathan Niedere7feb692010-03-06 16:48:38 -06004090# Convert $newviewopts($n, ...) into args for git log.
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004091proc encode_view_opts {n} {
4092 global known_view_options newviewopts
4093
4094 set rargs [list]
4095 foreach opt $known_view_options {
4096 set patterns [lindex $opt 3]
4097 if {$patterns eq {}} continue
4098 set pattern [lindex $patterns 0]
4099
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004100 if {[lindex $opt 1] eq "b"} {
Elijah Newren13d40b62009-03-23 11:57:46 -06004101 set val $newviewopts($n,[lindex $opt 0])
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004102 if {$val} {
4103 lappend rargs $pattern
4104 }
Elijah Newren13d40b62009-03-23 11:57:46 -06004105 } elseif {[regexp {^r(\d+)$} [lindex $opt 1] type value]} {
4106 regexp {^(.*_)} [lindex $opt 0] uselessvar button_id
4107 set val $newviewopts($n,$button_id)
4108 if {$val eq $value} {
4109 lappend rargs $pattern
4110 }
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004111 } else {
Elijah Newren13d40b62009-03-23 11:57:46 -06004112 set val $newviewopts($n,[lindex $opt 0])
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004113 set val [string trim $val]
4114 if {$val ne {}} {
4115 set pfix [string range $pattern 0 end-1]
4116 lappend rargs $pfix$val
4117 }
4118 }
4119 }
Elijah Newren13d40b62009-03-23 11:57:46 -06004120 set rargs [concat $rargs [shellsplit $newviewopts($n,refs)]]
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004121 return [concat $rargs [shellsplit $newviewopts($n,args)]]
4122}
4123
Jonathan Niedere7feb692010-03-06 16:48:38 -06004124# Fill $newviewopts($n, ...) based on args for git log.
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004125proc decode_view_opts {n view_args} {
4126 global known_view_options newviewopts
4127
4128 foreach opt $known_view_options {
Elijah Newren13d40b62009-03-23 11:57:46 -06004129 set id [lindex $opt 0]
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004130 if {[lindex $opt 1] eq "b"} {
Elijah Newren13d40b62009-03-23 11:57:46 -06004131 # Checkboxes
4132 set val 0
4133 } elseif {[regexp {^r(\d+)$} [lindex $opt 1]]} {
4134 # Radiobuttons
4135 regexp {^(.*_)} $id uselessvar id
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004136 set val 0
4137 } else {
Elijah Newren13d40b62009-03-23 11:57:46 -06004138 # Text fields
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004139 set val {}
4140 }
Elijah Newren13d40b62009-03-23 11:57:46 -06004141 set newviewopts($n,$id) $val
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004142 }
4143 set oargs [list]
Elijah Newren13d40b62009-03-23 11:57:46 -06004144 set refargs [list]
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004145 foreach arg $view_args {
4146 if {[regexp -- {^-([0-9]+)$} $arg arg cnt]
4147 && ![info exists found(limit)]} {
4148 set newviewopts($n,limit) $cnt
4149 set found(limit) 1
4150 continue
4151 }
4152 catch { unset val }
4153 foreach opt $known_view_options {
4154 set id [lindex $opt 0]
4155 if {[info exists found($id)]} continue
4156 foreach pattern [lindex $opt 3] {
4157 if {![string match $pattern $arg]} continue
Elijah Newren13d40b62009-03-23 11:57:46 -06004158 if {[lindex $opt 1] eq "b"} {
4159 # Check buttons
4160 set val 1
4161 } elseif {[regexp {^r(\d+)$} [lindex $opt 1] match num]} {
4162 # Radio buttons
4163 regexp {^(.*_)} $id uselessvar id
4164 set val $num
4165 } else {
4166 # Text input fields
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004167 set size [string length $pattern]
4168 set val [string range $arg [expr {$size-1}] end]
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004169 }
4170 set newviewopts($n,$id) $val
4171 set found($id) 1
4172 break
4173 }
4174 if {[info exists val]} break
4175 }
4176 if {[info exists val]} continue
Elijah Newren13d40b62009-03-23 11:57:46 -06004177 if {[regexp {^-} $arg]} {
4178 lappend oargs $arg
4179 } else {
4180 lappend refargs $arg
4181 }
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004182 }
Elijah Newren13d40b62009-03-23 11:57:46 -06004183 set newviewopts($n,refs) [shellarglist $refargs]
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004184 set newviewopts($n,args) [shellarglist $oargs]
4185}
4186
Alexander Gavrilovcea07cf2008-11-09 13:00:45 +03004187proc edit_or_newview {} {
4188 global curview
4189
4190 if {$curview > 0} {
4191 editview
4192 } else {
4193 newview 0
4194 }
4195}
4196
Paul Mackerrasd16c0812006-04-25 21:21:10 +10004197proc editview {} {
4198 global curview
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004199 global viewname viewperm newviewname newviewopts
4200 global viewargs viewargscmd
Paul Mackerrasd16c0812006-04-25 21:21:10 +10004201
4202 set top .gitkvedit-$curview
4203 if {[winfo exists $top]} {
4204 raise $top
4205 return
4206 }
Jonathan Nieder5d11f792010-03-06 16:58:42 -06004207 decode_view_opts $curview $viewargs($curview)
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004208 set newviewname($curview) $viewname($curview)
4209 set newviewopts($curview,perm) $viewperm($curview)
4210 set newviewopts($curview,cmd) $viewargscmd($curview)
Michele Ballabiob56e0a92009-03-30 21:17:25 +02004211 vieweditor $top $curview "[mc "Gitk: edit view"] $viewname($curview)"
Paul Mackerrasd16c0812006-04-25 21:21:10 +10004212}
4213
4214proc vieweditor {top n title} {
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004215 global newviewname newviewopts viewfiles bgcolor
Pat Thoytsd93f1712009-04-17 01:24:35 +01004216 global known_view_options NS
Paul Mackerrasd16c0812006-04-25 21:21:10 +10004217
Pat Thoytsd93f1712009-04-17 01:24:35 +01004218 ttk_toplevel $top
Michele Ballabioe0a01992009-05-23 11:48:25 +02004219 wm title $top [concat $title [mc "-- criteria for selecting revisions"]]
Alexander Gavrilove7d64002008-11-11 23:55:42 +03004220 make_transient $top .
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004221
4222 # View name
Pat Thoytsd93f1712009-04-17 01:24:35 +01004223 ${NS}::frame $top.nfr
Paul Mackerraseae7d642009-09-05 17:34:03 +10004224 ${NS}::label $top.nl -text [mc "View Name"]
Pat Thoytsd93f1712009-04-17 01:24:35 +01004225 ${NS}::entry $top.name -width 20 -textvariable newviewname($n)
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004226 pack $top.nfr -in $top -fill x -pady 5 -padx 3
Elijah Newren13d40b62009-03-23 11:57:46 -06004227 pack $top.nl -in $top.nfr -side left -padx {0 5}
4228 pack $top.name -in $top.nfr -side left -padx {0 25}
Yann Dirson2d480852008-02-21 21:23:31 +01004229
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004230 # View options
4231 set cframe $top.nfr
4232 set cexpand 0
4233 set cnt 0
4234 foreach opt $known_view_options {
4235 set id [lindex $opt 0]
4236 set type [lindex $opt 1]
4237 set flags [lindex $opt 2]
4238 set title [eval [lindex $opt 4]]
4239 set lxpad 0
Yann Dirson2d480852008-02-21 21:23:31 +01004240
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004241 if {$flags eq "+" || $flags eq "*"} {
4242 set cframe $top.fr$cnt
4243 incr cnt
Pat Thoytsd93f1712009-04-17 01:24:35 +01004244 ${NS}::frame $cframe
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004245 pack $cframe -in $top -fill x -pady 3 -padx 3
4246 set cexpand [expr {$flags eq "*"}]
Elijah Newren13d40b62009-03-23 11:57:46 -06004247 } elseif {$flags eq ".." || $flags eq "*."} {
4248 set cframe $top.fr$cnt
4249 incr cnt
Paul Mackerraseae7d642009-09-05 17:34:03 +10004250 ${NS}::frame $cframe
Elijah Newren13d40b62009-03-23 11:57:46 -06004251 pack $cframe -in $top -fill x -pady 3 -padx [list 15 3]
4252 set cexpand [expr {$flags eq "*."}]
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004253 } else {
4254 set lxpad 5
4255 }
4256
Elijah Newren13d40b62009-03-23 11:57:46 -06004257 if {$type eq "l"} {
Paul Mackerraseae7d642009-09-05 17:34:03 +10004258 ${NS}::label $cframe.l_$id -text $title
Elijah Newren13d40b62009-03-23 11:57:46 -06004259 pack $cframe.l_$id -in $cframe -side left -pady [list 3 0] -anchor w
4260 } elseif {$type eq "b"} {
Pat Thoytsd93f1712009-04-17 01:24:35 +01004261 ${NS}::checkbutton $cframe.c_$id -text $title -variable newviewopts($n,$id)
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004262 pack $cframe.c_$id -in $cframe -side left \
4263 -padx [list $lxpad 0] -expand $cexpand -anchor w
Elijah Newren13d40b62009-03-23 11:57:46 -06004264 } elseif {[regexp {^r(\d+)$} $type type sz]} {
4265 regexp {^(.*_)} $id uselessvar button_id
Paul Mackerraseae7d642009-09-05 17:34:03 +10004266 ${NS}::radiobutton $cframe.c_$id -text $title -variable newviewopts($n,$button_id) -value $sz
Elijah Newren13d40b62009-03-23 11:57:46 -06004267 pack $cframe.c_$id -in $cframe -side left \
4268 -padx [list $lxpad 0] -expand $cexpand -anchor w
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004269 } elseif {[regexp {^t(\d+)$} $type type sz]} {
Pat Thoytsd93f1712009-04-17 01:24:35 +01004270 ${NS}::label $cframe.l_$id -text $title
4271 ${NS}::entry $cframe.e_$id -width $sz -background $bgcolor \
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004272 -textvariable newviewopts($n,$id)
4273 pack $cframe.l_$id -in $cframe -side left -padx [list $lxpad 0]
4274 pack $cframe.e_$id -in $cframe -side left -expand 1 -fill x
4275 } elseif {[regexp {^t(\d+)=$} $type type sz]} {
Pat Thoytsd93f1712009-04-17 01:24:35 +01004276 ${NS}::label $cframe.l_$id -text $title
4277 ${NS}::entry $cframe.e_$id -width $sz -background $bgcolor \
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004278 -textvariable newviewopts($n,$id)
4279 pack $cframe.l_$id -in $cframe -side top -pady [list 3 0] -anchor w
4280 pack $cframe.e_$id -in $cframe -side top -fill x
Elijah Newren13d40b62009-03-23 11:57:46 -06004281 } elseif {$type eq "path"} {
Paul Mackerraseae7d642009-09-05 17:34:03 +10004282 ${NS}::label $top.l -text $title
Elijah Newren13d40b62009-03-23 11:57:46 -06004283 pack $top.l -in $top -side top -pady [list 3 0] -anchor w -padx 3
Mark Hillsb9b142f2010-01-13 20:40:22 +00004284 text $top.t -width 40 -height 5 -background $bgcolor
Elijah Newren13d40b62009-03-23 11:57:46 -06004285 if {[info exists viewfiles($n)]} {
4286 foreach f $viewfiles($n) {
4287 $top.t insert end $f
4288 $top.t insert end "\n"
4289 }
4290 $top.t delete {end - 1c} end
4291 $top.t mark set insert 0.0
4292 }
4293 pack $top.t -in $top -side top -pady [list 0 5] -fill both -expand 1 -padx 3
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004294 }
4295 }
4296
Pat Thoytsd93f1712009-04-17 01:24:35 +01004297 ${NS}::frame $top.buts
4298 ${NS}::button $top.buts.ok -text [mc "OK"] -command [list newviewok $top $n]
4299 ${NS}::button $top.buts.apply -text [mc "Apply (F5)"] -command [list newviewok $top $n 1]
4300 ${NS}::button $top.buts.can -text [mc "Cancel"] -command [list destroy $top]
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004301 bind $top <Control-Return> [list newviewok $top $n]
4302 bind $top <F5> [list newviewok $top $n 1]
Alexander Gavrilov76f15942008-11-02 21:59:44 +03004303 bind $top <Escape> [list destroy $top]
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004304 grid $top.buts.ok $top.buts.apply $top.buts.can
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004305 grid columnconfigure $top.buts 0 -weight 1 -uniform a
4306 grid columnconfigure $top.buts 1 -weight 1 -uniform a
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004307 grid columnconfigure $top.buts 2 -weight 1 -uniform a
4308 pack $top.buts -in $top -side top -fill x
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004309 focus $top.t
4310}
4311
Paul Mackerras908c3582006-05-20 09:38:11 +10004312proc doviewmenu {m first cmd op argv} {
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004313 set nmenu [$m index end]
4314 for {set i $first} {$i <= $nmenu} {incr i} {
4315 if {[$m entrycget $i -command] eq $cmd} {
Paul Mackerras908c3582006-05-20 09:38:11 +10004316 eval $m $op $i $argv
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004317 break
Paul Mackerrasd16c0812006-04-25 21:21:10 +10004318 }
4319 }
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004320}
4321
4322proc allviewmenus {n op args} {
Paul Mackerras687c8762007-09-22 12:49:33 +10004323 # global viewhlmenu
Paul Mackerras908c3582006-05-20 09:38:11 +10004324
Paul Mackerras3cd204e2006-11-23 21:06:16 +11004325 doviewmenu .bar.view 5 [list showview $n] $op $args
Paul Mackerras687c8762007-09-22 12:49:33 +10004326 # doviewmenu $viewhlmenu 1 [list addvhighlight $n] $op $args
Paul Mackerrasd16c0812006-04-25 21:21:10 +10004327}
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004328
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004329proc newviewok {top n {apply 0}} {
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004330 global nextviewnum newviewperm newviewname newishighlight
Max Kirillov995f7922015-03-04 05:58:16 +02004331 global viewname viewfiles viewperm viewchanged selectedview curview
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004332 global viewargs viewargscmd newviewopts viewhlmenu
Paul Mackerrasd16c0812006-04-25 21:21:10 +10004333
Paul Mackerras098dd8a2006-05-03 09:32:53 +10004334 if {[catch {
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004335 set newargs [encode_view_opts $n]
Paul Mackerras098dd8a2006-05-03 09:32:53 +10004336 } err]} {
Alexander Gavrilov84a76f12008-11-02 21:59:45 +03004337 error_popup "[mc "Error in commit selection arguments:"] $err" $top
Paul Mackerras098dd8a2006-05-03 09:32:53 +10004338 return
4339 }
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004340 set files {}
Paul Mackerrasd16c0812006-04-25 21:21:10 +10004341 foreach f [split [$top.t get 0.0 end] "\n"] {
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004342 set ft [string trim $f]
4343 if {$ft ne {}} {
4344 lappend files $ft
4345 }
4346 }
Paul Mackerrasd16c0812006-04-25 21:21:10 +10004347 if {![info exists viewfiles($n)]} {
4348 # creating a new view
4349 incr nextviewnum
4350 set viewname($n) $newviewname($n)
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004351 set viewperm($n) $newviewopts($n,perm)
Max Kirillov995f7922015-03-04 05:58:16 +02004352 set viewchanged($n) 1
Paul Mackerrasd16c0812006-04-25 21:21:10 +10004353 set viewfiles($n) $files
Paul Mackerras098dd8a2006-05-03 09:32:53 +10004354 set viewargs($n) $newargs
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004355 set viewargscmd($n) $newviewopts($n,cmd)
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004356 addviewmenu $n
4357 if {!$newishighlight} {
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004358 run showview $n
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004359 } else {
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004360 run addvhighlight $n
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004361 }
Paul Mackerrasd16c0812006-04-25 21:21:10 +10004362 } else {
4363 # editing an existing view
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004364 set viewperm($n) $newviewopts($n,perm)
Max Kirillov995f7922015-03-04 05:58:16 +02004365 set viewchanged($n) 1
Paul Mackerrasd16c0812006-04-25 21:21:10 +10004366 if {$newviewname($n) ne $viewname($n)} {
4367 set viewname($n) $newviewname($n)
Paul Mackerras3cd204e2006-11-23 21:06:16 +11004368 doviewmenu .bar.view 5 [list showview $n] \
Paul Mackerras908c3582006-05-20 09:38:11 +10004369 entryconf [list -label $viewname($n)]
Paul Mackerras687c8762007-09-22 12:49:33 +10004370 # doviewmenu $viewhlmenu 1 [list addvhighlight $n] \
4371 # entryconf [list -label $viewname($n) -value $viewname($n)]
Paul Mackerrasd16c0812006-04-25 21:21:10 +10004372 }
Yann Dirson2d480852008-02-21 21:23:31 +01004373 if {$files ne $viewfiles($n) || $newargs ne $viewargs($n) || \
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004374 $newviewopts($n,cmd) ne $viewargscmd($n)} {
Paul Mackerrasd16c0812006-04-25 21:21:10 +10004375 set viewfiles($n) $files
Paul Mackerras098dd8a2006-05-03 09:32:53 +10004376 set viewargs($n) $newargs
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004377 set viewargscmd($n) $newviewopts($n,cmd)
Paul Mackerrasd16c0812006-04-25 21:21:10 +10004378 if {$curview == $n} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004379 run reloadcommits
Paul Mackerrasd16c0812006-04-25 21:21:10 +10004380 }
4381 }
4382 }
Alexander Gavrilov218a9002008-11-02 21:59:48 +03004383 if {$apply} return
Paul Mackerrasd16c0812006-04-25 21:21:10 +10004384 catch {destroy $top}
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004385}
4386
4387proc delview {} {
Max Kirillov995f7922015-03-04 05:58:16 +02004388 global curview viewperm hlview selectedhlview viewchanged
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004389
4390 if {$curview == 0} return
Paul Mackerras908c3582006-05-20 09:38:11 +10004391 if {[info exists hlview] && $hlview == $curview} {
Christian Stimmingb007ee22007-11-07 18:44:35 +01004392 set selectedhlview [mc "None"]
Paul Mackerras908c3582006-05-20 09:38:11 +10004393 unset hlview
4394 }
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004395 allviewmenus $curview delete
Paul Mackerrasa90a6d22006-04-25 17:12:46 +10004396 set viewperm($curview) 0
Max Kirillov995f7922015-03-04 05:58:16 +02004397 set viewchanged($curview) 1
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004398 showview 0
4399}
4400
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004401proc addviewmenu {n} {
Paul Mackerras908c3582006-05-20 09:38:11 +10004402 global viewname viewhlmenu
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004403
4404 .bar.view add radiobutton -label $viewname($n) \
4405 -command [list showview $n] -variable selectedview -value $n
Paul Mackerras687c8762007-09-22 12:49:33 +10004406 #$viewhlmenu add radiobutton -label $viewname($n) \
4407 # -command [list addvhighlight $n] -variable selectedhlview
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004408}
4409
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004410proc showview {n} {
Paul Mackerras3ed31a82008-04-26 16:00:00 +10004411 global curview cached_commitrow ordertok
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10004412 global displayorder parentlist rowidlist rowisopt rowfinal
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004413 global colormap rowtextx nextcolor canvxmax
4414 global numcommits viewcomplete
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004415 global selectedline currentid canv canvy0
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004416 global treediffs
Paul Mackerras3e766082008-01-13 17:26:30 +11004417 global pending_select mainheadid
Paul Mackerras03800812007-08-29 21:45:21 +10004418 global commitidx
Paul Mackerras3e766082008-01-13 17:26:30 +11004419 global selectedview
Paul Mackerras97645682007-08-23 22:24:38 +10004420 global hlview selectedhlview commitinterest
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004421
4422 if {$n == $curview} return
4423 set selid {}
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004424 set ymax [lindex [$canv cget -scrollregion] 3]
4425 set span [$canv yview]
4426 set ytop [expr {[lindex $span 0] * $ymax}]
4427 set ybot [expr {[lindex $span 1] * $ymax}]
4428 set yscreen [expr {($ybot - $ytop) / 2}]
Paul Mackerras94b4a692008-05-20 20:51:06 +10004429 if {$selectedline ne {}} {
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004430 set selid $currentid
4431 set y [yc $selectedline]
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004432 if {$ytop < $y && $y < $ybot} {
4433 set yscreen [expr {$y - $ytop}]
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004434 }
Paul Mackerrase507fd42007-06-16 21:51:08 +10004435 } elseif {[info exists pending_select]} {
4436 set selid $pending_select
4437 unset pending_select
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004438 }
4439 unselectline
Paul Mackerrasfdedbcf2006-04-06 21:22:52 +10004440 normalline
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004441 catch {unset treediffs}
4442 clear_display
Paul Mackerras908c3582006-05-20 09:38:11 +10004443 if {[info exists hlview] && $hlview == $n} {
4444 unset hlview
Christian Stimmingb007ee22007-11-07 18:44:35 +01004445 set selectedhlview [mc "None"]
Paul Mackerras908c3582006-05-20 09:38:11 +10004446 }
Paul Mackerras97645682007-08-23 22:24:38 +10004447 catch {unset commitinterest}
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004448 catch {unset cached_commitrow}
Paul Mackerras9257d8f2007-12-11 10:45:38 +11004449 catch {unset ordertok}
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004450
4451 set curview $n
Paul Mackerrasa90a6d22006-04-25 17:12:46 +10004452 set selectedview $n
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11004453 .bar.view entryconf [mca "Edit view..."] -state [expr {$n == 0? "disabled": "normal"}]
4454 .bar.view entryconf [mca "Delete view"] -state [expr {$n == 0? "disabled": "normal"}]
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004455
Paul Mackerrasdf904492007-08-29 22:03:07 +10004456 run refill_reflist
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004457 if {![info exists viewcomplete($n)]} {
Alexander Gavrilov567c34e2008-07-26 20:13:45 +04004458 getcommits $selid
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004459 return
4460 }
4461
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004462 set displayorder {}
4463 set parentlist {}
4464 set rowidlist {}
4465 set rowisopt {}
4466 set rowfinal {}
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10004467 set numcommits $commitidx($n)
Paul Mackerras22626ef2006-04-17 09:56:02 +10004468
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004469 catch {unset colormap}
4470 catch {unset rowtextx}
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004471 set nextcolor 0
4472 set canvxmax [$canv cget -width]
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004473 set curview $n
4474 set row 0
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004475 setcanvscroll
4476 set yf 0
Paul Mackerrase507fd42007-06-16 21:51:08 +10004477 set row {}
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004478 if {$selid ne {} && [commitinview $selid $n]} {
4479 set row [rowofcommit $selid]
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004480 # try to get the selected row in the same position on the screen
4481 set ymax [lindex [$canv cget -scrollregion] 3]
4482 set ytop [expr {[yc $row] - $yscreen}]
4483 if {$ytop < 0} {
4484 set ytop 0
4485 }
4486 set yf [expr {$ytop * 1.0 / $ymax}]
4487 }
4488 allcanvs yview moveto $yf
4489 drawvisible
Paul Mackerrase507fd42007-06-16 21:51:08 +10004490 if {$row ne {}} {
4491 selectline $row 0
Paul Mackerras3e766082008-01-13 17:26:30 +11004492 } elseif {!$viewcomplete($n)} {
Alexander Gavrilov567c34e2008-07-26 20:13:45 +04004493 reset_pending_select $selid
Paul Mackerrase507fd42007-06-16 21:51:08 +10004494 } else {
Alexander Gavrilov835e62a2008-07-26 20:15:54 +04004495 reset_pending_select {}
4496
4497 if {[commitinview $pending_select $curview]} {
4498 selectline [rowofcommit $pending_select] 1
4499 } else {
4500 set row [first_real_row]
4501 if {$row < $numcommits} {
4502 selectline $row 0
4503 }
Paul Mackerrase507fd42007-06-16 21:51:08 +10004504 }
4505 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004506 if {!$viewcomplete($n)} {
4507 if {$numcommits == 0} {
Christian Stimmingd990ced2007-11-07 18:42:55 +01004508 show_status [mc "Reading commits..."]
Paul Mackerrasd16c0812006-04-25 21:21:10 +10004509 }
Paul Mackerras098dd8a2006-05-03 09:32:53 +10004510 } elseif {$numcommits == 0} {
Christian Stimmingd990ced2007-11-07 18:42:55 +01004511 show_status [mc "No commits selected"]
Paul Mackerras2516dae2006-04-21 10:35:31 +10004512 }
Paul Mackerras50b44ec2006-04-04 10:16:22 +10004513}
4514
Paul Mackerras908c3582006-05-20 09:38:11 +10004515# Stuff relating to the highlighting facility
4516
Paul Mackerras476ca632008-01-07 22:16:31 +11004517proc ishighlighted {id} {
Paul Mackerras164ff272006-05-29 19:50:02 +10004518 global vhighlights fhighlights nhighlights rhighlights
Paul Mackerras908c3582006-05-20 09:38:11 +10004519
Paul Mackerras476ca632008-01-07 22:16:31 +11004520 if {[info exists nhighlights($id)] && $nhighlights($id) > 0} {
4521 return $nhighlights($id)
Paul Mackerras908c3582006-05-20 09:38:11 +10004522 }
Paul Mackerras476ca632008-01-07 22:16:31 +11004523 if {[info exists vhighlights($id)] && $vhighlights($id) > 0} {
4524 return $vhighlights($id)
Paul Mackerras908c3582006-05-20 09:38:11 +10004525 }
Paul Mackerras476ca632008-01-07 22:16:31 +11004526 if {[info exists fhighlights($id)] && $fhighlights($id) > 0} {
4527 return $fhighlights($id)
Paul Mackerras908c3582006-05-20 09:38:11 +10004528 }
Paul Mackerras476ca632008-01-07 22:16:31 +11004529 if {[info exists rhighlights($id)] && $rhighlights($id) > 0} {
4530 return $rhighlights($id)
Paul Mackerras164ff272006-05-29 19:50:02 +10004531 }
Paul Mackerras908c3582006-05-20 09:38:11 +10004532 return 0
4533}
4534
Paul Mackerras28593d32008-11-13 23:01:46 +11004535proc bolden {id font} {
Paul Mackerrasb9fdba72009-04-09 09:34:46 +10004536 global canv linehtag currentid boldids need_redisplay markedid
Paul Mackerras908c3582006-05-20 09:38:11 +10004537
Paul Mackerrasd98d50e2008-11-13 22:39:00 +11004538 # need_redisplay = 1 means the display is stale and about to be redrawn
4539 if {$need_redisplay} return
Paul Mackerras28593d32008-11-13 23:01:46 +11004540 lappend boldids $id
4541 $canv itemconf $linehtag($id) -font $font
4542 if {[info exists currentid] && $id eq $currentid} {
Paul Mackerras908c3582006-05-20 09:38:11 +10004543 $canv delete secsel
Paul Mackerras28593d32008-11-13 23:01:46 +11004544 set t [eval $canv create rect [$canv bbox $linehtag($id)] \
Paul Mackerras908c3582006-05-20 09:38:11 +10004545 -outline {{}} -tags secsel \
4546 -fill [$canv cget -selectbackground]]
4547 $canv lower $t
4548 }
Paul Mackerrasb9fdba72009-04-09 09:34:46 +10004549 if {[info exists markedid] && $id eq $markedid} {
4550 make_idmark $id
4551 }
Paul Mackerras908c3582006-05-20 09:38:11 +10004552}
4553
Paul Mackerras28593d32008-11-13 23:01:46 +11004554proc bolden_name {id font} {
4555 global canv2 linentag currentid boldnameids need_redisplay
Paul Mackerras908c3582006-05-20 09:38:11 +10004556
Paul Mackerrasd98d50e2008-11-13 22:39:00 +11004557 if {$need_redisplay} return
Paul Mackerras28593d32008-11-13 23:01:46 +11004558 lappend boldnameids $id
4559 $canv2 itemconf $linentag($id) -font $font
4560 if {[info exists currentid] && $id eq $currentid} {
Paul Mackerras908c3582006-05-20 09:38:11 +10004561 $canv2 delete secsel
Paul Mackerras28593d32008-11-13 23:01:46 +11004562 set t [eval $canv2 create rect [$canv2 bbox $linentag($id)] \
Paul Mackerras908c3582006-05-20 09:38:11 +10004563 -outline {{}} -tags secsel \
4564 -fill [$canv2 cget -selectbackground]]
4565 $canv2 lower $t
4566 }
4567}
4568
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004569proc unbolden {} {
Paul Mackerras28593d32008-11-13 23:01:46 +11004570 global boldids
Paul Mackerras908c3582006-05-20 09:38:11 +10004571
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004572 set stillbold {}
Paul Mackerras28593d32008-11-13 23:01:46 +11004573 foreach id $boldids {
4574 if {![ishighlighted $id]} {
4575 bolden $id mainfont
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004576 } else {
Paul Mackerras28593d32008-11-13 23:01:46 +11004577 lappend stillbold $id
Paul Mackerras908c3582006-05-20 09:38:11 +10004578 }
4579 }
Paul Mackerras28593d32008-11-13 23:01:46 +11004580 set boldids $stillbold
Paul Mackerras908c3582006-05-20 09:38:11 +10004581}
4582
4583proc addvhighlight {n} {
Paul Mackerras476ca632008-01-07 22:16:31 +11004584 global hlview viewcomplete curview vhl_done commitidx
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004585
4586 if {[info exists hlview]} {
Paul Mackerras908c3582006-05-20 09:38:11 +10004587 delvhighlight
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004588 }
4589 set hlview $n
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004590 if {$n != $curview && ![info exists viewcomplete($n)]} {
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004591 start_rev_list $n
Paul Mackerras908c3582006-05-20 09:38:11 +10004592 }
4593 set vhl_done $commitidx($hlview)
4594 if {$vhl_done > 0} {
4595 drawvisible
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004596 }
4597}
4598
Paul Mackerras908c3582006-05-20 09:38:11 +10004599proc delvhighlight {} {
4600 global hlview vhighlights
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004601
4602 if {![info exists hlview]} return
4603 unset hlview
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004604 catch {unset vhighlights}
4605 unbolden
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004606}
4607
Paul Mackerras908c3582006-05-20 09:38:11 +10004608proc vhighlightmore {} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004609 global hlview vhl_done commitidx vhighlights curview
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004610
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004611 set max $commitidx($hlview)
Paul Mackerras908c3582006-05-20 09:38:11 +10004612 set vr [visiblerows]
4613 set r0 [lindex $vr 0]
4614 set r1 [lindex $vr 1]
4615 for {set i $vhl_done} {$i < $max} {incr i} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004616 set id [commitonrow $i $hlview]
4617 if {[commitinview $id $curview]} {
4618 set row [rowofcommit $id]
Paul Mackerras908c3582006-05-20 09:38:11 +10004619 if {$r0 <= $row && $row <= $r1} {
4620 if {![highlighted $row]} {
Paul Mackerras28593d32008-11-13 23:01:46 +11004621 bolden $id mainfontbold
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004622 }
Paul Mackerras476ca632008-01-07 22:16:31 +11004623 set vhighlights($id) 1
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004624 }
4625 }
4626 }
Paul Mackerras908c3582006-05-20 09:38:11 +10004627 set vhl_done $max
Paul Mackerrasac1276a2008-03-03 10:11:08 +11004628 return 0
Paul Mackerras908c3582006-05-20 09:38:11 +10004629}
4630
4631proc askvhighlight {row id} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004632 global hlview vhighlights iddrawn
Paul Mackerras908c3582006-05-20 09:38:11 +10004633
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004634 if {[commitinview $id $hlview]} {
Paul Mackerras476ca632008-01-07 22:16:31 +11004635 if {[info exists iddrawn($id)] && ![ishighlighted $id]} {
Paul Mackerras28593d32008-11-13 23:01:46 +11004636 bolden $id mainfontbold
Paul Mackerras908c3582006-05-20 09:38:11 +10004637 }
Paul Mackerras476ca632008-01-07 22:16:31 +11004638 set vhighlights($id) 1
Paul Mackerras908c3582006-05-20 09:38:11 +10004639 } else {
Paul Mackerras476ca632008-01-07 22:16:31 +11004640 set vhighlights($id) 0
Paul Mackerras908c3582006-05-20 09:38:11 +10004641 }
4642}
4643
Paul Mackerras687c8762007-09-22 12:49:33 +10004644proc hfiles_change {} {
Paul Mackerras908c3582006-05-20 09:38:11 +10004645 global highlight_files filehighlight fhighlights fh_serial
Paul Mackerras8b39e042008-12-02 09:02:46 +11004646 global highlight_paths
Paul Mackerras908c3582006-05-20 09:38:11 +10004647
4648 if {[info exists filehighlight]} {
4649 # delete previous highlights
4650 catch {close $filehighlight}
4651 unset filehighlight
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004652 catch {unset fhighlights}
4653 unbolden
Paul Mackerras63b79192006-05-20 21:31:52 +10004654 unhighlight_filelist
Paul Mackerras908c3582006-05-20 09:38:11 +10004655 }
Paul Mackerras63b79192006-05-20 21:31:52 +10004656 set highlight_paths {}
Paul Mackerras908c3582006-05-20 09:38:11 +10004657 after cancel do_file_hl $fh_serial
4658 incr fh_serial
4659 if {$highlight_files ne {}} {
4660 after 300 do_file_hl $fh_serial
4661 }
4662}
4663
Paul Mackerras687c8762007-09-22 12:49:33 +10004664proc gdttype_change {name ix op} {
4665 global gdttype highlight_files findstring findpattern
4666
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10004667 stopfinding
Paul Mackerras687c8762007-09-22 12:49:33 +10004668 if {$findstring ne {}} {
Christian Stimmingb007ee22007-11-07 18:44:35 +01004669 if {$gdttype eq [mc "containing:"]} {
Paul Mackerras687c8762007-09-22 12:49:33 +10004670 if {$highlight_files ne {}} {
4671 set highlight_files {}
4672 hfiles_change
4673 }
4674 findcom_change
4675 } else {
4676 if {$findpattern ne {}} {
4677 set findpattern {}
4678 findcom_change
4679 }
4680 set highlight_files $findstring
4681 hfiles_change
4682 }
4683 drawvisible
4684 }
4685 # enable/disable findtype/findloc menus too
4686}
4687
4688proc find_change {name ix op} {
4689 global gdttype findstring highlight_files
4690
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10004691 stopfinding
Christian Stimmingb007ee22007-11-07 18:44:35 +01004692 if {$gdttype eq [mc "containing:"]} {
Paul Mackerras687c8762007-09-22 12:49:33 +10004693 findcom_change
4694 } else {
4695 if {$highlight_files ne $findstring} {
4696 set highlight_files $findstring
4697 hfiles_change
4698 }
4699 }
4700 drawvisible
4701}
4702
Paul Mackerras64b5f142007-10-04 22:19:24 +10004703proc findcom_change args {
Paul Mackerras28593d32008-11-13 23:01:46 +11004704 global nhighlights boldnameids
Paul Mackerras687c8762007-09-22 12:49:33 +10004705 global findpattern findtype findstring gdttype
4706
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10004707 stopfinding
Paul Mackerras687c8762007-09-22 12:49:33 +10004708 # delete previous highlights, if any
Paul Mackerras28593d32008-11-13 23:01:46 +11004709 foreach id $boldnameids {
4710 bolden_name $id mainfont
Paul Mackerras687c8762007-09-22 12:49:33 +10004711 }
Paul Mackerras28593d32008-11-13 23:01:46 +11004712 set boldnameids {}
Paul Mackerras687c8762007-09-22 12:49:33 +10004713 catch {unset nhighlights}
4714 unbolden
4715 unmarkmatches
Christian Stimmingb007ee22007-11-07 18:44:35 +01004716 if {$gdttype ne [mc "containing:"] || $findstring eq {}} {
Paul Mackerras687c8762007-09-22 12:49:33 +10004717 set findpattern {}
Christian Stimmingb007ee22007-11-07 18:44:35 +01004718 } elseif {$findtype eq [mc "Regexp"]} {
Paul Mackerras687c8762007-09-22 12:49:33 +10004719 set findpattern $findstring
4720 } else {
4721 set e [string map {"*" "\\*" "?" "\\?" "\[" "\\\[" "\\" "\\\\"} \
4722 $findstring]
4723 set findpattern "*$e*"
4724 }
4725}
4726
Paul Mackerras63b79192006-05-20 21:31:52 +10004727proc makepatterns {l} {
4728 set ret {}
4729 foreach e $l {
4730 set ee [string map {"*" "\\*" "?" "\\?" "\[" "\\\[" "\\" "\\\\"} $e]
4731 if {[string index $ee end] eq "/"} {
4732 lappend ret "$ee*"
4733 } else {
4734 lappend ret $ee
4735 lappend ret "$ee/*"
4736 }
4737 }
4738 return $ret
4739}
4740
Paul Mackerras908c3582006-05-20 09:38:11 +10004741proc do_file_hl {serial} {
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004742 global highlight_files filehighlight highlight_paths gdttype fhl_list
Yggy Kingde665fd2011-07-13 01:30:26 -07004743 global cdup findtype
Paul Mackerras908c3582006-05-20 09:38:11 +10004744
Christian Stimmingb007ee22007-11-07 18:44:35 +01004745 if {$gdttype eq [mc "touching paths:"]} {
Yggy Kingde665fd2011-07-13 01:30:26 -07004746 # If "exact" match then convert backslashes to forward slashes.
4747 # Most useful to support Windows-flavoured file paths.
4748 if {$findtype eq [mc "Exact"]} {
4749 set highlight_files [string map {"\\" "/"} $highlight_files]
4750 }
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10004751 if {[catch {set paths [shellsplit $highlight_files]}]} return
4752 set highlight_paths [makepatterns $paths]
4753 highlight_filelist
Martin von Zweigbergkc332f442011-04-04 22:14:12 -04004754 set relative_paths {}
4755 foreach path $paths {
4756 lappend relative_paths [file join $cdup $path]
4757 }
4758 set gdtargs [concat -- $relative_paths]
Christian Stimmingb007ee22007-11-07 18:44:35 +01004759 } elseif {$gdttype eq [mc "adding/removing string:"]} {
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10004760 set gdtargs [list "-S$highlight_files"]
Martin Langhoffc33cb902012-06-14 20:34:11 +02004761 } elseif {$gdttype eq [mc "changing lines matching:"]} {
4762 set gdtargs [list "-G$highlight_files"]
Paul Mackerras687c8762007-09-22 12:49:33 +10004763 } else {
4764 # must be "containing:", i.e. we're searching commit info
4765 return
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10004766 }
Brandon Casey1ce09dd2007-03-19 18:00:37 -05004767 set cmd [concat | git diff-tree -r -s --stdin $gdtargs]
Paul Mackerras908c3582006-05-20 09:38:11 +10004768 set filehighlight [open $cmd r+]
4769 fconfigure $filehighlight -blocking 0
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004770 filerun $filehighlight readfhighlight
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004771 set fhl_list {}
Paul Mackerras908c3582006-05-20 09:38:11 +10004772 drawvisible
4773 flushhighlights
4774}
4775
4776proc flushhighlights {} {
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004777 global filehighlight fhl_list
Paul Mackerras908c3582006-05-20 09:38:11 +10004778
4779 if {[info exists filehighlight]} {
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004780 lappend fhl_list {}
Paul Mackerras908c3582006-05-20 09:38:11 +10004781 puts $filehighlight ""
4782 flush $filehighlight
4783 }
4784}
4785
4786proc askfilehighlight {row id} {
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004787 global filehighlight fhighlights fhl_list
Paul Mackerras908c3582006-05-20 09:38:11 +10004788
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004789 lappend fhl_list $id
Paul Mackerras476ca632008-01-07 22:16:31 +11004790 set fhighlights($id) -1
Paul Mackerras908c3582006-05-20 09:38:11 +10004791 puts $filehighlight $id
4792}
4793
4794proc readfhighlight {} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004795 global filehighlight fhighlights curview iddrawn
Paul Mackerras687c8762007-09-22 12:49:33 +10004796 global fhl_list find_dirn
Paul Mackerras908c3582006-05-20 09:38:11 +10004797
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004798 if {![info exists filehighlight]} {
4799 return 0
4800 }
4801 set nr 0
4802 while {[incr nr] <= 100 && [gets $filehighlight line] >= 0} {
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004803 set line [string trim $line]
4804 set i [lsearch -exact $fhl_list $line]
4805 if {$i < 0} continue
4806 for {set j 0} {$j < $i} {incr j} {
4807 set id [lindex $fhl_list $j]
Paul Mackerras476ca632008-01-07 22:16:31 +11004808 set fhighlights($id) 0
Paul Mackerras908c3582006-05-20 09:38:11 +10004809 }
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004810 set fhl_list [lrange $fhl_list [expr {$i+1}] end]
4811 if {$line eq {}} continue
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004812 if {![commitinview $line $curview]} continue
Paul Mackerras476ca632008-01-07 22:16:31 +11004813 if {[info exists iddrawn($line)] && ![ishighlighted $line]} {
Paul Mackerras28593d32008-11-13 23:01:46 +11004814 bolden $line mainfontbold
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004815 }
Paul Mackerras476ca632008-01-07 22:16:31 +11004816 set fhighlights($line) 1
Paul Mackerras908c3582006-05-20 09:38:11 +10004817 }
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004818 if {[eof $filehighlight]} {
4819 # strange...
Brandon Casey1ce09dd2007-03-19 18:00:37 -05004820 puts "oops, git diff-tree died"
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004821 catch {close $filehighlight}
4822 unset filehighlight
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004823 return 0
Paul Mackerras908c3582006-05-20 09:38:11 +10004824 }
Paul Mackerras687c8762007-09-22 12:49:33 +10004825 if {[info exists find_dirn]} {
Paul Mackerrascca5d942007-10-27 21:16:56 +10004826 run findmore
Paul Mackerras687c8762007-09-22 12:49:33 +10004827 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004828 return 1
Paul Mackerras908c3582006-05-20 09:38:11 +10004829}
4830
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004831proc doesmatch {f} {
Paul Mackerras687c8762007-09-22 12:49:33 +10004832 global findtype findpattern
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004833
Christian Stimmingb007ee22007-11-07 18:44:35 +01004834 if {$findtype eq [mc "Regexp"]} {
Paul Mackerras687c8762007-09-22 12:49:33 +10004835 return [regexp $findpattern $f]
Christian Stimmingb007ee22007-11-07 18:44:35 +01004836 } elseif {$findtype eq [mc "IgnCase"]} {
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004837 return [string match -nocase $findpattern $f]
4838 } else {
4839 return [string match $findpattern $f]
4840 }
4841}
4842
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10004843proc askfindhighlight {row id} {
Paul Mackerras9c311b32007-10-04 22:27:13 +10004844 global nhighlights commitinfo iddrawn
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004845 global findloc
4846 global markingmatches
Paul Mackerras908c3582006-05-20 09:38:11 +10004847
4848 if {![info exists commitinfo($id)]} {
4849 getcommit $id
4850 }
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10004851 set info $commitinfo($id)
Paul Mackerras908c3582006-05-20 09:38:11 +10004852 set isbold 0
Frédéric Brière585c27c2010-03-14 18:59:09 -04004853 set fldtypes [list [mc Headline] [mc Author] "" [mc Committer] "" [mc Comments]]
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10004854 foreach f $info ty $fldtypes {
Frédéric Brière585c27c2010-03-14 18:59:09 -04004855 if {$ty eq ""} continue
Christian Stimmingb007ee22007-11-07 18:44:35 +01004856 if {($findloc eq [mc "All fields"] || $findloc eq $ty) &&
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004857 [doesmatch $f]} {
Christian Stimmingb007ee22007-11-07 18:44:35 +01004858 if {$ty eq [mc "Author"]} {
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10004859 set isbold 2
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004860 break
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10004861 }
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004862 set isbold 1
Paul Mackerras908c3582006-05-20 09:38:11 +10004863 }
4864 }
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004865 if {$isbold && [info exists iddrawn($id)]} {
Paul Mackerras476ca632008-01-07 22:16:31 +11004866 if {![ishighlighted $id]} {
Paul Mackerras28593d32008-11-13 23:01:46 +11004867 bolden $id mainfontbold
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004868 if {$isbold > 1} {
Paul Mackerras28593d32008-11-13 23:01:46 +11004869 bolden_name $id mainfontbold
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004870 }
Paul Mackerras908c3582006-05-20 09:38:11 +10004871 }
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004872 if {$markingmatches} {
Paul Mackerras005a2f42007-07-26 22:36:39 +10004873 markrowmatches $row $id
Paul Mackerras908c3582006-05-20 09:38:11 +10004874 }
4875 }
Paul Mackerras476ca632008-01-07 22:16:31 +11004876 set nhighlights($id) $isbold
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10004877}
4878
Paul Mackerras005a2f42007-07-26 22:36:39 +10004879proc markrowmatches {row id} {
4880 global canv canv2 linehtag linentag commitinfo findloc
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004881
Paul Mackerras005a2f42007-07-26 22:36:39 +10004882 set headline [lindex $commitinfo($id) 0]
4883 set author [lindex $commitinfo($id) 1]
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004884 $canv delete match$row
4885 $canv2 delete match$row
Christian Stimmingb007ee22007-11-07 18:44:35 +01004886 if {$findloc eq [mc "All fields"] || $findloc eq [mc "Headline"]} {
Paul Mackerras005a2f42007-07-26 22:36:39 +10004887 set m [findmatches $headline]
4888 if {$m ne {}} {
Paul Mackerras28593d32008-11-13 23:01:46 +11004889 markmatches $canv $row $headline $linehtag($id) $m \
4890 [$canv itemcget $linehtag($id) -font] $row
Paul Mackerras005a2f42007-07-26 22:36:39 +10004891 }
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004892 }
Christian Stimmingb007ee22007-11-07 18:44:35 +01004893 if {$findloc eq [mc "All fields"] || $findloc eq [mc "Author"]} {
Paul Mackerras005a2f42007-07-26 22:36:39 +10004894 set m [findmatches $author]
4895 if {$m ne {}} {
Paul Mackerras28593d32008-11-13 23:01:46 +11004896 markmatches $canv2 $row $author $linentag($id) $m \
4897 [$canv2 itemcget $linentag($id) -font] $row
Paul Mackerras005a2f42007-07-26 22:36:39 +10004898 }
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10004899 }
4900}
4901
Paul Mackerras164ff272006-05-29 19:50:02 +10004902proc vrel_change {name ix op} {
4903 global highlight_related
4904
4905 rhighlight_none
Christian Stimmingb007ee22007-11-07 18:44:35 +01004906 if {$highlight_related ne [mc "None"]} {
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004907 run drawvisible
Paul Mackerras164ff272006-05-29 19:50:02 +10004908 }
4909}
4910
4911# prepare for testing whether commits are descendents or ancestors of a
4912proc rhighlight_sel {a} {
4913 global descendent desc_todo ancestor anc_todo
Paul Mackerras476ca632008-01-07 22:16:31 +11004914 global highlight_related
Paul Mackerras164ff272006-05-29 19:50:02 +10004915
4916 catch {unset descendent}
4917 set desc_todo [list $a]
4918 catch {unset ancestor}
4919 set anc_todo [list $a]
Christian Stimmingb007ee22007-11-07 18:44:35 +01004920 if {$highlight_related ne [mc "None"]} {
Paul Mackerras164ff272006-05-29 19:50:02 +10004921 rhighlight_none
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10004922 run drawvisible
Paul Mackerras164ff272006-05-29 19:50:02 +10004923 }
4924}
4925
4926proc rhighlight_none {} {
4927 global rhighlights
4928
Paul Mackerras4e7d6772006-05-30 21:33:07 +10004929 catch {unset rhighlights}
4930 unbolden
Paul Mackerras164ff272006-05-29 19:50:02 +10004931}
4932
4933proc is_descendent {a} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004934 global curview children descendent desc_todo
Paul Mackerras164ff272006-05-29 19:50:02 +10004935
4936 set v $curview
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004937 set la [rowofcommit $a]
Paul Mackerras164ff272006-05-29 19:50:02 +10004938 set todo $desc_todo
4939 set leftover {}
4940 set done 0
4941 for {set i 0} {$i < [llength $todo]} {incr i} {
4942 set do [lindex $todo $i]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004943 if {[rowofcommit $do] < $la} {
Paul Mackerras164ff272006-05-29 19:50:02 +10004944 lappend leftover $do
4945 continue
4946 }
4947 foreach nk $children($v,$do) {
4948 if {![info exists descendent($nk)]} {
4949 set descendent($nk) 1
4950 lappend todo $nk
4951 if {$nk eq $a} {
4952 set done 1
4953 }
4954 }
4955 }
4956 if {$done} {
4957 set desc_todo [concat $leftover [lrange $todo [expr {$i+1}] end]]
4958 return
4959 }
4960 }
4961 set descendent($a) 0
4962 set desc_todo $leftover
4963}
4964
4965proc is_ancestor {a} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004966 global curview parents ancestor anc_todo
Paul Mackerras164ff272006-05-29 19:50:02 +10004967
4968 set v $curview
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004969 set la [rowofcommit $a]
Paul Mackerras164ff272006-05-29 19:50:02 +10004970 set todo $anc_todo
4971 set leftover {}
4972 set done 0
4973 for {set i 0} {$i < [llength $todo]} {incr i} {
4974 set do [lindex $todo $i]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004975 if {![commitinview $do $v] || [rowofcommit $do] > $la} {
Paul Mackerras164ff272006-05-29 19:50:02 +10004976 lappend leftover $do
4977 continue
4978 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11004979 foreach np $parents($v,$do) {
Paul Mackerras164ff272006-05-29 19:50:02 +10004980 if {![info exists ancestor($np)]} {
4981 set ancestor($np) 1
4982 lappend todo $np
4983 if {$np eq $a} {
4984 set done 1
4985 }
4986 }
4987 }
4988 if {$done} {
4989 set anc_todo [concat $leftover [lrange $todo [expr {$i+1}] end]]
4990 return
4991 }
4992 }
4993 set ancestor($a) 0
4994 set anc_todo $leftover
4995}
4996
4997proc askrelhighlight {row id} {
Paul Mackerras9c311b32007-10-04 22:27:13 +10004998 global descendent highlight_related iddrawn rhighlights
Paul Mackerras164ff272006-05-29 19:50:02 +10004999 global selectedline ancestor
5000
Paul Mackerras94b4a692008-05-20 20:51:06 +10005001 if {$selectedline eq {}} return
Paul Mackerras164ff272006-05-29 19:50:02 +10005002 set isbold 0
Christian Stimming55e34432008-01-09 22:23:18 +01005003 if {$highlight_related eq [mc "Descendant"] ||
5004 $highlight_related eq [mc "Not descendant"]} {
Paul Mackerras164ff272006-05-29 19:50:02 +10005005 if {![info exists descendent($id)]} {
5006 is_descendent $id
5007 }
Christian Stimming55e34432008-01-09 22:23:18 +01005008 if {$descendent($id) == ($highlight_related eq [mc "Descendant"])} {
Paul Mackerras164ff272006-05-29 19:50:02 +10005009 set isbold 1
5010 }
Christian Stimmingb007ee22007-11-07 18:44:35 +01005011 } elseif {$highlight_related eq [mc "Ancestor"] ||
5012 $highlight_related eq [mc "Not ancestor"]} {
Paul Mackerras164ff272006-05-29 19:50:02 +10005013 if {![info exists ancestor($id)]} {
5014 is_ancestor $id
5015 }
Christian Stimmingb007ee22007-11-07 18:44:35 +01005016 if {$ancestor($id) == ($highlight_related eq [mc "Ancestor"])} {
Paul Mackerras164ff272006-05-29 19:50:02 +10005017 set isbold 1
5018 }
5019 }
5020 if {[info exists iddrawn($id)]} {
Paul Mackerras476ca632008-01-07 22:16:31 +11005021 if {$isbold && ![ishighlighted $id]} {
Paul Mackerras28593d32008-11-13 23:01:46 +11005022 bolden $id mainfontbold
Paul Mackerras164ff272006-05-29 19:50:02 +10005023 }
5024 }
Paul Mackerras476ca632008-01-07 22:16:31 +11005025 set rhighlights($id) $isbold
Paul Mackerras164ff272006-05-29 19:50:02 +10005026}
5027
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10005028# Graph layout functions
5029
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005030proc shortids {ids} {
5031 set res {}
5032 foreach id $ids {
5033 if {[llength $id] > 1} {
5034 lappend res [shortids $id]
5035 } elseif {[regexp {^[0-9a-f]{40}$} $id]} {
5036 lappend res [string range $id 0 7]
5037 } else {
5038 lappend res $id
5039 }
5040 }
5041 return $res
5042}
5043
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005044proc ntimes {n o} {
5045 set ret {}
Paul Mackerras03800812007-08-29 21:45:21 +10005046 set o [list $o]
5047 for {set mask 1} {$mask <= $n} {incr mask $mask} {
5048 if {($n & $mask) != 0} {
5049 set ret [concat $ret $o]
5050 }
5051 set o [concat $o $o]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005052 }
5053 return $ret
5054}
5055
Paul Mackerras9257d8f2007-12-11 10:45:38 +11005056proc ordertoken {id} {
5057 global ordertok curview varcid varcstart varctok curview parents children
5058 global nullid nullid2
5059
5060 if {[info exists ordertok($id)]} {
5061 return $ordertok($id)
5062 }
5063 set origid $id
5064 set todo {}
5065 while {1} {
5066 if {[info exists varcid($curview,$id)]} {
5067 set a $varcid($curview,$id)
5068 set p [lindex $varcstart($curview) $a]
5069 } else {
5070 set p [lindex $children($curview,$id) 0]
5071 }
5072 if {[info exists ordertok($p)]} {
5073 set tok $ordertok($p)
5074 break
5075 }
Paul Mackerrasc8c9f3d2008-01-06 13:54:58 +11005076 set id [first_real_child $curview,$p]
5077 if {$id eq {}} {
Paul Mackerras9257d8f2007-12-11 10:45:38 +11005078 # it's a root
Paul Mackerras46308ea2008-01-15 22:16:32 +11005079 set tok [lindex $varctok($curview) $varcid($curview,$p)]
Paul Mackerras9257d8f2007-12-11 10:45:38 +11005080 break
5081 }
Paul Mackerras9257d8f2007-12-11 10:45:38 +11005082 if {[llength $parents($curview,$id)] == 1} {
5083 lappend todo [list $p {}]
5084 } else {
5085 set j [lsearch -exact $parents($curview,$id) $p]
5086 if {$j < 0} {
5087 puts "oops didn't find [shortids $p] in parents of [shortids $id]"
5088 }
5089 lappend todo [list $p [strrep $j]]
5090 }
5091 }
5092 for {set i [llength $todo]} {[incr i -1] >= 0} {} {
5093 set p [lindex $todo $i 0]
5094 append tok [lindex $todo $i 1]
5095 set ordertok($p) $tok
5096 }
5097 set ordertok($origid) $tok
5098 return $tok
5099}
5100
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005101# Work out where id should go in idlist so that order-token
5102# values increase from left to right
5103proc idcol {idlist id {i 0}} {
Paul Mackerras9257d8f2007-12-11 10:45:38 +11005104 set t [ordertoken $id]
Paul Mackerrase5b37ac2007-12-12 18:13:51 +11005105 if {$i < 0} {
5106 set i 0
5107 }
Paul Mackerras9257d8f2007-12-11 10:45:38 +11005108 if {$i >= [llength $idlist] || $t < [ordertoken [lindex $idlist $i]]} {
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005109 if {$i > [llength $idlist]} {
5110 set i [llength $idlist]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005111 }
Paul Mackerras9257d8f2007-12-11 10:45:38 +11005112 while {[incr i -1] >= 0 && $t < [ordertoken [lindex $idlist $i]]} {}
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005113 incr i
5114 } else {
Paul Mackerras9257d8f2007-12-11 10:45:38 +11005115 if {$t > [ordertoken [lindex $idlist $i]]} {
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005116 while {[incr i] < [llength $idlist] &&
Paul Mackerras9257d8f2007-12-11 10:45:38 +11005117 $t >= [ordertoken [lindex $idlist $i]]} {}
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005118 }
5119 }
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005120 return $i
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005121}
5122
5123proc initlayout {} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005124 global rowidlist rowisopt rowfinal displayorder parentlist
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10005125 global numcommits canvxmax canv
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11005126 global nextcolor
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10005127 global colormap rowtextx
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005128
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11005129 set numcommits 0
5130 set displayorder {}
Paul Mackerras79b2c752006-04-02 20:47:40 +10005131 set parentlist {}
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11005132 set nextcolor 0
Paul Mackerras03800812007-08-29 21:45:21 +10005133 set rowidlist {}
5134 set rowisopt {}
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10005135 set rowfinal {}
Paul Mackerrasbe0cd092006-03-31 09:55:11 +11005136 set canvxmax [$canv cget -width]
Paul Mackerras50b44ec2006-04-04 10:16:22 +10005137 catch {unset colormap}
5138 catch {unset rowtextx}
Paul Mackerrasac1276a2008-03-03 10:11:08 +11005139 setcanvscroll
Paul Mackerrasbe0cd092006-03-31 09:55:11 +11005140}
5141
5142proc setcanvscroll {} {
5143 global canv canv2 canv3 numcommits linespc canvxmax canvy0
Paul Mackerrasac1276a2008-03-03 10:11:08 +11005144 global lastscrollset lastscrollrows
Paul Mackerrasbe0cd092006-03-31 09:55:11 +11005145
5146 set ymax [expr {$canvy0 + ($numcommits - 0.5) * $linespc + 2}]
5147 $canv conf -scrollregion [list 0 0 $canvxmax $ymax]
5148 $canv2 conf -scrollregion [list 0 0 0 $ymax]
5149 $canv3 conf -scrollregion [list 0 0 0 $ymax]
Paul Mackerrasac1276a2008-03-03 10:11:08 +11005150 set lastscrollset [clock clicks -milliseconds]
5151 set lastscrollrows $numcommits
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005152}
5153
5154proc visiblerows {} {
5155 global canv numcommits linespc
5156
5157 set ymax [lindex [$canv cget -scrollregion] 3]
5158 if {$ymax eq {} || $ymax == 0} return
5159 set f [$canv yview]
5160 set y0 [expr {int([lindex $f 0] * $ymax)}]
5161 set r0 [expr {int(($y0 - 3) / $linespc) - 1}]
5162 if {$r0 < 0} {
5163 set r0 0
5164 }
5165 set y1 [expr {int([lindex $f 1] * $ymax)}]
5166 set r1 [expr {int(($y1 - 3) / $linespc) + 1}]
5167 if {$r1 >= $numcommits} {
5168 set r1 [expr {$numcommits - 1}]
5169 }
5170 return [list $r0 $r1]
5171}
5172
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10005173proc layoutmore {} {
Paul Mackerras38dfe932007-12-06 20:50:31 +11005174 global commitidx viewcomplete curview
Paul Mackerras94b4a692008-05-20 20:51:06 +10005175 global numcommits pending_select curview
Paul Mackerrasd375ef92008-10-21 10:18:12 +11005176 global lastscrollset lastscrollrows
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005177
Paul Mackerrasac1276a2008-03-03 10:11:08 +11005178 if {$lastscrollrows < 100 || $viewcomplete($curview) ||
5179 [clock clicks -milliseconds] - $lastscrollset > 500} {
Paul Mackerrasa2c22362006-10-31 15:00:53 +11005180 setcanvscroll
5181 }
Paul Mackerrasd94f8cd2006-04-06 10:18:23 +10005182 if {[info exists pending_select] &&
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005183 [commitinview $pending_select $curview]} {
Alexander Gavrilov567c34e2008-07-26 20:13:45 +04005184 update
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005185 selectline [rowofcommit $pending_select] 1
Paul Mackerrasd94f8cd2006-04-06 10:18:23 +10005186 }
Paul Mackerrasac1276a2008-03-03 10:11:08 +11005187 drawvisible
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005188}
5189
Paul Mackerrascdc84292008-11-18 19:54:14 +11005190# With path limiting, we mightn't get the actual HEAD commit,
5191# so ask git rev-list what is the first ancestor of HEAD that
5192# touches a file in the path limit.
5193proc get_viewmainhead {view} {
5194 global viewmainheadid vfilelimit viewinstances mainheadid
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005195
Paul Mackerrascdc84292008-11-18 19:54:14 +11005196 catch {
5197 set rfd [open [concat | git rev-list -1 $mainheadid \
5198 -- $vfilelimit($view)] r]
5199 set j [reg_instance $rfd]
5200 lappend viewinstances($view) $j
5201 fconfigure $rfd -blocking 0
5202 filerun $rfd [list getviewhead $rfd $j $view]
5203 set viewmainheadid($curview) {}
5204 }
5205}
5206
5207# git rev-list should give us just 1 line to use as viewmainheadid($view)
5208proc getviewhead {fd inst view} {
5209 global viewmainheadid commfd curview viewinstances showlocalchanges
5210
5211 set id {}
5212 if {[gets $fd line] < 0} {
5213 if {![eof $fd]} {
5214 return 1
5215 }
5216 } elseif {[string length $line] == 40 && [string is xdigit $line]} {
5217 set id $line
5218 }
5219 set viewmainheadid($view) $id
5220 close $fd
5221 unset commfd($inst)
5222 set i [lsearch -exact $viewinstances($view) $inst]
5223 if {$i >= 0} {
5224 set viewinstances($view) [lreplace $viewinstances($view) $i $i]
5225 }
5226 if {$showlocalchanges && $id ne {} && $view == $curview} {
5227 doshowlocalchanges
5228 }
5229 return 0
5230}
5231
5232proc doshowlocalchanges {} {
5233 global curview viewmainheadid
5234
5235 if {$viewmainheadid($curview) eq {}} return
5236 if {[commitinview $viewmainheadid($curview) $curview]} {
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005237 dodiffindex
Paul Mackerras38dfe932007-12-06 20:50:31 +11005238 } else {
Paul Mackerrascdc84292008-11-18 19:54:14 +11005239 interestedin $viewmainheadid($curview) dodiffindex
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005240 }
5241}
5242
5243proc dohidelocalchanges {} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005244 global nullid nullid2 lserial curview
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005245
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005246 if {[commitinview $nullid $curview]} {
Paul Mackerrasb8a938c2008-02-13 22:12:31 +11005247 removefakerow $nullid
Paul Mackerras8f489362007-07-13 19:49:37 +10005248 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005249 if {[commitinview $nullid2 $curview]} {
Paul Mackerrasb8a938c2008-02-13 22:12:31 +11005250 removefakerow $nullid2
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005251 }
5252 incr lserial
5253}
5254
Paul Mackerras8f489362007-07-13 19:49:37 +10005255# spawn off a process to do git diff-index --cached HEAD
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005256proc dodiffindex {} {
Paul Mackerrascdc84292008-11-18 19:54:14 +11005257 global lserial showlocalchanges vfilelimit curview
Jens Lehmann17f98362014-04-08 21:36:08 +02005258 global hasworktree git_version
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005259
Martin von Zweigbergk74cb8842011-05-23 22:44:08 -04005260 if {!$showlocalchanges || !$hasworktree} return
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005261 incr lserial
Jens Lehmann17f98362014-04-08 21:36:08 +02005262 if {[package vcompare $git_version "1.7.2"] >= 0} {
5263 set cmd "|git diff-index --cached --ignore-submodules=dirty HEAD"
5264 } else {
5265 set cmd "|git diff-index --cached HEAD"
5266 }
Paul Mackerrascdc84292008-11-18 19:54:14 +11005267 if {$vfilelimit($curview) ne {}} {
5268 set cmd [concat $cmd -- $vfilelimit($curview)]
5269 }
5270 set fd [open $cmd r]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005271 fconfigure $fd -blocking 0
Alexander Gavrilove439e092008-07-13 16:40:47 +04005272 set i [reg_instance $fd]
5273 filerun $fd [list readdiffindex $fd $lserial $i]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005274}
5275
Alexander Gavrilove439e092008-07-13 16:40:47 +04005276proc readdiffindex {fd serial inst} {
Paul Mackerrascdc84292008-11-18 19:54:14 +11005277 global viewmainheadid nullid nullid2 curview commitinfo commitdata lserial
5278 global vfilelimit
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005279
Paul Mackerras8f489362007-07-13 19:49:37 +10005280 set isdiff 1
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005281 if {[gets $fd line] < 0} {
Paul Mackerras8f489362007-07-13 19:49:37 +10005282 if {![eof $fd]} {
5283 return 1
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005284 }
Paul Mackerras8f489362007-07-13 19:49:37 +10005285 set isdiff 0
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005286 }
5287 # we only need to see one line and we don't really care what it says...
Alexander Gavrilove439e092008-07-13 16:40:47 +04005288 stop_instance $inst
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005289
Paul Mackerras24f7a662007-12-19 09:35:33 +11005290 if {$serial != $lserial} {
5291 return 0
Paul Mackerras8f489362007-07-13 19:49:37 +10005292 }
5293
Paul Mackerras24f7a662007-12-19 09:35:33 +11005294 # now see if there are any local changes not checked in to the index
Paul Mackerrascdc84292008-11-18 19:54:14 +11005295 set cmd "|git diff-files"
5296 if {$vfilelimit($curview) ne {}} {
5297 set cmd [concat $cmd -- $vfilelimit($curview)]
5298 }
5299 set fd [open $cmd r]
Paul Mackerras24f7a662007-12-19 09:35:33 +11005300 fconfigure $fd -blocking 0
Alexander Gavrilove439e092008-07-13 16:40:47 +04005301 set i [reg_instance $fd]
5302 filerun $fd [list readdifffiles $fd $serial $i]
Paul Mackerras24f7a662007-12-19 09:35:33 +11005303
5304 if {$isdiff && ![commitinview $nullid2 $curview]} {
Paul Mackerras8f489362007-07-13 19:49:37 +10005305 # add the line for the changes in the index to the graph
Christian Stimmingd990ced2007-11-07 18:42:55 +01005306 set hl [mc "Local changes checked in to index but not committed"]
Paul Mackerras8f489362007-07-13 19:49:37 +10005307 set commitinfo($nullid2) [list $hl {} {} {} {} " $hl\n"]
5308 set commitdata($nullid2) "\n $hl\n"
Paul Mackerrasfc2a2562007-12-26 23:03:43 +11005309 if {[commitinview $nullid $curview]} {
Paul Mackerrasb8a938c2008-02-13 22:12:31 +11005310 removefakerow $nullid
Paul Mackerrasfc2a2562007-12-26 23:03:43 +11005311 }
Paul Mackerrascdc84292008-11-18 19:54:14 +11005312 insertfakerow $nullid2 $viewmainheadid($curview)
Paul Mackerras24f7a662007-12-19 09:35:33 +11005313 } elseif {!$isdiff && [commitinview $nullid2 $curview]} {
Paul Mackerrascdc84292008-11-18 19:54:14 +11005314 if {[commitinview $nullid $curview]} {
5315 removefakerow $nullid
5316 }
Paul Mackerrasb8a938c2008-02-13 22:12:31 +11005317 removefakerow $nullid2
Paul Mackerras8f489362007-07-13 19:49:37 +10005318 }
5319 return 0
5320}
5321
Alexander Gavrilove439e092008-07-13 16:40:47 +04005322proc readdifffiles {fd serial inst} {
Paul Mackerrascdc84292008-11-18 19:54:14 +11005323 global viewmainheadid nullid nullid2 curview
Paul Mackerras8f489362007-07-13 19:49:37 +10005324 global commitinfo commitdata lserial
5325
5326 set isdiff 1
5327 if {[gets $fd line] < 0} {
5328 if {![eof $fd]} {
5329 return 1
5330 }
5331 set isdiff 0
5332 }
5333 # we only need to see one line and we don't really care what it says...
Alexander Gavrilove439e092008-07-13 16:40:47 +04005334 stop_instance $inst
Paul Mackerras8f489362007-07-13 19:49:37 +10005335
Paul Mackerras24f7a662007-12-19 09:35:33 +11005336 if {$serial != $lserial} {
5337 return 0
5338 }
5339
5340 if {$isdiff && ![commitinview $nullid $curview]} {
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005341 # add the line for the local diff to the graph
Christian Stimmingd990ced2007-11-07 18:42:55 +01005342 set hl [mc "Local uncommitted changes, not checked in to index"]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005343 set commitinfo($nullid) [list $hl {} {} {} {} " $hl\n"]
5344 set commitdata($nullid) "\n $hl\n"
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005345 if {[commitinview $nullid2 $curview]} {
5346 set p $nullid2
5347 } else {
Paul Mackerrascdc84292008-11-18 19:54:14 +11005348 set p $viewmainheadid($curview)
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005349 }
Paul Mackerrasb8a938c2008-02-13 22:12:31 +11005350 insertfakerow $nullid $p
Paul Mackerras24f7a662007-12-19 09:35:33 +11005351 } elseif {!$isdiff && [commitinview $nullid $curview]} {
Paul Mackerrasb8a938c2008-02-13 22:12:31 +11005352 removefakerow $nullid
Paul Mackerras219ea3a2006-09-07 10:21:39 +10005353 }
5354 return 0
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005355}
5356
Paul Mackerras8f0bc7e2007-08-24 22:16:42 +10005357proc nextuse {id row} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005358 global curview children
Paul Mackerras8f0bc7e2007-08-24 22:16:42 +10005359
5360 if {[info exists children($curview,$id)]} {
5361 foreach kid $children($curview,$id) {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005362 if {![commitinview $kid $curview]} {
Paul Mackerras03800812007-08-29 21:45:21 +10005363 return -1
5364 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005365 if {[rowofcommit $kid] > $row} {
5366 return [rowofcommit $kid]
Paul Mackerras8f0bc7e2007-08-24 22:16:42 +10005367 }
5368 }
5369 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005370 if {[commitinview $id $curview]} {
5371 return [rowofcommit $id]
Paul Mackerras8f0bc7e2007-08-24 22:16:42 +10005372 }
5373 return -1
5374}
5375
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10005376proc prevuse {id row} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005377 global curview children
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10005378
5379 set ret -1
5380 if {[info exists children($curview,$id)]} {
5381 foreach kid $children($curview,$id) {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005382 if {![commitinview $kid $curview]} break
5383 if {[rowofcommit $kid] < $row} {
5384 set ret [rowofcommit $kid]
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10005385 }
5386 }
5387 }
5388 return $ret
5389}
5390
Paul Mackerras03800812007-08-29 21:45:21 +10005391proc make_idlist {row} {
5392 global displayorder parentlist uparrowlen downarrowlen mingaplen
Paul Mackerras9257d8f2007-12-11 10:45:38 +11005393 global commitidx curview children
Paul Mackerras03800812007-08-29 21:45:21 +10005394
5395 set r [expr {$row - $mingaplen - $downarrowlen - 1}]
5396 if {$r < 0} {
5397 set r 0
5398 }
5399 set ra [expr {$row - $downarrowlen}]
5400 if {$ra < 0} {
5401 set ra 0
5402 }
5403 set rb [expr {$row + $uparrowlen}]
5404 if {$rb > $commitidx($curview)} {
5405 set rb $commitidx($curview)
5406 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005407 make_disporder $r [expr {$rb + 1}]
Paul Mackerras03800812007-08-29 21:45:21 +10005408 set ids {}
5409 for {} {$r < $ra} {incr r} {
5410 set nextid [lindex $displayorder [expr {$r + 1}]]
5411 foreach p [lindex $parentlist $r] {
5412 if {$p eq $nextid} continue
5413 set rn [nextuse $p $r]
5414 if {$rn >= $row &&
5415 $rn <= $r + $downarrowlen + $mingaplen + $uparrowlen} {
Paul Mackerras9257d8f2007-12-11 10:45:38 +11005416 lappend ids [list [ordertoken $p] $p]
Paul Mackerras03800812007-08-29 21:45:21 +10005417 }
5418 }
5419 }
5420 for {} {$r < $row} {incr r} {
5421 set nextid [lindex $displayorder [expr {$r + 1}]]
5422 foreach p [lindex $parentlist $r] {
5423 if {$p eq $nextid} continue
5424 set rn [nextuse $p $r]
5425 if {$rn < 0 || $rn >= $row} {
Paul Mackerras9257d8f2007-12-11 10:45:38 +11005426 lappend ids [list [ordertoken $p] $p]
Paul Mackerras03800812007-08-29 21:45:21 +10005427 }
5428 }
5429 }
5430 set id [lindex $displayorder $row]
Paul Mackerras9257d8f2007-12-11 10:45:38 +11005431 lappend ids [list [ordertoken $id] $id]
Paul Mackerras03800812007-08-29 21:45:21 +10005432 while {$r < $rb} {
5433 foreach p [lindex $parentlist $r] {
5434 set firstkid [lindex $children($curview,$p) 0]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005435 if {[rowofcommit $firstkid] < $row} {
Paul Mackerras9257d8f2007-12-11 10:45:38 +11005436 lappend ids [list [ordertoken $p] $p]
Paul Mackerras03800812007-08-29 21:45:21 +10005437 }
5438 }
5439 incr r
5440 set id [lindex $displayorder $r]
5441 if {$id ne {}} {
5442 set firstkid [lindex $children($curview,$id) 0]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005443 if {$firstkid ne {} && [rowofcommit $firstkid] < $row} {
Paul Mackerras9257d8f2007-12-11 10:45:38 +11005444 lappend ids [list [ordertoken $id] $id]
Paul Mackerras03800812007-08-29 21:45:21 +10005445 }
5446 }
5447 }
5448 set idlist {}
5449 foreach idx [lsort -unique $ids] {
5450 lappend idlist [lindex $idx 1]
5451 }
5452 return $idlist
5453}
5454
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10005455proc rowsequal {a b} {
5456 while {[set i [lsearch -exact $a {}]] >= 0} {
5457 set a [lreplace $a $i $i]
5458 }
5459 while {[set i [lsearch -exact $b {}]] >= 0} {
5460 set b [lreplace $b $i $i]
5461 }
5462 return [expr {$a eq $b}]
5463}
5464
5465proc makeupline {id row rend col} {
5466 global rowidlist uparrowlen downarrowlen mingaplen
5467
5468 for {set r $rend} {1} {set r $rstart} {
5469 set rstart [prevuse $id $r]
5470 if {$rstart < 0} return
5471 if {$rstart < $row} break
5472 }
5473 if {$rstart + $uparrowlen + $mingaplen + $downarrowlen < $rend} {
5474 set rstart [expr {$rend - $uparrowlen - 1}]
5475 }
5476 for {set r $rstart} {[incr r] <= $row} {} {
5477 set idlist [lindex $rowidlist $r]
5478 if {$idlist ne {} && [lsearch -exact $idlist $id] < 0} {
5479 set col [idcol $idlist $id $col]
5480 lset rowidlist $r [linsert $idlist $col $id]
5481 changedrow $r
5482 }
5483 }
5484}
5485
Paul Mackerras03800812007-08-29 21:45:21 +10005486proc layoutrows {row endrow} {
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10005487 global rowidlist rowisopt rowfinal displayorder
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005488 global uparrowlen downarrowlen maxwidth mingaplen
Paul Mackerras6a90bff2007-06-18 09:48:23 +10005489 global children parentlist
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005490 global commitidx viewcomplete curview
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005491
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005492 make_disporder [expr {$row - 1}] [expr {$endrow + $uparrowlen}]
Paul Mackerras03800812007-08-29 21:45:21 +10005493 set idlist {}
5494 if {$row > 0} {
Paul Mackerrasf56782a2007-09-15 09:04:11 +10005495 set rm1 [expr {$row - 1}]
5496 foreach id [lindex $rowidlist $rm1] {
Paul Mackerras03800812007-08-29 21:45:21 +10005497 if {$id ne {}} {
5498 lappend idlist $id
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005499 }
5500 }
Paul Mackerrasf56782a2007-09-15 09:04:11 +10005501 set final [lindex $rowfinal $rm1]
Paul Mackerras8f0bc7e2007-08-24 22:16:42 +10005502 }
Paul Mackerras03800812007-08-29 21:45:21 +10005503 for {} {$row < $endrow} {incr row} {
5504 set rm1 [expr {$row - 1}]
Paul Mackerrasf56782a2007-09-15 09:04:11 +10005505 if {$rm1 < 0 || $idlist eq {}} {
Paul Mackerras03800812007-08-29 21:45:21 +10005506 set idlist [make_idlist $row]
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10005507 set final 1
Paul Mackerras03800812007-08-29 21:45:21 +10005508 } else {
5509 set id [lindex $displayorder $rm1]
5510 set col [lsearch -exact $idlist $id]
5511 set idlist [lreplace $idlist $col $col]
5512 foreach p [lindex $parentlist $rm1] {
5513 if {[lsearch -exact $idlist $p] < 0} {
5514 set col [idcol $idlist $p $col]
5515 set idlist [linsert $idlist $col $p]
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10005516 # if not the first child, we have to insert a line going up
5517 if {$id ne [lindex $children($curview,$p) 0]} {
5518 makeupline $p $rm1 $row $col
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005519 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005520 }
5521 }
Paul Mackerras03800812007-08-29 21:45:21 +10005522 set id [lindex $displayorder $row]
5523 if {$row > $downarrowlen} {
5524 set termrow [expr {$row - $downarrowlen - 1}]
5525 foreach p [lindex $parentlist $termrow] {
5526 set i [lsearch -exact $idlist $p]
5527 if {$i < 0} continue
5528 set nr [nextuse $p $termrow]
5529 if {$nr < 0 || $nr >= $row + $mingaplen + $uparrowlen} {
5530 set idlist [lreplace $idlist $i $i]
5531 }
5532 }
5533 }
5534 set col [lsearch -exact $idlist $id]
5535 if {$col < 0} {
5536 set col [idcol $idlist $id]
5537 set idlist [linsert $idlist $col $id]
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10005538 if {$children($curview,$id) ne {}} {
5539 makeupline $id $rm1 $row $col
5540 }
Paul Mackerras03800812007-08-29 21:45:21 +10005541 }
5542 set r [expr {$row + $uparrowlen - 1}]
5543 if {$r < $commitidx($curview)} {
5544 set x $col
5545 foreach p [lindex $parentlist $r] {
5546 if {[lsearch -exact $idlist $p] >= 0} continue
5547 set fk [lindex $children($curview,$p) 0]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005548 if {[rowofcommit $fk] < $row} {
Paul Mackerras03800812007-08-29 21:45:21 +10005549 set x [idcol $idlist $p $x]
5550 set idlist [linsert $idlist $x $p]
5551 }
5552 }
5553 if {[incr r] < $commitidx($curview)} {
5554 set p [lindex $displayorder $r]
5555 if {[lsearch -exact $idlist $p] < 0} {
5556 set fk [lindex $children($curview,$p) 0]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005557 if {$fk ne {} && [rowofcommit $fk] < $row} {
Paul Mackerras03800812007-08-29 21:45:21 +10005558 set x [idcol $idlist $p $x]
5559 set idlist [linsert $idlist $x $p]
5560 }
5561 }
5562 }
Paul Mackerras7b459a12007-08-13 14:52:00 +10005563 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005564 }
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10005565 if {$final && !$viewcomplete($curview) &&
5566 $row + $uparrowlen + $mingaplen + $downarrowlen
5567 >= $commitidx($curview)} {
5568 set final 0
Paul Mackerras7b459a12007-08-13 14:52:00 +10005569 }
Paul Mackerras03800812007-08-29 21:45:21 +10005570 set l [llength $rowidlist]
5571 if {$row == $l} {
5572 lappend rowidlist $idlist
5573 lappend rowisopt 0
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10005574 lappend rowfinal $final
Paul Mackerras03800812007-08-29 21:45:21 +10005575 } elseif {$row < $l} {
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10005576 if {![rowsequal $idlist [lindex $rowidlist $row]]} {
Paul Mackerras03800812007-08-29 21:45:21 +10005577 lset rowidlist $row $idlist
5578 changedrow $row
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005579 }
Paul Mackerrasf56782a2007-09-15 09:04:11 +10005580 lset rowfinal $row $final
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005581 } else {
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10005582 set pad [ntimes [expr {$row - $l}] {}]
5583 set rowidlist [concat $rowidlist $pad]
Paul Mackerras03800812007-08-29 21:45:21 +10005584 lappend rowidlist $idlist
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10005585 set rowfinal [concat $rowfinal $pad]
5586 lappend rowfinal $final
Paul Mackerras03800812007-08-29 21:45:21 +10005587 set rowisopt [concat $rowisopt [ntimes [expr {$row - $l + 1}] 0]]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005588 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005589 }
5590 return $row
5591}
5592
Paul Mackerras03800812007-08-29 21:45:21 +10005593proc changedrow {row} {
5594 global displayorder iddrawn rowisopt need_redisplay
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005595
Paul Mackerras03800812007-08-29 21:45:21 +10005596 set l [llength $rowisopt]
5597 if {$row < $l} {
5598 lset rowisopt $row 0
5599 if {$row + 1 < $l} {
5600 lset rowisopt [expr {$row + 1}] 0
5601 if {$row + 2 < $l} {
5602 lset rowisopt [expr {$row + 2}] 0
5603 }
5604 }
Paul Mackerras79b2c752006-04-02 20:47:40 +10005605 }
Paul Mackerras03800812007-08-29 21:45:21 +10005606 set id [lindex $displayorder $row]
5607 if {[info exists iddrawn($id)]} {
5608 set need_redisplay 1
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005609 }
5610}
5611
5612proc insert_pad {row col npad} {
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005613 global rowidlist
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005614
5615 set pad [ntimes $npad {}]
Paul Mackerrase341c062007-08-12 12:42:57 +10005616 set idlist [lindex $rowidlist $row]
5617 set bef [lrange $idlist 0 [expr {$col - 1}]]
5618 set aft [lrange $idlist $col end]
5619 set i [lsearch -exact $aft {}]
5620 if {$i > 0} {
5621 set aft [lreplace $aft $i $i]
5622 }
5623 lset rowidlist $row [concat $bef $pad $aft]
Paul Mackerras03800812007-08-29 21:45:21 +10005624 changedrow $row
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005625}
5626
5627proc optimize_rows {row col endrow} {
Paul Mackerras03800812007-08-29 21:45:21 +10005628 global rowidlist rowisopt displayorder curview children
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005629
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005630 if {$row < 1} {
5631 set row 1
5632 }
Paul Mackerras03800812007-08-29 21:45:21 +10005633 for {} {$row < $endrow} {incr row; set col 0} {
5634 if {[lindex $rowisopt $row]} continue
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005635 set haspad 0
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005636 set y0 [expr {$row - 1}]
5637 set ym [expr {$row - 2}]
Paul Mackerras03800812007-08-29 21:45:21 +10005638 set idlist [lindex $rowidlist $row]
5639 set previdlist [lindex $rowidlist $y0]
5640 if {$idlist eq {} || $previdlist eq {}} continue
5641 if {$ym >= 0} {
5642 set pprevidlist [lindex $rowidlist $ym]
5643 if {$pprevidlist eq {}} continue
5644 } else {
5645 set pprevidlist {}
5646 }
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005647 set x0 -1
5648 set xm -1
5649 for {} {$col < [llength $idlist]} {incr col} {
5650 set id [lindex $idlist $col]
5651 if {[lindex $previdlist $col] eq $id} continue
5652 if {$id eq {}} {
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005653 set haspad 1
5654 continue
5655 }
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005656 set x0 [lsearch -exact $previdlist $id]
5657 if {$x0 < 0} continue
5658 set z [expr {$x0 - $col}]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005659 set isarrow 0
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005660 set z0 {}
5661 if {$ym >= 0} {
5662 set xm [lsearch -exact $pprevidlist $id]
5663 if {$xm >= 0} {
5664 set z0 [expr {$xm - $x0}]
5665 }
5666 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005667 if {$z0 eq {}} {
Paul Mackerras92ed6662007-08-22 22:35:28 +10005668 # if row y0 is the first child of $id then it's not an arrow
5669 if {[lindex $children($curview,$id) 0] ne
5670 [lindex $displayorder $y0]} {
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005671 set isarrow 1
5672 }
5673 }
Paul Mackerrase341c062007-08-12 12:42:57 +10005674 if {!$isarrow && $id ne [lindex $displayorder $row] &&
5675 [lsearch -exact [lindex $rowidlist [expr {$row+1}]] $id] < 0} {
5676 set isarrow 1
5677 }
Paul Mackerras3fc42792006-09-15 09:45:23 +10005678 # Looking at lines from this row to the previous row,
5679 # make them go straight up if they end in an arrow on
5680 # the previous row; otherwise make them go straight up
5681 # or at 45 degrees.
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005682 if {$z < -1 || ($z < 0 && $isarrow)} {
Paul Mackerras3fc42792006-09-15 09:45:23 +10005683 # Line currently goes left too much;
5684 # insert pads in the previous row, then optimize it
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005685 set npad [expr {-1 - $z + $isarrow}]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005686 insert_pad $y0 $x0 $npad
5687 if {$y0 > 0} {
5688 optimize_rows $y0 $x0 $row
5689 }
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005690 set previdlist [lindex $rowidlist $y0]
5691 set x0 [lsearch -exact $previdlist $id]
5692 set z [expr {$x0 - $col}]
5693 if {$z0 ne {}} {
5694 set pprevidlist [lindex $rowidlist $ym]
5695 set xm [lsearch -exact $pprevidlist $id]
5696 set z0 [expr {$xm - $x0}]
5697 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005698 } elseif {$z > 1 || ($z > 0 && $isarrow)} {
Paul Mackerras3fc42792006-09-15 09:45:23 +10005699 # Line currently goes right too much;
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005700 # insert pads in this line
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005701 set npad [expr {$z - 1 + $isarrow}]
Paul Mackerrase341c062007-08-12 12:42:57 +10005702 insert_pad $row $col $npad
5703 set idlist [lindex $rowidlist $row]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005704 incr col $npad
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005705 set z [expr {$x0 - $col}]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005706 set haspad 1
5707 }
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005708 if {$z0 eq {} && !$isarrow && $ym >= 0} {
Paul Mackerraseb447a12006-03-18 23:11:37 +11005709 # this line links to its first child on row $row-2
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005710 set id [lindex $displayorder $ym]
5711 set xc [lsearch -exact $pprevidlist $id]
Paul Mackerraseb447a12006-03-18 23:11:37 +11005712 if {$xc >= 0} {
5713 set z0 [expr {$xc - $x0}]
5714 }
5715 }
Paul Mackerras3fc42792006-09-15 09:45:23 +10005716 # avoid lines jigging left then immediately right
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005717 if {$z0 ne {} && $z < 0 && $z0 > 0} {
5718 insert_pad $y0 $x0 1
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005719 incr x0
5720 optimize_rows $y0 $x0 $row
5721 set previdlist [lindex $rowidlist $y0]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005722 }
5723 }
5724 if {!$haspad} {
Paul Mackerras3fc42792006-09-15 09:45:23 +10005725 # Find the first column that doesn't have a line going right
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005726 for {set col [llength $idlist]} {[incr col -1] >= 0} {} {
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005727 set id [lindex $idlist $col]
5728 if {$id eq {}} break
5729 set x0 [lsearch -exact $previdlist $id]
5730 if {$x0 < 0} {
Paul Mackerraseb447a12006-03-18 23:11:37 +11005731 # check if this is the link to the first child
Paul Mackerras92ed6662007-08-22 22:35:28 +10005732 set kid [lindex $displayorder $y0]
5733 if {[lindex $children($curview,$id) 0] eq $kid} {
Paul Mackerraseb447a12006-03-18 23:11:37 +11005734 # it is, work out offset to child
Paul Mackerras92ed6662007-08-22 22:35:28 +10005735 set x0 [lsearch -exact $previdlist $kid]
Paul Mackerraseb447a12006-03-18 23:11:37 +11005736 }
5737 }
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005738 if {$x0 <= $col} break
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005739 }
Paul Mackerras3fc42792006-09-15 09:45:23 +10005740 # Insert a pad at that column as long as it has a line and
Paul Mackerras6e8c8702007-07-31 21:03:06 +10005741 # isn't the last column
5742 if {$x0 >= 0 && [incr col] < [llength $idlist]} {
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005743 set idlist [linsert $idlist $col {}]
Paul Mackerras03800812007-08-29 21:45:21 +10005744 lset rowidlist $row $idlist
5745 changedrow $row
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005746 }
5747 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005748 }
5749}
5750
5751proc xc {row col} {
5752 global canvx0 linespc
5753 return [expr {$canvx0 + $col * $linespc}]
5754}
5755
5756proc yc {row} {
5757 global canvy0 linespc
5758 return [expr {$canvy0 + $row * $linespc}]
5759}
5760
Paul Mackerrasc934a8a2006-03-02 23:00:44 +11005761proc linewidth {id} {
5762 global thickerline lthickness
5763
5764 set wid $lthickness
5765 if {[info exists thickerline] && $id eq $thickerline} {
5766 set wid [expr {2 * $lthickness}]
5767 }
5768 return $wid
5769}
5770
Paul Mackerras50b44ec2006-04-04 10:16:22 +10005771proc rowranges {id} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005772 global curview children uparrowlen downarrowlen
Paul Mackerras92ed6662007-08-22 22:35:28 +10005773 global rowidlist
Paul Mackerras50b44ec2006-04-04 10:16:22 +10005774
Paul Mackerras92ed6662007-08-22 22:35:28 +10005775 set kids $children($curview,$id)
5776 if {$kids eq {}} {
5777 return {}
Paul Mackerras50b44ec2006-04-04 10:16:22 +10005778 }
Paul Mackerras92ed6662007-08-22 22:35:28 +10005779 set ret {}
5780 lappend kids $id
5781 foreach child $kids {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005782 if {![commitinview $child $curview]} break
5783 set row [rowofcommit $child]
Paul Mackerras92ed6662007-08-22 22:35:28 +10005784 if {![info exists prev]} {
5785 lappend ret [expr {$row + 1}]
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005786 } else {
Paul Mackerras92ed6662007-08-22 22:35:28 +10005787 if {$row <= $prevrow} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005788 puts "oops children of [shortids $id] out of order [shortids $child] $row <= [shortids $prev] $prevrow"
Paul Mackerras92ed6662007-08-22 22:35:28 +10005789 }
5790 # see if the line extends the whole way from prevrow to row
5791 if {$row > $prevrow + $uparrowlen + $downarrowlen &&
5792 [lsearch -exact [lindex $rowidlist \
5793 [expr {int(($row + $prevrow) / 2)}]] $id] < 0} {
5794 # it doesn't, see where it ends
5795 set r [expr {$prevrow + $downarrowlen}]
5796 if {[lsearch -exact [lindex $rowidlist $r] $id] < 0} {
5797 while {[incr r -1] > $prevrow &&
5798 [lsearch -exact [lindex $rowidlist $r] $id] < 0} {}
5799 } else {
5800 while {[incr r] <= $row &&
5801 [lsearch -exact [lindex $rowidlist $r] $id] >= 0} {}
5802 incr r -1
5803 }
5804 lappend ret $r
5805 # see where it starts up again
5806 set r [expr {$row - $uparrowlen}]
5807 if {[lsearch -exact [lindex $rowidlist $r] $id] < 0} {
5808 while {[incr r] < $row &&
5809 [lsearch -exact [lindex $rowidlist $r] $id] < 0} {}
5810 } else {
5811 while {[incr r -1] >= $prevrow &&
5812 [lsearch -exact [lindex $rowidlist $r] $id] >= 0} {}
5813 incr r
5814 }
5815 lappend ret $r
5816 }
Paul Mackerraseb447a12006-03-18 23:11:37 +11005817 }
Paul Mackerras92ed6662007-08-22 22:35:28 +10005818 if {$child eq $id} {
5819 lappend ret $row
5820 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11005821 set prev $child
Paul Mackerras92ed6662007-08-22 22:35:28 +10005822 set prevrow $row
Paul Mackerraseb447a12006-03-18 23:11:37 +11005823 }
Paul Mackerras92ed6662007-08-22 22:35:28 +10005824 return $ret
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005825}
5826
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005827proc drawlineseg {id row endrow arrowlow} {
5828 global rowidlist displayorder iddrawn linesegs
Paul Mackerrase341c062007-08-12 12:42:57 +10005829 global canv colormap linespc curview maxlinelen parentlist
Paul Mackerras9f1afe02006-02-19 22:44:47 +11005830
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005831 set cols [list [lsearch -exact [lindex $rowidlist $row] $id]]
5832 set le [expr {$row + 1}]
5833 set arrowhigh 1
5834 while {1} {
5835 set c [lsearch -exact [lindex $rowidlist $le] $id]
5836 if {$c < 0} {
5837 incr le -1
5838 break
5839 }
5840 lappend cols $c
5841 set x [lindex $displayorder $le]
5842 if {$x eq $id} {
5843 set arrowhigh 0
5844 break
5845 }
5846 if {[info exists iddrawn($x)] || $le == $endrow} {
5847 set c [lsearch -exact [lindex $rowidlist [expr {$le+1}]] $id]
5848 if {$c >= 0} {
5849 lappend cols $c
5850 set arrowhigh 0
5851 }
5852 break
5853 }
5854 incr le
5855 }
5856 if {$le <= $row} {
5857 return $row
5858 }
5859
5860 set lines {}
5861 set i 0
5862 set joinhigh 0
5863 if {[info exists linesegs($id)]} {
5864 set lines $linesegs($id)
5865 foreach li $lines {
5866 set r0 [lindex $li 0]
5867 if {$r0 > $row} {
5868 if {$r0 == $le && [lindex $li 1] - $row <= $maxlinelen} {
5869 set joinhigh 1
5870 }
5871 break
5872 }
5873 incr i
5874 }
5875 }
5876 set joinlow 0
5877 if {$i > 0} {
5878 set li [lindex $lines [expr {$i-1}]]
5879 set r1 [lindex $li 1]
5880 if {$r1 == $row && $le - [lindex $li 0] <= $maxlinelen} {
5881 set joinlow 1
5882 }
5883 }
5884
5885 set x [lindex $cols [expr {$le - $row}]]
5886 set xp [lindex $cols [expr {$le - 1 - $row}]]
5887 set dir [expr {$xp - $x}]
5888 if {$joinhigh} {
5889 set ith [lindex $lines $i 2]
5890 set coords [$canv coords $ith]
5891 set ah [$canv itemcget $ith -arrow]
5892 set arrowhigh [expr {$ah eq "first" || $ah eq "both"}]
5893 set x2 [lindex $cols [expr {$le + 1 - $row}]]
5894 if {$x2 ne {} && $x - $x2 == $dir} {
5895 set coords [lrange $coords 0 end-2]
5896 }
5897 } else {
5898 set coords [list [xc $le $x] [yc $le]]
5899 }
5900 if {$joinlow} {
5901 set itl [lindex $lines [expr {$i-1}] 2]
5902 set al [$canv itemcget $itl -arrow]
5903 set arrowlow [expr {$al eq "last" || $al eq "both"}]
Paul Mackerrase341c062007-08-12 12:42:57 +10005904 } elseif {$arrowlow} {
5905 if {[lsearch -exact [lindex $rowidlist [expr {$row-1}]] $id] >= 0 ||
5906 [lsearch -exact [lindex $parentlist [expr {$row-1}]] $id] >= 0} {
5907 set arrowlow 0
5908 }
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005909 }
5910 set arrow [lindex {none first last both} [expr {$arrowhigh + 2*$arrowlow}]]
5911 for {set y $le} {[incr y -1] > $row} {} {
5912 set x $xp
5913 set xp [lindex $cols [expr {$y - 1 - $row}]]
5914 set ndir [expr {$xp - $x}]
5915 if {$dir != $ndir || $xp < 0} {
5916 lappend coords [xc $y $x] [yc $y]
5917 }
5918 set dir $ndir
5919 }
5920 if {!$joinlow} {
5921 if {$xp < 0} {
5922 # join parent line to first child
5923 set ch [lindex $displayorder $row]
5924 set xc [lsearch -exact [lindex $rowidlist $row] $ch]
5925 if {$xc < 0} {
5926 puts "oops: drawlineseg: child $ch not on row $row"
Paul Mackerrase341c062007-08-12 12:42:57 +10005927 } elseif {$xc != $x} {
5928 if {($arrowhigh && $le == $row + 1) || $dir == 0} {
5929 set d [expr {int(0.5 * $linespc)}]
5930 set x1 [xc $row $x]
5931 if {$xc < $x} {
5932 set x2 [expr {$x1 - $d}]
5933 } else {
5934 set x2 [expr {$x1 + $d}]
5935 }
5936 set y2 [yc $row]
5937 set y1 [expr {$y2 + $d}]
5938 lappend coords $x1 $y1 $x2 $y2
5939 } elseif {$xc < $x - 1} {
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005940 lappend coords [xc $row [expr {$x-1}]] [yc $row]
5941 } elseif {$xc > $x + 1} {
5942 lappend coords [xc $row [expr {$x+1}]] [yc $row]
5943 }
5944 set x $xc
5945 }
5946 lappend coords [xc $row $x] [yc $row]
5947 } else {
5948 set xn [xc $row $xp]
5949 set yn [yc $row]
Paul Mackerrase341c062007-08-12 12:42:57 +10005950 lappend coords $xn $yn
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005951 }
5952 if {!$joinhigh} {
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005953 assigncolor $id
5954 set t [$canv create line $coords -width [linewidth $id] \
5955 -fill $colormap($id) -tags lines.$id -arrow $arrow]
5956 $canv lower $t
5957 bindline $t $id
5958 set lines [linsert $lines $i [list $row $le $t]]
5959 } else {
5960 $canv coords $ith $coords
5961 if {$arrow ne $ah} {
5962 $canv itemconf $ith -arrow $arrow
5963 }
5964 lset lines $i 0 $row
5965 }
5966 } else {
5967 set xo [lsearch -exact [lindex $rowidlist [expr {$row - 1}]] $id]
5968 set ndir [expr {$xo - $xp}]
5969 set clow [$canv coords $itl]
5970 if {$dir == $ndir} {
5971 set clow [lrange $clow 2 end]
5972 }
5973 set coords [concat $coords $clow]
5974 if {!$joinhigh} {
5975 lset lines [expr {$i-1}] 1 $le
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005976 } else {
5977 # coalesce two pieces
5978 $canv delete $ith
5979 set b [lindex $lines [expr {$i-1}] 0]
5980 set e [lindex $lines $i 1]
5981 set lines [lreplace $lines [expr {$i-1}] $i [list $b $e $itl]]
5982 }
5983 $canv coords $itl $coords
5984 if {$arrow ne $al} {
5985 $canv itemconf $itl -arrow $arrow
5986 }
5987 }
5988
5989 set linesegs($id) $lines
5990 return $le
5991}
5992
5993proc drawparentlinks {id row} {
5994 global rowidlist canv colormap curview parentlist
Paul Mackerras513a54d2007-08-01 22:27:57 +10005995 global idpos linespc
Paul Mackerras322a8cc2006-10-15 18:03:46 +10005996
5997 set rowids [lindex $rowidlist $row]
5998 set col [lsearch -exact $rowids $id]
5999 if {$col < 0} return
6000 set olds [lindex $parentlist $row]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006001 set row2 [expr {$row + 1}]
6002 set x [xc $row $col]
6003 set y [yc $row]
6004 set y2 [yc $row2]
Paul Mackerrase341c062007-08-12 12:42:57 +10006005 set d [expr {int(0.5 * $linespc)}]
Paul Mackerras513a54d2007-08-01 22:27:57 +10006006 set ymid [expr {$y + $d}]
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11006007 set ids [lindex $rowidlist $row2]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006008 # rmx = right-most X coord used
6009 set rmx 0
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006010 foreach p $olds {
Paul Mackerrasf3408442006-03-31 09:54:24 +11006011 set i [lsearch -exact $ids $p]
6012 if {$i < 0} {
6013 puts "oops, parent $p of $id not in list"
6014 continue
6015 }
6016 set x2 [xc $row2 $i]
6017 if {$x2 > $rmx} {
6018 set rmx $x2
6019 }
Paul Mackerras513a54d2007-08-01 22:27:57 +10006020 set j [lsearch -exact $rowids $p]
6021 if {$j < 0} {
Paul Mackerraseb447a12006-03-18 23:11:37 +11006022 # drawlineseg will do this one for us
6023 continue
6024 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006025 assigncolor $p
6026 # should handle duplicated parents here...
6027 set coords [list $x $y]
Paul Mackerras513a54d2007-08-01 22:27:57 +10006028 if {$i != $col} {
6029 # if attaching to a vertical segment, draw a smaller
6030 # slant for visual distinctness
6031 if {$i == $j} {
6032 if {$i < $col} {
6033 lappend coords [expr {$x2 + $d}] $y $x2 $ymid
6034 } else {
6035 lappend coords [expr {$x2 - $d}] $y $x2 $ymid
6036 }
6037 } elseif {$i < $col && $i < $j} {
6038 # segment slants towards us already
6039 lappend coords [xc $row $j] $y
6040 } else {
6041 if {$i < $col - 1} {
6042 lappend coords [expr {$x2 + $linespc}] $y
6043 } elseif {$i > $col + 1} {
6044 lappend coords [expr {$x2 - $linespc}] $y
6045 }
6046 lappend coords $x2 $y2
6047 }
6048 } else {
6049 lappend coords $x2 $y2
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006050 }
Paul Mackerrasc934a8a2006-03-02 23:00:44 +11006051 set t [$canv create line $coords -width [linewidth $p] \
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006052 -fill $colormap($p) -tags lines.$p]
6053 $canv lower $t
6054 bindline $t $p
6055 }
Paul Mackerras322a8cc2006-10-15 18:03:46 +10006056 if {$rmx > [lindex $idpos($id) 1]} {
6057 lset idpos($id) 1 $rmx
6058 redrawtags $id
6059 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006060}
6061
Paul Mackerrasc934a8a2006-03-02 23:00:44 +11006062proc drawlines {id} {
Paul Mackerras322a8cc2006-10-15 18:03:46 +10006063 global canv
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006064
Paul Mackerras322a8cc2006-10-15 18:03:46 +10006065 $canv itemconf lines.$id -width [linewidth $id]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006066}
6067
Paul Mackerras322a8cc2006-10-15 18:03:46 +10006068proc drawcmittext {id row col} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11006069 global linespc canv canv2 canv3 fgcolor curview
6070 global cmitlisted commitinfo rowidlist parentlist
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006071 global rowtextx idpos idtags idheads idotherrefs
Paul Mackerras03800812007-08-29 21:45:21 +10006072 global linehtag linentag linedtag selectedline
Paul Mackerrasb9fdba72009-04-09 09:34:46 +10006073 global canvxmax boldids boldnameids fgcolor markedid
Paul Mackerrasd277e892008-09-21 18:11:37 -05006074 global mainheadid nullid nullid2 circleitem circlecolors ctxbut
Gauthier Östervall252c52d2013-03-27 14:40:51 +01006075 global mainheadcirclecolor workingfilescirclecolor indexcirclecolor
6076 global circleoutlinecolor
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006077
Linus Torvalds1407ade2008-02-09 14:02:07 -08006078 # listed is 0 for boundary, 1 for normal, 2 for negative, 3 for left, 4 for right
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11006079 set listed $cmitlisted($curview,$id)
Paul Mackerras219ea3a2006-09-07 10:21:39 +10006080 if {$id eq $nullid} {
Gauthier Östervall252c52d2013-03-27 14:40:51 +01006081 set ofill $workingfilescirclecolor
Paul Mackerras8f489362007-07-13 19:49:37 +10006082 } elseif {$id eq $nullid2} {
Gauthier Östervall252c52d2013-03-27 14:40:51 +01006083 set ofill $indexcirclecolor
Paul Mackerrasc11ff122008-05-26 10:11:33 +10006084 } elseif {$id eq $mainheadid} {
Gauthier Östervall252c52d2013-03-27 14:40:51 +01006085 set ofill $mainheadcirclecolor
Paul Mackerras219ea3a2006-09-07 10:21:39 +10006086 } else {
Paul Mackerrasc11ff122008-05-26 10:11:33 +10006087 set ofill [lindex $circlecolors $listed]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10006088 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006089 set x [xc $row $col]
6090 set y [yc $row]
6091 set orad [expr {$linespc / 3}]
Linus Torvalds1407ade2008-02-09 14:02:07 -08006092 if {$listed <= 2} {
Paul Mackerrasc961b222007-07-09 22:45:47 +10006093 set t [$canv create oval [expr {$x - $orad}] [expr {$y - $orad}] \
6094 [expr {$x + $orad - 1}] [expr {$y + $orad - 1}] \
Gauthier Östervall252c52d2013-03-27 14:40:51 +01006095 -fill $ofill -outline $circleoutlinecolor -width 1 -tags circle]
Linus Torvalds1407ade2008-02-09 14:02:07 -08006096 } elseif {$listed == 3} {
Paul Mackerrasc961b222007-07-09 22:45:47 +10006097 # triangle pointing left for left-side commits
6098 set t [$canv create polygon \
6099 [expr {$x - $orad}] $y \
6100 [expr {$x + $orad - 1}] [expr {$y - $orad}] \
6101 [expr {$x + $orad - 1}] [expr {$y + $orad - 1}] \
Gauthier Östervall252c52d2013-03-27 14:40:51 +01006102 -fill $ofill -outline $circleoutlinecolor -width 1 -tags circle]
Paul Mackerrasc961b222007-07-09 22:45:47 +10006103 } else {
6104 # triangle pointing right for right-side commits
6105 set t [$canv create polygon \
6106 [expr {$x + $orad - 1}] $y \
6107 [expr {$x - $orad}] [expr {$y - $orad}] \
6108 [expr {$x - $orad}] [expr {$y + $orad - 1}] \
Gauthier Östervall252c52d2013-03-27 14:40:51 +01006109 -fill $ofill -outline $circleoutlinecolor -width 1 -tags circle]
Paul Mackerrasc961b222007-07-09 22:45:47 +10006110 }
Paul Mackerrasc11ff122008-05-26 10:11:33 +10006111 set circleitem($row) $t
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006112 $canv raise $t
6113 $canv bind $t <1> {selcanvline {} %x %y}
Paul Mackerras322a8cc2006-10-15 18:03:46 +10006114 set rmx [llength [lindex $rowidlist $row]]
6115 set olds [lindex $parentlist $row]
6116 if {$olds ne {}} {
6117 set nextids [lindex $rowidlist [expr {$row + 1}]]
6118 foreach p $olds {
6119 set i [lsearch -exact $nextids $p]
6120 if {$i > $rmx} {
6121 set rmx $i
6122 }
6123 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006124 }
Paul Mackerras322a8cc2006-10-15 18:03:46 +10006125 set xt [xc $row $rmx]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006126 set rowtextx($row) $xt
6127 set idpos($id) [list $x $xt $y]
6128 if {[info exists idtags($id)] || [info exists idheads($id)]
6129 || [info exists idotherrefs($id)]} {
6130 set xt [drawtags $id $x $xt $y]
6131 }
Raphael Zimmerer36242492011-04-19 22:37:09 +02006132 if {[lindex $commitinfo($id) 6] > 0} {
6133 set xt [drawnotesign $xt $y]
6134 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006135 set headline [lindex $commitinfo($id) 0]
6136 set name [lindex $commitinfo($id) 1]
6137 set date [lindex $commitinfo($id) 2]
6138 set date [formatdate $date]
Paul Mackerras9c311b32007-10-04 22:27:13 +10006139 set font mainfont
6140 set nfont mainfont
Paul Mackerras476ca632008-01-07 22:16:31 +11006141 set isbold [ishighlighted $id]
Paul Mackerras908c3582006-05-20 09:38:11 +10006142 if {$isbold > 0} {
Paul Mackerras28593d32008-11-13 23:01:46 +11006143 lappend boldids $id
Paul Mackerras9c311b32007-10-04 22:27:13 +10006144 set font mainfontbold
Paul Mackerras908c3582006-05-20 09:38:11 +10006145 if {$isbold > 1} {
Paul Mackerras28593d32008-11-13 23:01:46 +11006146 lappend boldnameids $id
Paul Mackerras9c311b32007-10-04 22:27:13 +10006147 set nfont mainfontbold
Paul Mackerras908c3582006-05-20 09:38:11 +10006148 }
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10006149 }
Paul Mackerras28593d32008-11-13 23:01:46 +11006150 set linehtag($id) [$canv create text $xt $y -anchor w -fill $fgcolor \
6151 -text $headline -font $font -tags text]
6152 $canv bind $linehtag($id) $ctxbut "rowmenu %X %Y $id"
6153 set linentag($id) [$canv2 create text 3 $y -anchor w -fill $fgcolor \
6154 -text $name -font $nfont -tags text]
6155 set linedtag($id) [$canv3 create text 3 $y -anchor w -fill $fgcolor \
6156 -text $date -font mainfont -tags text]
Paul Mackerras94b4a692008-05-20 20:51:06 +10006157 if {$selectedline == $row} {
Paul Mackerras28593d32008-11-13 23:01:46 +11006158 make_secsel $id
Paul Mackerras03800812007-08-29 21:45:21 +10006159 }
Paul Mackerrasb9fdba72009-04-09 09:34:46 +10006160 if {[info exists markedid] && $markedid eq $id} {
6161 make_idmark $id
6162 }
Paul Mackerras9c311b32007-10-04 22:27:13 +10006163 set xr [expr {$xt + [font measure $font $headline]}]
Paul Mackerrasbe0cd092006-03-31 09:55:11 +11006164 if {$xr > $canvxmax} {
6165 set canvxmax $xr
6166 setcanvscroll
6167 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006168}
6169
6170proc drawcmitrow {row} {
Paul Mackerras03800812007-08-29 21:45:21 +10006171 global displayorder rowidlist nrows_drawn
Paul Mackerras005a2f42007-07-26 22:36:39 +10006172 global iddrawn markingmatches
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11006173 global commitinfo numcommits
Paul Mackerras687c8762007-09-22 12:49:33 +10006174 global filehighlight fhighlights findpattern nhighlights
Paul Mackerras908c3582006-05-20 09:38:11 +10006175 global hlview vhighlights
Paul Mackerras164ff272006-05-29 19:50:02 +10006176 global highlight_related rhighlights
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006177
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11006178 if {$row >= $numcommits} return
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006179
6180 set id [lindex $displayorder $row]
Paul Mackerras476ca632008-01-07 22:16:31 +11006181 if {[info exists hlview] && ![info exists vhighlights($id)]} {
Paul Mackerras908c3582006-05-20 09:38:11 +10006182 askvhighlight $row $id
6183 }
Paul Mackerras476ca632008-01-07 22:16:31 +11006184 if {[info exists filehighlight] && ![info exists fhighlights($id)]} {
Paul Mackerras908c3582006-05-20 09:38:11 +10006185 askfilehighlight $row $id
6186 }
Paul Mackerras476ca632008-01-07 22:16:31 +11006187 if {$findpattern ne {} && ![info exists nhighlights($id)]} {
Paul Mackerras60f7a7d2006-05-26 10:43:47 +10006188 askfindhighlight $row $id
Paul Mackerras908c3582006-05-20 09:38:11 +10006189 }
Paul Mackerras476ca632008-01-07 22:16:31 +11006190 if {$highlight_related ne [mc "None"] && ![info exists rhighlights($id)]} {
Paul Mackerras164ff272006-05-29 19:50:02 +10006191 askrelhighlight $row $id
6192 }
Paul Mackerras005a2f42007-07-26 22:36:39 +10006193 if {![info exists iddrawn($id)]} {
6194 set col [lsearch -exact [lindex $rowidlist $row] $id]
6195 if {$col < 0} {
6196 puts "oops, row $row id $id not in list"
6197 return
6198 }
6199 if {![info exists commitinfo($id)]} {
6200 getcommit $id
6201 }
6202 assigncolor $id
6203 drawcmittext $id $row $col
6204 set iddrawn($id) 1
Paul Mackerras03800812007-08-29 21:45:21 +10006205 incr nrows_drawn
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006206 }
Paul Mackerras005a2f42007-07-26 22:36:39 +10006207 if {$markingmatches} {
6208 markrowmatches $row $id
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006209 }
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006210}
6211
Paul Mackerras322a8cc2006-10-15 18:03:46 +10006212proc drawcommits {row {endrow {}}} {
Paul Mackerras03800812007-08-29 21:45:21 +10006213 global numcommits iddrawn displayorder curview need_redisplay
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10006214 global parentlist rowidlist rowfinal uparrowlen downarrowlen nrows_drawn
Paul Mackerras322a8cc2006-10-15 18:03:46 +10006215
6216 if {$row < 0} {
6217 set row 0
6218 }
6219 if {$endrow eq {}} {
6220 set endrow $row
6221 }
6222 if {$endrow >= $numcommits} {
6223 set endrow [expr {$numcommits - 1}]
6224 }
6225
Paul Mackerras03800812007-08-29 21:45:21 +10006226 set rl1 [expr {$row - $downarrowlen - 3}]
6227 if {$rl1 < 0} {
6228 set rl1 0
6229 }
6230 set ro1 [expr {$row - 3}]
6231 if {$ro1 < 0} {
6232 set ro1 0
6233 }
6234 set r2 [expr {$endrow + $uparrowlen + 3}]
6235 if {$r2 > $numcommits} {
6236 set r2 $numcommits
6237 }
6238 for {set r $rl1} {$r < $r2} {incr r} {
Paul Mackerrasf5f3c2e2007-09-05 02:19:56 +10006239 if {[lindex $rowidlist $r] ne {} && [lindex $rowfinal $r]} {
Paul Mackerras03800812007-08-29 21:45:21 +10006240 if {$rl1 < $r} {
6241 layoutrows $rl1 $r
6242 }
6243 set rl1 [expr {$r + 1}]
6244 }
6245 }
6246 if {$rl1 < $r} {
6247 layoutrows $rl1 $r
6248 }
6249 optimize_rows $ro1 0 $r2
6250 if {$need_redisplay || $nrows_drawn > 2000} {
6251 clear_display
Paul Mackerras03800812007-08-29 21:45:21 +10006252 }
6253
Paul Mackerras322a8cc2006-10-15 18:03:46 +10006254 # make the lines join to already-drawn rows either side
6255 set r [expr {$row - 1}]
6256 if {$r < 0 || ![info exists iddrawn([lindex $displayorder $r])]} {
6257 set r $row
6258 }
6259 set er [expr {$endrow + 1}]
6260 if {$er >= $numcommits ||
6261 ![info exists iddrawn([lindex $displayorder $er])]} {
6262 set er $endrow
6263 }
6264 for {} {$r <= $er} {incr r} {
6265 set id [lindex $displayorder $r]
6266 set wasdrawn [info exists iddrawn($id)]
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006267 drawcmitrow $r
Paul Mackerras322a8cc2006-10-15 18:03:46 +10006268 if {$r == $er} break
6269 set nextid [lindex $displayorder [expr {$r + 1}]]
Paul Mackerrase5ef6f92007-10-21 12:58:42 +10006270 if {$wasdrawn && [info exists iddrawn($nextid)]} continue
Paul Mackerras322a8cc2006-10-15 18:03:46 +10006271 drawparentlinks $id $r
6272
Paul Mackerras322a8cc2006-10-15 18:03:46 +10006273 set rowids [lindex $rowidlist $r]
6274 foreach lid $rowids {
6275 if {$lid eq {}} continue
Paul Mackerrase5ef6f92007-10-21 12:58:42 +10006276 if {[info exists lineend($lid)] && $lineend($lid) > $r} continue
Paul Mackerras322a8cc2006-10-15 18:03:46 +10006277 if {$lid eq $id} {
6278 # see if this is the first child of any of its parents
6279 foreach p [lindex $parentlist $r] {
6280 if {[lsearch -exact $rowids $p] < 0} {
6281 # make this line extend up to the child
Paul Mackerrase5ef6f92007-10-21 12:58:42 +10006282 set lineend($p) [drawlineseg $p $r $er 0]
Paul Mackerras322a8cc2006-10-15 18:03:46 +10006283 }
6284 }
Paul Mackerrase5ef6f92007-10-21 12:58:42 +10006285 } else {
6286 set lineend($lid) [drawlineseg $lid $r $er 1]
Paul Mackerras322a8cc2006-10-15 18:03:46 +10006287 }
6288 }
6289 }
6290}
6291
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11006292proc undolayout {row} {
6293 global uparrowlen mingaplen downarrowlen
6294 global rowidlist rowisopt rowfinal need_redisplay
6295
6296 set r [expr {$row - ($uparrowlen + $mingaplen + $downarrowlen)}]
6297 if {$r < 0} {
6298 set r 0
6299 }
6300 if {[llength $rowidlist] > $r} {
6301 incr r -1
6302 set rowidlist [lrange $rowidlist 0 $r]
6303 set rowfinal [lrange $rowfinal 0 $r]
6304 set rowisopt [lrange $rowisopt 0 $r]
6305 set need_redisplay 1
6306 run drawvisible
6307 }
6308}
6309
Paul Mackerras31c0eaa2007-12-30 22:41:14 +11006310proc drawvisible {} {
6311 global canv linespc curview vrowmod selectedline targetrow targetid
Paul Mackerras42a671f2008-01-02 09:59:39 +11006312 global need_redisplay cscroll numcommits
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006313
Paul Mackerras31c0eaa2007-12-30 22:41:14 +11006314 set fs [$canv yview]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006315 set ymax [lindex [$canv cget -scrollregion] 3]
Paul Mackerras5a7f5772008-01-15 22:45:36 +11006316 if {$ymax eq {} || $ymax == 0 || $numcommits == 0} return
Paul Mackerras31c0eaa2007-12-30 22:41:14 +11006317 set f0 [lindex $fs 0]
6318 set f1 [lindex $fs 1]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006319 set y0 [expr {int($f0 * $ymax)}]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006320 set y1 [expr {int($f1 * $ymax)}]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006321
Paul Mackerras31c0eaa2007-12-30 22:41:14 +11006322 if {[info exists targetid]} {
Paul Mackerras42a671f2008-01-02 09:59:39 +11006323 if {[commitinview $targetid $curview]} {
6324 set r [rowofcommit $targetid]
6325 if {$r != $targetrow} {
6326 # Fix up the scrollregion and change the scrolling position
6327 # now that our target row has moved.
6328 set diff [expr {($r - $targetrow) * $linespc}]
6329 set targetrow $r
6330 setcanvscroll
6331 set ymax [lindex [$canv cget -scrollregion] 3]
6332 incr y0 $diff
6333 incr y1 $diff
6334 set f0 [expr {$y0 / $ymax}]
6335 set f1 [expr {$y1 / $ymax}]
6336 allcanvs yview moveto $f0
6337 $cscroll set $f0 $f1
6338 set need_redisplay 1
6339 }
6340 } else {
6341 unset targetid
Paul Mackerras31c0eaa2007-12-30 22:41:14 +11006342 }
6343 }
6344
6345 set row [expr {int(($y0 - 3) / $linespc) - 1}]
6346 set endrow [expr {int(($y1 - 3) / $linespc) + 1}]
6347 if {$endrow >= $vrowmod($curview)} {
6348 update_arcrows $curview
6349 }
Paul Mackerras94b4a692008-05-20 20:51:06 +10006350 if {$selectedline ne {} &&
Paul Mackerras31c0eaa2007-12-30 22:41:14 +11006351 $row <= $selectedline && $selectedline <= $endrow} {
6352 set targetrow $selectedline
Paul Mackerrasac1276a2008-03-03 10:11:08 +11006353 } elseif {[info exists targetid]} {
Paul Mackerras31c0eaa2007-12-30 22:41:14 +11006354 set targetrow [expr {int(($row + $endrow) / 2)}]
6355 }
Paul Mackerrasac1276a2008-03-03 10:11:08 +11006356 if {[info exists targetrow]} {
6357 if {$targetrow >= $numcommits} {
6358 set targetrow [expr {$numcommits - 1}]
6359 }
6360 set targetid [commitonrow $targetrow]
Paul Mackerras42a671f2008-01-02 09:59:39 +11006361 }
Paul Mackerras31c0eaa2007-12-30 22:41:14 +11006362 drawcommits $row $endrow
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006363}
6364
6365proc clear_display {} {
Paul Mackerras03800812007-08-29 21:45:21 +10006366 global iddrawn linesegs need_redisplay nrows_drawn
Paul Mackerras164ff272006-05-29 19:50:02 +10006367 global vhighlights fhighlights nhighlights rhighlights
Paul Mackerras28593d32008-11-13 23:01:46 +11006368 global linehtag linentag linedtag boldids boldnameids
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006369
6370 allcanvs delete all
6371 catch {unset iddrawn}
Paul Mackerras322a8cc2006-10-15 18:03:46 +10006372 catch {unset linesegs}
Paul Mackerras94503a62008-05-19 09:48:45 +10006373 catch {unset linehtag}
6374 catch {unset linentag}
6375 catch {unset linedtag}
Paul Mackerras28593d32008-11-13 23:01:46 +11006376 set boldids {}
6377 set boldnameids {}
Paul Mackerras908c3582006-05-20 09:38:11 +10006378 catch {unset vhighlights}
6379 catch {unset fhighlights}
6380 catch {unset nhighlights}
Paul Mackerras164ff272006-05-29 19:50:02 +10006381 catch {unset rhighlights}
Paul Mackerras03800812007-08-29 21:45:21 +10006382 set need_redisplay 0
6383 set nrows_drawn 0
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006384}
6385
Paul Mackerras50b44ec2006-04-04 10:16:22 +10006386proc findcrossings {id} {
Paul Mackerras6e8c8702007-07-31 21:03:06 +10006387 global rowidlist parentlist numcommits displayorder
Paul Mackerras50b44ec2006-04-04 10:16:22 +10006388
6389 set cross {}
6390 set ccross {}
6391 foreach {s e} [rowranges $id] {
6392 if {$e >= $numcommits} {
6393 set e [expr {$numcommits - 1}]
Paul Mackerras50b44ec2006-04-04 10:16:22 +10006394 }
Paul Mackerrasd94f8cd2006-04-06 10:18:23 +10006395 if {$e <= $s} continue
Paul Mackerras50b44ec2006-04-04 10:16:22 +10006396 for {set row $e} {[incr row -1] >= $s} {} {
Paul Mackerras6e8c8702007-07-31 21:03:06 +10006397 set x [lsearch -exact [lindex $rowidlist $row] $id]
6398 if {$x < 0} break
Paul Mackerras50b44ec2006-04-04 10:16:22 +10006399 set olds [lindex $parentlist $row]
6400 set kid [lindex $displayorder $row]
6401 set kidx [lsearch -exact [lindex $rowidlist $row] $kid]
6402 if {$kidx < 0} continue
6403 set nextrow [lindex $rowidlist [expr {$row + 1}]]
6404 foreach p $olds {
6405 set px [lsearch -exact $nextrow $p]
6406 if {$px < 0} continue
6407 if {($kidx < $x && $x < $px) || ($px < $x && $x < $kidx)} {
6408 if {[lsearch -exact $ccross $p] >= 0} continue
6409 if {$x == $px + ($kidx < $px? -1: 1)} {
6410 lappend ccross $p
6411 } elseif {[lsearch -exact $cross $p] < 0} {
6412 lappend cross $p
6413 }
6414 }
6415 }
Paul Mackerras50b44ec2006-04-04 10:16:22 +10006416 }
6417 }
6418 return [concat $ccross {{}} $cross]
6419}
6420
Paul Mackerrase5c2d852005-05-11 23:44:54 +00006421proc assigncolor {id} {
Paul Mackerrasaa81d972006-02-28 11:27:12 +11006422 global colormap colors nextcolor
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11006423 global parents children children curview
Paul Mackerras6c20ff32005-06-22 19:53:32 +10006424
Paul Mackerras418c4c72006-02-07 09:10:18 +11006425 if {[info exists colormap($id)]} return
Paul Mackerrase5c2d852005-05-11 23:44:54 +00006426 set ncolors [llength $colors]
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10006427 if {[info exists children($curview,$id)]} {
6428 set kids $children($curview,$id)
Paul Mackerras79b2c752006-04-02 20:47:40 +10006429 } else {
6430 set kids {}
6431 }
6432 if {[llength $kids] == 1} {
6433 set child [lindex $kids 0]
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +00006434 if {[info exists colormap($child)]
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11006435 && [llength $parents($curview,$child)] == 1} {
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +00006436 set colormap($id) $colormap($child)
6437 return
Paul Mackerrase5c2d852005-05-11 23:44:54 +00006438 }
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +00006439 }
6440 set badcolors {}
Paul Mackerras50b44ec2006-04-04 10:16:22 +10006441 set origbad {}
6442 foreach x [findcrossings $id] {
6443 if {$x eq {}} {
6444 # delimiter between corner crossings and other crossings
6445 if {[llength $badcolors] >= $ncolors - 1} break
6446 set origbad $badcolors
Paul Mackerrase5c2d852005-05-11 23:44:54 +00006447 }
Paul Mackerras50b44ec2006-04-04 10:16:22 +10006448 if {[info exists colormap($x)]
6449 && [lsearch -exact $badcolors $colormap($x)] < 0} {
6450 lappend badcolors $colormap($x)
Paul Mackerras6c20ff32005-06-22 19:53:32 +10006451 }
6452 }
Paul Mackerras50b44ec2006-04-04 10:16:22 +10006453 if {[llength $badcolors] >= $ncolors} {
6454 set badcolors $origbad
6455 }
Paul Mackerras6c20ff32005-06-22 19:53:32 +10006456 set origbad $badcolors
6457 if {[llength $badcolors] < $ncolors - 1} {
Paul Mackerras79b2c752006-04-02 20:47:40 +10006458 foreach child $kids {
Paul Mackerras6c20ff32005-06-22 19:53:32 +10006459 if {[info exists colormap($child)]
6460 && [lsearch -exact $badcolors $colormap($child)] < 0} {
6461 lappend badcolors $colormap($child)
6462 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11006463 foreach p $parents($curview,$child) {
Paul Mackerras79b2c752006-04-02 20:47:40 +10006464 if {[info exists colormap($p)]
6465 && [lsearch -exact $badcolors $colormap($p)] < 0} {
6466 lappend badcolors $colormap($p)
Paul Mackerrase5c2d852005-05-11 23:44:54 +00006467 }
6468 }
6469 }
Paul Mackerras6c20ff32005-06-22 19:53:32 +10006470 if {[llength $badcolors] >= $ncolors} {
6471 set badcolors $origbad
6472 }
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +00006473 }
6474 for {set i 0} {$i <= $ncolors} {incr i} {
6475 set c [lindex $colors $nextcolor]
6476 if {[incr nextcolor] >= $ncolors} {
6477 set nextcolor 0
Paul Mackerrase5c2d852005-05-11 23:44:54 +00006478 }
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +00006479 if {[lsearch -exact $badcolors $c]} break
6480 }
6481 set colormap($id) $c
6482}
6483
Paul Mackerrasa823a912005-06-21 10:01:38 +10006484proc bindline {t id} {
6485 global canv
6486
Paul Mackerrasa823a912005-06-21 10:01:38 +10006487 $canv bind $t <Enter> "lineenter %x %y $id"
6488 $canv bind $t <Motion> "linemotion %x %y $id"
6489 $canv bind $t <Leave> "lineleave $id"
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10006490 $canv bind $t <Button-1> "lineclick %x %y $id 1"
Paul Mackerrasa823a912005-06-21 10:01:38 +10006491}
6492
Paul Mackerras4399fe32013-01-03 10:10:31 +11006493proc graph_pane_width {} {
6494 global use_ttk
6495
6496 if {$use_ttk} {
6497 set g [.tf.histframe.pwclist sashpos 0]
6498 } else {
6499 set g [.tf.histframe.pwclist sash coord 0]
6500 }
6501 return [lindex $g 0]
6502}
6503
6504proc totalwidth {l font extra} {
6505 set tot 0
6506 foreach str $l {
6507 set tot [expr {$tot + [font measure $font $str] + $extra}]
6508 }
6509 return $tot
6510}
6511
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006512proc drawtags {id x xt y1} {
Paul Mackerras8a485712006-07-06 10:21:23 +10006513 global idtags idheads idotherrefs mainhead
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006514 global linespc lthickness
Paul Mackerrasd277e892008-09-21 18:11:37 -05006515 global canv rowtextx curview fgcolor bgcolor ctxbut
Gauthier Östervall252c52d2013-03-27 14:40:51 +01006516 global headbgcolor headfgcolor headoutlinecolor remotebgcolor
6517 global tagbgcolor tagfgcolor tagoutlinecolor
6518 global reflinecolor
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006519
6520 set marks {}
6521 set ntags 0
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10006522 set nheads 0
Paul Mackerras4399fe32013-01-03 10:10:31 +11006523 set singletag 0
6524 set maxtags 3
6525 set maxtagpct 25
6526 set maxwidth [expr {[graph_pane_width] * $maxtagpct / 100}]
6527 set delta [expr {int(0.5 * ($linespc - $lthickness))}]
6528 set extra [expr {$delta + $lthickness + $linespc}]
6529
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006530 if {[info exists idtags($id)]} {
6531 set marks $idtags($id)
6532 set ntags [llength $marks]
Paul Mackerras4399fe32013-01-03 10:10:31 +11006533 if {$ntags > $maxtags ||
6534 [totalwidth $marks mainfont $extra] > $maxwidth} {
6535 # show just a single "n tags..." tag
6536 set singletag 1
6537 if {$ntags == 1} {
6538 set marks [list "tag..."]
6539 } else {
6540 set marks [list [format "%d tags..." $ntags]]
6541 }
6542 set ntags 1
6543 }
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006544 }
6545 if {[info exists idheads($id)]} {
6546 set marks [concat $marks $idheads($id)]
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10006547 set nheads [llength $idheads($id)]
6548 }
6549 if {[info exists idotherrefs($id)]} {
6550 set marks [concat $marks $idotherrefs($id)]
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006551 }
6552 if {$marks eq {}} {
6553 return $xt
6554 }
6555
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08006556 set yt [expr {$y1 - 0.5 * $linespc}]
6557 set yb [expr {$yt + $linespc - 1}]
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006558 set xvals {}
6559 set wvals {}
Paul Mackerras8a485712006-07-06 10:21:23 +10006560 set i -1
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006561 foreach tag $marks {
Paul Mackerras8a485712006-07-06 10:21:23 +10006562 incr i
6563 if {$i >= $ntags && $i < $ntags + $nheads && $tag eq $mainhead} {
Paul Mackerras9c311b32007-10-04 22:27:13 +10006564 set wid [font measure mainfontbold $tag]
Paul Mackerras8a485712006-07-06 10:21:23 +10006565 } else {
Paul Mackerras9c311b32007-10-04 22:27:13 +10006566 set wid [font measure mainfont $tag]
Paul Mackerras8a485712006-07-06 10:21:23 +10006567 }
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006568 lappend xvals $xt
6569 lappend wvals $wid
Paul Mackerras4399fe32013-01-03 10:10:31 +11006570 set xt [expr {$xt + $wid + $extra}]
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006571 }
6572 set t [$canv create line $x $y1 [lindex $xvals end] $y1 \
Gauthier Östervall252c52d2013-03-27 14:40:51 +01006573 -width $lthickness -fill $reflinecolor -tags tag.$id]
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006574 $canv lower $t
6575 foreach tag $marks x $xvals wid $wvals {
Pat Thoyts8dd60f52011-03-01 23:50:50 +00006576 set tag_quoted [string map {% %%} $tag]
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08006577 set xl [expr {$x + $delta}]
6578 set xr [expr {$x + $delta + $wid + $lthickness}]
Paul Mackerras9c311b32007-10-04 22:27:13 +10006579 set font mainfont
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006580 if {[incr ntags -1] >= 0} {
6581 # draw a tag
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08006582 set t [$canv create polygon $x [expr {$yt + $delta}] $xl $yt \
6583 $xr $yt $xr $yb $xl $yb $x [expr {$yb - $delta}] \
Gauthier Östervall252c52d2013-03-27 14:40:51 +01006584 -width 1 -outline $tagoutlinecolor -fill $tagbgcolor \
6585 -tags tag.$id]
Paul Mackerras4399fe32013-01-03 10:10:31 +11006586 if {$singletag} {
6587 set tagclick [list showtags $id 1]
6588 } else {
6589 set tagclick [list showtag $tag_quoted 1]
6590 }
6591 $canv bind $t <1> $tagclick
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11006592 set rowtextx([rowofcommit $id]) [expr {$xr + $linespc}]
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006593 } else {
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10006594 # draw a head or other ref
6595 if {[incr nheads -1] >= 0} {
Gauthier Östervall252c52d2013-03-27 14:40:51 +01006596 set col $headbgcolor
Paul Mackerras8a485712006-07-06 10:21:23 +10006597 if {$tag eq $mainhead} {
Paul Mackerras9c311b32007-10-04 22:27:13 +10006598 set font mainfontbold
Paul Mackerras8a485712006-07-06 10:21:23 +10006599 }
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10006600 } else {
6601 set col "#ddddff"
6602 }
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08006603 set xl [expr {$xl - $delta/2}]
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006604 $canv create polygon $x $yt $xr $yt $xr $yb $x $yb \
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10006605 -width 1 -outline black -fill $col -tags tag.$id
Josef Weidendorfera970fcf2006-04-18 23:53:07 +02006606 if {[regexp {^(remotes/.*/|remotes/)} $tag match remoteprefix]} {
Paul Mackerras9c311b32007-10-04 22:27:13 +10006607 set rwid [font measure mainfont $remoteprefix]
Josef Weidendorfera970fcf2006-04-18 23:53:07 +02006608 set xi [expr {$x + 1}]
6609 set yti [expr {$yt + 1}]
6610 set xri [expr {$x + $rwid}]
6611 $canv create polygon $xi $yti $xri $yti $xri $yb $xi $yb \
Gauthier Östervall252c52d2013-03-27 14:40:51 +01006612 -width 0 -fill $remotebgcolor -tags tag.$id
Josef Weidendorfera970fcf2006-04-18 23:53:07 +02006613 }
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006614 }
Gauthier Östervall252c52d2013-03-27 14:40:51 +01006615 set t [$canv create text $xl $y1 -anchor w -text $tag -fill $headfgcolor \
Paul Mackerras8a485712006-07-06 10:21:23 +10006616 -font $font -tags [list tag.$id text]]
Paul Mackerras106288c2005-08-19 23:11:39 +10006617 if {$ntags >= 0} {
Paul Mackerras4399fe32013-01-03 10:10:31 +11006618 $canv bind $t <1> $tagclick
Paul Mackerras10299152006-08-02 09:52:01 +10006619 } elseif {$nheads >= 0} {
Pat Thoyts8dd60f52011-03-01 23:50:50 +00006620 $canv bind $t $ctxbut [list headmenu %X %Y $id $tag_quoted]
Paul Mackerras106288c2005-08-19 23:11:39 +10006621 }
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10006622 }
6623 return $xt
6624}
6625
Raphael Zimmerer36242492011-04-19 22:37:09 +02006626proc drawnotesign {xt y} {
6627 global linespc canv fgcolor
6628
6629 set orad [expr {$linespc / 3}]
6630 set t [$canv create rectangle [expr {$xt - $orad}] [expr {$y - $orad}] \
6631 [expr {$xt + $orad - 1}] [expr {$y + $orad - 1}] \
6632 -fill yellow -outline $fgcolor -width 1 -tags circle]
6633 set xt [expr {$xt + $orad * 3}]
6634 return $xt
6635}
6636
Paul Mackerras8d858d12005-08-05 09:52:16 +10006637proc xcoord {i level ln} {
6638 global canvx0 xspc1 xspc2
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +00006639
Paul Mackerras8d858d12005-08-05 09:52:16 +10006640 set x [expr {$canvx0 + $i * $xspc1($ln)}]
6641 if {$i > 0 && $i == $level} {
6642 set x [expr {$x + 0.5 * ($xspc2 - $xspc1($ln))}]
6643 } elseif {$i > $level} {
6644 set x [expr {$x + $xspc2 - $xspc1($ln)}]
6645 }
6646 return $x
6647}
6648
Paul Mackerras098dd8a2006-05-03 09:32:53 +10006649proc show_status {msg} {
Paul Mackerras9c311b32007-10-04 22:27:13 +10006650 global canv fgcolor
Paul Mackerras098dd8a2006-05-03 09:32:53 +10006651
6652 clear_display
Paul Mackerras9c311b32007-10-04 22:27:13 +10006653 $canv create text 3 3 -anchor nw -text $msg -font mainfont \
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10006654 -tags text -fill $fgcolor
Paul Mackerras098dd8a2006-05-03 09:32:53 +10006655}
6656
Paul Mackerras94a2eed2005-08-07 15:27:57 +10006657# Don't change the text pane cursor if it is currently the hand cursor,
6658# showing that we are over a sha1 ID link.
6659proc settextcursor {c} {
6660 global ctext curtextcursor
6661
6662 if {[$ctext cget -cursor] == $curtextcursor} {
6663 $ctext config -cursor $c
6664 }
6665 set curtextcursor $c
Paul Mackerras9ccbdfb2005-06-16 00:27:23 +00006666}
6667
Paul Mackerrasa137a902007-10-23 21:12:49 +10006668proc nowbusy {what {name {}}} {
6669 global isbusy busyname statusw
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10006670
6671 if {[array names isbusy] eq {}} {
6672 . config -cursor watch
6673 settextcursor watch
6674 }
6675 set isbusy($what) 1
Paul Mackerrasa137a902007-10-23 21:12:49 +10006676 set busyname($what) $name
6677 if {$name ne {}} {
6678 $statusw conf -text $name
6679 }
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10006680}
6681
6682proc notbusy {what} {
Paul Mackerrasa137a902007-10-23 21:12:49 +10006683 global isbusy maincursor textcursor busyname statusw
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10006684
Paul Mackerrasa137a902007-10-23 21:12:49 +10006685 catch {
6686 unset isbusy($what)
6687 if {$busyname($what) ne {} &&
6688 [$statusw cget -text] eq $busyname($what)} {
6689 $statusw conf -text {}
6690 }
6691 }
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10006692 if {[array names isbusy] eq {}} {
6693 . config -cursor $maincursor
6694 settextcursor $textcursor
6695 }
6696}
6697
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00006698proc findmatches {f} {
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006699 global findtype findstring
Christian Stimmingb007ee22007-11-07 18:44:35 +01006700 if {$findtype == [mc "Regexp"]} {
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006701 set matches [regexp -indices -all -inline $findstring $f]
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00006702 } else {
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006703 set fs $findstring
Christian Stimmingb007ee22007-11-07 18:44:35 +01006704 if {$findtype == [mc "IgnCase"]} {
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006705 set f [string tolower $f]
6706 set fs [string tolower $fs]
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00006707 }
6708 set matches {}
6709 set i 0
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006710 set l [string length $fs]
6711 while {[set j [string first $fs $f $i]] >= 0} {
6712 lappend matches [list $j [expr {$j+$l-1}]]
6713 set i [expr {$j + $l}]
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00006714 }
6715 }
6716 return $matches
6717}
6718
Paul Mackerrascca5d942007-10-27 21:16:56 +10006719proc dofind {{dirn 1} {wrap 1}} {
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006720 global findstring findstartline findcurline selectedline numcommits
Paul Mackerrascca5d942007-10-27 21:16:56 +10006721 global gdttype filehighlight fh_serial find_dirn findallowwrap
Paul Mackerrasb74fd572005-07-16 07:46:13 -04006722
Paul Mackerrascca5d942007-10-27 21:16:56 +10006723 if {[info exists find_dirn]} {
6724 if {$find_dirn == $dirn} return
6725 stopfinding
6726 }
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00006727 focus .
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006728 if {$findstring eq {} || $numcommits == 0} return
Paul Mackerras94b4a692008-05-20 20:51:06 +10006729 if {$selectedline eq {}} {
Paul Mackerrascca5d942007-10-27 21:16:56 +10006730 set findstartline [lindex [visiblerows] [expr {$dirn < 0}]]
Paul Mackerras98f350e2005-05-15 05:56:51 +00006731 } else {
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006732 set findstartline $selectedline
Paul Mackerras98f350e2005-05-15 05:56:51 +00006733 }
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006734 set findcurline $findstartline
Christian Stimmingb007ee22007-11-07 18:44:35 +01006735 nowbusy finding [mc "Searching"]
6736 if {$gdttype ne [mc "containing:"] && ![info exists filehighlight]} {
Paul Mackerras687c8762007-09-22 12:49:33 +10006737 after cancel do_file_hl $fh_serial
6738 do_file_hl $fh_serial
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006739 }
Paul Mackerrascca5d942007-10-27 21:16:56 +10006740 set find_dirn $dirn
6741 set findallowwrap $wrap
6742 run findmore
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006743}
6744
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10006745proc stopfinding {} {
6746 global find_dirn findcurline fprogcoord
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006747
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10006748 if {[info exists find_dirn]} {
6749 unset find_dirn
6750 unset findcurline
6751 notbusy finding
6752 set fprogcoord 0
6753 adjustprogress
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006754 }
Paul Mackerras8a897742008-10-27 21:36:25 +11006755 stopblaming
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006756}
6757
6758proc findmore {} {
Paul Mackerras687c8762007-09-22 12:49:33 +10006759 global commitdata commitinfo numcommits findpattern findloc
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11006760 global findstartline findcurline findallowwrap
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10006761 global find_dirn gdttype fhighlights fprogcoord
Paul Mackerrascd2bcae2008-01-02 21:44:06 +11006762 global curview varcorder vrownum varccommits vrowmod
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006763
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10006764 if {![info exists find_dirn]} {
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006765 return 0
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00006766 }
Frédéric Brière585c27c2010-03-14 18:59:09 -04006767 set fldtypes [list [mc "Headline"] [mc "Author"] "" [mc "Committer"] "" [mc "Comments"]]
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006768 set l $findcurline
Paul Mackerrascca5d942007-10-27 21:16:56 +10006769 set moretodo 0
6770 if {$find_dirn > 0} {
6771 incr l
6772 if {$l >= $numcommits} {
6773 set l 0
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006774 }
Paul Mackerrascca5d942007-10-27 21:16:56 +10006775 if {$l <= $findstartline} {
6776 set lim [expr {$findstartline + 1}]
6777 } else {
6778 set lim $numcommits
6779 set moretodo $findallowwrap
6780 }
Paul Mackerras98f350e2005-05-15 05:56:51 +00006781 } else {
Paul Mackerrascca5d942007-10-27 21:16:56 +10006782 if {$l == 0} {
6783 set l $numcommits
6784 }
6785 incr l -1
6786 if {$l >= $findstartline} {
6787 set lim [expr {$findstartline - 1}]
6788 } else {
6789 set lim -1
6790 set moretodo $findallowwrap
6791 }
Paul Mackerras98f350e2005-05-15 05:56:51 +00006792 }
Paul Mackerrascca5d942007-10-27 21:16:56 +10006793 set n [expr {($lim - $l) * $find_dirn}]
6794 if {$n > 500} {
6795 set n 500
6796 set moretodo 1
Paul Mackerras98f350e2005-05-15 05:56:51 +00006797 }
Paul Mackerrascd2bcae2008-01-02 21:44:06 +11006798 if {$l + ($find_dirn > 0? $n: 1) > $vrowmod($curview)} {
6799 update_arcrows $curview
6800 }
Paul Mackerras687c8762007-09-22 12:49:33 +10006801 set found 0
6802 set domore 1
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11006803 set ai [bsearch $vrownum($curview) $l]
6804 set a [lindex $varcorder($curview) $ai]
6805 set arow [lindex $vrownum($curview) $ai]
6806 set ids [lindex $varccommits($curview,$a)]
6807 set arowend [expr {$arow + [llength $ids]}]
Christian Stimmingb007ee22007-11-07 18:44:35 +01006808 if {$gdttype eq [mc "containing:"]} {
Paul Mackerrascca5d942007-10-27 21:16:56 +10006809 for {} {$n > 0} {incr n -1; incr l $find_dirn} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11006810 if {$l < $arow || $l >= $arowend} {
6811 incr ai $find_dirn
6812 set a [lindex $varcorder($curview) $ai]
6813 set arow [lindex $vrownum($curview) $ai]
6814 set ids [lindex $varccommits($curview,$a)]
6815 set arowend [expr {$arow + [llength $ids]}]
6816 }
6817 set id [lindex $ids [expr {$l - $arow}]]
Paul Mackerras687c8762007-09-22 12:49:33 +10006818 # shouldn't happen unless git log doesn't give all the commits...
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11006819 if {![info exists commitdata($id)] ||
6820 ![doesmatch $commitdata($id)]} {
6821 continue
6822 }
Paul Mackerras687c8762007-09-22 12:49:33 +10006823 if {![info exists commitinfo($id)]} {
6824 getcommit $id
6825 }
6826 set info $commitinfo($id)
6827 foreach f $info ty $fldtypes {
Frédéric Brière585c27c2010-03-14 18:59:09 -04006828 if {$ty eq ""} continue
Christian Stimmingb007ee22007-11-07 18:44:35 +01006829 if {($findloc eq [mc "All fields"] || $findloc eq $ty) &&
Paul Mackerras687c8762007-09-22 12:49:33 +10006830 [doesmatch $f]} {
6831 set found 1
6832 break
6833 }
6834 }
6835 if {$found} break
Paul Mackerras98f350e2005-05-15 05:56:51 +00006836 }
Paul Mackerras687c8762007-09-22 12:49:33 +10006837 } else {
Paul Mackerrascca5d942007-10-27 21:16:56 +10006838 for {} {$n > 0} {incr n -1; incr l $find_dirn} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11006839 if {$l < $arow || $l >= $arowend} {
6840 incr ai $find_dirn
6841 set a [lindex $varcorder($curview) $ai]
6842 set arow [lindex $vrownum($curview) $ai]
6843 set ids [lindex $varccommits($curview,$a)]
6844 set arowend [expr {$arow + [llength $ids]}]
6845 }
6846 set id [lindex $ids [expr {$l - $arow}]]
Paul Mackerras476ca632008-01-07 22:16:31 +11006847 if {![info exists fhighlights($id)]} {
6848 # this sets fhighlights($id) to -1
Paul Mackerras687c8762007-09-22 12:49:33 +10006849 askfilehighlight $l $id
Paul Mackerrascd2bcae2008-01-02 21:44:06 +11006850 }
Paul Mackerras476ca632008-01-07 22:16:31 +11006851 if {$fhighlights($id) > 0} {
Paul Mackerrascd2bcae2008-01-02 21:44:06 +11006852 set found $domore
6853 break
6854 }
Paul Mackerras476ca632008-01-07 22:16:31 +11006855 if {$fhighlights($id) < 0} {
Paul Mackerras687c8762007-09-22 12:49:33 +10006856 if {$domore} {
6857 set domore 0
Paul Mackerrascca5d942007-10-27 21:16:56 +10006858 set findcurline [expr {$l - $find_dirn}]
Paul Mackerras687c8762007-09-22 12:49:33 +10006859 }
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006860 }
6861 }
6862 }
Paul Mackerrascca5d942007-10-27 21:16:56 +10006863 if {$found || ($domore && !$moretodo)} {
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006864 unset findcurline
Paul Mackerras687c8762007-09-22 12:49:33 +10006865 unset find_dirn
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006866 notbusy finding
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10006867 set fprogcoord 0
6868 adjustprogress
6869 if {$found} {
6870 findselectline $l
6871 } else {
6872 bell
6873 }
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006874 return 0
6875 }
Paul Mackerras687c8762007-09-22 12:49:33 +10006876 if {!$domore} {
6877 flushhighlights
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10006878 } else {
Paul Mackerrascca5d942007-10-27 21:16:56 +10006879 set findcurline [expr {$l - $find_dirn}]
Paul Mackerras687c8762007-09-22 12:49:33 +10006880 }
Paul Mackerrascca5d942007-10-27 21:16:56 +10006881 set n [expr {($findcurline - $findstartline) * $find_dirn - 1}]
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10006882 if {$n < 0} {
6883 incr n $numcommits
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006884 }
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10006885 set fprogcoord [expr {$n * 1.0 / $numcommits}]
6886 adjustprogress
6887 return $domore
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00006888}
6889
6890proc findselectline {l} {
Paul Mackerras687c8762007-09-22 12:49:33 +10006891 global findloc commentend ctext findcurline markingmatches gdttype
Paul Mackerras005a2f42007-07-26 22:36:39 +10006892
Paul Mackerras8b39e042008-12-02 09:02:46 +11006893 set markingmatches [expr {$gdttype eq [mc "containing:"]}]
Paul Mackerras005a2f42007-07-26 22:36:39 +10006894 set findcurline $l
Paul Mackerrasd6982062005-08-06 22:06:06 +10006895 selectline $l 1
Paul Mackerras8b39e042008-12-02 09:02:46 +11006896 if {$markingmatches &&
6897 ($findloc eq [mc "All fields"] || $findloc eq [mc "Comments"])} {
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00006898 # highlight the matches in the comments
6899 set f [$ctext get 1.0 $commentend]
6900 set matches [findmatches $f]
6901 foreach match $matches {
6902 set start [lindex $match 0]
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08006903 set end [expr {[lindex $match 1] + 1}]
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00006904 $ctext tag add found "1.0 + $start c" "1.0 + $end c"
6905 }
Paul Mackerras98f350e2005-05-15 05:56:51 +00006906 }
Paul Mackerras005a2f42007-07-26 22:36:39 +10006907 drawvisible
Paul Mackerras98f350e2005-05-15 05:56:51 +00006908}
6909
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006910# mark the bits of a headline or author that match a find string
Paul Mackerras005a2f42007-07-26 22:36:39 +10006911proc markmatches {canv l str tag matches font row} {
6912 global selectedline
6913
Paul Mackerras98f350e2005-05-15 05:56:51 +00006914 set bbox [$canv bbox $tag]
6915 set x0 [lindex $bbox 0]
6916 set y0 [lindex $bbox 1]
6917 set y1 [lindex $bbox 3]
6918 foreach match $matches {
6919 set start [lindex $match 0]
6920 set end [lindex $match 1]
6921 if {$start > $end} continue
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08006922 set xoff [font measure $font [string range $str 0 [expr {$start-1}]]]
6923 set xlen [font measure $font [string range $str 0 [expr {$end}]]]
6924 set t [$canv create rect [expr {$x0+$xoff}] $y0 \
6925 [expr {$x0+$xlen+2}] $y1 \
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006926 -outline {} -tags [list match$l matches] -fill yellow]
Paul Mackerras98f350e2005-05-15 05:56:51 +00006927 $canv lower $t
Paul Mackerras94b4a692008-05-20 20:51:06 +10006928 if {$row == $selectedline} {
Paul Mackerras005a2f42007-07-26 22:36:39 +10006929 $canv raise $t secsel
6930 }
Paul Mackerras98f350e2005-05-15 05:56:51 +00006931 }
6932}
6933
6934proc unmarkmatches {} {
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10006935 global markingmatches
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006936
Paul Mackerras98f350e2005-05-15 05:56:51 +00006937 allcanvs delete matches
Paul Mackerras4fb0fa12007-07-04 19:43:51 +10006938 set markingmatches 0
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10006939 stopfinding
Paul Mackerras98f350e2005-05-15 05:56:51 +00006940}
6941
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10006942proc selcanvline {w x y} {
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10006943 global canv canvy0 ctext linespc
Paul Mackerras9f1afe02006-02-19 22:44:47 +11006944 global rowtextx
Paul Mackerras1db95b02005-05-09 04:08:39 +00006945 set ymax [lindex [$canv cget -scrollregion] 3]
Paul Mackerrascfb45632005-05-31 12:14:42 +00006946 if {$ymax == {}} return
Paul Mackerras1db95b02005-05-09 04:08:39 +00006947 set yfrac [lindex [$canv yview] 0]
6948 set y [expr {$y + $yfrac * $ymax}]
6949 set l [expr {int(($y - $canvy0) / $linespc + 0.5)}]
6950 if {$l < 0} {
6951 set l 0
6952 }
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10006953 if {$w eq $canv} {
Paul Mackerrasfc2a2562007-12-26 23:03:43 +11006954 set xmax [lindex [$canv cget -scrollregion] 2]
6955 set xleft [expr {[lindex [$canv xview] 0] * $xmax}]
6956 if {![info exists rowtextx($l)] || $xleft + $x < $rowtextx($l)} return
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10006957 }
Paul Mackerras98f350e2005-05-15 05:56:51 +00006958 unmarkmatches
Paul Mackerrasd6982062005-08-06 22:06:06 +10006959 selectline $l 1
Paul Mackerras5ad588d2005-05-10 01:02:55 +00006960}
6961
Linus Torvaldsb1ba39e2005-08-08 20:04:20 -07006962proc commit_descriptor {p} {
6963 global commitinfo
Paul Mackerrasb0934482006-05-15 09:56:08 +10006964 if {![info exists commitinfo($p)]} {
6965 getcommit $p
6966 }
Linus Torvaldsb1ba39e2005-08-08 20:04:20 -07006967 set l "..."
Paul Mackerrasb0934482006-05-15 09:56:08 +10006968 if {[llength $commitinfo($p)] > 1} {
Linus Torvaldsb1ba39e2005-08-08 20:04:20 -07006969 set l [lindex $commitinfo($p) 0]
6970 }
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10006971 return "$p ($l)\n"
Linus Torvaldsb1ba39e2005-08-08 20:04:20 -07006972}
6973
Paul Mackerras106288c2005-08-19 23:11:39 +10006974# append some text to the ctext widget, and make any SHA1 ID
6975# that we know about be a clickable link.
Sergey Vlasovf1b86292006-05-15 19:13:14 +04006976proc appendwithlinks {text tags} {
Paul Mackerrasd375ef92008-10-21 10:18:12 +11006977 global ctext linknum curview
Paul Mackerras106288c2005-08-19 23:11:39 +10006978
6979 set start [$ctext index "end - 1c"]
Sergey Vlasovf1b86292006-05-15 19:13:14 +04006980 $ctext insert end $text $tags
Jim Meyering6c9e2d12011-12-10 16:08:57 +01006981 set links [regexp -indices -all -inline {(?:\m|-g)[0-9a-f]{6,40}\M} $text]
Paul Mackerras106288c2005-08-19 23:11:39 +10006982 foreach l $links {
6983 set s [lindex $l 0]
6984 set e [lindex $l 1]
6985 set linkid [string range $text $s $e]
Paul Mackerras106288c2005-08-19 23:11:39 +10006986 incr e
Paul Mackerrasc73adce2007-09-27 10:35:05 +10006987 $ctext tag delete link$linknum
Paul Mackerras106288c2005-08-19 23:11:39 +10006988 $ctext tag add link$linknum "$start + $s c" "$start + $e c"
Paul Mackerras97645682007-08-23 22:24:38 +10006989 setlink $linkid link$linknum
Paul Mackerras106288c2005-08-19 23:11:39 +10006990 incr linknum
6991 }
Paul Mackerras97645682007-08-23 22:24:38 +10006992}
6993
6994proc setlink {id lk} {
Paul Mackerrasd375ef92008-10-21 10:18:12 +11006995 global curview ctext pendinglinks
Gauthier Östervall252c52d2013-03-27 14:40:51 +01006996 global linkfgcolor
Paul Mackerras97645682007-08-23 22:24:38 +10006997
Jim Meyering6c9e2d12011-12-10 16:08:57 +01006998 if {[string range $id 0 1] eq "-g"} {
6999 set id [string range $id 2 end]
7000 }
7001
Paul Mackerrasd375ef92008-10-21 10:18:12 +11007002 set known 0
7003 if {[string length $id] < 40} {
7004 set matches [longid $id]
7005 if {[llength $matches] > 0} {
7006 if {[llength $matches] > 1} return
7007 set known 1
7008 set id [lindex $matches 0]
7009 }
7010 } else {
7011 set known [commitinview $id $curview]
7012 }
7013 if {$known} {
Gauthier Östervall252c52d2013-03-27 14:40:51 +01007014 $ctext tag conf $lk -foreground $linkfgcolor -underline 1
Paul Mackerrasd375ef92008-10-21 10:18:12 +11007015 $ctext tag bind $lk <1> [list selbyid $id]
Paul Mackerras97645682007-08-23 22:24:38 +10007016 $ctext tag bind $lk <Enter> {linkcursor %W 1}
7017 $ctext tag bind $lk <Leave> {linkcursor %W -1}
7018 } else {
7019 lappend pendinglinks($id) $lk
Paul Mackerrasd375ef92008-10-21 10:18:12 +11007020 interestedin $id {makelink %P}
Paul Mackerras97645682007-08-23 22:24:38 +10007021 }
7022}
7023
Paul Mackerras6f63fc12009-04-21 22:22:31 +10007024proc appendshortlink {id {pre {}} {post {}}} {
7025 global ctext linknum
7026
7027 $ctext insert end $pre
7028 $ctext tag delete link$linknum
7029 $ctext insert end [string range $id 0 7] link$linknum
7030 $ctext insert end $post
7031 setlink $id link$linknum
7032 incr linknum
7033}
7034
Paul Mackerras97645682007-08-23 22:24:38 +10007035proc makelink {id} {
7036 global pendinglinks
7037
7038 if {![info exists pendinglinks($id)]} return
7039 foreach lk $pendinglinks($id) {
7040 setlink $id $lk
7041 }
7042 unset pendinglinks($id)
7043}
7044
7045proc linkcursor {w inc} {
7046 global linkentercount curtextcursor
7047
7048 if {[incr linkentercount $inc] > 0} {
7049 $w configure -cursor hand2
7050 } else {
7051 $w configure -cursor $curtextcursor
7052 if {$linkentercount < 0} {
7053 set linkentercount 0
7054 }
7055 }
Paul Mackerras106288c2005-08-19 23:11:39 +10007056}
7057
Rutger Nijlunsing6e5f7202006-04-05 10:24:03 +10007058proc viewnextline {dir} {
7059 global canv linespc
7060
7061 $canv delete hover
7062 set ymax [lindex [$canv cget -scrollregion] 3]
7063 set wnow [$canv yview]
7064 set wtop [expr {[lindex $wnow 0] * $ymax}]
7065 set newtop [expr {$wtop + $dir * $linespc}]
7066 if {$newtop < 0} {
7067 set newtop 0
7068 } elseif {$newtop > $ymax} {
7069 set newtop $ymax
7070 }
7071 allcanvs yview moveto [expr {$newtop * 1.0 / $ymax}]
7072}
7073
Paul Mackerrasef030b82006-06-04 11:50:38 +10007074# add a list of tag or branch names at position pos
7075# returns the number of names inserted
Paul Mackerrase11f1232007-06-16 20:29:25 +10007076proc appendrefs {pos ids var} {
Max Kirillovbde4a0f2014-06-24 08:19:44 +03007077 global ctext linknum curview $var maxrefs visiblerefs mainheadid
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10007078
Paul Mackerrasef030b82006-06-04 11:50:38 +10007079 if {[catch {$ctext index $pos}]} {
7080 return 0
7081 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10007082 $ctext conf -state normal
7083 $ctext delete $pos "$pos lineend"
7084 set tags {}
7085 foreach id $ids {
7086 foreach tag [set $var\($id\)] {
7087 lappend tags [list $tag $id]
7088 }
7089 }
Paul Mackerras386befb2013-01-02 15:25:29 +11007090
7091 set sep {}
7092 set tags [lsort -index 0 -decreasing $tags]
7093 set nutags 0
7094
Paul Mackerras0a4dd8b2007-06-16 21:21:57 +10007095 if {[llength $tags] > $maxrefs} {
Paul Mackerras386befb2013-01-02 15:25:29 +11007096 # If we are displaying heads, and there are too many,
7097 # see if there are some important heads to display.
Max Kirillovbde4a0f2014-06-24 08:19:44 +03007098 # Currently that are the current head and heads listed in $visiblerefs option
Paul Mackerras386befb2013-01-02 15:25:29 +11007099 set itags {}
7100 if {$var eq "idheads"} {
7101 set utags {}
7102 foreach ti $tags {
7103 set hname [lindex $ti 0]
7104 set id [lindex $ti 1]
Max Kirillovbde4a0f2014-06-24 08:19:44 +03007105 if {([lsearch -exact $visiblerefs $hname] != -1 || $id eq $mainheadid) &&
Paul Mackerras386befb2013-01-02 15:25:29 +11007106 [llength $itags] < $maxrefs} {
7107 lappend itags $ti
7108 } else {
7109 lappend utags $ti
7110 }
7111 }
7112 set tags $utags
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10007113 }
Paul Mackerras386befb2013-01-02 15:25:29 +11007114 if {$itags ne {}} {
7115 set str [mc "and many more"]
7116 set sep " "
7117 } else {
7118 set str [mc "many"]
7119 }
7120 $ctext insert $pos "$str ([llength $tags])"
7121 set nutags [llength $tags]
7122 set tags $itags
7123 }
7124
7125 foreach ti $tags {
7126 set id [lindex $ti 1]
7127 set lk link$linknum
7128 incr linknum
7129 $ctext tag delete $lk
7130 $ctext insert $pos $sep
7131 $ctext insert $pos [lindex $ti 0] $lk
7132 setlink $id $lk
7133 set sep ", "
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10007134 }
Paul Mackerrasd34835c2013-01-01 23:08:12 +11007135 $ctext tag add wwrap "$pos linestart" "$pos lineend"
Paul Mackerrase11f1232007-06-16 20:29:25 +10007136 $ctext conf -state disabled
Paul Mackerras386befb2013-01-02 15:25:29 +11007137 return [expr {[llength $tags] + $nutags}]
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10007138}
7139
7140# called when we have finished computing the nearby tags
Paul Mackerrase11f1232007-06-16 20:29:25 +10007141proc dispneartags {delay} {
7142 global selectedline currentid showneartags tagphase
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10007143
Paul Mackerras94b4a692008-05-20 20:51:06 +10007144 if {$selectedline eq {} || !$showneartags} return
Paul Mackerrase11f1232007-06-16 20:29:25 +10007145 after cancel dispnexttag
7146 if {$delay} {
7147 after 200 dispnexttag
7148 set tagphase -1
7149 } else {
7150 after idle dispnexttag
7151 set tagphase 0
7152 }
7153}
7154
7155proc dispnexttag {} {
7156 global selectedline currentid showneartags tagphase ctext
7157
Paul Mackerras94b4a692008-05-20 20:51:06 +10007158 if {$selectedline eq {} || !$showneartags} return
Paul Mackerrase11f1232007-06-16 20:29:25 +10007159 switch -- $tagphase {
7160 0 {
7161 set dtags [desctags $currentid]
7162 if {$dtags ne {}} {
7163 appendrefs precedes $dtags idtags
7164 }
7165 }
7166 1 {
7167 set atags [anctags $currentid]
7168 if {$atags ne {}} {
7169 appendrefs follows $atags idtags
7170 }
7171 }
7172 2 {
7173 set dheads [descheads $currentid]
7174 if {$dheads ne {}} {
7175 if {[appendrefs branch $dheads idheads] > 1
7176 && [$ctext get "branch -3c"] eq "h"} {
7177 # turn "Branch" into "Branches"
7178 $ctext conf -state normal
7179 $ctext insert "branch -2c" "es"
7180 $ctext conf -state disabled
7181 }
7182 }
Paul Mackerrasef030b82006-06-04 11:50:38 +10007183 }
7184 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10007185 if {[incr tagphase] <= 2} {
7186 after idle dispnexttag
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10007187 }
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10007188}
7189
Paul Mackerras28593d32008-11-13 23:01:46 +11007190proc make_secsel {id} {
Paul Mackerras03800812007-08-29 21:45:21 +10007191 global linehtag linentag linedtag canv canv2 canv3
7192
Paul Mackerras28593d32008-11-13 23:01:46 +11007193 if {![info exists linehtag($id)]} return
Paul Mackerras03800812007-08-29 21:45:21 +10007194 $canv delete secsel
Paul Mackerras28593d32008-11-13 23:01:46 +11007195 set t [eval $canv create rect [$canv bbox $linehtag($id)] -outline {{}} \
Paul Mackerras03800812007-08-29 21:45:21 +10007196 -tags secsel -fill [$canv cget -selectbackground]]
7197 $canv lower $t
7198 $canv2 delete secsel
Paul Mackerras28593d32008-11-13 23:01:46 +11007199 set t [eval $canv2 create rect [$canv2 bbox $linentag($id)] -outline {{}} \
Paul Mackerras03800812007-08-29 21:45:21 +10007200 -tags secsel -fill [$canv2 cget -selectbackground]]
7201 $canv2 lower $t
7202 $canv3 delete secsel
Paul Mackerras28593d32008-11-13 23:01:46 +11007203 set t [eval $canv3 create rect [$canv3 bbox $linedtag($id)] -outline {{}} \
Paul Mackerras03800812007-08-29 21:45:21 +10007204 -tags secsel -fill [$canv3 cget -selectbackground]]
7205 $canv3 lower $t
7206}
7207
Paul Mackerrasb9fdba72009-04-09 09:34:46 +10007208proc make_idmark {id} {
7209 global linehtag canv fgcolor
7210
7211 if {![info exists linehtag($id)]} return
7212 $canv delete markid
7213 set t [eval $canv create rect [$canv bbox $linehtag($id)] \
7214 -tags markid -outline $fgcolor]
7215 $canv raise $t
7216}
7217
Max Kirillov4135d362014-04-05 23:38:50 +03007218proc selectline {l isnew {desired_loc {}} {switch_to_patch 0}} {
Paul Mackerras03800812007-08-29 21:45:21 +10007219 global canv ctext commitinfo selectedline
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11007220 global canvy0 linespc parents children curview
Paul Mackerras7fcceed2006-04-27 19:21:49 +10007221 global currentid sha1entry
Paul Mackerras9f1afe02006-02-19 22:44:47 +11007222 global commentend idtags linknum
Paul Mackerrasd94f8cd2006-04-06 10:18:23 +10007223 global mergemax numcommits pending_select
Paul Mackerrase11f1232007-06-16 20:29:25 +10007224 global cmitmode showneartags allcommits
Paul Mackerrasc30acc72008-03-07 22:51:55 +11007225 global targetrow targetid lastscrollrows
Paul Mackerras21ac8a82011-03-09 20:52:38 +11007226 global autoselect autosellen jump_to_here
Thomas Rast9403bd02013-11-16 18:37:43 +01007227 global vinlinediff
Paul Mackerrasd6982062005-08-06 22:06:06 +10007228
Paul Mackerrasd94f8cd2006-04-06 10:18:23 +10007229 catch {unset pending_select}
Paul Mackerras84ba7342005-06-17 00:12:26 +00007230 $canv delete hover
Paul Mackerras9843c302005-08-30 10:57:11 +10007231 normalline
Paul Mackerras887c9962007-08-20 19:36:20 +10007232 unsel_reflist
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10007233 stopfinding
Paul Mackerras8f7d0ce2006-02-28 22:10:19 +11007234 if {$l < 0 || $l >= $numcommits} return
Paul Mackerrasac1276a2008-03-03 10:11:08 +11007235 set id [commitonrow $l]
7236 set targetid $id
7237 set targetrow $l
Paul Mackerrasc30acc72008-03-07 22:51:55 +11007238 set selectedline $l
7239 set currentid $id
7240 if {$lastscrollrows < $numcommits} {
7241 setcanvscroll
7242 }
Paul Mackerrasac1276a2008-03-03 10:11:08 +11007243
Max Kirillov4135d362014-04-05 23:38:50 +03007244 if {$cmitmode ne "patch" && $switch_to_patch} {
7245 set cmitmode "patch"
7246 }
7247
Paul Mackerras5ad588d2005-05-10 01:02:55 +00007248 set y [expr {$canvy0 + $l * $linespc}]
Paul Mackerras17386062005-05-18 22:51:00 +00007249 set ymax [lindex [$canv cget -scrollregion] 3]
Paul Mackerras58422152005-05-19 10:56:42 +00007250 set ytop [expr {$y - $linespc - 1}]
7251 set ybot [expr {$y + $linespc + 1}]
Paul Mackerras5ad588d2005-05-10 01:02:55 +00007252 set wnow [$canv yview]
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08007253 set wtop [expr {[lindex $wnow 0] * $ymax}]
7254 set wbot [expr {[lindex $wnow 1] * $ymax}]
Paul Mackerras58422152005-05-19 10:56:42 +00007255 set wh [expr {$wbot - $wtop}]
7256 set newtop $wtop
Paul Mackerras17386062005-05-18 22:51:00 +00007257 if {$ytop < $wtop} {
Paul Mackerras58422152005-05-19 10:56:42 +00007258 if {$ybot < $wtop} {
7259 set newtop [expr {$y - $wh / 2.0}]
7260 } else {
7261 set newtop $ytop
7262 if {$newtop > $wtop - $linespc} {
7263 set newtop [expr {$wtop - $linespc}]
7264 }
Paul Mackerras17386062005-05-18 22:51:00 +00007265 }
Paul Mackerras58422152005-05-19 10:56:42 +00007266 } elseif {$ybot > $wbot} {
7267 if {$ytop > $wbot} {
7268 set newtop [expr {$y - $wh / 2.0}]
7269 } else {
7270 set newtop [expr {$ybot - $wh}]
7271 if {$newtop < $wtop + $linespc} {
7272 set newtop [expr {$wtop + $linespc}]
7273 }
Paul Mackerras17386062005-05-18 22:51:00 +00007274 }
Paul Mackerras58422152005-05-19 10:56:42 +00007275 }
7276 if {$newtop != $wtop} {
7277 if {$newtop < 0} {
7278 set newtop 0
7279 }
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08007280 allcanvs yview moveto [expr {$newtop * 1.0 / $ymax}]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11007281 drawvisible
Paul Mackerras5ad588d2005-05-10 01:02:55 +00007282 }
Paul Mackerrasd6982062005-08-06 22:06:06 +10007283
Paul Mackerras28593d32008-11-13 23:01:46 +11007284 make_secsel $id
Paul Mackerras9f1afe02006-02-19 22:44:47 +11007285
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10007286 if {$isnew} {
Paul Mackerras354af6b2008-11-23 13:14:23 +11007287 addtohistory [list selbyid $id 0] savecmitpos
Paul Mackerrasd6982062005-08-06 22:06:06 +10007288 }
7289
Paul Mackerras98f350e2005-05-15 05:56:51 +00007290 $sha1entry delete 0 end
7291 $sha1entry insert 0 $id
Jeff King95293b52008-03-06 06:49:25 -05007292 if {$autoselect} {
Paul Mackerras21ac8a82011-03-09 20:52:38 +11007293 $sha1entry selection range 0 $autosellen
Jeff King95293b52008-03-06 06:49:25 -05007294 }
Paul Mackerras164ff272006-05-29 19:50:02 +10007295 rhighlight_sel $id
Paul Mackerras98f350e2005-05-15 05:56:51 +00007296
Paul Mackerras5ad588d2005-05-10 01:02:55 +00007297 $ctext conf -state normal
Paul Mackerras3ea06f92006-05-24 10:16:03 +10007298 clear_ctext
Paul Mackerras106288c2005-08-19 23:11:39 +10007299 set linknum 0
Paul Mackerrasd76afb12008-03-07 21:19:18 +11007300 if {![info exists commitinfo($id)]} {
7301 getcommit $id
7302 }
Paul Mackerras1db95b02005-05-09 04:08:39 +00007303 set info $commitinfo($id)
Paul Mackerras232475d2005-11-15 10:34:03 +11007304 set date [formatdate [lindex $info 2]]
Christian Stimmingd990ced2007-11-07 18:42:55 +01007305 $ctext insert end "[mc "Author"]: [lindex $info 1] $date\n"
Paul Mackerras232475d2005-11-15 10:34:03 +11007306 set date [formatdate [lindex $info 4]]
Christian Stimmingd990ced2007-11-07 18:42:55 +01007307 $ctext insert end "[mc "Committer"]: [lindex $info 3] $date\n"
Paul Mackerras887fe3c2005-05-21 07:35:37 +00007308 if {[info exists idtags($id)]} {
Christian Stimmingd990ced2007-11-07 18:42:55 +01007309 $ctext insert end [mc "Tags:"]
Paul Mackerras887fe3c2005-05-21 07:35:37 +00007310 foreach tag $idtags($id) {
7311 $ctext insert end " $tag"
7312 }
7313 $ctext insert end "\n"
7314 }
Mark Levedahl40b87ff2007-02-01 08:44:46 -05007315
Sergey Vlasovf1b86292006-05-15 19:13:14 +04007316 set headers {}
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11007317 set olds $parents($curview,$id)
Paul Mackerras79b2c752006-04-02 20:47:40 +10007318 if {[llength $olds] > 1} {
Paul Mackerrasb77b0272006-02-07 09:13:52 +11007319 set np 0
Paul Mackerras79b2c752006-04-02 20:47:40 +10007320 foreach p $olds {
Paul Mackerrasb77b0272006-02-07 09:13:52 +11007321 if {$np >= $mergemax} {
7322 set tag mmax
7323 } else {
7324 set tag m$np
7325 }
Christian Stimmingd990ced2007-11-07 18:42:55 +01007326 $ctext insert end "[mc "Parent"]: " $tag
Sergey Vlasovf1b86292006-05-15 19:13:14 +04007327 appendwithlinks [commit_descriptor $p] {}
Paul Mackerrasb77b0272006-02-07 09:13:52 +11007328 incr np
7329 }
7330 } else {
Paul Mackerras79b2c752006-04-02 20:47:40 +10007331 foreach p $olds {
Christian Stimmingd990ced2007-11-07 18:42:55 +01007332 append headers "[mc "Parent"]: [commit_descriptor $p]"
Linus Torvalds8b192802005-08-07 13:58:56 -07007333 }
Linus Torvaldsb1ba39e2005-08-08 20:04:20 -07007334 }
Paul Mackerrasb77b0272006-02-07 09:13:52 +11007335
Paul Mackerras6a90bff2007-06-18 09:48:23 +10007336 foreach c $children($curview,$id) {
Christian Stimmingd990ced2007-11-07 18:42:55 +01007337 append headers "[mc "Child"]: [commit_descriptor $c]"
Linus Torvalds8b192802005-08-07 13:58:56 -07007338 }
Paul Mackerrasd6982062005-08-06 22:06:06 +10007339
7340 # make anything that looks like a SHA1 ID be a clickable link
Sergey Vlasovf1b86292006-05-15 19:13:14 +04007341 appendwithlinks $headers {}
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10007342 if {$showneartags} {
7343 if {![info exists allcommits]} {
7344 getallcommits
7345 }
Christian Stimmingd990ced2007-11-07 18:42:55 +01007346 $ctext insert end "[mc "Branch"]: "
Paul Mackerrasef030b82006-06-04 11:50:38 +10007347 $ctext mark set branch "end -1c"
7348 $ctext mark gravity branch left
Christian Stimmingd990ced2007-11-07 18:42:55 +01007349 $ctext insert end "\n[mc "Follows"]: "
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10007350 $ctext mark set follows "end -1c"
7351 $ctext mark gravity follows left
Christian Stimmingd990ced2007-11-07 18:42:55 +01007352 $ctext insert end "\n[mc "Precedes"]: "
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10007353 $ctext mark set precedes "end -1c"
7354 $ctext mark gravity precedes left
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10007355 $ctext insert end "\n"
Paul Mackerrase11f1232007-06-16 20:29:25 +10007356 dispneartags 1
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10007357 }
7358 $ctext insert end "\n"
Paul Mackerras43c25072006-09-27 10:56:02 +10007359 set comment [lindex $info 5]
7360 if {[string first "\r" $comment] >= 0} {
7361 set comment [string map {"\r" "\n "} $comment]
7362 }
7363 appendwithlinks $comment {comment}
Paul Mackerrasd6982062005-08-06 22:06:06 +10007364
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00007365 $ctext tag remove found 1.0 end
Paul Mackerras5ad588d2005-05-10 01:02:55 +00007366 $ctext conf -state disabled
Paul Mackerrasdf3d83b2005-05-17 23:23:07 +00007367 set commentend [$ctext index "end - 1c"]
Paul Mackerras5ad588d2005-05-10 01:02:55 +00007368
Paul Mackerras8a897742008-10-27 21:36:25 +11007369 set jump_to_here $desired_loc
Christian Stimmingb007ee22007-11-07 18:44:35 +01007370 init_flist [mc "Comments"]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007371 if {$cmitmode eq "tree"} {
7372 gettree $id
Thomas Rast9403bd02013-11-16 18:37:43 +01007373 } elseif {$vinlinediff($curview) == 1} {
7374 showinlinediff $id
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007375 } elseif {[llength $olds] <= 1} {
Paul Mackerrasd3272442005-11-28 20:41:56 +11007376 startdiff $id
Paul Mackerras7b5ff7e2006-03-30 20:50:40 +11007377 } else {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11007378 mergediff $id
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10007379 }
7380}
7381
Rutger Nijlunsing6e5f7202006-04-05 10:24:03 +10007382proc selfirstline {} {
7383 unmarkmatches
7384 selectline 0 1
7385}
7386
7387proc sellastline {} {
7388 global numcommits
7389 unmarkmatches
7390 set l [expr {$numcommits - 1}]
7391 selectline $l 1
7392}
7393
Paul Mackerrase5c2d852005-05-11 23:44:54 +00007394proc selnextline {dir} {
7395 global selectedline
Mark Levedahlbd441de2007-08-07 21:40:34 -04007396 focus .
Paul Mackerras94b4a692008-05-20 20:51:06 +10007397 if {$selectedline eq {}} return
Jeff Hobbs2ed49d52005-11-22 17:39:53 -08007398 set l [expr {$selectedline + $dir}]
Paul Mackerras98f350e2005-05-15 05:56:51 +00007399 unmarkmatches
Paul Mackerrasd6982062005-08-06 22:06:06 +10007400 selectline $l 1
7401}
7402
Rutger Nijlunsing6e5f7202006-04-05 10:24:03 +10007403proc selnextpage {dir} {
7404 global canv linespc selectedline numcommits
7405
7406 set lpp [expr {([winfo height $canv] - 2) / $linespc}]
7407 if {$lpp < 1} {
7408 set lpp 1
7409 }
7410 allcanvs yview scroll [expr {$dir * $lpp}] units
Paul Mackerrase72ee5e2006-05-20 09:58:49 +10007411 drawvisible
Paul Mackerras94b4a692008-05-20 20:51:06 +10007412 if {$selectedline eq {}} return
Rutger Nijlunsing6e5f7202006-04-05 10:24:03 +10007413 set l [expr {$selectedline + $dir * $lpp}]
7414 if {$l < 0} {
7415 set l 0
7416 } elseif {$l >= $numcommits} {
7417 set l [expr $numcommits - 1]
7418 }
7419 unmarkmatches
Mark Levedahl40b87ff2007-02-01 08:44:46 -05007420 selectline $l 1
Rutger Nijlunsing6e5f7202006-04-05 10:24:03 +10007421}
7422
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10007423proc unselectline {} {
Paul Mackerras50b44ec2006-04-04 10:16:22 +10007424 global selectedline currentid
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10007425
Paul Mackerras94b4a692008-05-20 20:51:06 +10007426 set selectedline {}
Paul Mackerras50b44ec2006-04-04 10:16:22 +10007427 catch {unset currentid}
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10007428 allcanvs delete secsel
Paul Mackerras164ff272006-05-29 19:50:02 +10007429 rhighlight_none
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10007430}
7431
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007432proc reselectline {} {
7433 global selectedline
7434
Paul Mackerras94b4a692008-05-20 20:51:06 +10007435 if {$selectedline ne {}} {
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007436 selectline $selectedline 0
7437 }
7438}
7439
Paul Mackerras354af6b2008-11-23 13:14:23 +11007440proc addtohistory {cmd {saveproc {}}} {
Paul Mackerras2516dae2006-04-21 10:35:31 +10007441 global history historyindex curview
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10007442
Paul Mackerras354af6b2008-11-23 13:14:23 +11007443 unset_posvars
7444 save_position
7445 set elt [list $curview $cmd $saveproc {}]
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10007446 if {$historyindex > 0
Paul Mackerras2516dae2006-04-21 10:35:31 +10007447 && [lindex $history [expr {$historyindex - 1}]] == $elt} {
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10007448 return
7449 }
7450
7451 if {$historyindex < [llength $history]} {
Paul Mackerras2516dae2006-04-21 10:35:31 +10007452 set history [lreplace $history $historyindex end $elt]
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10007453 } else {
Paul Mackerras2516dae2006-04-21 10:35:31 +10007454 lappend history $elt
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10007455 }
7456 incr historyindex
7457 if {$historyindex > 1} {
Junio C Hamanoe9937d22007-02-01 08:46:38 -05007458 .tf.bar.leftbut conf -state normal
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10007459 } else {
Junio C Hamanoe9937d22007-02-01 08:46:38 -05007460 .tf.bar.leftbut conf -state disabled
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10007461 }
Junio C Hamanoe9937d22007-02-01 08:46:38 -05007462 .tf.bar.rightbut conf -state disabled
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10007463}
7464
Paul Mackerras354af6b2008-11-23 13:14:23 +11007465# save the scrolling position of the diff display pane
7466proc save_position {} {
7467 global historyindex history
7468
7469 if {$historyindex < 1} return
7470 set hi [expr {$historyindex - 1}]
7471 set fn [lindex $history $hi 2]
7472 if {$fn ne {}} {
7473 lset history $hi 3 [eval $fn]
7474 }
7475}
7476
7477proc unset_posvars {} {
7478 global last_posvars
7479
7480 if {[info exists last_posvars]} {
7481 foreach {var val} $last_posvars {
7482 global $var
7483 catch {unset $var}
7484 }
7485 unset last_posvars
7486 }
7487}
7488
Paul Mackerras2516dae2006-04-21 10:35:31 +10007489proc godo {elt} {
Paul Mackerras354af6b2008-11-23 13:14:23 +11007490 global curview last_posvars
Paul Mackerras2516dae2006-04-21 10:35:31 +10007491
7492 set view [lindex $elt 0]
7493 set cmd [lindex $elt 1]
Paul Mackerras354af6b2008-11-23 13:14:23 +11007494 set pv [lindex $elt 3]
Paul Mackerras2516dae2006-04-21 10:35:31 +10007495 if {$curview != $view} {
7496 showview $view
7497 }
Paul Mackerras354af6b2008-11-23 13:14:23 +11007498 unset_posvars
7499 foreach {var val} $pv {
7500 global $var
7501 set $var $val
7502 }
7503 set last_posvars $pv
Paul Mackerras2516dae2006-04-21 10:35:31 +10007504 eval $cmd
7505}
7506
Paul Mackerrasd6982062005-08-06 22:06:06 +10007507proc goback {} {
7508 global history historyindex
Mark Levedahlbd441de2007-08-07 21:40:34 -04007509 focus .
Paul Mackerrasd6982062005-08-06 22:06:06 +10007510
7511 if {$historyindex > 1} {
Paul Mackerras354af6b2008-11-23 13:14:23 +11007512 save_position
Paul Mackerrasd6982062005-08-06 22:06:06 +10007513 incr historyindex -1
Paul Mackerras2516dae2006-04-21 10:35:31 +10007514 godo [lindex $history [expr {$historyindex - 1}]]
Junio C Hamanoe9937d22007-02-01 08:46:38 -05007515 .tf.bar.rightbut conf -state normal
Paul Mackerrasd6982062005-08-06 22:06:06 +10007516 }
7517 if {$historyindex <= 1} {
Junio C Hamanoe9937d22007-02-01 08:46:38 -05007518 .tf.bar.leftbut conf -state disabled
Paul Mackerrasd6982062005-08-06 22:06:06 +10007519 }
7520}
7521
7522proc goforw {} {
7523 global history historyindex
Mark Levedahlbd441de2007-08-07 21:40:34 -04007524 focus .
Paul Mackerrasd6982062005-08-06 22:06:06 +10007525
7526 if {$historyindex < [llength $history]} {
Paul Mackerras354af6b2008-11-23 13:14:23 +11007527 save_position
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10007528 set cmd [lindex $history $historyindex]
Paul Mackerrasd6982062005-08-06 22:06:06 +10007529 incr historyindex
Paul Mackerras2516dae2006-04-21 10:35:31 +10007530 godo $cmd
Junio C Hamanoe9937d22007-02-01 08:46:38 -05007531 .tf.bar.leftbut conf -state normal
Paul Mackerrasd6982062005-08-06 22:06:06 +10007532 }
7533 if {$historyindex >= [llength $history]} {
Junio C Hamanoe9937d22007-02-01 08:46:38 -05007534 .tf.bar.rightbut conf -state disabled
Paul Mackerrasd6982062005-08-06 22:06:06 +10007535 }
Paul Mackerras5ad588d2005-05-10 01:02:55 +00007536}
7537
Max Kirillovd4ec30b2014-07-08 23:45:35 +03007538proc go_to_parent {i} {
7539 global parents curview targetid
7540 set ps $parents($curview,$targetid)
7541 if {[llength $ps] >= $i} {
7542 selbyid [lindex $ps [expr $i - 1]]
7543 }
7544}
7545
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007546proc gettree {id} {
Paul Mackerras8f489362007-07-13 19:49:37 +10007547 global treefilelist treeidlist diffids diffmergeid treepending
7548 global nullid nullid2
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007549
7550 set diffids $id
7551 catch {unset diffmergeid}
7552 if {![info exists treefilelist($id)]} {
7553 if {![info exists treepending]} {
Paul Mackerras8f489362007-07-13 19:49:37 +10007554 if {$id eq $nullid} {
7555 set cmd [list | git ls-files]
7556 } elseif {$id eq $nullid2} {
7557 set cmd [list | git ls-files --stage -t]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007558 } else {
Paul Mackerras8f489362007-07-13 19:49:37 +10007559 set cmd [list | git ls-tree -r $id]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007560 }
7561 if {[catch {set gtf [open $cmd r]}]} {
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007562 return
7563 }
7564 set treepending $id
7565 set treefilelist($id) {}
7566 set treeidlist($id) {}
Alexander Gavrilov09c70292008-10-13 12:12:31 +04007567 fconfigure $gtf -blocking 0 -encoding binary
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007568 filerun $gtf [list gettreeline $gtf $id]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007569 }
7570 } else {
7571 setfilelist $id
7572 }
7573}
7574
7575proc gettreeline {gtf id} {
Paul Mackerras8f489362007-07-13 19:49:37 +10007576 global treefilelist treeidlist treepending cmitmode diffids nullid nullid2
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007577
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007578 set nl 0
7579 while {[incr nl] <= 1000 && [gets $gtf line] >= 0} {
Paul Mackerras8f489362007-07-13 19:49:37 +10007580 if {$diffids eq $nullid} {
7581 set fname $line
7582 } else {
Paul Mackerras9396cd32007-06-23 20:28:15 +10007583 set i [string first "\t" $line]
7584 if {$i < 0} continue
Paul Mackerras9396cd32007-06-23 20:28:15 +10007585 set fname [string range $line [expr {$i+1}] end]
Paul Mackerrasf31fa2c2008-04-28 09:40:50 +10007586 set line [string range $line 0 [expr {$i-1}]]
7587 if {$diffids ne $nullid2 && [lindex $line 1] ne "blob"} continue
7588 set sha1 [lindex $line 2]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007589 lappend treeidlist($id) $sha1
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007590 }
Alexander Gavrilov09c70292008-10-13 12:12:31 +04007591 if {[string index $fname 0] eq "\""} {
7592 set fname [lindex $fname 0]
7593 }
7594 set fname [encoding convertfrom $fname]
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007595 lappend treefilelist($id) $fname
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007596 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007597 if {![eof $gtf]} {
7598 return [expr {$nl >= 1000? 2: 1}]
7599 }
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007600 close $gtf
7601 unset treepending
7602 if {$cmitmode ne "tree"} {
7603 if {![info exists diffmergeid]} {
7604 gettreediffs $diffids
7605 }
7606 } elseif {$id ne $diffids} {
7607 gettree $diffids
7608 } else {
7609 setfilelist $id
7610 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007611 return 0
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007612}
7613
7614proc showfile {f} {
Paul Mackerras8f489362007-07-13 19:49:37 +10007615 global treefilelist treeidlist diffids nullid nullid2
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04007616 global ctext_file_names ctext_file_lines
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007617 global ctext commentend
7618
7619 set i [lsearch -exact $treefilelist($diffids) $f]
7620 if {$i < 0} {
7621 puts "oops, $f not in list for id $diffids"
7622 return
7623 }
Paul Mackerras8f489362007-07-13 19:49:37 +10007624 if {$diffids eq $nullid} {
7625 if {[catch {set bf [open $f r]} err]} {
7626 puts "oops, can't read $f: $err"
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007627 return
7628 }
7629 } else {
Paul Mackerras8f489362007-07-13 19:49:37 +10007630 set blob [lindex $treeidlist($diffids) $i]
7631 if {[catch {set bf [open [concat | git cat-file blob $blob] r]} err]} {
7632 puts "oops, error reading blob $blob: $err"
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007633 return
7634 }
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007635 }
Alexander Gavrilov09c70292008-10-13 12:12:31 +04007636 fconfigure $bf -blocking 0 -encoding [get_path_encoding $f]
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007637 filerun $bf [list getblobline $bf $diffids]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007638 $ctext config -state normal
Paul Mackerras3ea06f92006-05-24 10:16:03 +10007639 clear_ctext $commentend
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04007640 lappend ctext_file_names $f
7641 lappend ctext_file_lines [lindex [split $commentend "."] 0]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007642 $ctext insert end "\n"
7643 $ctext insert end "$f\n" filesep
7644 $ctext config -state disabled
7645 $ctext yview $commentend
Paul Mackerras32f1b3e2007-09-28 21:27:39 +10007646 settabs 0
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007647}
7648
7649proc getblobline {bf id} {
7650 global diffids cmitmode ctext
7651
7652 if {$id ne $diffids || $cmitmode ne "tree"} {
7653 catch {close $bf}
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007654 return 0
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007655 }
7656 $ctext config -state normal
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007657 set nl 0
7658 while {[incr nl] <= 1000 && [gets $bf line] >= 0} {
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007659 $ctext insert end "$line\n"
7660 }
7661 if {[eof $bf]} {
Paul Mackerras8a897742008-10-27 21:36:25 +11007662 global jump_to_here ctext_file_names commentend
7663
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007664 # delete last newline
7665 $ctext delete "end - 2c" "end - 1c"
7666 close $bf
Paul Mackerras8a897742008-10-27 21:36:25 +11007667 if {$jump_to_here ne {} &&
7668 [lindex $jump_to_here 0] eq [lindex $ctext_file_names 0]} {
7669 set lnum [expr {[lindex $jump_to_here 1] +
7670 [lindex [split $commentend .] 0]}]
7671 mark_ctext_line $lnum
7672 }
Stefan Haller120ea892010-11-14 13:21:50 +01007673 $ctext config -state disabled
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007674 return 0
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007675 }
7676 $ctext config -state disabled
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007677 return [expr {$nl >= 1000? 2: 1}]
Paul Mackerrasf8b28a42006-05-01 09:50:57 +10007678}
7679
Paul Mackerras8a897742008-10-27 21:36:25 +11007680proc mark_ctext_line {lnum} {
Paul Mackerrase3e901b2008-10-27 22:37:21 +11007681 global ctext markbgcolor
Paul Mackerras8a897742008-10-27 21:36:25 +11007682
7683 $ctext tag delete omark
7684 $ctext tag add omark $lnum.0 "$lnum.0 + 1 line"
Paul Mackerrase3e901b2008-10-27 22:37:21 +11007685 $ctext tag conf omark -background $markbgcolor
Paul Mackerras8a897742008-10-27 21:36:25 +11007686 $ctext see $lnum.0
7687}
7688
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11007689proc mergediff {id} {
Paul Mackerras8b07dca2008-11-02 22:34:47 +11007690 global diffmergeid
Alexander Gavrilov2df64422008-10-08 11:05:37 +04007691 global diffids treediffs
Paul Mackerras8b07dca2008-11-02 22:34:47 +11007692 global parents curview
Paul Mackerrase2ed4322005-07-17 03:39:44 -04007693
Paul Mackerras3c461ff2005-07-20 09:13:46 -04007694 set diffmergeid $id
Paul Mackerras7a1d9d12006-03-22 10:21:45 +11007695 set diffids $id
Alexander Gavrilov2df64422008-10-08 11:05:37 +04007696 set treediffs($id) {}
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11007697 set np [llength $parents($curview,$id)]
Paul Mackerras32f1b3e2007-09-28 21:27:39 +10007698 settabs $np
Paul Mackerras8b07dca2008-11-02 22:34:47 +11007699 getblobdiffs $id
Paul Mackerrasc8a4acb2005-07-29 09:23:03 -05007700}
7701
Paul Mackerras3c461ff2005-07-20 09:13:46 -04007702proc startdiff {ids} {
Paul Mackerras8f489362007-07-13 19:49:37 +10007703 global treediffs diffids treepending diffmergeid nullid nullid2
Paul Mackerras3c461ff2005-07-20 09:13:46 -04007704
Paul Mackerras32f1b3e2007-09-28 21:27:39 +10007705 settabs 1
Paul Mackerras3c461ff2005-07-20 09:13:46 -04007706 set diffids $ids
7707 catch {unset diffmergeid}
Paul Mackerras8f489362007-07-13 19:49:37 +10007708 if {![info exists treediffs($ids)] ||
7709 [lsearch -exact $ids $nullid] >= 0 ||
7710 [lsearch -exact $ids $nullid2] >= 0} {
Paul Mackerras3c461ff2005-07-20 09:13:46 -04007711 if {![info exists treepending]} {
7712 gettreediffs $ids
7713 }
7714 } else {
7715 addtocflist $ids
7716 }
7717}
7718
Thomas Rast9403bd02013-11-16 18:37:43 +01007719proc showinlinediff {ids} {
7720 global commitinfo commitdata ctext
7721 global treediffs
7722
7723 set info $commitinfo($ids)
7724 set diff [lindex $info 7]
7725 set difflines [split $diff "\n"]
7726
7727 initblobdiffvars
7728 set treediff {}
7729
7730 set inhdr 0
7731 foreach line $difflines {
7732 if {![string compare -length 5 "diff " $line]} {
7733 set inhdr 1
7734 } elseif {$inhdr && ![string compare -length 4 "+++ " $line]} {
7735 # offset also accounts for the b/ prefix
7736 lappend treediff [string range $line 6 end]
7737 set inhdr 0
7738 }
7739 }
7740
7741 set treediffs($ids) $treediff
7742 add_flist $treediff
7743
7744 $ctext conf -state normal
7745 foreach line $difflines {
7746 parseblobdiffline $ids $line
7747 }
7748 maybe_scroll_ctext 1
7749 $ctext conf -state disabled
7750}
7751
Pat Thoyts65bb0bd2011-12-13 16:50:50 +00007752# If the filename (name) is under any of the passed filter paths
7753# then return true to include the file in the listing.
Paul Mackerras7a39a172007-10-23 10:15:11 +10007754proc path_filter {filter name} {
Pat Thoyts65bb0bd2011-12-13 16:50:50 +00007755 set worktree [gitworktree]
Paul Mackerras7a39a172007-10-23 10:15:11 +10007756 foreach p $filter {
Pat Thoyts65bb0bd2011-12-13 16:50:50 +00007757 set fq_p [file normalize $p]
7758 set fq_n [file normalize [file join $worktree $name]]
7759 if {[string match [file normalize $fq_p]* $fq_n]} {
7760 return 1
Paul Mackerras7a39a172007-10-23 10:15:11 +10007761 }
7762 }
7763 return 0
7764}
7765
Paul Mackerras3c461ff2005-07-20 09:13:46 -04007766proc addtocflist {ids} {
Paul Mackerras74a40c72007-10-24 10:16:56 +10007767 global treediffs
Paul Mackerras7a39a172007-10-23 10:15:11 +10007768
Paul Mackerras74a40c72007-10-24 10:16:56 +10007769 add_flist $treediffs($ids)
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10007770 getblobdiffs $ids
Paul Mackerrasd2610d12005-05-11 00:45:38 +00007771}
7772
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007773proc diffcmd {ids flags} {
Jens Lehmann17f98362014-04-08 21:36:08 +02007774 global log_showroot nullid nullid2 git_version
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007775
7776 set i [lsearch -exact $ids $nullid]
Paul Mackerras8f489362007-07-13 19:49:37 +10007777 set j [lsearch -exact $ids $nullid2]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007778 if {$i >= 0} {
Paul Mackerras8f489362007-07-13 19:49:37 +10007779 if {[llength $ids] > 1 && $j < 0} {
7780 # comparing working directory with some specific revision
7781 set cmd [concat | git diff-index $flags]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007782 if {$i == 0} {
7783 lappend cmd -R [lindex $ids 1]
7784 } else {
7785 lappend cmd [lindex $ids 0]
7786 }
7787 } else {
Paul Mackerras8f489362007-07-13 19:49:37 +10007788 # comparing working directory with index
7789 set cmd [concat | git diff-files $flags]
7790 if {$j == 1} {
7791 lappend cmd -R
7792 }
7793 }
7794 } elseif {$j >= 0} {
Jens Lehmann17f98362014-04-08 21:36:08 +02007795 if {[package vcompare $git_version "1.7.2"] >= 0} {
7796 set flags "$flags --ignore-submodules=dirty"
7797 }
Paul Mackerras8f489362007-07-13 19:49:37 +10007798 set cmd [concat | git diff-index --cached $flags]
7799 if {[llength $ids] > 1} {
7800 # comparing index with specific revision
Jens Lehmann90a77922009-10-27 18:13:42 +01007801 if {$j == 0} {
Paul Mackerras8f489362007-07-13 19:49:37 +10007802 lappend cmd -R [lindex $ids 1]
7803 } else {
7804 lappend cmd [lindex $ids 0]
7805 }
7806 } else {
7807 # comparing index with HEAD
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007808 lappend cmd HEAD
7809 }
7810 } else {
Marcus Karlssonb2b76d12011-10-04 22:08:13 +02007811 if {$log_showroot} {
7812 lappend flags --root
7813 }
Paul Mackerras8f489362007-07-13 19:49:37 +10007814 set cmd [concat | git diff-tree -r $flags $ids]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007815 }
7816 return $cmd
7817}
7818
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10007819proc gettreediffs {ids} {
Felipe Contreras2c8cd902013-04-27 17:01:39 -05007820 global treediff treepending limitdiffs vfilelimit curview
Paul Mackerras219ea3a2006-09-07 10:21:39 +10007821
Felipe Contreras2c8cd902013-04-27 17:01:39 -05007822 set cmd [diffcmd $ids {--no-commit-id}]
7823 if {$limitdiffs && $vfilelimit($curview) ne {}} {
7824 set cmd [concat $cmd -- $vfilelimit($curview)]
7825 }
7826 if {[catch {set gdtf [open $cmd r]}]} return
Alexander Gavrilov72721312008-07-26 18:48:41 +04007827
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10007828 set treepending $ids
Paul Mackerras3c461ff2005-07-20 09:13:46 -04007829 set treediff {}
Alexander Gavrilov09c70292008-10-13 12:12:31 +04007830 fconfigure $gdtf -blocking 0 -encoding binary
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007831 filerun $gdtf [list gettreediffline $gdtf $ids]
Paul Mackerrasd2610d12005-05-11 00:45:38 +00007832}
7833
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10007834proc gettreediffline {gdtf ids} {
Paul Mackerras3c461ff2005-07-20 09:13:46 -04007835 global treediff treediffs treepending diffids diffmergeid
Paul Mackerras39ee47e2008-10-15 22:23:03 +11007836 global cmitmode vfilelimit curview limitdiffs perfile_attrs
Paul Mackerras3c461ff2005-07-20 09:13:46 -04007837
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007838 set nr 0
Alexander Gavrilov4db09302008-10-13 12:12:33 +04007839 set sublist {}
Paul Mackerras39ee47e2008-10-15 22:23:03 +11007840 set max 1000
7841 if {$perfile_attrs} {
7842 # cache_gitattr is slow, and even slower on win32 where we
7843 # have to invoke it for only about 30 paths at a time
7844 set max 500
7845 if {[tk windowingsystem] == "win32"} {
7846 set max 120
7847 }
7848 }
7849 while {[incr nr] <= $max && [gets $gdtf line] >= 0} {
Paul Mackerras9396cd32007-06-23 20:28:15 +10007850 set i [string first "\t" $line]
7851 if {$i >= 0} {
7852 set file [string range $line [expr {$i+1}] end]
7853 if {[string index $file 0] eq "\""} {
7854 set file [lindex $file 0]
7855 }
Alexander Gavrilov09c70292008-10-13 12:12:31 +04007856 set file [encoding convertfrom $file]
Paul Mackerras48a81b72008-11-04 21:09:00 +11007857 if {$file ne [lindex $treediff end]} {
7858 lappend treediff $file
7859 lappend sublist $file
7860 }
Paul Mackerras9396cd32007-06-23 20:28:15 +10007861 }
Paul Mackerrasd2610d12005-05-11 00:45:38 +00007862 }
Paul Mackerras39ee47e2008-10-15 22:23:03 +11007863 if {$perfile_attrs} {
7864 cache_gitattr encoding $sublist
7865 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007866 if {![eof $gdtf]} {
Paul Mackerras39ee47e2008-10-15 22:23:03 +11007867 return [expr {$nr >= $max? 2: 1}]
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007868 }
7869 close $gdtf
Felipe Contreras2c8cd902013-04-27 17:01:39 -05007870 set treediffs($ids) $treediff
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007871 unset treepending
Paul Mackerrase1160132008-11-18 21:40:32 +11007872 if {$cmitmode eq "tree" && [llength $diffids] == 1} {
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007873 gettree $diffids
7874 } elseif {$ids != $diffids} {
7875 if {![info exists diffmergeid]} {
7876 gettreediffs $diffids
7877 }
7878 } else {
7879 addtocflist $ids
7880 }
7881 return 0
Paul Mackerrasd2610d12005-05-11 00:45:38 +00007882}
7883
Steffen Prohaska890fae72007-08-12 12:05:46 +02007884# empty string or positive integer
7885proc diffcontextvalidate {v} {
7886 return [regexp {^(|[1-9][0-9]*)$} $v]
7887}
7888
7889proc diffcontextchange {n1 n2 op} {
7890 global diffcontextstring diffcontext
7891
7892 if {[string is integer -strict $diffcontextstring]} {
Markus Heidelberga41ddbb2009-05-23 19:31:37 +02007893 if {$diffcontextstring >= 0} {
Steffen Prohaska890fae72007-08-12 12:05:46 +02007894 set diffcontext $diffcontextstring
7895 reselectline
7896 }
7897 }
7898}
7899
Steffen Prohaskab9b86002008-01-17 23:42:55 +01007900proc changeignorespace {} {
7901 reselectline
7902}
7903
Thomas Rastae4e3ff2010-10-16 12:15:10 +02007904proc changeworddiff {name ix op} {
7905 reselectline
7906}
7907
Thomas Rast5de460a2013-11-16 18:37:41 +01007908proc initblobdiffvars {} {
7909 global diffencoding targetline diffnparents
7910 global diffinhdr currdiffsubmod diffseehere
7911 set targetline {}
7912 set diffnparents 0
7913 set diffinhdr 0
7914 set diffencoding [get_path_encoding {}]
7915 set currdiffsubmod ""
7916 set diffseehere -1
7917}
7918
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10007919proc getblobdiffs {ids} {
Paul Mackerras8d73b242007-10-06 20:22:00 +10007920 global blobdifffd diffids env
Thomas Rast5de460a2013-11-16 18:37:41 +01007921 global treediffs
Steffen Prohaska890fae72007-08-12 12:05:46 +02007922 global diffcontext
Steffen Prohaskab9b86002008-01-17 23:42:55 +01007923 global ignorespace
Thomas Rastae4e3ff2010-10-16 12:15:10 +02007924 global worddiff
Paul Mackerras3ed31a82008-04-26 16:00:00 +10007925 global limitdiffs vfilelimit curview
Thomas Rast5de460a2013-11-16 18:37:41 +01007926 global git_version
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10007927
Paul Mackerrasa8138732009-05-16 21:06:01 +10007928 set textconv {}
7929 if {[package vcompare $git_version "1.6.1"] >= 0} {
7930 set textconv "--textconv"
7931 }
Jens Lehmann5c838d22009-10-28 12:40:45 +01007932 set submodule {}
7933 if {[package vcompare $git_version "1.6.6"] >= 0} {
7934 set submodule "--submodule"
7935 }
7936 set cmd [diffcmd $ids "-p $textconv $submodule -C --cc --no-commit-id -U$diffcontext"]
Steffen Prohaskab9b86002008-01-17 23:42:55 +01007937 if {$ignorespace} {
7938 append cmd " -w"
7939 }
Thomas Rastae4e3ff2010-10-16 12:15:10 +02007940 if {$worddiff ne [mc "Line diff"]} {
7941 append cmd " --word-diff=porcelain"
7942 }
Paul Mackerras3ed31a82008-04-26 16:00:00 +10007943 if {$limitdiffs && $vfilelimit($curview) ne {}} {
7944 set cmd [concat $cmd -- $vfilelimit($curview)]
Paul Mackerras7a39a172007-10-23 10:15:11 +10007945 }
7946 if {[catch {set bdf [open $cmd r]} err]} {
Paul Mackerras8b07dca2008-11-02 22:34:47 +11007947 error_popup [mc "Error getting diffs: %s" $err]
Paul Mackerrase5c2d852005-05-11 23:44:54 +00007948 return
7949 }
Pat Thoyts681c3292009-03-16 10:24:40 +00007950 fconfigure $bdf -blocking 0 -encoding binary -eofchar {}
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10007951 set blobdifffd($ids) $bdf
Thomas Rast5de460a2013-11-16 18:37:41 +01007952 initblobdiffvars
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10007953 filerun $bdf [list getblobdiffline $bdf $diffids]
Paul Mackerrase5c2d852005-05-11 23:44:54 +00007954}
7955
Paul Mackerras354af6b2008-11-23 13:14:23 +11007956proc savecmitpos {} {
7957 global ctext cmitmode
7958
7959 if {$cmitmode eq "tree"} {
7960 return {}
7961 }
7962 return [list target_scrollpos [$ctext index @0,0]]
7963}
7964
7965proc savectextpos {} {
7966 global ctext
7967
7968 return [list target_scrollpos [$ctext index @0,0]]
7969}
7970
7971proc maybe_scroll_ctext {ateof} {
7972 global ctext target_scrollpos
7973
7974 if {![info exists target_scrollpos]} return
7975 if {!$ateof} {
7976 set nlines [expr {[winfo height $ctext]
7977 / [font metrics textfont -linespace]}]
7978 if {[$ctext compare "$target_scrollpos + $nlines lines" <= end]} return
7979 }
7980 $ctext yview $target_scrollpos
7981 unset target_scrollpos
7982}
7983
Paul Mackerras89b11d32006-05-02 19:55:31 +10007984proc setinlist {var i val} {
7985 global $var
7986
7987 while {[llength [set $var]] < $i} {
7988 lappend $var {}
7989 }
7990 if {[llength [set $var]] == $i} {
7991 lappend $var $val
7992 } else {
7993 lset $var $i $val
7994 }
7995}
7996
Paul Mackerras9396cd32007-06-23 20:28:15 +10007997proc makediffhdr {fname ids} {
Paul Mackerras8b07dca2008-11-02 22:34:47 +11007998 global ctext curdiffstart treediffs diffencoding
Paul Mackerras8a897742008-10-27 21:36:25 +11007999 global ctext_file_names jump_to_here targetline diffline
Paul Mackerras9396cd32007-06-23 20:28:15 +10008000
Paul Mackerras8b07dca2008-11-02 22:34:47 +11008001 set fname [encoding convertfrom $fname]
8002 set diffencoding [get_path_encoding $fname]
Paul Mackerras9396cd32007-06-23 20:28:15 +10008003 set i [lsearch -exact $treediffs($ids) $fname]
8004 if {$i >= 0} {
8005 setinlist difffilestart $i $curdiffstart
8006 }
Paul Mackerras48a81b72008-11-04 21:09:00 +11008007 lset ctext_file_names end $fname
Paul Mackerras9396cd32007-06-23 20:28:15 +10008008 set l [expr {(78 - [string length $fname]) / 2}]
8009 set pad [string range "----------------------------------------" 1 $l]
8010 $ctext insert $curdiffstart "$pad $fname $pad" filesep
Paul Mackerras8a897742008-10-27 21:36:25 +11008011 set targetline {}
8012 if {$jump_to_here ne {} && [lindex $jump_to_here 0] eq $fname} {
8013 set targetline [lindex $jump_to_here 1]
8014 }
8015 set diffline 0
Paul Mackerras9396cd32007-06-23 20:28:15 +10008016}
8017
Thomas Rast5de460a2013-11-16 18:37:41 +01008018proc blobdiffmaybeseehere {ateof} {
8019 global diffseehere
8020 if {$diffseehere >= 0} {
8021 mark_ctext_line [lindex [split $diffseehere .] 0]
8022 }
Max Kirillov1f3c8722014-01-18 14:58:51 +02008023 maybe_scroll_ctext $ateof
Thomas Rast5de460a2013-11-16 18:37:41 +01008024}
8025
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008026proc getblobdiffline {bdf ids} {
Thomas Rast5de460a2013-11-16 18:37:41 +01008027 global diffids blobdifffd
8028 global ctext
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008029
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10008030 set nr 0
Paul Mackerrase5c2d852005-05-11 23:44:54 +00008031 $ctext conf -state normal
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10008032 while {[incr nr] <= 1000 && [gets $bdf line] >= 0} {
8033 if {$ids != $diffids || $bdf != $blobdifffd($ids)} {
Paul Mackerrasc21398b2009-09-07 10:08:21 +10008034 catch {close $bdf}
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10008035 return 0
Paul Mackerras89b11d32006-05-02 19:55:31 +10008036 }
Thomas Rast5de460a2013-11-16 18:37:41 +01008037 parseblobdiffline $ids $line
Paul Mackerrase5c2d852005-05-11 23:44:54 +00008038 }
8039 $ctext conf -state disabled
Thomas Rast5de460a2013-11-16 18:37:41 +01008040 blobdiffmaybeseehere [eof $bdf]
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10008041 if {[eof $bdf]} {
Paul Mackerrasc21398b2009-09-07 10:08:21 +10008042 catch {close $bdf}
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10008043 return 0
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008044 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +10008045 return [expr {$nr >= 1000? 2: 1}]
Paul Mackerrase5c2d852005-05-11 23:44:54 +00008046}
8047
Thomas Rast5de460a2013-11-16 18:37:41 +01008048proc parseblobdiffline {ids line} {
8049 global ctext curdiffstart
8050 global diffnexthead diffnextnote difffilestart
8051 global ctext_file_names ctext_file_lines
8052 global diffinhdr treediffs mergemax diffnparents
8053 global diffencoding jump_to_here targetline diffline currdiffsubmod
8054 global worddiff diffseehere
8055
8056 if {![string compare -length 5 "diff " $line]} {
8057 if {![regexp {^diff (--cc|--git) } $line m type]} {
8058 set line [encoding convertfrom $line]
8059 $ctext insert end "$line\n" hunksep
8060 continue
8061 }
8062 # start of a new file
8063 set diffinhdr 1
8064 $ctext insert end "\n"
8065 set curdiffstart [$ctext index "end - 1c"]
8066 lappend ctext_file_names ""
8067 lappend ctext_file_lines [lindex [split $curdiffstart "."] 0]
8068 $ctext insert end "\n" filesep
8069
8070 if {$type eq "--cc"} {
8071 # start of a new file in a merge diff
8072 set fname [string range $line 10 end]
8073 if {[lsearch -exact $treediffs($ids) $fname] < 0} {
8074 lappend treediffs($ids) $fname
8075 add_flist [list $fname]
8076 }
8077
8078 } else {
8079 set line [string range $line 11 end]
8080 # If the name hasn't changed the length will be odd,
8081 # the middle char will be a space, and the two bits either
8082 # side will be a/name and b/name, or "a/name" and "b/name".
8083 # If the name has changed we'll get "rename from" and
8084 # "rename to" or "copy from" and "copy to" lines following
8085 # this, and we'll use them to get the filenames.
8086 # This complexity is necessary because spaces in the
8087 # filename(s) don't get escaped.
8088 set l [string length $line]
8089 set i [expr {$l / 2}]
8090 if {!(($l & 1) && [string index $line $i] eq " " &&
8091 [string range $line 2 [expr {$i - 1}]] eq \
8092 [string range $line [expr {$i + 3}] end])} {
8093 return
8094 }
8095 # unescape if quoted and chop off the a/ from the front
8096 if {[string index $line 0] eq "\""} {
8097 set fname [string range [lindex $line 0] 2 end]
8098 } else {
8099 set fname [string range $line 2 [expr {$i - 1}]]
8100 }
8101 }
8102 makediffhdr $fname $ids
8103
8104 } elseif {![string compare -length 16 "* Unmerged path " $line]} {
8105 set fname [encoding convertfrom [string range $line 16 end]]
8106 $ctext insert end "\n"
8107 set curdiffstart [$ctext index "end - 1c"]
8108 lappend ctext_file_names $fname
8109 lappend ctext_file_lines [lindex [split $curdiffstart "."] 0]
8110 $ctext insert end "$line\n" filesep
8111 set i [lsearch -exact $treediffs($ids) $fname]
8112 if {$i >= 0} {
8113 setinlist difffilestart $i $curdiffstart
8114 }
8115
8116 } elseif {![string compare -length 2 "@@" $line]} {
8117 regexp {^@@+} $line ats
8118 set line [encoding convertfrom $diffencoding $line]
8119 $ctext insert end "$line\n" hunksep
8120 if {[regexp { \+(\d+),\d+ @@} $line m nl]} {
8121 set diffline $nl
8122 }
8123 set diffnparents [expr {[string length $ats] - 1}]
8124 set diffinhdr 0
8125
8126 } elseif {![string compare -length 10 "Submodule " $line]} {
8127 # start of a new submodule
8128 if {[regexp -indices "\[0-9a-f\]+\\.\\." $line nameend]} {
8129 set fname [string range $line 10 [expr [lindex $nameend 0] - 2]]
8130 } else {
8131 set fname [string range $line 10 [expr [string first "contains " $line] - 2]]
8132 }
8133 if {$currdiffsubmod != $fname} {
8134 $ctext insert end "\n"; # Add newline after commit message
8135 }
8136 set curdiffstart [$ctext index "end - 1c"]
8137 lappend ctext_file_names ""
8138 if {$currdiffsubmod != $fname} {
8139 lappend ctext_file_lines $fname
8140 makediffhdr $fname $ids
8141 set currdiffsubmod $fname
8142 $ctext insert end "\n$line\n" filesep
8143 } else {
8144 $ctext insert end "$line\n" filesep
8145 }
8146 } elseif {![string compare -length 3 " >" $line]} {
8147 set $currdiffsubmod ""
8148 set line [encoding convertfrom $diffencoding $line]
8149 $ctext insert end "$line\n" dresult
8150 } elseif {![string compare -length 3 " <" $line]} {
8151 set $currdiffsubmod ""
8152 set line [encoding convertfrom $diffencoding $line]
8153 $ctext insert end "$line\n" d0
8154 } elseif {$diffinhdr} {
8155 if {![string compare -length 12 "rename from " $line]} {
8156 set fname [string range $line [expr 6 + [string first " from " $line] ] end]
8157 if {[string index $fname 0] eq "\""} {
8158 set fname [lindex $fname 0]
8159 }
8160 set fname [encoding convertfrom $fname]
8161 set i [lsearch -exact $treediffs($ids) $fname]
8162 if {$i >= 0} {
8163 setinlist difffilestart $i $curdiffstart
8164 }
8165 } elseif {![string compare -length 10 $line "rename to "] ||
8166 ![string compare -length 8 $line "copy to "]} {
8167 set fname [string range $line [expr 4 + [string first " to " $line] ] end]
8168 if {[string index $fname 0] eq "\""} {
8169 set fname [lindex $fname 0]
8170 }
8171 makediffhdr $fname $ids
8172 } elseif {[string compare -length 3 $line "---"] == 0} {
8173 # do nothing
8174 return
8175 } elseif {[string compare -length 3 $line "+++"] == 0} {
8176 set diffinhdr 0
8177 return
8178 }
8179 $ctext insert end "$line\n" filesep
8180
8181 } else {
8182 set line [string map {\x1A ^Z} \
8183 [encoding convertfrom $diffencoding $line]]
8184 # parse the prefix - one ' ', '-' or '+' for each parent
8185 set prefix [string range $line 0 [expr {$diffnparents - 1}]]
8186 set tag [expr {$diffnparents > 1? "m": "d"}]
8187 set dowords [expr {$worddiff ne [mc "Line diff"] && $diffnparents == 1}]
8188 set words_pre_markup ""
8189 set words_post_markup ""
8190 if {[string trim $prefix " -+"] eq {}} {
8191 # prefix only has " ", "-" and "+" in it: normal diff line
8192 set num [string first "-" $prefix]
8193 if {$dowords} {
8194 set line [string range $line 1 end]
8195 }
8196 if {$num >= 0} {
8197 # removed line, first parent with line is $num
8198 if {$num >= $mergemax} {
8199 set num "max"
8200 }
8201 if {$dowords && $worddiff eq [mc "Markup words"]} {
8202 $ctext insert end "\[-$line-\]" $tag$num
8203 } else {
8204 $ctext insert end "$line" $tag$num
8205 }
8206 if {!$dowords} {
8207 $ctext insert end "\n" $tag$num
8208 }
8209 } else {
8210 set tags {}
8211 if {[string first "+" $prefix] >= 0} {
8212 # added line
8213 lappend tags ${tag}result
8214 if {$diffnparents > 1} {
8215 set num [string first " " $prefix]
8216 if {$num >= 0} {
8217 if {$num >= $mergemax} {
8218 set num "max"
8219 }
8220 lappend tags m$num
8221 }
8222 }
8223 set words_pre_markup "{+"
8224 set words_post_markup "+}"
8225 }
8226 if {$targetline ne {}} {
8227 if {$diffline == $targetline} {
8228 set diffseehere [$ctext index "end - 1 chars"]
8229 set targetline {}
8230 } else {
8231 incr diffline
8232 }
8233 }
8234 if {$dowords && $worddiff eq [mc "Markup words"]} {
8235 $ctext insert end "$words_pre_markup$line$words_post_markup" $tags
8236 } else {
8237 $ctext insert end "$line" $tags
8238 }
8239 if {!$dowords} {
8240 $ctext insert end "\n" $tags
8241 }
8242 }
8243 } elseif {$dowords && $prefix eq "~"} {
8244 $ctext insert end "\n" {}
8245 } else {
8246 # "\ No newline at end of file",
8247 # or something else we don't recognize
8248 $ctext insert end "$line\n" hunksep
8249 }
8250 }
8251}
8252
Paul Mackerrasa8d610a2007-04-19 11:39:12 +10008253proc changediffdisp {} {
8254 global ctext diffelide
8255
8256 $ctext tag conf d0 -elide [lindex $diffelide 0]
Paul Mackerras8b07dca2008-11-02 22:34:47 +11008257 $ctext tag conf dresult -elide [lindex $diffelide 1]
Paul Mackerrasa8d610a2007-04-19 11:39:12 +10008258}
8259
Stefan Hallerb9671352012-09-19 20:17:27 +02008260proc highlightfile {cline} {
8261 global cflist cflist_top
Paul Mackerrasf4c54b32008-05-10 13:15:36 +10008262
Stefan Hallerce837c92012-10-04 22:50:16 +02008263 if {![info exists cflist_top]} return
8264
Paul Mackerrasf4c54b32008-05-10 13:15:36 +10008265 $cflist tag remove highlight $cflist_top.0 "$cflist_top.0 lineend"
8266 $cflist tag add highlight $cline.0 "$cline.0 lineend"
8267 $cflist see $cline.0
8268 set cflist_top $cline
8269}
8270
Stefan Hallerb9671352012-09-19 20:17:27 +02008271proc highlightfile_for_scrollpos {topidx} {
Stefan Haller978904b2012-10-04 22:50:17 +02008272 global cmitmode difffilestart
Stefan Hallerb9671352012-09-19 20:17:27 +02008273
Stefan Haller978904b2012-10-04 22:50:17 +02008274 if {$cmitmode eq "tree"} return
Stefan Hallerb9671352012-09-19 20:17:27 +02008275 if {![info exists difffilestart]} return
8276
8277 set top [lindex [split $topidx .] 0]
8278 if {$difffilestart eq {} || $top < [lindex $difffilestart 0]} {
8279 highlightfile 0
8280 } else {
8281 highlightfile [expr {[bsearch $difffilestart $top] + 2}]
8282 }
8283}
8284
OGAWA Hirofumi67c22872006-09-27 12:32:19 +09008285proc prevfile {} {
Paul Mackerrasf4c54b32008-05-10 13:15:36 +10008286 global difffilestart ctext cmitmode
8287
8288 if {$cmitmode eq "tree"} return
8289 set prev 0.0
OGAWA Hirofumi67c22872006-09-27 12:32:19 +09008290 set here [$ctext index @0,0]
8291 foreach loc $difffilestart {
8292 if {[$ctext compare $loc >= $here]} {
Stefan Hallerb9671352012-09-19 20:17:27 +02008293 $ctext yview $prev
OGAWA Hirofumi67c22872006-09-27 12:32:19 +09008294 return
8295 }
8296 set prev $loc
8297 }
Stefan Hallerb9671352012-09-19 20:17:27 +02008298 $ctext yview $prev
OGAWA Hirofumi67c22872006-09-27 12:32:19 +09008299}
8300
Paul Mackerras39ad8572005-05-19 12:35:53 +00008301proc nextfile {} {
Paul Mackerrasf4c54b32008-05-10 13:15:36 +10008302 global difffilestart ctext cmitmode
8303
8304 if {$cmitmode eq "tree"} return
Paul Mackerras39ad8572005-05-19 12:35:53 +00008305 set here [$ctext index @0,0]
Paul Mackerras7fcceed2006-04-27 19:21:49 +10008306 foreach loc $difffilestart {
8307 if {[$ctext compare $loc > $here]} {
Stefan Hallerb9671352012-09-19 20:17:27 +02008308 $ctext yview $loc
OGAWA Hirofumi67c22872006-09-27 12:32:19 +09008309 return
Paul Mackerras39ad8572005-05-19 12:35:53 +00008310 }
8311 }
Paul Mackerras1db95b02005-05-09 04:08:39 +00008312}
8313
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008314proc clear_ctext {{first 1.0}} {
8315 global ctext smarktop smarkbot
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04008316 global ctext_file_names ctext_file_lines
Paul Mackerras97645682007-08-23 22:24:38 +10008317 global pendinglinks
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008318
Paul Mackerras1902c272006-05-25 21:25:13 +10008319 set l [lindex [split $first .] 0]
8320 if {![info exists smarktop] || [$ctext compare $first < $smarktop.0]} {
8321 set smarktop $l
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008322 }
Paul Mackerras1902c272006-05-25 21:25:13 +10008323 if {![info exists smarkbot] || [$ctext compare $first < $smarkbot.0]} {
8324 set smarkbot $l
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008325 }
8326 $ctext delete $first end
Paul Mackerras97645682007-08-23 22:24:38 +10008327 if {$first eq "1.0"} {
8328 catch {unset pendinglinks}
8329 }
Alexander Gavrilov7cdc3552008-10-24 12:13:01 +04008330 set ctext_file_names {}
8331 set ctext_file_lines {}
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008332}
8333
Paul Mackerras32f1b3e2007-09-28 21:27:39 +10008334proc settabs {{firstab {}}} {
Paul Mackerras9c311b32007-10-04 22:27:13 +10008335 global firsttabstop tabstop ctext have_tk85
Paul Mackerras32f1b3e2007-09-28 21:27:39 +10008336
8337 if {$firstab ne {} && $have_tk85} {
8338 set firsttabstop $firstab
8339 }
Paul Mackerras9c311b32007-10-04 22:27:13 +10008340 set w [font measure textfont "0"]
Paul Mackerras32f1b3e2007-09-28 21:27:39 +10008341 if {$firsttabstop != 0} {
Paul Mackerras64b5f142007-10-04 22:19:24 +10008342 $ctext conf -tabs [list [expr {($firsttabstop + $tabstop) * $w}] \
8343 [expr {($firsttabstop + 2 * $tabstop) * $w}]]
Paul Mackerras32f1b3e2007-09-28 21:27:39 +10008344 } elseif {$have_tk85 || $tabstop != 8} {
8345 $ctext conf -tabs [expr {$tabstop * $w}]
8346 } else {
8347 $ctext conf -tabs {}
8348 }
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008349}
8350
8351proc incrsearch {name ix op} {
Paul Mackerras1902c272006-05-25 21:25:13 +10008352 global ctext searchstring searchdirn
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008353
Paul Mackerras1902c272006-05-25 21:25:13 +10008354 if {[catch {$ctext index anchor}]} {
8355 # no anchor set, use start of selection, or of visible area
8356 set sel [$ctext tag ranges sel]
8357 if {$sel ne {}} {
8358 $ctext mark set anchor [lindex $sel 0]
8359 } elseif {$searchdirn eq "-forwards"} {
8360 $ctext mark set anchor @0,0
8361 } else {
8362 $ctext mark set anchor @0,[winfo height $ctext]
8363 }
8364 }
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008365 if {$searchstring ne {}} {
Stefan Haller30441a62012-09-22 09:40:25 +02008366 set here [$ctext search -count mlen $searchdirn -- $searchstring anchor]
Paul Mackerras1902c272006-05-25 21:25:13 +10008367 if {$here ne {}} {
8368 $ctext see $here
Stefan Haller30441a62012-09-22 09:40:25 +02008369 set mend "$here + $mlen c"
8370 $ctext tag remove sel 1.0 end
8371 $ctext tag add sel $here $mend
Stefan Hallerb9671352012-09-19 20:17:27 +02008372 suppress_highlighting_file_for_current_scrollpos
8373 highlightfile_for_scrollpos $here
Paul Mackerras1902c272006-05-25 21:25:13 +10008374 }
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008375 }
Stefan Hallerc4614992012-09-22 09:40:24 +02008376 rehighlight_search_results
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008377}
8378
8379proc dosearch {} {
Paul Mackerras1902c272006-05-25 21:25:13 +10008380 global sstring ctext searchstring searchdirn
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008381
8382 focus $sstring
8383 $sstring icursor end
Paul Mackerras1902c272006-05-25 21:25:13 +10008384 set searchdirn -forwards
8385 if {$searchstring ne {}} {
8386 set sel [$ctext tag ranges sel]
8387 if {$sel ne {}} {
8388 set start "[lindex $sel 0] + 1c"
8389 } elseif {[catch {set start [$ctext index anchor]}]} {
8390 set start "@0,0"
8391 }
8392 set match [$ctext search -count mlen -- $searchstring $start]
8393 $ctext tag remove sel 1.0 end
8394 if {$match eq {}} {
8395 bell
8396 return
8397 }
8398 $ctext see $match
Stefan Hallerb9671352012-09-19 20:17:27 +02008399 suppress_highlighting_file_for_current_scrollpos
8400 highlightfile_for_scrollpos $match
Paul Mackerras1902c272006-05-25 21:25:13 +10008401 set mend "$match + $mlen c"
8402 $ctext tag add sel $match $mend
8403 $ctext mark unset anchor
Stefan Hallerc4614992012-09-22 09:40:24 +02008404 rehighlight_search_results
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008405 }
Paul Mackerras1902c272006-05-25 21:25:13 +10008406}
8407
8408proc dosearchback {} {
8409 global sstring ctext searchstring searchdirn
8410
8411 focus $sstring
8412 $sstring icursor end
8413 set searchdirn -backwards
8414 if {$searchstring ne {}} {
8415 set sel [$ctext tag ranges sel]
8416 if {$sel ne {}} {
8417 set start [lindex $sel 0]
8418 } elseif {[catch {set start [$ctext index anchor]}]} {
8419 set start @0,[winfo height $ctext]
8420 }
8421 set match [$ctext search -backwards -count ml -- $searchstring $start]
8422 $ctext tag remove sel 1.0 end
8423 if {$match eq {}} {
8424 bell
8425 return
8426 }
8427 $ctext see $match
Stefan Hallerb9671352012-09-19 20:17:27 +02008428 suppress_highlighting_file_for_current_scrollpos
8429 highlightfile_for_scrollpos $match
Paul Mackerras1902c272006-05-25 21:25:13 +10008430 set mend "$match + $ml c"
8431 $ctext tag add sel $match $mend
8432 $ctext mark unset anchor
Stefan Hallerc4614992012-09-22 09:40:24 +02008433 rehighlight_search_results
8434 }
8435}
8436
8437proc rehighlight_search_results {} {
8438 global ctext searchstring
8439
8440 $ctext tag remove found 1.0 end
8441 $ctext tag remove currentsearchhit 1.0 end
8442
8443 if {$searchstring ne {}} {
8444 searchmarkvisible 1
Paul Mackerras1902c272006-05-25 21:25:13 +10008445 }
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008446}
8447
8448proc searchmark {first last} {
8449 global ctext searchstring
8450
Stefan Hallerc4614992012-09-22 09:40:24 +02008451 set sel [$ctext tag ranges sel]
8452
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008453 set mend $first.0
8454 while {1} {
8455 set match [$ctext search -count mlen -- $searchstring $mend $last.end]
8456 if {$match eq {}} break
8457 set mend "$match + $mlen c"
Stefan Hallerc4614992012-09-22 09:40:24 +02008458 if {$sel ne {} && [$ctext compare $match == [lindex $sel 0]]} {
8459 $ctext tag add currentsearchhit $match $mend
8460 } else {
8461 $ctext tag add found $match $mend
8462 }
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008463 }
8464}
8465
8466proc searchmarkvisible {doall} {
8467 global ctext smarktop smarkbot
8468
8469 set topline [lindex [split [$ctext index @0,0] .] 0]
8470 set botline [lindex [split [$ctext index @0,[winfo height $ctext]] .] 0]
8471 if {$doall || $botline < $smarktop || $topline > $smarkbot} {
8472 # no overlap with previous
8473 searchmark $topline $botline
8474 set smarktop $topline
8475 set smarkbot $botline
8476 } else {
8477 if {$topline < $smarktop} {
8478 searchmark $topline [expr {$smarktop-1}]
8479 set smarktop $topline
8480 }
8481 if {$botline > $smarkbot} {
8482 searchmark [expr {$smarkbot+1}] $botline
8483 set smarkbot $botline
8484 }
8485 }
8486}
8487
Stefan Hallerb9671352012-09-19 20:17:27 +02008488proc suppress_highlighting_file_for_current_scrollpos {} {
8489 global ctext suppress_highlighting_file_for_this_scrollpos
8490
8491 set suppress_highlighting_file_for_this_scrollpos [$ctext index @0,0]
8492}
8493
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008494proc scrolltext {f0 f1} {
Stefan Hallerb9671352012-09-19 20:17:27 +02008495 global searchstring cmitmode ctext
8496 global suppress_highlighting_file_for_this_scrollpos
8497
Stefan Haller978904b2012-10-04 22:50:17 +02008498 set topidx [$ctext index @0,0]
8499 if {![info exists suppress_highlighting_file_for_this_scrollpos]
8500 || $topidx ne $suppress_highlighting_file_for_this_scrollpos} {
8501 highlightfile_for_scrollpos $topidx
Stefan Hallerb9671352012-09-19 20:17:27 +02008502 }
8503
8504 catch {unset suppress_highlighting_file_for_this_scrollpos}
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008505
Pekka Kaitaniemi8809d692008-03-08 14:27:23 +02008506 .bleft.bottom.sb set $f0 $f1
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008507 if {$searchstring ne {}} {
8508 searchmarkvisible 0
8509 }
8510}
8511
Paul Mackerras1d10f362005-05-15 12:55:47 +00008512proc setcoords {} {
Paul Mackerras9c311b32007-10-04 22:27:13 +10008513 global linespc charspc canvx0 canvy0
Paul Mackerrasf6075eb2005-08-18 09:30:10 +10008514 global xspc1 xspc2 lthickness
Paul Mackerras8d858d12005-08-05 09:52:16 +10008515
Paul Mackerras9c311b32007-10-04 22:27:13 +10008516 set linespc [font metrics mainfont -linespace]
8517 set charspc [font measure mainfont "m"]
Paul Mackerras9f1afe02006-02-19 22:44:47 +11008518 set canvy0 [expr {int(3 + 0.5 * $linespc)}]
8519 set canvx0 [expr {int(3 + 0.5 * $linespc)}]
Paul Mackerrasf6075eb2005-08-18 09:30:10 +10008520 set lthickness [expr {int($linespc / 9) + 1}]
Paul Mackerras8d858d12005-08-05 09:52:16 +10008521 set xspc1(0) $linespc
8522 set xspc2 $linespc
Paul Mackerras9a40c502005-05-12 23:46:16 +00008523}
Paul Mackerras1db95b02005-05-09 04:08:39 +00008524
Paul Mackerras1d10f362005-05-15 12:55:47 +00008525proc redisplay {} {
Paul Mackerrasbe0cd092006-03-31 09:55:11 +11008526 global canv
Paul Mackerras9f1afe02006-02-19 22:44:47 +11008527 global selectedline
8528
8529 set ymax [lindex [$canv cget -scrollregion] 3]
8530 if {$ymax eq {} || $ymax == 0} return
8531 set span [$canv yview]
8532 clear_display
Paul Mackerrasbe0cd092006-03-31 09:55:11 +11008533 setcanvscroll
Paul Mackerras9f1afe02006-02-19 22:44:47 +11008534 allcanvs yview moveto [lindex $span 0]
8535 drawvisible
Paul Mackerras94b4a692008-05-20 20:51:06 +10008536 if {$selectedline ne {}} {
Paul Mackerras9f1afe02006-02-19 22:44:47 +11008537 selectline $selectedline 0
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10008538 allcanvs yview moveto [lindex $span 0]
Paul Mackerras1db95b02005-05-09 04:08:39 +00008539 }
8540}
Paul Mackerras1d10f362005-05-15 12:55:47 +00008541
Paul Mackerras0ed1dd32007-10-06 18:27:37 +10008542proc parsefont {f n} {
8543 global fontattr
8544
8545 set fontattr($f,family) [lindex $n 0]
8546 set s [lindex $n 1]
8547 if {$s eq {} || $s == 0} {
8548 set s 10
8549 } elseif {$s < 0} {
8550 set s [expr {int(-$s / [winfo fpixels . 1p] + 0.5)}]
Paul Mackerras9c311b32007-10-04 22:27:13 +10008551 }
Paul Mackerras0ed1dd32007-10-06 18:27:37 +10008552 set fontattr($f,size) $s
8553 set fontattr($f,weight) normal
8554 set fontattr($f,slant) roman
8555 foreach style [lrange $n 2 end] {
8556 switch -- $style {
8557 "normal" -
8558 "bold" {set fontattr($f,weight) $style}
8559 "roman" -
8560 "italic" {set fontattr($f,slant) $style}
8561 }
Paul Mackerras9c311b32007-10-04 22:27:13 +10008562 }
Paul Mackerras0ed1dd32007-10-06 18:27:37 +10008563}
8564
8565proc fontflags {f {isbold 0}} {
8566 global fontattr
8567
8568 return [list -family $fontattr($f,family) -size $fontattr($f,size) \
8569 -weight [expr {$isbold? "bold": $fontattr($f,weight)}] \
8570 -slant $fontattr($f,slant)]
8571}
8572
8573proc fontname {f} {
8574 global fontattr
8575
8576 set n [list $fontattr($f,family) $fontattr($f,size)]
8577 if {$fontattr($f,weight) eq "bold"} {
8578 lappend n "bold"
Paul Mackerras9c311b32007-10-04 22:27:13 +10008579 }
Paul Mackerras0ed1dd32007-10-06 18:27:37 +10008580 if {$fontattr($f,slant) eq "italic"} {
8581 lappend n "italic"
Paul Mackerras9c311b32007-10-04 22:27:13 +10008582 }
Paul Mackerras0ed1dd32007-10-06 18:27:37 +10008583 return $n
Paul Mackerras9c311b32007-10-04 22:27:13 +10008584}
8585
Paul Mackerras1d10f362005-05-15 12:55:47 +00008586proc incrfont {inc} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11008587 global mainfont textfont ctext canv cflist showrefstop
Paul Mackerras0ed1dd32007-10-06 18:27:37 +10008588 global stopped entries fontattr
8589
Paul Mackerras1d10f362005-05-15 12:55:47 +00008590 unmarkmatches
Paul Mackerras0ed1dd32007-10-06 18:27:37 +10008591 set s $fontattr(mainfont,size)
Paul Mackerras9c311b32007-10-04 22:27:13 +10008592 incr s $inc
8593 if {$s < 1} {
8594 set s 1
8595 }
Paul Mackerras0ed1dd32007-10-06 18:27:37 +10008596 set fontattr(mainfont,size) $s
Paul Mackerras9c311b32007-10-04 22:27:13 +10008597 font config mainfont -size $s
8598 font config mainfontbold -size $s
Paul Mackerras0ed1dd32007-10-06 18:27:37 +10008599 set mainfont [fontname mainfont]
8600 set s $fontattr(textfont,size)
Paul Mackerras9c311b32007-10-04 22:27:13 +10008601 incr s $inc
8602 if {$s < 1} {
8603 set s 1
8604 }
Paul Mackerras0ed1dd32007-10-06 18:27:37 +10008605 set fontattr(textfont,size) $s
Paul Mackerras9c311b32007-10-04 22:27:13 +10008606 font config textfont -size $s
8607 font config textfontbold -size $s
Paul Mackerras0ed1dd32007-10-06 18:27:37 +10008608 set textfont [fontname textfont]
Paul Mackerras1d10f362005-05-15 12:55:47 +00008609 setcoords
Paul Mackerras32f1b3e2007-09-28 21:27:39 +10008610 settabs
Paul Mackerras1d10f362005-05-15 12:55:47 +00008611 redisplay
Paul Mackerras1db95b02005-05-09 04:08:39 +00008612}
Paul Mackerras1d10f362005-05-15 12:55:47 +00008613
Paul Mackerrasee3dc722005-06-25 16:37:13 +10008614proc clearsha1 {} {
8615 global sha1entry sha1string
8616 if {[string length $sha1string] == 40} {
8617 $sha1entry delete 0 end
8618 }
8619}
8620
Paul Mackerras887fe3c2005-05-21 07:35:37 +00008621proc sha1change {n1 n2 op} {
8622 global sha1string currentid sha1but
8623 if {$sha1string == {}
8624 || ([info exists currentid] && $sha1string == $currentid)} {
8625 set state disabled
8626 } else {
8627 set state normal
8628 }
8629 if {[$sha1but cget -state] == $state} return
8630 if {$state == "normal"} {
Christian Stimmingd990ced2007-11-07 18:42:55 +01008631 $sha1but conf -state normal -relief raised -text "[mc "Goto:"] "
Paul Mackerras887fe3c2005-05-21 07:35:37 +00008632 } else {
Christian Stimmingd990ced2007-11-07 18:42:55 +01008633 $sha1but conf -state disabled -relief flat -text "[mc "SHA1 ID:"] "
Paul Mackerras887fe3c2005-05-21 07:35:37 +00008634 }
8635}
8636
8637proc gotocommit {} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11008638 global sha1string tagids headids curview varcid
Paul Mackerrasf3b8b3c2005-07-18 12:16:35 -04008639
Paul Mackerras887fe3c2005-05-21 07:35:37 +00008640 if {$sha1string == {}
8641 || ([info exists currentid] && $sha1string == $currentid)} return
8642 if {[info exists tagids($sha1string)]} {
8643 set id $tagids($sha1string)
Stephen Rothwelle1007122006-03-30 16:13:12 +11008644 } elseif {[info exists headids($sha1string)]} {
8645 set id $headids($sha1string)
Paul Mackerras887fe3c2005-05-21 07:35:37 +00008646 } else {
8647 set id [string tolower $sha1string]
Paul Mackerrasf3b8b3c2005-07-18 12:16:35 -04008648 if {[regexp {^[0-9a-f]{4,39}$} $id]} {
Paul Mackerrasd375ef92008-10-21 10:18:12 +11008649 set matches [longid $id]
Paul Mackerrasf3b8b3c2005-07-18 12:16:35 -04008650 if {$matches ne {}} {
8651 if {[llength $matches] > 1} {
Christian Stimmingd990ced2007-11-07 18:42:55 +01008652 error_popup [mc "Short SHA1 id %s is ambiguous" $id]
Paul Mackerrasf3b8b3c2005-07-18 12:16:35 -04008653 return
8654 }
Paul Mackerrasd375ef92008-10-21 10:18:12 +11008655 set id [lindex $matches 0]
Paul Mackerrasf3b8b3c2005-07-18 12:16:35 -04008656 }
Thomas Rast9bf3acf2009-08-13 09:25:03 +02008657 } else {
8658 if {[catch {set id [exec git rev-parse --verify $sha1string]}]} {
8659 error_popup [mc "Revision %s is not known" $sha1string]
8660 return
8661 }
Paul Mackerrasf3b8b3c2005-07-18 12:16:35 -04008662 }
Paul Mackerras887fe3c2005-05-21 07:35:37 +00008663 }
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11008664 if {[commitinview $id $curview]} {
8665 selectline [rowofcommit $id] 1
Paul Mackerras887fe3c2005-05-21 07:35:37 +00008666 return
8667 }
Paul Mackerrasf3b8b3c2005-07-18 12:16:35 -04008668 if {[regexp {^[0-9a-fA-F]{4,}$} $sha1string]} {
Christian Stimmingd990ced2007-11-07 18:42:55 +01008669 set msg [mc "SHA1 id %s is not known" $sha1string]
Paul Mackerras887fe3c2005-05-21 07:35:37 +00008670 } else {
Thomas Rast9bf3acf2009-08-13 09:25:03 +02008671 set msg [mc "Revision %s is not in the current view" $sha1string]
Paul Mackerras887fe3c2005-05-21 07:35:37 +00008672 }
Christian Stimmingd990ced2007-11-07 18:42:55 +01008673 error_popup $msg
Paul Mackerras887fe3c2005-05-21 07:35:37 +00008674}
8675
Paul Mackerras84ba7342005-06-17 00:12:26 +00008676proc lineenter {x y id} {
8677 global hoverx hovery hoverid hovertimer
8678 global commitinfo canv
8679
Paul Mackerras8ed16482006-03-02 22:56:44 +11008680 if {![info exists commitinfo($id)] && ![getcommit $id]} return
Paul Mackerras84ba7342005-06-17 00:12:26 +00008681 set hoverx $x
8682 set hovery $y
8683 set hoverid $id
8684 if {[info exists hovertimer]} {
8685 after cancel $hovertimer
8686 }
8687 set hovertimer [after 500 linehover]
8688 $canv delete hover
8689}
8690
8691proc linemotion {x y id} {
8692 global hoverx hovery hoverid hovertimer
8693
8694 if {[info exists hoverid] && $id == $hoverid} {
8695 set hoverx $x
8696 set hovery $y
8697 if {[info exists hovertimer]} {
8698 after cancel $hovertimer
8699 }
8700 set hovertimer [after 500 linehover]
8701 }
8702}
8703
8704proc lineleave {id} {
8705 global hoverid hovertimer canv
8706
8707 if {[info exists hoverid] && $id == $hoverid} {
8708 $canv delete hover
8709 if {[info exists hovertimer]} {
8710 after cancel $hovertimer
8711 unset hovertimer
8712 }
8713 unset hoverid
8714 }
8715}
8716
8717proc linehover {} {
8718 global hoverx hovery hoverid hovertimer
8719 global canv linespc lthickness
Gauthier Östervall252c52d2013-03-27 14:40:51 +01008720 global linehoverbgcolor linehoverfgcolor linehoveroutlinecolor
8721
Paul Mackerras9c311b32007-10-04 22:27:13 +10008722 global commitinfo
Paul Mackerras84ba7342005-06-17 00:12:26 +00008723
8724 set text [lindex $commitinfo($hoverid) 0]
8725 set ymax [lindex [$canv cget -scrollregion] 3]
8726 if {$ymax == {}} return
8727 set yfrac [lindex [$canv yview] 0]
8728 set x [expr {$hoverx + 2 * $linespc}]
8729 set y [expr {$hovery + $yfrac * $ymax - $linespc / 2}]
8730 set x0 [expr {$x - 2 * $lthickness}]
8731 set y0 [expr {$y - 2 * $lthickness}]
Paul Mackerras9c311b32007-10-04 22:27:13 +10008732 set x1 [expr {$x + [font measure mainfont $text] + 2 * $lthickness}]
Paul Mackerras84ba7342005-06-17 00:12:26 +00008733 set y1 [expr {$y + $linespc + 2 * $lthickness}]
8734 set t [$canv create rectangle $x0 $y0 $x1 $y1 \
Gauthier Östervall252c52d2013-03-27 14:40:51 +01008735 -fill $linehoverbgcolor -outline $linehoveroutlinecolor \
8736 -width 1 -tags hover]
Paul Mackerras84ba7342005-06-17 00:12:26 +00008737 $canv raise $t
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +10008738 set t [$canv create text $x $y -anchor nw -text $text -tags hover \
Gauthier Östervall252c52d2013-03-27 14:40:51 +01008739 -font mainfont -fill $linehoverfgcolor]
Paul Mackerras84ba7342005-06-17 00:12:26 +00008740 $canv raise $t
8741}
8742
Paul Mackerras9843c302005-08-30 10:57:11 +10008743proc clickisonarrow {id y} {
Paul Mackerras50b44ec2006-04-04 10:16:22 +10008744 global lthickness
Paul Mackerras9843c302005-08-30 10:57:11 +10008745
Paul Mackerras50b44ec2006-04-04 10:16:22 +10008746 set ranges [rowranges $id]
Paul Mackerras9843c302005-08-30 10:57:11 +10008747 set thresh [expr {2 * $lthickness + 6}]
Paul Mackerras50b44ec2006-04-04 10:16:22 +10008748 set n [expr {[llength $ranges] - 1}]
Paul Mackerrasf6342482006-02-28 10:02:03 +11008749 for {set i 1} {$i < $n} {incr i} {
Paul Mackerras50b44ec2006-04-04 10:16:22 +10008750 set row [lindex $ranges $i]
Paul Mackerrasf6342482006-02-28 10:02:03 +11008751 if {abs([yc $row] - $y) < $thresh} {
8752 return $i
Paul Mackerras9843c302005-08-30 10:57:11 +10008753 }
8754 }
8755 return {}
8756}
8757
Paul Mackerrasf6342482006-02-28 10:02:03 +11008758proc arrowjump {id n y} {
Paul Mackerras50b44ec2006-04-04 10:16:22 +10008759 global canv
Paul Mackerras9843c302005-08-30 10:57:11 +10008760
Paul Mackerrasf6342482006-02-28 10:02:03 +11008761 # 1 <-> 2, 3 <-> 4, etc...
8762 set n [expr {(($n - 1) ^ 1) + 1}]
Paul Mackerras50b44ec2006-04-04 10:16:22 +10008763 set row [lindex [rowranges $id] $n]
Paul Mackerrasf6342482006-02-28 10:02:03 +11008764 set yt [yc $row]
Paul Mackerras9843c302005-08-30 10:57:11 +10008765 set ymax [lindex [$canv cget -scrollregion] 3]
8766 if {$ymax eq {} || $ymax <= 0} return
8767 set view [$canv yview]
8768 set yspan [expr {[lindex $view 1] - [lindex $view 0]}]
8769 set yfrac [expr {$yt / $ymax - $yspan / 2}]
8770 if {$yfrac < 0} {
8771 set yfrac 0
8772 }
Paul Mackerrasf6342482006-02-28 10:02:03 +11008773 allcanvs yview moveto $yfrac
Paul Mackerras9843c302005-08-30 10:57:11 +10008774}
8775
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10008776proc lineclick {x y id isnew} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11008777 global ctext commitinfo children canv thickerline curview
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008778
Paul Mackerras8ed16482006-03-02 22:56:44 +11008779 if {![info exists commitinfo($id)] && ![getcommit $id]} return
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008780 unmarkmatches
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10008781 unselectline
Paul Mackerras9843c302005-08-30 10:57:11 +10008782 normalline
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008783 $canv delete hover
Paul Mackerras9843c302005-08-30 10:57:11 +10008784 # draw this line thicker than normal
Paul Mackerras9843c302005-08-30 10:57:11 +10008785 set thickerline $id
Paul Mackerrasc934a8a2006-03-02 23:00:44 +11008786 drawlines $id
Paul Mackerras9843c302005-08-30 10:57:11 +10008787 if {$isnew} {
8788 set ymax [lindex [$canv cget -scrollregion] 3]
8789 if {$ymax eq {}} return
8790 set yfrac [lindex [$canv yview] 0]
8791 set y [expr {$y + $yfrac * $ymax}]
8792 }
8793 set dirn [clickisonarrow $id $y]
8794 if {$dirn ne {}} {
8795 arrowjump $id $dirn $y
8796 return
8797 }
8798
8799 if {$isnew} {
Paul Mackerras354af6b2008-11-23 13:14:23 +11008800 addtohistory [list lineclick $x $y $id 0] savectextpos
Paul Mackerras9843c302005-08-30 10:57:11 +10008801 }
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008802 # fill the details pane with info about this line
8803 $ctext conf -state normal
Paul Mackerras3ea06f92006-05-24 10:16:03 +10008804 clear_ctext
Paul Mackerras32f1b3e2007-09-28 21:27:39 +10008805 settabs 0
Christian Stimmingd990ced2007-11-07 18:42:55 +01008806 $ctext insert end "[mc "Parent"]:\t"
Paul Mackerras97645682007-08-23 22:24:38 +10008807 $ctext insert end $id link0
8808 setlink $id link0
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008809 set info $commitinfo($id)
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10008810 $ctext insert end "\n\t[lindex $info 0]\n"
Christian Stimmingd990ced2007-11-07 18:42:55 +01008811 $ctext insert end "\t[mc "Author"]:\t[lindex $info 1]\n"
Paul Mackerras232475d2005-11-15 10:34:03 +11008812 set date [formatdate [lindex $info 2]]
Christian Stimmingd990ced2007-11-07 18:42:55 +01008813 $ctext insert end "\t[mc "Date"]:\t$date\n"
Paul Mackerrasda7c24d2006-05-02 11:15:29 +10008814 set kids $children($curview,$id)
Paul Mackerras79b2c752006-04-02 20:47:40 +10008815 if {$kids ne {}} {
Christian Stimmingd990ced2007-11-07 18:42:55 +01008816 $ctext insert end "\n[mc "Children"]:"
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10008817 set i 0
Paul Mackerras79b2c752006-04-02 20:47:40 +10008818 foreach child $kids {
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10008819 incr i
Paul Mackerras8ed16482006-03-02 22:56:44 +11008820 if {![info exists commitinfo($child)] && ![getcommit $child]} continue
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008821 set info $commitinfo($child)
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10008822 $ctext insert end "\n\t"
Paul Mackerras97645682007-08-23 22:24:38 +10008823 $ctext insert end $child link$i
8824 setlink $child link$i
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10008825 $ctext insert end "\n\t[lindex $info 0]"
Christian Stimmingd990ced2007-11-07 18:42:55 +01008826 $ctext insert end "\n\t[mc "Author"]:\t[lindex $info 1]"
Paul Mackerras232475d2005-11-15 10:34:03 +11008827 set date [formatdate [lindex $info 2]]
Christian Stimmingd990ced2007-11-07 18:42:55 +01008828 $ctext insert end "\n\t[mc "Date"]:\t$date\n"
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008829 }
8830 }
Paul Mackerras354af6b2008-11-23 13:14:23 +11008831 maybe_scroll_ctext 1
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008832 $ctext conf -state disabled
Paul Mackerras7fcceed2006-04-27 19:21:49 +10008833 init_flist {}
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008834}
8835
Paul Mackerras9843c302005-08-30 10:57:11 +10008836proc normalline {} {
8837 global thickerline
8838 if {[info exists thickerline]} {
Paul Mackerrasc934a8a2006-03-02 23:00:44 +11008839 set id $thickerline
Paul Mackerras9843c302005-08-30 10:57:11 +10008840 unset thickerline
Paul Mackerrasc934a8a2006-03-02 23:00:44 +11008841 drawlines $id
Paul Mackerras9843c302005-08-30 10:57:11 +10008842 }
8843}
8844
Paul Mackerras354af6b2008-11-23 13:14:23 +11008845proc selbyid {id {isnew 1}} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11008846 global curview
8847 if {[commitinview $id $curview]} {
Paul Mackerras354af6b2008-11-23 13:14:23 +11008848 selectline [rowofcommit $id] $isnew
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008849 }
8850}
8851
8852proc mstime {} {
8853 global startmstime
8854 if {![info exists startmstime]} {
8855 set startmstime [clock clicks -milliseconds]
8856 }
8857 return [format "%.3f" [expr {([clock click -milliseconds] - $startmstime) / 1000.0}]]
8858}
8859
8860proc rowmenu {x y id} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11008861 global rowctxmenu selectedline rowmenuid curview
Paul Mackerrasb9fdba72009-04-09 09:34:46 +10008862 global nullid nullid2 fakerowmenu mainhead markedid
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008863
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10008864 stopfinding
Paul Mackerras219ea3a2006-09-07 10:21:39 +10008865 set rowmenuid $id
Paul Mackerras94b4a692008-05-20 20:51:06 +10008866 if {$selectedline eq {} || [rowofcommit $id] eq $selectedline} {
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008867 set state disabled
8868 } else {
8869 set state normal
8870 }
Paul Mackerras6febded2012-03-23 22:07:27 +11008871 if {[info exists markedid] && $markedid ne $id} {
8872 set mstate normal
8873 } else {
8874 set mstate disabled
8875 }
Paul Mackerras8f489362007-07-13 19:49:37 +10008876 if {$id ne $nullid && $id ne $nullid2} {
Paul Mackerras219ea3a2006-09-07 10:21:39 +10008877 set menu $rowctxmenu
Michele Ballabio5e3502d2008-05-02 17:46:20 +02008878 if {$mainhead ne {}} {
Johannes Sixtda12e592008-12-03 13:43:20 +01008879 $menu entryconfigure 7 -label [mc "Reset %s branch to here" $mainhead] -state normal
Michele Ballabio5e3502d2008-05-02 17:46:20 +02008880 } else {
8881 $menu entryconfigure 7 -label [mc "Detached head: can't reset" $mainhead] -state disabled
8882 }
Paul Mackerras6febded2012-03-23 22:07:27 +11008883 $menu entryconfigure 9 -state $mstate
8884 $menu entryconfigure 10 -state $mstate
8885 $menu entryconfigure 11 -state $mstate
Paul Mackerras219ea3a2006-09-07 10:21:39 +10008886 } else {
8887 set menu $fakerowmenu
8888 }
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +11008889 $menu entryconfigure [mca "Diff this -> selected"] -state $state
8890 $menu entryconfigure [mca "Diff selected -> this"] -state $state
8891 $menu entryconfigure [mca "Make patch"] -state $state
Paul Mackerras6febded2012-03-23 22:07:27 +11008892 $menu entryconfigure [mca "Diff this -> marked commit"] -state $mstate
8893 $menu entryconfigure [mca "Diff marked commit -> this"] -state $mstate
Paul Mackerras219ea3a2006-09-07 10:21:39 +10008894 tk_popup $menu $x $y
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10008895}
8896
Paul Mackerrasb9fdba72009-04-09 09:34:46 +10008897proc markhere {} {
8898 global rowmenuid markedid canv
8899
8900 set markedid $rowmenuid
8901 make_idmark $markedid
8902}
8903
8904proc gotomark {} {
8905 global markedid
8906
8907 if {[info exists markedid]} {
8908 selbyid $markedid
8909 }
8910}
8911
8912proc replace_by_kids {l r} {
8913 global curview children
8914
8915 set id [commitonrow $r]
8916 set l [lreplace $l 0 0]
8917 foreach kid $children($curview,$id) {
8918 lappend l [rowofcommit $kid]
8919 }
8920 return [lsort -integer -decreasing -unique $l]
8921}
8922
8923proc find_common_desc {} {
8924 global markedid rowmenuid curview children
8925
8926 if {![info exists markedid]} return
8927 if {![commitinview $markedid $curview] ||
8928 ![commitinview $rowmenuid $curview]} return
8929 #set t1 [clock clicks -milliseconds]
8930 set l1 [list [rowofcommit $markedid]]
8931 set l2 [list [rowofcommit $rowmenuid]]
8932 while 1 {
8933 set r1 [lindex $l1 0]
8934 set r2 [lindex $l2 0]
8935 if {$r1 eq {} || $r2 eq {}} break
8936 if {$r1 == $r2} {
8937 selectline $r1 1
8938 break
8939 }
8940 if {$r1 > $r2} {
8941 set l1 [replace_by_kids $l1 $r1]
8942 } else {
8943 set l2 [replace_by_kids $l2 $r2]
8944 }
8945 }
8946 #set t2 [clock clicks -milliseconds]
8947 #puts "took [expr {$t2-$t1}]ms"
8948}
8949
Paul Mackerras010509f2009-04-09 22:10:20 +10008950proc compare_commits {} {
8951 global markedid rowmenuid curview children
8952
8953 if {![info exists markedid]} return
8954 if {![commitinview $markedid $curview]} return
8955 addtohistory [list do_cmp_commits $markedid $rowmenuid]
8956 do_cmp_commits $markedid $rowmenuid
8957}
8958
8959proc getpatchid {id} {
8960 global patchids
8961
8962 if {![info exists patchids($id)]} {
Paul Mackerras6f63fc12009-04-21 22:22:31 +10008963 set cmd [diffcmd [list $id] {-p --root}]
8964 # trim off the initial "|"
8965 set cmd [lrange $cmd 1 end]
8966 if {[catch {
8967 set x [eval exec $cmd | git patch-id]
8968 set patchids($id) [lindex $x 0]
8969 }]} {
8970 set patchids($id) "error"
8971 }
Paul Mackerras010509f2009-04-09 22:10:20 +10008972 }
8973 return $patchids($id)
8974}
8975
8976proc do_cmp_commits {a b} {
8977 global ctext curview parents children patchids commitinfo
8978
8979 $ctext conf -state normal
8980 clear_ctext
8981 init_flist {}
8982 for {set i 0} {$i < 100} {incr i} {
Paul Mackerras010509f2009-04-09 22:10:20 +10008983 set skipa 0
8984 set skipb 0
8985 if {[llength $parents($curview,$a)] > 1} {
Paul Mackerras6f63fc12009-04-21 22:22:31 +10008986 appendshortlink $a [mc "Skipping merge commit "] "\n"
Paul Mackerras010509f2009-04-09 22:10:20 +10008987 set skipa 1
8988 } else {
8989 set patcha [getpatchid $a]
8990 }
8991 if {[llength $parents($curview,$b)] > 1} {
Paul Mackerras6f63fc12009-04-21 22:22:31 +10008992 appendshortlink $b [mc "Skipping merge commit "] "\n"
Paul Mackerras010509f2009-04-09 22:10:20 +10008993 set skipb 1
8994 } else {
8995 set patchb [getpatchid $b]
8996 }
8997 if {!$skipa && !$skipb} {
8998 set heada [lindex $commitinfo($a) 0]
8999 set headb [lindex $commitinfo($b) 0]
Paul Mackerras6f63fc12009-04-21 22:22:31 +10009000 if {$patcha eq "error"} {
9001 appendshortlink $a [mc "Error getting patch ID for "] \
9002 [mc " - stopping\n"]
9003 break
9004 }
9005 if {$patchb eq "error"} {
9006 appendshortlink $b [mc "Error getting patch ID for "] \
9007 [mc " - stopping\n"]
9008 break
9009 }
Paul Mackerras010509f2009-04-09 22:10:20 +10009010 if {$patcha eq $patchb} {
9011 if {$heada eq $headb} {
Paul Mackerras6f63fc12009-04-21 22:22:31 +10009012 appendshortlink $a [mc "Commit "]
9013 appendshortlink $b " == " " $heada\n"
Paul Mackerras010509f2009-04-09 22:10:20 +10009014 } else {
Paul Mackerras6f63fc12009-04-21 22:22:31 +10009015 appendshortlink $a [mc "Commit "] " $heada\n"
9016 appendshortlink $b [mc " is the same patch as\n "] \
9017 " $headb\n"
Paul Mackerras010509f2009-04-09 22:10:20 +10009018 }
9019 set skipa 1
9020 set skipb 1
9021 } else {
9022 $ctext insert end "\n"
Paul Mackerras6f63fc12009-04-21 22:22:31 +10009023 appendshortlink $a [mc "Commit "] " $heada\n"
9024 appendshortlink $b [mc " differs from\n "] \
9025 " $headb\n"
Paul Mackerrasc21398b2009-09-07 10:08:21 +10009026 $ctext insert end [mc "Diff of commits:\n\n"]
9027 $ctext conf -state disabled
9028 update
9029 diffcommits $a $b
9030 return
Paul Mackerras010509f2009-04-09 22:10:20 +10009031 }
9032 }
9033 if {$skipa} {
Paul Mackerrasaa435612009-09-10 21:58:40 +10009034 set kids [real_children $curview,$a]
9035 if {[llength $kids] != 1} {
Paul Mackerras010509f2009-04-09 22:10:20 +10009036 $ctext insert end "\n"
Paul Mackerras6f63fc12009-04-21 22:22:31 +10009037 appendshortlink $a [mc "Commit "] \
Paul Mackerrasaa435612009-09-10 21:58:40 +10009038 [mc " has %s children - stopping\n" [llength $kids]]
Paul Mackerras010509f2009-04-09 22:10:20 +10009039 break
9040 }
Paul Mackerrasaa435612009-09-10 21:58:40 +10009041 set a [lindex $kids 0]
Paul Mackerras010509f2009-04-09 22:10:20 +10009042 }
9043 if {$skipb} {
Paul Mackerrasaa435612009-09-10 21:58:40 +10009044 set kids [real_children $curview,$b]
9045 if {[llength $kids] != 1} {
Paul Mackerras6f63fc12009-04-21 22:22:31 +10009046 appendshortlink $b [mc "Commit "] \
Paul Mackerrasaa435612009-09-10 21:58:40 +10009047 [mc " has %s children - stopping\n" [llength $kids]]
Paul Mackerras010509f2009-04-09 22:10:20 +10009048 break
9049 }
Paul Mackerrasaa435612009-09-10 21:58:40 +10009050 set b [lindex $kids 0]
Paul Mackerras010509f2009-04-09 22:10:20 +10009051 }
9052 }
9053 $ctext conf -state disabled
9054}
9055
Paul Mackerrasc21398b2009-09-07 10:08:21 +10009056proc diffcommits {a b} {
Jens Lehmanna1d383c2010-04-09 22:16:42 +02009057 global diffcontext diffids blobdifffd diffinhdr currdiffsubmod
Paul Mackerrasc21398b2009-09-07 10:08:21 +10009058
9059 set tmpdir [gitknewtmpdir]
9060 set fna [file join $tmpdir "commit-[string range $a 0 7]"]
9061 set fnb [file join $tmpdir "commit-[string range $b 0 7]"]
9062 if {[catch {
9063 exec git diff-tree -p --pretty $a >$fna
9064 exec git diff-tree -p --pretty $b >$fnb
9065 } err]} {
9066 error_popup [mc "Error writing commit to file: %s" $err]
9067 return
9068 }
9069 if {[catch {
9070 set fd [open "| diff -U$diffcontext $fna $fnb" r]
9071 } err]} {
9072 error_popup [mc "Error diffing commits: %s" $err]
9073 return
9074 }
9075 set diffids [list commits $a $b]
9076 set blobdifffd($diffids) $fd
9077 set diffinhdr 0
Jens Lehmanna1d383c2010-04-09 22:16:42 +02009078 set currdiffsubmod ""
Paul Mackerrasc21398b2009-09-07 10:08:21 +10009079 filerun $fd [list getblobdiffline $fd $diffids]
9080}
9081
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10009082proc diffvssel {dirn} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11009083 global rowmenuid selectedline
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10009084
Paul Mackerras94b4a692008-05-20 20:51:06 +10009085 if {$selectedline eq {}} return
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10009086 if {$dirn} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11009087 set oldid [commitonrow $selectedline]
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10009088 set newid $rowmenuid
9089 } else {
9090 set oldid $rowmenuid
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11009091 set newid [commitonrow $selectedline]
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10009092 }
Paul Mackerras354af6b2008-11-23 13:14:23 +11009093 addtohistory [list doseldiff $oldid $newid] savectextpos
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10009094 doseldiff $oldid $newid
9095}
9096
Paul Mackerras6febded2012-03-23 22:07:27 +11009097proc diffvsmark {dirn} {
9098 global rowmenuid markedid
9099
9100 if {![info exists markedid]} return
9101 if {$dirn} {
9102 set oldid $markedid
9103 set newid $rowmenuid
9104 } else {
9105 set oldid $rowmenuid
9106 set newid $markedid
9107 }
9108 addtohistory [list doseldiff $oldid $newid] savectextpos
9109 doseldiff $oldid $newid
9110}
9111
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10009112proc doseldiff {oldid newid} {
Paul Mackerras7fcceed2006-04-27 19:21:49 +10009113 global ctext
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10009114 global commitinfo
9115
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10009116 $ctext conf -state normal
Paul Mackerras3ea06f92006-05-24 10:16:03 +10009117 clear_ctext
Christian Stimmingd990ced2007-11-07 18:42:55 +01009118 init_flist [mc "Top"]
9119 $ctext insert end "[mc "From"] "
Paul Mackerras97645682007-08-23 22:24:38 +10009120 $ctext insert end $oldid link0
9121 setlink $oldid link0
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10009122 $ctext insert end "\n "
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10009123 $ctext insert end [lindex $commitinfo($oldid) 0]
Christian Stimmingd990ced2007-11-07 18:42:55 +01009124 $ctext insert end "\n\n[mc "To"] "
Paul Mackerras97645682007-08-23 22:24:38 +10009125 $ctext insert end $newid link1
9126 setlink $newid link1
Paul Mackerrasfa4da7b2005-08-08 09:47:22 +10009127 $ctext insert end "\n "
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10009128 $ctext insert end [lindex $commitinfo($newid) 0]
9129 $ctext insert end "\n"
9130 $ctext conf -state disabled
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10009131 $ctext tag remove found 1.0 end
Paul Mackerrasd3272442005-11-28 20:41:56 +11009132 startdiff [list $oldid $newid]
Paul Mackerrasc8dfbcf2005-06-25 15:39:21 +10009133}
9134
Paul Mackerras74daedb2005-06-27 19:27:32 +10009135proc mkpatch {} {
Pat Thoytsd93f1712009-04-17 01:24:35 +01009136 global rowmenuid currentid commitinfo patchtop patchnum NS
Paul Mackerras74daedb2005-06-27 19:27:32 +10009137
9138 if {![info exists currentid]} return
9139 set oldid $currentid
9140 set oldhead [lindex $commitinfo($oldid) 0]
9141 set newid $rowmenuid
9142 set newhead [lindex $commitinfo($newid) 0]
9143 set top .patch
9144 set patchtop $top
9145 catch {destroy $top}
Pat Thoytsd93f1712009-04-17 01:24:35 +01009146 ttk_toplevel $top
Alexander Gavrilove7d64002008-11-11 23:55:42 +03009147 make_transient $top .
Pat Thoytsd93f1712009-04-17 01:24:35 +01009148 ${NS}::label $top.title -text [mc "Generate patch"]
Paul Mackerras4a2139f2005-06-29 09:47:48 +10009149 grid $top.title - -pady 10
Pat Thoytsd93f1712009-04-17 01:24:35 +01009150 ${NS}::label $top.from -text [mc "From:"]
9151 ${NS}::entry $top.fromsha1 -width 40
Paul Mackerras74daedb2005-06-27 19:27:32 +10009152 $top.fromsha1 insert 0 $oldid
9153 $top.fromsha1 conf -state readonly
9154 grid $top.from $top.fromsha1 -sticky w
Pat Thoytsd93f1712009-04-17 01:24:35 +01009155 ${NS}::entry $top.fromhead -width 60
Paul Mackerras74daedb2005-06-27 19:27:32 +10009156 $top.fromhead insert 0 $oldhead
9157 $top.fromhead conf -state readonly
9158 grid x $top.fromhead -sticky w
Pat Thoytsd93f1712009-04-17 01:24:35 +01009159 ${NS}::label $top.to -text [mc "To:"]
9160 ${NS}::entry $top.tosha1 -width 40
Paul Mackerras74daedb2005-06-27 19:27:32 +10009161 $top.tosha1 insert 0 $newid
9162 $top.tosha1 conf -state readonly
9163 grid $top.to $top.tosha1 -sticky w
Pat Thoytsd93f1712009-04-17 01:24:35 +01009164 ${NS}::entry $top.tohead -width 60
Paul Mackerras74daedb2005-06-27 19:27:32 +10009165 $top.tohead insert 0 $newhead
9166 $top.tohead conf -state readonly
9167 grid x $top.tohead -sticky w
Pat Thoytsd93f1712009-04-17 01:24:35 +01009168 ${NS}::button $top.rev -text [mc "Reverse"] -command mkpatchrev
9169 grid $top.rev x -pady 10 -padx 5
9170 ${NS}::label $top.flab -text [mc "Output file:"]
9171 ${NS}::entry $top.fname -width 60
Paul Mackerras74daedb2005-06-27 19:27:32 +10009172 $top.fname insert 0 [file normalize "patch$patchnum.patch"]
9173 incr patchnum
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10009174 grid $top.flab $top.fname -sticky w
Pat Thoytsd93f1712009-04-17 01:24:35 +01009175 ${NS}::frame $top.buts
9176 ${NS}::button $top.buts.gen -text [mc "Generate"] -command mkpatchgo
9177 ${NS}::button $top.buts.can -text [mc "Cancel"] -command mkpatchcan
Alexander Gavrilov76f15942008-11-02 21:59:44 +03009178 bind $top <Key-Return> mkpatchgo
9179 bind $top <Key-Escape> mkpatchcan
Paul Mackerras74daedb2005-06-27 19:27:32 +10009180 grid $top.buts.gen $top.buts.can
9181 grid columnconfigure $top.buts 0 -weight 1 -uniform a
9182 grid columnconfigure $top.buts 1 -weight 1 -uniform a
9183 grid $top.buts - -pady 10 -sticky ew
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10009184 focus $top.fname
Paul Mackerras74daedb2005-06-27 19:27:32 +10009185}
9186
9187proc mkpatchrev {} {
9188 global patchtop
9189
9190 set oldid [$patchtop.fromsha1 get]
9191 set oldhead [$patchtop.fromhead get]
9192 set newid [$patchtop.tosha1 get]
9193 set newhead [$patchtop.tohead get]
9194 foreach e [list fromsha1 fromhead tosha1 tohead] \
9195 v [list $newid $newhead $oldid $oldhead] {
9196 $patchtop.$e conf -state normal
9197 $patchtop.$e delete 0 end
9198 $patchtop.$e insert 0 $v
9199 $patchtop.$e conf -state readonly
9200 }
9201}
9202
9203proc mkpatchgo {} {
Paul Mackerras8f489362007-07-13 19:49:37 +10009204 global patchtop nullid nullid2
Paul Mackerras74daedb2005-06-27 19:27:32 +10009205
9206 set oldid [$patchtop.fromsha1 get]
9207 set newid [$patchtop.tosha1 get]
9208 set fname [$patchtop.fname get]
Paul Mackerras8f489362007-07-13 19:49:37 +10009209 set cmd [diffcmd [list $oldid $newid] -p]
Paul Mackerrasd372e212007-09-15 12:08:38 +10009210 # trim off the initial "|"
9211 set cmd [lrange $cmd 1 end]
Paul Mackerras219ea3a2006-09-07 10:21:39 +10009212 lappend cmd >$fname &
9213 if {[catch {eval exec $cmd} err]} {
Alexander Gavrilov84a76f12008-11-02 21:59:45 +03009214 error_popup "[mc "Error creating patch:"] $err" $patchtop
Paul Mackerras74daedb2005-06-27 19:27:32 +10009215 }
9216 catch {destroy $patchtop}
9217 unset patchtop
9218}
9219
9220proc mkpatchcan {} {
9221 global patchtop
9222
9223 catch {destroy $patchtop}
9224 unset patchtop
9225}
9226
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10009227proc mktag {} {
Pat Thoytsd93f1712009-04-17 01:24:35 +01009228 global rowmenuid mktagtop commitinfo NS
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10009229
9230 set top .maketag
9231 set mktagtop $top
9232 catch {destroy $top}
Pat Thoytsd93f1712009-04-17 01:24:35 +01009233 ttk_toplevel $top
Alexander Gavrilove7d64002008-11-11 23:55:42 +03009234 make_transient $top .
Pat Thoytsd93f1712009-04-17 01:24:35 +01009235 ${NS}::label $top.title -text [mc "Create tag"]
Paul Mackerras4a2139f2005-06-29 09:47:48 +10009236 grid $top.title - -pady 10
Pat Thoytsd93f1712009-04-17 01:24:35 +01009237 ${NS}::label $top.id -text [mc "ID:"]
9238 ${NS}::entry $top.sha1 -width 40
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10009239 $top.sha1 insert 0 $rowmenuid
9240 $top.sha1 conf -state readonly
9241 grid $top.id $top.sha1 -sticky w
Pat Thoytsd93f1712009-04-17 01:24:35 +01009242 ${NS}::entry $top.head -width 60
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10009243 $top.head insert 0 [lindex $commitinfo($rowmenuid) 0]
9244 $top.head conf -state readonly
9245 grid x $top.head -sticky w
Pat Thoytsd93f1712009-04-17 01:24:35 +01009246 ${NS}::label $top.tlab -text [mc "Tag name:"]
9247 ${NS}::entry $top.tag -width 60
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10009248 grid $top.tlab $top.tag -sticky w
Dave Dulsondfb891e2010-01-03 14:55:52 +00009249 ${NS}::label $top.op -text [mc "Tag message is optional"]
9250 grid $top.op -columnspan 2 -sticky we
9251 ${NS}::label $top.mlab -text [mc "Tag message:"]
9252 ${NS}::entry $top.msg -width 60
9253 grid $top.mlab $top.msg -sticky w
Pat Thoytsd93f1712009-04-17 01:24:35 +01009254 ${NS}::frame $top.buts
9255 ${NS}::button $top.buts.gen -text [mc "Create"] -command mktaggo
9256 ${NS}::button $top.buts.can -text [mc "Cancel"] -command mktagcan
Alexander Gavrilov76f15942008-11-02 21:59:44 +03009257 bind $top <Key-Return> mktaggo
9258 bind $top <Key-Escape> mktagcan
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10009259 grid $top.buts.gen $top.buts.can
9260 grid columnconfigure $top.buts 0 -weight 1 -uniform a
9261 grid columnconfigure $top.buts 1 -weight 1 -uniform a
9262 grid $top.buts - -pady 10 -sticky ew
9263 focus $top.tag
9264}
9265
9266proc domktag {} {
9267 global mktagtop env tagids idtags
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10009268
9269 set id [$mktagtop.sha1 get]
9270 set tag [$mktagtop.tag get]
Dave Dulsondfb891e2010-01-03 14:55:52 +00009271 set msg [$mktagtop.msg get]
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10009272 if {$tag == {}} {
Alexander Gavrilov84a76f12008-11-02 21:59:45 +03009273 error_popup [mc "No tag name specified"] $mktagtop
9274 return 0
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10009275 }
9276 if {[info exists tagids($tag)]} {
Alexander Gavrilov84a76f12008-11-02 21:59:45 +03009277 error_popup [mc "Tag \"%s\" already exists" $tag] $mktagtop
9278 return 0
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10009279 }
9280 if {[catch {
Dave Dulsondfb891e2010-01-03 14:55:52 +00009281 if {$msg != {}} {
9282 exec git tag -a -m $msg $tag $id
9283 } else {
9284 exec git tag $tag $id
9285 }
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10009286 } err]} {
Alexander Gavrilov84a76f12008-11-02 21:59:45 +03009287 error_popup "[mc "Error creating tag:"] $err" $mktagtop
9288 return 0
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10009289 }
9290
9291 set tagids($tag) $id
9292 lappend idtags($id) $tag
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10009293 redrawtags $id
Paul Mackerrasceadfe92006-08-08 20:55:36 +10009294 addedtag $id
Paul Mackerras887c9962007-08-20 19:36:20 +10009295 dispneartags 0
9296 run refill_reflist
Alexander Gavrilov84a76f12008-11-02 21:59:45 +03009297 return 1
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10009298}
9299
9300proc redrawtags {id} {
Paul Mackerrasb9fdba72009-04-09 09:34:46 +10009301 global canv linehtag idpos currentid curview cmitlisted markedid
Paul Mackerrasc11ff122008-05-26 10:11:33 +10009302 global canvxmax iddrawn circleitem mainheadid circlecolors
Gauthier Östervall252c52d2013-03-27 14:40:51 +01009303 global mainheadcirclecolor
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10009304
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11009305 if {![commitinview $id $curview]} return
Paul Mackerras322a8cc2006-10-15 18:03:46 +10009306 if {![info exists iddrawn($id)]} return
Paul Mackerrasfc2a2562007-12-26 23:03:43 +11009307 set row [rowofcommit $id]
Paul Mackerrasc11ff122008-05-26 10:11:33 +10009308 if {$id eq $mainheadid} {
Gauthier Östervall252c52d2013-03-27 14:40:51 +01009309 set ofill $mainheadcirclecolor
Paul Mackerrasc11ff122008-05-26 10:11:33 +10009310 } else {
9311 set ofill [lindex $circlecolors $cmitlisted($curview,$id)]
9312 }
9313 $canv itemconf $circleitem($row) -fill $ofill
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10009314 $canv delete tag.$id
9315 set xt [eval drawtags $id $idpos($id)]
Paul Mackerras28593d32008-11-13 23:01:46 +11009316 $canv coords $linehtag($id) $xt [lindex $idpos($id) 2]
9317 set text [$canv itemcget $linehtag($id) -text]
9318 set font [$canv itemcget $linehtag($id) -font]
Paul Mackerrasfc2a2562007-12-26 23:03:43 +11009319 set xr [expr {$xt + [font measure $font $text]}]
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10009320 if {$xr > $canvxmax} {
9321 set canvxmax $xr
9322 setcanvscroll
9323 }
Paul Mackerrasfc2a2562007-12-26 23:03:43 +11009324 if {[info exists currentid] && $currentid == $id} {
Paul Mackerras28593d32008-11-13 23:01:46 +11009325 make_secsel $id
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10009326 }
Paul Mackerrasb9fdba72009-04-09 09:34:46 +10009327 if {[info exists markedid] && $markedid eq $id} {
9328 make_idmark $id
9329 }
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10009330}
9331
9332proc mktagcan {} {
9333 global mktagtop
9334
9335 catch {destroy $mktagtop}
9336 unset mktagtop
9337}
9338
9339proc mktaggo {} {
Alexander Gavrilov84a76f12008-11-02 21:59:45 +03009340 if {![domktag]} return
Paul Mackerrasbdbfbe32005-06-27 22:56:40 +10009341 mktagcan
9342}
9343
Paul Mackerras4a2139f2005-06-29 09:47:48 +10009344proc writecommit {} {
Pat Thoytsd93f1712009-04-17 01:24:35 +01009345 global rowmenuid wrcomtop commitinfo wrcomcmd NS
Paul Mackerras4a2139f2005-06-29 09:47:48 +10009346
9347 set top .writecommit
9348 set wrcomtop $top
9349 catch {destroy $top}
Pat Thoytsd93f1712009-04-17 01:24:35 +01009350 ttk_toplevel $top
Alexander Gavrilove7d64002008-11-11 23:55:42 +03009351 make_transient $top .
Pat Thoytsd93f1712009-04-17 01:24:35 +01009352 ${NS}::label $top.title -text [mc "Write commit to file"]
Paul Mackerras4a2139f2005-06-29 09:47:48 +10009353 grid $top.title - -pady 10
Pat Thoytsd93f1712009-04-17 01:24:35 +01009354 ${NS}::label $top.id -text [mc "ID:"]
9355 ${NS}::entry $top.sha1 -width 40
Paul Mackerras4a2139f2005-06-29 09:47:48 +10009356 $top.sha1 insert 0 $rowmenuid
9357 $top.sha1 conf -state readonly
9358 grid $top.id $top.sha1 -sticky w
Pat Thoytsd93f1712009-04-17 01:24:35 +01009359 ${NS}::entry $top.head -width 60
Paul Mackerras4a2139f2005-06-29 09:47:48 +10009360 $top.head insert 0 [lindex $commitinfo($rowmenuid) 0]
9361 $top.head conf -state readonly
9362 grid x $top.head -sticky w
Pat Thoytsd93f1712009-04-17 01:24:35 +01009363 ${NS}::label $top.clab -text [mc "Command:"]
9364 ${NS}::entry $top.cmd -width 60 -textvariable wrcomcmd
Paul Mackerras4a2139f2005-06-29 09:47:48 +10009365 grid $top.clab $top.cmd -sticky w -pady 10
Pat Thoytsd93f1712009-04-17 01:24:35 +01009366 ${NS}::label $top.flab -text [mc "Output file:"]
9367 ${NS}::entry $top.fname -width 60
Paul Mackerras4a2139f2005-06-29 09:47:48 +10009368 $top.fname insert 0 [file normalize "commit-[string range $rowmenuid 0 6]"]
9369 grid $top.flab $top.fname -sticky w
Pat Thoytsd93f1712009-04-17 01:24:35 +01009370 ${NS}::frame $top.buts
9371 ${NS}::button $top.buts.gen -text [mc "Write"] -command wrcomgo
9372 ${NS}::button $top.buts.can -text [mc "Cancel"] -command wrcomcan
Alexander Gavrilov76f15942008-11-02 21:59:44 +03009373 bind $top <Key-Return> wrcomgo
9374 bind $top <Key-Escape> wrcomcan
Paul Mackerras4a2139f2005-06-29 09:47:48 +10009375 grid $top.buts.gen $top.buts.can
9376 grid columnconfigure $top.buts 0 -weight 1 -uniform a
9377 grid columnconfigure $top.buts 1 -weight 1 -uniform a
9378 grid $top.buts - -pady 10 -sticky ew
9379 focus $top.fname
9380}
9381
9382proc wrcomgo {} {
9383 global wrcomtop
9384
9385 set id [$wrcomtop.sha1 get]
9386 set cmd "echo $id | [$wrcomtop.cmd get]"
9387 set fname [$wrcomtop.fname get]
9388 if {[catch {exec sh -c $cmd >$fname &} err]} {
Alexander Gavrilov84a76f12008-11-02 21:59:45 +03009389 error_popup "[mc "Error writing commit:"] $err" $wrcomtop
Paul Mackerras4a2139f2005-06-29 09:47:48 +10009390 }
9391 catch {destroy $wrcomtop}
9392 unset wrcomtop
9393}
9394
9395proc wrcomcan {} {
9396 global wrcomtop
9397
9398 catch {destroy $wrcomtop}
9399 unset wrcomtop
9400}
9401
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10009402proc mkbranch {} {
Pat Thoytsd93f1712009-04-17 01:24:35 +01009403 global rowmenuid mkbrtop NS
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10009404
9405 set top .makebranch
9406 catch {destroy $top}
Pat Thoytsd93f1712009-04-17 01:24:35 +01009407 ttk_toplevel $top
Alexander Gavrilove7d64002008-11-11 23:55:42 +03009408 make_transient $top .
Pat Thoytsd93f1712009-04-17 01:24:35 +01009409 ${NS}::label $top.title -text [mc "Create new branch"]
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10009410 grid $top.title - -pady 10
Pat Thoytsd93f1712009-04-17 01:24:35 +01009411 ${NS}::label $top.id -text [mc "ID:"]
9412 ${NS}::entry $top.sha1 -width 40
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10009413 $top.sha1 insert 0 $rowmenuid
9414 $top.sha1 conf -state readonly
9415 grid $top.id $top.sha1 -sticky w
Pat Thoytsd93f1712009-04-17 01:24:35 +01009416 ${NS}::label $top.nlab -text [mc "Name:"]
9417 ${NS}::entry $top.name -width 40
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10009418 grid $top.nlab $top.name -sticky w
Pat Thoytsd93f1712009-04-17 01:24:35 +01009419 ${NS}::frame $top.buts
9420 ${NS}::button $top.buts.go -text [mc "Create"] -command [list mkbrgo $top]
9421 ${NS}::button $top.buts.can -text [mc "Cancel"] -command "catch {destroy $top}"
Alexander Gavrilov76f15942008-11-02 21:59:44 +03009422 bind $top <Key-Return> [list mkbrgo $top]
9423 bind $top <Key-Escape> "catch {destroy $top}"
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10009424 grid $top.buts.go $top.buts.can
9425 grid columnconfigure $top.buts 0 -weight 1 -uniform a
9426 grid columnconfigure $top.buts 1 -weight 1 -uniform a
9427 grid $top.buts - -pady 10 -sticky ew
9428 focus $top.name
9429}
9430
9431proc mkbrgo {top} {
9432 global headids idheads
9433
9434 set name [$top.name get]
9435 set id [$top.sha1 get]
Alexander Gavrilovbee866f2008-10-08 11:05:35 +04009436 set cmdargs {}
9437 set old_id {}
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10009438 if {$name eq {}} {
Alexander Gavrilov84a76f12008-11-02 21:59:45 +03009439 error_popup [mc "Please specify a name for the new branch"] $top
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10009440 return
9441 }
Alexander Gavrilovbee866f2008-10-08 11:05:35 +04009442 if {[info exists headids($name)]} {
9443 if {![confirm_popup [mc \
Alexander Gavrilov84a76f12008-11-02 21:59:45 +03009444 "Branch '%s' already exists. Overwrite?" $name] $top]} {
Alexander Gavrilovbee866f2008-10-08 11:05:35 +04009445 return
9446 }
9447 set old_id $headids($name)
9448 lappend cmdargs -f
9449 }
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10009450 catch {destroy $top}
Alexander Gavrilovbee866f2008-10-08 11:05:35 +04009451 lappend cmdargs $name $id
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10009452 nowbusy newbranch
9453 update
9454 if {[catch {
Alexander Gavrilovbee866f2008-10-08 11:05:35 +04009455 eval exec git branch $cmdargs
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10009456 } err]} {
9457 notbusy newbranch
9458 error_popup $err
9459 } else {
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10009460 notbusy newbranch
Alexander Gavrilovbee866f2008-10-08 11:05:35 +04009461 if {$old_id ne {}} {
9462 movehead $id $name
9463 movedhead $id $name
9464 redrawtags $old_id
9465 redrawtags $id
9466 } else {
9467 set headids($name) $id
9468 lappend idheads($id) $name
9469 addedhead $id $name
9470 redrawtags $id
9471 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10009472 dispneartags 0
Paul Mackerras887c9962007-08-20 19:36:20 +10009473 run refill_reflist
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +10009474 }
9475}
9476
Alexander Gavrilov15e35052008-11-02 21:59:47 +03009477proc exec_citool {tool_args {baseid {}}} {
9478 global commitinfo env
9479
9480 set save_env [array get env GIT_AUTHOR_*]
9481
9482 if {$baseid ne {}} {
9483 if {![info exists commitinfo($baseid)]} {
9484 getcommit $baseid
9485 }
9486 set author [lindex $commitinfo($baseid) 1]
9487 set date [lindex $commitinfo($baseid) 2]
9488 if {[regexp {^\s*(\S.*\S|\S)\s*<(.*)>\s*$} \
9489 $author author name email]
9490 && $date ne {}} {
9491 set env(GIT_AUTHOR_NAME) $name
9492 set env(GIT_AUTHOR_EMAIL) $email
9493 set env(GIT_AUTHOR_DATE) $date
9494 }
9495 }
9496
9497 eval exec git citool $tool_args &
9498
9499 array unset env GIT_AUTHOR_*
9500 array set env $save_env
9501}
9502
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10009503proc cherrypick {} {
Paul Mackerras468bcae2008-03-03 10:19:35 +11009504 global rowmenuid curview
Paul Mackerrasb8a938c2008-02-13 22:12:31 +11009505 global mainhead mainheadid
Martin von Zweigbergkda616db2011-04-04 22:14:17 -04009506 global gitdir
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10009507
Paul Mackerrase11f1232007-06-16 20:29:25 +10009508 set oldhead [exec git rev-parse HEAD]
9509 set dheads [descheads $rowmenuid]
9510 if {$dheads ne {} && [lsearch -exact $dheads $oldhead] >= 0} {
Christian Stimmingd990ced2007-11-07 18:42:55 +01009511 set ok [confirm_popup [mc "Commit %s is already\
9512 included in branch %s -- really re-apply it?" \
9513 [string range $rowmenuid 0 7] $mainhead]]
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10009514 if {!$ok} return
9515 }
Christian Stimmingd990ced2007-11-07 18:42:55 +01009516 nowbusy cherrypick [mc "Cherry-picking"]
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10009517 update
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10009518 # Unfortunately git-cherry-pick writes stuff to stderr even when
9519 # no error occurs, and exec takes that as an indication of error...
9520 if {[catch {exec sh -c "git cherry-pick -r $rowmenuid 2>&1"} err]} {
9521 notbusy cherrypick
Alexander Gavrilov15e35052008-11-02 21:59:47 +03009522 if {[regexp -line \
Paul Mackerras887a7912008-11-08 21:37:09 +11009523 {Entry '(.*)' (would be overwritten by merge|not uptodate)} \
9524 $err msg fname]} {
9525 error_popup [mc "Cherry-pick failed because of local changes\
9526 to file '%s'.\nPlease commit, reset or stash\
9527 your changes and try again." $fname]
9528 } elseif {[regexp -line \
Anders Kaseorgb74307f2011-01-19 14:45:00 -05009529 {^(CONFLICT \(.*\):|Automatic cherry-pick failed|error: could not apply)} \
Paul Mackerras887a7912008-11-08 21:37:09 +11009530 $err]} {
9531 if {[confirm_popup [mc "Cherry-pick failed because of merge\
9532 conflict.\nDo you wish to run git citool to\
9533 resolve it?"]]} {
9534 # Force citool to read MERGE_MSG
Martin von Zweigbergkda616db2011-04-04 22:14:17 -04009535 file delete [file join $gitdir "GITGUI_MSG"]
Paul Mackerras887a7912008-11-08 21:37:09 +11009536 exec_citool {} $rowmenuid
9537 }
Alexander Gavrilov15e35052008-11-02 21:59:47 +03009538 } else {
9539 error_popup $err
9540 }
Paul Mackerras887a7912008-11-08 21:37:09 +11009541 run updatecommits
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10009542 return
9543 }
9544 set newhead [exec git rev-parse HEAD]
9545 if {$newhead eq $oldhead} {
9546 notbusy cherrypick
Christian Stimmingd990ced2007-11-07 18:42:55 +01009547 error_popup [mc "No changes committed"]
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10009548 return
9549 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10009550 addnewchild $newhead $oldhead
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11009551 if {[commitinview $oldhead $curview]} {
Paul Mackerrascdc84292008-11-18 19:54:14 +11009552 # XXX this isn't right if we have a path limit...
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11009553 insertrow $newhead $oldhead $curview
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10009554 if {$mainhead ne {}} {
Paul Mackerrase11f1232007-06-16 20:29:25 +10009555 movehead $newhead $mainhead
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10009556 movedhead $newhead $mainhead
9557 }
Paul Mackerrasc11ff122008-05-26 10:11:33 +10009558 set mainheadid $newhead
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10009559 redrawtags $oldhead
9560 redrawtags $newhead
Paul Mackerras46308ea2008-01-15 22:16:32 +11009561 selbyid $newhead
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10009562 }
9563 notbusy cherrypick
9564}
9565
Knut Franke8f3ff932013-04-27 16:36:13 +02009566proc revert {} {
9567 global rowmenuid curview
9568 global mainhead mainheadid
9569 global gitdir
9570
9571 set oldhead [exec git rev-parse HEAD]
9572 set dheads [descheads $rowmenuid]
9573 if { $dheads eq {} || [lsearch -exact $dheads $oldhead] == -1 } {
9574 set ok [confirm_popup [mc "Commit %s is not\
9575 included in branch %s -- really revert it?" \
9576 [string range $rowmenuid 0 7] $mainhead]]
9577 if {!$ok} return
9578 }
9579 nowbusy revert [mc "Reverting"]
9580 update
9581
9582 if [catch {exec git revert --no-edit $rowmenuid} err] {
9583 notbusy revert
9584 if [regexp {files would be overwritten by merge:(\n(( |\t)+[^\n]+\n)+)}\
9585 $err match files] {
9586 regsub {\n( |\t)+} $files "\n" files
9587 error_popup [mc "Revert failed because of local changes to\
9588 the following files:%s Please commit, reset or stash \
9589 your changes and try again." $files]
9590 } elseif [regexp {error: could not revert} $err] {
9591 if [confirm_popup [mc "Revert failed because of merge conflict.\n\
9592 Do you wish to run git citool to resolve it?"]] {
9593 # Force citool to read MERGE_MSG
9594 file delete [file join $gitdir "GITGUI_MSG"]
9595 exec_citool {} $rowmenuid
9596 }
9597 } else { error_popup $err }
9598 run updatecommits
9599 return
9600 }
9601
9602 set newhead [exec git rev-parse HEAD]
9603 if { $newhead eq $oldhead } {
9604 notbusy revert
9605 error_popup [mc "No changes committed"]
9606 return
9607 }
9608
9609 addnewchild $newhead $oldhead
9610
9611 if [commitinview $oldhead $curview] {
9612 # XXX this isn't right if we have a path limit...
9613 insertrow $newhead $oldhead $curview
9614 if {$mainhead ne {}} {
9615 movehead $newhead $mainhead
9616 movedhead $newhead $mainhead
9617 }
9618 set mainheadid $newhead
9619 redrawtags $oldhead
9620 redrawtags $newhead
9621 selbyid $newhead
9622 }
9623
9624 notbusy revert
9625}
9626
Paul Mackerras6fb735a2006-10-19 10:09:06 +10009627proc resethead {} {
Pat Thoytsd93f1712009-04-17 01:24:35 +01009628 global mainhead rowmenuid confirm_ok resettype NS
Paul Mackerras6fb735a2006-10-19 10:09:06 +10009629
9630 set confirm_ok 0
9631 set w ".confirmreset"
Pat Thoytsd93f1712009-04-17 01:24:35 +01009632 ttk_toplevel $w
Alexander Gavrilove7d64002008-11-11 23:55:42 +03009633 make_transient $w .
Christian Stimmingd990ced2007-11-07 18:42:55 +01009634 wm title $w [mc "Confirm reset"]
Pat Thoytsd93f1712009-04-17 01:24:35 +01009635 ${NS}::label $w.m -text \
9636 [mc "Reset branch %s to %s?" $mainhead [string range $rowmenuid 0 7]]
Paul Mackerras6fb735a2006-10-19 10:09:06 +10009637 pack $w.m -side top -fill x -padx 20 -pady 20
Pat Thoytsd93f1712009-04-17 01:24:35 +01009638 ${NS}::labelframe $w.f -text [mc "Reset type:"]
Paul Mackerras6fb735a2006-10-19 10:09:06 +10009639 set resettype mixed
Pat Thoytsd93f1712009-04-17 01:24:35 +01009640 ${NS}::radiobutton $w.f.soft -value soft -variable resettype \
Christian Stimmingd990ced2007-11-07 18:42:55 +01009641 -text [mc "Soft: Leave working tree and index untouched"]
Paul Mackerras6fb735a2006-10-19 10:09:06 +10009642 grid $w.f.soft -sticky w
Pat Thoytsd93f1712009-04-17 01:24:35 +01009643 ${NS}::radiobutton $w.f.mixed -value mixed -variable resettype \
Christian Stimmingd990ced2007-11-07 18:42:55 +01009644 -text [mc "Mixed: Leave working tree untouched, reset index"]
Paul Mackerras6fb735a2006-10-19 10:09:06 +10009645 grid $w.f.mixed -sticky w
Pat Thoytsd93f1712009-04-17 01:24:35 +01009646 ${NS}::radiobutton $w.f.hard -value hard -variable resettype \
Christian Stimmingd990ced2007-11-07 18:42:55 +01009647 -text [mc "Hard: Reset working tree and index\n(discard ALL local changes)"]
Paul Mackerras6fb735a2006-10-19 10:09:06 +10009648 grid $w.f.hard -sticky w
Pat Thoytsd93f1712009-04-17 01:24:35 +01009649 pack $w.f -side top -fill x -padx 4
9650 ${NS}::button $w.ok -text [mc OK] -command "set confirm_ok 1; destroy $w"
Paul Mackerras6fb735a2006-10-19 10:09:06 +10009651 pack $w.ok -side left -fill x -padx 20 -pady 20
Pat Thoytsd93f1712009-04-17 01:24:35 +01009652 ${NS}::button $w.cancel -text [mc Cancel] -command "destroy $w"
Alexander Gavrilov76f15942008-11-02 21:59:44 +03009653 bind $w <Key-Escape> [list destroy $w]
Paul Mackerras6fb735a2006-10-19 10:09:06 +10009654 pack $w.cancel -side right -fill x -padx 20 -pady 20
9655 bind $w <Visibility> "grab $w; focus $w"
9656 tkwait window $w
9657 if {!$confirm_ok} return
Paul Mackerras706d6c32007-06-26 11:09:49 +10009658 if {[catch {set fd [open \
Paul Mackerras08ba8202008-05-12 10:18:38 +10009659 [list | git reset --$resettype $rowmenuid 2>@1] r]} err]} {
Paul Mackerras6fb735a2006-10-19 10:09:06 +10009660 error_popup $err
9661 } else {
Paul Mackerras706d6c32007-06-26 11:09:49 +10009662 dohidelocalchanges
Paul Mackerrasa137a902007-10-23 21:12:49 +10009663 filerun $fd [list readresetstat $fd]
Christian Stimmingd990ced2007-11-07 18:42:55 +01009664 nowbusy reset [mc "Resetting"]
Paul Mackerras46308ea2008-01-15 22:16:32 +11009665 selbyid $rowmenuid
Paul Mackerras706d6c32007-06-26 11:09:49 +10009666 }
9667}
9668
Paul Mackerrasa137a902007-10-23 21:12:49 +10009669proc readresetstat {fd} {
9670 global mainhead mainheadid showlocalchanges rprogcoord
Paul Mackerras706d6c32007-06-26 11:09:49 +10009671
9672 if {[gets $fd line] >= 0} {
9673 if {[regexp {([0-9]+)% \(([0-9]+)/([0-9]+)\)} $line match p m n]} {
Paul Mackerrasa137a902007-10-23 21:12:49 +10009674 set rprogcoord [expr {1.0 * $m / $n}]
9675 adjustprogress
Paul Mackerras706d6c32007-06-26 11:09:49 +10009676 }
9677 return 1
9678 }
Paul Mackerrasa137a902007-10-23 21:12:49 +10009679 set rprogcoord 0
9680 adjustprogress
Paul Mackerras706d6c32007-06-26 11:09:49 +10009681 notbusy reset
9682 if {[catch {close $fd} err]} {
9683 error_popup $err
9684 }
9685 set oldhead $mainheadid
9686 set newhead [exec git rev-parse HEAD]
9687 if {$newhead ne $oldhead} {
9688 movehead $newhead $mainhead
9689 movedhead $newhead $mainhead
9690 set mainheadid $newhead
Paul Mackerras6fb735a2006-10-19 10:09:06 +10009691 redrawtags $oldhead
Paul Mackerras706d6c32007-06-26 11:09:49 +10009692 redrawtags $newhead
Paul Mackerras6fb735a2006-10-19 10:09:06 +10009693 }
9694 if {$showlocalchanges} {
9695 doshowlocalchanges
9696 }
Paul Mackerras706d6c32007-06-26 11:09:49 +10009697 return 0
Paul Mackerras6fb735a2006-10-19 10:09:06 +10009698}
9699
Paul Mackerras10299152006-08-02 09:52:01 +10009700# context menu for a head
9701proc headmenu {x y id head} {
Paul Mackerras00609462007-06-17 17:08:35 +10009702 global headmenuid headmenuhead headctxmenu mainhead
Paul Mackerras10299152006-08-02 09:52:01 +10009703
Paul Mackerrasbb3edc82007-09-27 11:00:25 +10009704 stopfinding
Paul Mackerras10299152006-08-02 09:52:01 +10009705 set headmenuid $id
9706 set headmenuhead $head
Paul Mackerras00609462007-06-17 17:08:35 +10009707 set state normal
Sitaram Chamarty70a5fc42009-11-03 21:30:12 +05309708 if {[string match "remotes/*" $head]} {
9709 set state disabled
9710 }
Paul Mackerras00609462007-06-17 17:08:35 +10009711 if {$head eq $mainhead} {
9712 set state disabled
9713 }
9714 $headctxmenu entryconfigure 0 -state $state
9715 $headctxmenu entryconfigure 1 -state $state
Paul Mackerras10299152006-08-02 09:52:01 +10009716 tk_popup $headctxmenu $x $y
9717}
9718
9719proc cobranch {} {
Paul Mackerrasc11ff122008-05-26 10:11:33 +10009720 global headmenuid headmenuhead headids
Paul Mackerrascdc84292008-11-18 19:54:14 +11009721 global showlocalchanges
Paul Mackerras10299152006-08-02 09:52:01 +10009722
9723 # check the tree is clean first??
Christian Stimmingd990ced2007-11-07 18:42:55 +01009724 nowbusy checkout [mc "Checking out"]
Paul Mackerras10299152006-08-02 09:52:01 +10009725 update
Paul Mackerras219ea3a2006-09-07 10:21:39 +10009726 dohidelocalchanges
Paul Mackerras10299152006-08-02 09:52:01 +10009727 if {[catch {
Paul Mackerras08ba8202008-05-12 10:18:38 +10009728 set fd [open [list | git checkout $headmenuhead 2>@1] r]
Paul Mackerras10299152006-08-02 09:52:01 +10009729 } err]} {
9730 notbusy checkout
9731 error_popup $err
Paul Mackerras08ba8202008-05-12 10:18:38 +10009732 if {$showlocalchanges} {
9733 dodiffindex
Paul Mackerras10299152006-08-02 09:52:01 +10009734 }
Paul Mackerras08ba8202008-05-12 10:18:38 +10009735 } else {
9736 filerun $fd [list readcheckoutstat $fd $headmenuhead $headmenuid]
Paul Mackerras6fb735a2006-10-19 10:09:06 +10009737 }
Paul Mackerras08ba8202008-05-12 10:18:38 +10009738}
9739
9740proc readcheckoutstat {fd newhead newheadid} {
9741 global mainhead mainheadid headids showlocalchanges progresscoords
Paul Mackerrascdc84292008-11-18 19:54:14 +11009742 global viewmainheadid curview
Paul Mackerras08ba8202008-05-12 10:18:38 +10009743
9744 if {[gets $fd line] >= 0} {
9745 if {[regexp {([0-9]+)% \(([0-9]+)/([0-9]+)\)} $line match p m n]} {
9746 set progresscoords [list 0 [expr {1.0 * $m / $n}]]
9747 adjustprogress
9748 }
9749 return 1
9750 }
9751 set progresscoords {0 0}
9752 adjustprogress
9753 notbusy checkout
9754 if {[catch {close $fd} err]} {
9755 error_popup $err
9756 }
Paul Mackerrasc11ff122008-05-26 10:11:33 +10009757 set oldmainid $mainheadid
Paul Mackerras08ba8202008-05-12 10:18:38 +10009758 set mainhead $newhead
9759 set mainheadid $newheadid
Paul Mackerrascdc84292008-11-18 19:54:14 +11009760 set viewmainheadid($curview) $newheadid
Paul Mackerrasc11ff122008-05-26 10:11:33 +10009761 redrawtags $oldmainid
Paul Mackerras08ba8202008-05-12 10:18:38 +10009762 redrawtags $newheadid
9763 selbyid $newheadid
Paul Mackerras6fb735a2006-10-19 10:09:06 +10009764 if {$showlocalchanges} {
9765 dodiffindex
Paul Mackerras10299152006-08-02 09:52:01 +10009766 }
9767}
9768
9769proc rmbranch {} {
Paul Mackerrase11f1232007-06-16 20:29:25 +10009770 global headmenuid headmenuhead mainhead
Paul Mackerrasb1054ac2007-08-15 10:09:47 +10009771 global idheads
Paul Mackerras10299152006-08-02 09:52:01 +10009772
9773 set head $headmenuhead
9774 set id $headmenuid
Paul Mackerras00609462007-06-17 17:08:35 +10009775 # this check shouldn't be needed any more...
Paul Mackerras10299152006-08-02 09:52:01 +10009776 if {$head eq $mainhead} {
Christian Stimmingd990ced2007-11-07 18:42:55 +01009777 error_popup [mc "Cannot delete the currently checked-out branch"]
Paul Mackerras10299152006-08-02 09:52:01 +10009778 return
9779 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10009780 set dheads [descheads $id]
Paul Mackerrasd7b16112007-08-17 17:57:31 +10009781 if {[llength $dheads] == 1 && $idheads($dheads) eq $head} {
Paul Mackerras10299152006-08-02 09:52:01 +10009782 # the stuff on this branch isn't on any other branch
Christian Stimmingd990ced2007-11-07 18:42:55 +01009783 if {![confirm_popup [mc "The commits on branch %s aren't on any other\
9784 branch.\nReally delete branch %s?" $head $head]]} return
Paul Mackerras10299152006-08-02 09:52:01 +10009785 }
9786 nowbusy rmbranch
9787 update
9788 if {[catch {exec git branch -D $head} err]} {
9789 notbusy rmbranch
9790 error_popup $err
9791 return
9792 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10009793 removehead $id $head
Paul Mackerrasca6d8f52006-08-06 21:08:05 +10009794 removedhead $id $head
Paul Mackerras10299152006-08-02 09:52:01 +10009795 redrawtags $id
9796 notbusy rmbranch
Paul Mackerrase11f1232007-06-16 20:29:25 +10009797 dispneartags 0
Paul Mackerras887c9962007-08-20 19:36:20 +10009798 run refill_reflist
9799}
9800
9801# Display a list of tags and heads
9802proc showrefs {} {
Pat Thoytsd93f1712009-04-17 01:24:35 +01009803 global showrefstop bgcolor fgcolor selectbgcolor NS
Paul Mackerras9c311b32007-10-04 22:27:13 +10009804 global bglist fglist reflistfilter reflist maincursor
Paul Mackerras887c9962007-08-20 19:36:20 +10009805
9806 set top .showrefs
9807 set showrefstop $top
9808 if {[winfo exists $top]} {
9809 raise $top
9810 refill_reflist
9811 return
9812 }
Pat Thoytsd93f1712009-04-17 01:24:35 +01009813 ttk_toplevel $top
Christian Stimmingd990ced2007-11-07 18:42:55 +01009814 wm title $top [mc "Tags and heads: %s" [file tail [pwd]]]
Alexander Gavrilove7d64002008-11-11 23:55:42 +03009815 make_transient $top .
Paul Mackerras887c9962007-08-20 19:36:20 +10009816 text $top.list -background $bgcolor -foreground $fgcolor \
Paul Mackerras9c311b32007-10-04 22:27:13 +10009817 -selectbackground $selectbgcolor -font mainfont \
Paul Mackerras887c9962007-08-20 19:36:20 +10009818 -xscrollcommand "$top.xsb set" -yscrollcommand "$top.ysb set" \
9819 -width 30 -height 20 -cursor $maincursor \
9820 -spacing1 1 -spacing3 1 -state disabled
9821 $top.list tag configure highlight -background $selectbgcolor
9822 lappend bglist $top.list
9823 lappend fglist $top.list
Pat Thoytsd93f1712009-04-17 01:24:35 +01009824 ${NS}::scrollbar $top.ysb -command "$top.list yview" -orient vertical
9825 ${NS}::scrollbar $top.xsb -command "$top.list xview" -orient horizontal
Paul Mackerras887c9962007-08-20 19:36:20 +10009826 grid $top.list $top.ysb -sticky nsew
9827 grid $top.xsb x -sticky ew
Pat Thoytsd93f1712009-04-17 01:24:35 +01009828 ${NS}::frame $top.f
9829 ${NS}::label $top.f.l -text "[mc "Filter"]: "
9830 ${NS}::entry $top.f.e -width 20 -textvariable reflistfilter
Paul Mackerras887c9962007-08-20 19:36:20 +10009831 set reflistfilter "*"
9832 trace add variable reflistfilter write reflistfilter_change
9833 pack $top.f.e -side right -fill x -expand 1
9834 pack $top.f.l -side left
9835 grid $top.f - -sticky ew -pady 2
Pat Thoytsd93f1712009-04-17 01:24:35 +01009836 ${NS}::button $top.close -command [list destroy $top] -text [mc "Close"]
Alexander Gavrilov76f15942008-11-02 21:59:44 +03009837 bind $top <Key-Escape> [list destroy $top]
Paul Mackerras887c9962007-08-20 19:36:20 +10009838 grid $top.close -
9839 grid columnconfigure $top 0 -weight 1
9840 grid rowconfigure $top 0 -weight 1
9841 bind $top.list <1> {break}
9842 bind $top.list <B1-Motion> {break}
9843 bind $top.list <ButtonRelease-1> {sel_reflist %W %x %y; break}
9844 set reflist {}
9845 refill_reflist
9846}
9847
9848proc sel_reflist {w x y} {
9849 global showrefstop reflist headids tagids otherrefids
9850
9851 if {![winfo exists $showrefstop]} return
9852 set l [lindex [split [$w index "@$x,$y"] "."] 0]
9853 set ref [lindex $reflist [expr {$l-1}]]
9854 set n [lindex $ref 0]
9855 switch -- [lindex $ref 1] {
9856 "H" {selbyid $headids($n)}
9857 "T" {selbyid $tagids($n)}
9858 "o" {selbyid $otherrefids($n)}
9859 }
9860 $showrefstop.list tag add highlight $l.0 "$l.0 lineend"
9861}
9862
9863proc unsel_reflist {} {
9864 global showrefstop
9865
9866 if {![info exists showrefstop] || ![winfo exists $showrefstop]} return
9867 $showrefstop.list tag remove highlight 0.0 end
9868}
9869
9870proc reflistfilter_change {n1 n2 op} {
9871 global reflistfilter
9872
9873 after cancel refill_reflist
9874 after 200 refill_reflist
9875}
9876
9877proc refill_reflist {} {
9878 global reflist reflistfilter showrefstop headids tagids otherrefids
Paul Mackerrasd375ef92008-10-21 10:18:12 +11009879 global curview
Paul Mackerras887c9962007-08-20 19:36:20 +10009880
9881 if {![info exists showrefstop] || ![winfo exists $showrefstop]} return
9882 set refs {}
9883 foreach n [array names headids] {
9884 if {[string match $reflistfilter $n]} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11009885 if {[commitinview $headids($n) $curview]} {
Paul Mackerras887c9962007-08-20 19:36:20 +10009886 lappend refs [list $n H]
9887 } else {
Paul Mackerrasd375ef92008-10-21 10:18:12 +11009888 interestedin $headids($n) {run refill_reflist}
Paul Mackerras887c9962007-08-20 19:36:20 +10009889 }
9890 }
9891 }
9892 foreach n [array names tagids] {
9893 if {[string match $reflistfilter $n]} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11009894 if {[commitinview $tagids($n) $curview]} {
Paul Mackerras887c9962007-08-20 19:36:20 +10009895 lappend refs [list $n T]
9896 } else {
Paul Mackerrasd375ef92008-10-21 10:18:12 +11009897 interestedin $tagids($n) {run refill_reflist}
Paul Mackerras887c9962007-08-20 19:36:20 +10009898 }
9899 }
9900 }
9901 foreach n [array names otherrefids] {
9902 if {[string match $reflistfilter $n]} {
Paul Mackerras7fcc92b2007-12-03 10:33:01 +11009903 if {[commitinview $otherrefids($n) $curview]} {
Paul Mackerras887c9962007-08-20 19:36:20 +10009904 lappend refs [list $n o]
9905 } else {
Paul Mackerrasd375ef92008-10-21 10:18:12 +11009906 interestedin $otherrefids($n) {run refill_reflist}
Paul Mackerras887c9962007-08-20 19:36:20 +10009907 }
9908 }
9909 }
9910 set refs [lsort -index 0 $refs]
9911 if {$refs eq $reflist} return
9912
9913 # Update the contents of $showrefstop.list according to the
9914 # differences between $reflist (old) and $refs (new)
9915 $showrefstop.list conf -state normal
9916 $showrefstop.list insert end "\n"
9917 set i 0
9918 set j 0
9919 while {$i < [llength $reflist] || $j < [llength $refs]} {
9920 if {$i < [llength $reflist]} {
9921 if {$j < [llength $refs]} {
9922 set cmp [string compare [lindex $reflist $i 0] \
9923 [lindex $refs $j 0]]
9924 if {$cmp == 0} {
9925 set cmp [string compare [lindex $reflist $i 1] \
9926 [lindex $refs $j 1]]
9927 }
9928 } else {
9929 set cmp -1
9930 }
9931 } else {
9932 set cmp 1
9933 }
9934 switch -- $cmp {
9935 -1 {
9936 $showrefstop.list delete "[expr {$j+1}].0" "[expr {$j+2}].0"
9937 incr i
9938 }
9939 0 {
9940 incr i
9941 incr j
9942 }
9943 1 {
9944 set l [expr {$j + 1}]
9945 $showrefstop.list image create $l.0 -align baseline \
9946 -image reficon-[lindex $refs $j 1] -padx 2
9947 $showrefstop.list insert $l.1 "[lindex $refs $j 0]\n"
9948 incr j
9949 }
9950 }
9951 }
9952 set reflist $refs
9953 # delete last newline
9954 $showrefstop.list delete end-2c end-1c
9955 $showrefstop.list conf -state disabled
Paul Mackerras10299152006-08-02 09:52:01 +10009956}
9957
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +10009958# Stuff for finding nearby tags
9959proc getallcommits {} {
Paul Mackerras5cd15b62007-08-30 21:54:17 +10009960 global allcommits nextarc seeds allccache allcwait cachedarcs allcupdate
9961 global idheads idtags idotherrefs allparents tagobjid
Martin von Zweigbergkda616db2011-04-04 22:14:17 -04009962 global gitdir
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +10009963
Paul Mackerrasa69b2d12007-08-13 15:02:02 +10009964 if {![info exists allcommits]} {
Paul Mackerrasa69b2d12007-08-13 15:02:02 +10009965 set nextarc 0
9966 set allcommits 0
9967 set seeds {}
Paul Mackerras5cd15b62007-08-30 21:54:17 +10009968 set allcwait 0
9969 set cachedarcs 0
Martin von Zweigbergkda616db2011-04-04 22:14:17 -04009970 set allccache [file join $gitdir "gitk.cache"]
Paul Mackerras5cd15b62007-08-30 21:54:17 +10009971 if {![catch {
9972 set f [open $allccache r]
9973 set allcwait 1
9974 getcache $f
9975 }]} return
Paul Mackerrasa69b2d12007-08-13 15:02:02 +10009976 }
Paul Mackerrase11f1232007-06-16 20:29:25 +10009977
Paul Mackerras5cd15b62007-08-30 21:54:17 +10009978 if {$allcwait} {
9979 return
Paul Mackerrase11f1232007-06-16 20:29:25 +10009980 }
Paul Mackerras5cd15b62007-08-30 21:54:17 +10009981 set cmd [list | git rev-list --parents]
9982 set allcupdate [expr {$seeds ne {}}]
9983 if {!$allcupdate} {
9984 set ids "--all"
9985 } else {
9986 set refs [concat [array names idheads] [array names idtags] \
9987 [array names idotherrefs]]
9988 set ids {}
9989 set tagobjs {}
9990 foreach name [array names tagobjid] {
9991 lappend tagobjs $tagobjid($name)
9992 }
9993 foreach id [lsort -unique $refs] {
9994 if {![info exists allparents($id)] &&
9995 [lsearch -exact $tagobjs $id] < 0} {
9996 lappend ids $id
9997 }
9998 }
9999 if {$ids ne {}} {
10000 foreach id $seeds {
10001 lappend ids "^$id"
10002 }
10003 }
10004 }
10005 if {$ids ne {}} {
10006 set fd [open [concat $cmd $ids] r]
10007 fconfigure $fd -blocking 0
10008 incr allcommits
10009 nowbusy allcommits
10010 filerun $fd [list getallclines $fd]
10011 } else {
10012 dispneartags 0
10013 }
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +100010014}
10015
Paul Mackerrase11f1232007-06-16 20:29:25 +100010016# Since most commits have 1 parent and 1 child, we group strings of
10017# such commits into "arcs" joining branch/merge points (BMPs), which
10018# are commits that either don't have 1 parent or don't have 1 child.
10019#
10020# arcnos(id) - incoming arcs for BMP, arc we're on for other nodes
10021# arcout(id) - outgoing arcs for BMP
10022# arcids(a) - list of IDs on arc including end but not start
10023# arcstart(a) - BMP ID at start of arc
10024# arcend(a) - BMP ID at end of arc
10025# growing(a) - arc a is still growing
10026# arctags(a) - IDs out of arcids (excluding end) that have tags
10027# archeads(a) - IDs out of arcids (excluding end) that have heads
10028# The start of an arc is at the descendent end, so "incoming" means
10029# coming from descendents, and "outgoing" means going towards ancestors.
Paul Mackerrascec7bec2006-08-02 09:38:10 +100010030
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +100010031proc getallclines {fd} {
Paul Mackerras5cd15b62007-08-30 21:54:17 +100010032 global allparents allchildren idtags idheads nextarc
Paul Mackerrase11f1232007-06-16 20:29:25 +100010033 global arcnos arcids arctags arcout arcend arcstart archeads growing
Paul Mackerras5cd15b62007-08-30 21:54:17 +100010034 global seeds allcommits cachedarcs allcupdate
Pat Thoytsd93f1712009-04-17 01:24:35 +010010035
Paul Mackerrase11f1232007-06-16 20:29:25 +100010036 set nid 0
Paul Mackerras7eb3cb92007-06-17 14:45:00 +100010037 while {[incr nid] <= 1000 && [gets $fd line] >= 0} {
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +100010038 set id [lindex $line 0]
Paul Mackerrase11f1232007-06-16 20:29:25 +100010039 if {[info exists allparents($id)]} {
10040 # seen it already
10041 continue
10042 }
Paul Mackerras5cd15b62007-08-30 21:54:17 +100010043 set cachedarcs 0
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +100010044 set olds [lrange $line 1 end]
10045 set allparents($id) $olds
10046 if {![info exists allchildren($id)]} {
10047 set allchildren($id) {}
Paul Mackerrase11f1232007-06-16 20:29:25 +100010048 set arcnos($id) {}
10049 lappend seeds $id
10050 } else {
10051 set a $arcnos($id)
10052 if {[llength $olds] == 1 && [llength $a] == 1} {
10053 lappend arcids($a) $id
10054 if {[info exists idtags($id)]} {
10055 lappend arctags($a) $id
10056 }
10057 if {[info exists idheads($id)]} {
10058 lappend archeads($a) $id
10059 }
10060 if {[info exists allparents($olds)]} {
10061 # seen parent already
10062 if {![info exists arcout($olds)]} {
10063 splitarc $olds
10064 }
10065 lappend arcids($a) $olds
10066 set arcend($a) $olds
10067 unset growing($a)
10068 }
10069 lappend allchildren($olds) $id
10070 lappend arcnos($olds) $a
10071 continue
10072 }
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +100010073 }
Paul Mackerrase11f1232007-06-16 20:29:25 +100010074 foreach a $arcnos($id) {
10075 lappend arcids($a) $id
10076 set arcend($a) $id
10077 unset growing($a)
10078 }
10079
10080 set ao {}
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +100010081 foreach p $olds {
10082 lappend allchildren($p) $id
Paul Mackerrase11f1232007-06-16 20:29:25 +100010083 set a [incr nextarc]
10084 set arcstart($a) $id
10085 set archeads($a) {}
10086 set arctags($a) {}
10087 set archeads($a) {}
10088 set arcids($a) {}
10089 lappend ao $a
10090 set growing($a) 1
10091 if {[info exists allparents($p)]} {
10092 # seen it already, may need to make a new branch
10093 if {![info exists arcout($p)]} {
10094 splitarc $p
10095 }
10096 lappend arcids($a) $p
10097 set arcend($a) $p
10098 unset growing($a)
10099 }
10100 lappend arcnos($p) $a
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +100010101 }
Paul Mackerrase11f1232007-06-16 20:29:25 +100010102 set arcout($id) $ao
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +100010103 }
Paul Mackerrasf3326b62007-06-18 22:39:21 +100010104 if {$nid > 0} {
10105 global cached_dheads cached_dtags cached_atags
10106 catch {unset cached_dheads}
10107 catch {unset cached_dtags}
10108 catch {unset cached_atags}
10109 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +100010110 if {![eof $fd]} {
10111 return [expr {$nid >= 1000? 2: 1}]
10112 }
Paul Mackerras5cd15b62007-08-30 21:54:17 +100010113 set cacheok 1
10114 if {[catch {
10115 fconfigure $fd -blocking 1
10116 close $fd
10117 } err]} {
10118 # got an error reading the list of commits
10119 # if we were updating, try rereading the whole thing again
10120 if {$allcupdate} {
10121 incr allcommits -1
10122 dropcache $err
10123 return
10124 }
Christian Stimmingd990ced2007-11-07 18:42:55 +010010125 error_popup "[mc "Error reading commit topology information;\
Paul Mackerras5cd15b62007-08-30 21:54:17 +100010126 branch and preceding/following tag information\
Christian Stimmingd990ced2007-11-07 18:42:55 +010010127 will be incomplete."]\n($err)"
Paul Mackerras5cd15b62007-08-30 21:54:17 +100010128 set cacheok 0
10129 }
Paul Mackerrase11f1232007-06-16 20:29:25 +100010130 if {[incr allcommits -1] == 0} {
10131 notbusy allcommits
Paul Mackerras5cd15b62007-08-30 21:54:17 +100010132 if {$cacheok} {
10133 run savecache
10134 }
Paul Mackerrase11f1232007-06-16 20:29:25 +100010135 }
10136 dispneartags 0
Paul Mackerras7eb3cb92007-06-17 14:45:00 +100010137 return 0
Paul Mackerrase11f1232007-06-16 20:29:25 +100010138}
10139
10140proc recalcarc {a} {
10141 global arctags archeads arcids idtags idheads
10142
10143 set at {}
10144 set ah {}
10145 foreach id [lrange $arcids($a) 0 end-1] {
10146 if {[info exists idtags($id)]} {
10147 lappend at $id
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +100010148 }
Paul Mackerrase11f1232007-06-16 20:29:25 +100010149 if {[info exists idheads($id)]} {
10150 lappend ah $id
10151 }
10152 }
10153 set arctags($a) $at
10154 set archeads($a) $ah
10155}
10156
10157proc splitarc {p} {
Paul Mackerras5cd15b62007-08-30 21:54:17 +100010158 global arcnos arcids nextarc arctags archeads idtags idheads
Paul Mackerrase11f1232007-06-16 20:29:25 +100010159 global arcstart arcend arcout allparents growing
10160
10161 set a $arcnos($p)
10162 if {[llength $a] != 1} {
10163 puts "oops splitarc called but [llength $a] arcs already"
10164 return
10165 }
10166 set a [lindex $a 0]
10167 set i [lsearch -exact $arcids($a) $p]
10168 if {$i < 0} {
10169 puts "oops splitarc $p not in arc $a"
10170 return
10171 }
10172 set na [incr nextarc]
10173 if {[info exists arcend($a)]} {
10174 set arcend($na) $arcend($a)
10175 } else {
10176 set l [lindex $allparents([lindex $arcids($a) end]) 0]
10177 set j [lsearch -exact $arcnos($l) $a]
10178 set arcnos($l) [lreplace $arcnos($l) $j $j $na]
10179 }
10180 set tail [lrange $arcids($a) [expr {$i+1}] end]
10181 set arcids($a) [lrange $arcids($a) 0 $i]
10182 set arcend($a) $p
10183 set arcstart($na) $p
10184 set arcout($p) $na
10185 set arcids($na) $tail
10186 if {[info exists growing($a)]} {
10187 set growing($na) 1
10188 unset growing($a)
10189 }
Paul Mackerrase11f1232007-06-16 20:29:25 +100010190
10191 foreach id $tail {
10192 if {[llength $arcnos($id)] == 1} {
10193 set arcnos($id) $na
10194 } else {
10195 set j [lsearch -exact $arcnos($id) $a]
10196 set arcnos($id) [lreplace $arcnos($id) $j $j $na]
10197 }
10198 }
10199
10200 # reconstruct tags and heads lists
10201 if {$arctags($a) ne {} || $archeads($a) ne {}} {
10202 recalcarc $a
10203 recalcarc $na
10204 } else {
10205 set arctags($na) {}
10206 set archeads($na) {}
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +100010207 }
10208}
10209
Paul Mackerrase11f1232007-06-16 20:29:25 +100010210# Update things for a new commit added that is a child of one
10211# existing commit. Used when cherry-picking.
10212proc addnewchild {id p} {
Paul Mackerras5cd15b62007-08-30 21:54:17 +100010213 global allparents allchildren idtags nextarc
Paul Mackerrase11f1232007-06-16 20:29:25 +100010214 global arcnos arcids arctags arcout arcend arcstart archeads growing
Paul Mackerras719c2b92007-08-29 22:41:34 +100010215 global seeds allcommits
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +100010216
Paul Mackerras3ebba3c2007-10-20 22:10:52 +100010217 if {![info exists allcommits] || ![info exists arcnos($p)]} return
Paul Mackerrase11f1232007-06-16 20:29:25 +100010218 set allparents($id) [list $p]
10219 set allchildren($id) {}
10220 set arcnos($id) {}
10221 lappend seeds $id
Paul Mackerrase11f1232007-06-16 20:29:25 +100010222 lappend allchildren($p) $id
10223 set a [incr nextarc]
10224 set arcstart($a) $id
10225 set archeads($a) {}
10226 set arctags($a) {}
10227 set arcids($a) [list $p]
10228 set arcend($a) $p
10229 if {![info exists arcout($p)]} {
10230 splitarc $p
10231 }
10232 lappend arcnos($p) $a
10233 set arcout($id) [list $a]
10234}
10235
Paul Mackerras5cd15b62007-08-30 21:54:17 +100010236# This implements a cache for the topology information.
10237# The cache saves, for each arc, the start and end of the arc,
10238# the ids on the arc, and the outgoing arcs from the end.
10239proc readcache {f} {
10240 global arcnos arcids arcout arcstart arcend arctags archeads nextarc
10241 global idtags idheads allparents cachedarcs possible_seeds seeds growing
10242 global allcwait
10243
10244 set a $nextarc
10245 set lim $cachedarcs
10246 if {$lim - $a > 500} {
10247 set lim [expr {$a + 500}]
10248 }
10249 if {[catch {
10250 if {$a == $lim} {
10251 # finish reading the cache and setting up arctags, etc.
10252 set line [gets $f]
10253 if {$line ne "1"} {error "bad final version"}
10254 close $f
10255 foreach id [array names idtags] {
10256 if {[info exists arcnos($id)] && [llength $arcnos($id)] == 1 &&
10257 [llength $allparents($id)] == 1} {
10258 set a [lindex $arcnos($id) 0]
10259 if {$arctags($a) eq {}} {
10260 recalcarc $a
10261 }
10262 }
10263 }
10264 foreach id [array names idheads] {
10265 if {[info exists arcnos($id)] && [llength $arcnos($id)] == 1 &&
10266 [llength $allparents($id)] == 1} {
10267 set a [lindex $arcnos($id) 0]
10268 if {$archeads($a) eq {}} {
10269 recalcarc $a
10270 }
10271 }
10272 }
10273 foreach id [lsort -unique $possible_seeds] {
10274 if {$arcnos($id) eq {}} {
10275 lappend seeds $id
10276 }
10277 }
10278 set allcwait 0
10279 } else {
10280 while {[incr a] <= $lim} {
10281 set line [gets $f]
10282 if {[llength $line] != 3} {error "bad line"}
10283 set s [lindex $line 0]
10284 set arcstart($a) $s
10285 lappend arcout($s) $a
10286 if {![info exists arcnos($s)]} {
10287 lappend possible_seeds $s
10288 set arcnos($s) {}
10289 }
10290 set e [lindex $line 1]
10291 if {$e eq {}} {
10292 set growing($a) 1
10293 } else {
10294 set arcend($a) $e
10295 if {![info exists arcout($e)]} {
10296 set arcout($e) {}
10297 }
10298 }
10299 set arcids($a) [lindex $line 2]
10300 foreach id $arcids($a) {
10301 lappend allparents($s) $id
10302 set s $id
10303 lappend arcnos($id) $a
10304 }
10305 if {![info exists allparents($s)]} {
10306 set allparents($s) {}
10307 }
10308 set arctags($a) {}
10309 set archeads($a) {}
10310 }
10311 set nextarc [expr {$a - 1}]
10312 }
10313 } err]} {
10314 dropcache $err
10315 return 0
10316 }
10317 if {!$allcwait} {
10318 getallcommits
10319 }
10320 return $allcwait
10321}
10322
10323proc getcache {f} {
10324 global nextarc cachedarcs possible_seeds
10325
10326 if {[catch {
10327 set line [gets $f]
10328 if {[llength $line] != 2 || [lindex $line 0] ne "1"} {error "bad version"}
10329 # make sure it's an integer
10330 set cachedarcs [expr {int([lindex $line 1])}]
10331 if {$cachedarcs < 0} {error "bad number of arcs"}
10332 set nextarc 0
10333 set possible_seeds {}
10334 run readcache $f
10335 } err]} {
10336 dropcache $err
10337 }
10338 return 0
10339}
10340
10341proc dropcache {err} {
10342 global allcwait nextarc cachedarcs seeds
10343
10344 #puts "dropping cache ($err)"
10345 foreach v {arcnos arcout arcids arcstart arcend growing \
10346 arctags archeads allparents allchildren} {
10347 global $v
10348 catch {unset $v}
10349 }
10350 set allcwait 0
10351 set nextarc 0
10352 set cachedarcs 0
10353 set seeds {}
10354 getallcommits
10355}
10356
10357proc writecache {f} {
10358 global cachearc cachedarcs allccache
10359 global arcstart arcend arcnos arcids arcout
10360
10361 set a $cachearc
10362 set lim $cachedarcs
10363 if {$lim - $a > 1000} {
10364 set lim [expr {$a + 1000}]
10365 }
10366 if {[catch {
10367 while {[incr a] <= $lim} {
10368 if {[info exists arcend($a)]} {
10369 puts $f [list $arcstart($a) $arcend($a) $arcids($a)]
10370 } else {
10371 puts $f [list $arcstart($a) {} $arcids($a)]
10372 }
10373 }
10374 } err]} {
10375 catch {close $f}
10376 catch {file delete $allccache}
10377 #puts "writing cache failed ($err)"
10378 return 0
10379 }
10380 set cachearc [expr {$a - 1}]
10381 if {$a > $cachedarcs} {
10382 puts $f "1"
10383 close $f
10384 return 0
10385 }
10386 return 1
10387}
10388
10389proc savecache {} {
10390 global nextarc cachedarcs cachearc allccache
10391
10392 if {$nextarc == $cachedarcs} return
10393 set cachearc 0
10394 set cachedarcs $nextarc
10395 catch {
10396 set f [open $allccache w]
10397 puts $f [list 1 $cachedarcs]
10398 run writecache $f
10399 }
10400}
10401
Paul Mackerrase11f1232007-06-16 20:29:25 +100010402# Returns 1 if a is an ancestor of b, -1 if b is an ancestor of a,
10403# or 0 if neither is true.
10404proc anc_or_desc {a b} {
10405 global arcout arcstart arcend arcnos cached_isanc
10406
10407 if {$arcnos($a) eq $arcnos($b)} {
10408 # Both are on the same arc(s); either both are the same BMP,
10409 # or if one is not a BMP, the other is also not a BMP or is
10410 # the BMP at end of the arc (and it only has 1 incoming arc).
Paul Mackerras69c0b5d2007-07-04 21:57:04 +100010411 # Or both can be BMPs with no incoming arcs.
10412 if {$a eq $b || $arcnos($a) eq {}} {
Paul Mackerrase11f1232007-06-16 20:29:25 +100010413 return 0
10414 }
10415 # assert {[llength $arcnos($a)] == 1}
10416 set arc [lindex $arcnos($a) 0]
10417 set i [lsearch -exact $arcids($arc) $a]
10418 set j [lsearch -exact $arcids($arc) $b]
10419 if {$i < 0 || $i > $j} {
10420 return 1
10421 } else {
10422 return -1
10423 }
10424 }
10425
10426 if {![info exists arcout($a)]} {
10427 set arc [lindex $arcnos($a) 0]
10428 if {[info exists arcend($arc)]} {
10429 set aend $arcend($arc)
10430 } else {
10431 set aend {}
10432 }
10433 set a $arcstart($arc)
10434 } else {
10435 set aend $a
10436 }
10437 if {![info exists arcout($b)]} {
10438 set arc [lindex $arcnos($b) 0]
10439 if {[info exists arcend($arc)]} {
10440 set bend $arcend($arc)
10441 } else {
10442 set bend {}
10443 }
10444 set b $arcstart($arc)
10445 } else {
10446 set bend $b
10447 }
10448 if {$a eq $bend} {
10449 return 1
10450 }
10451 if {$b eq $aend} {
10452 return -1
10453 }
10454 if {[info exists cached_isanc($a,$bend)]} {
10455 if {$cached_isanc($a,$bend)} {
10456 return 1
10457 }
10458 }
10459 if {[info exists cached_isanc($b,$aend)]} {
10460 if {$cached_isanc($b,$aend)} {
10461 return -1
10462 }
10463 if {[info exists cached_isanc($a,$bend)]} {
10464 return 0
10465 }
10466 }
10467
10468 set todo [list $a $b]
10469 set anc($a) a
10470 set anc($b) b
10471 for {set i 0} {$i < [llength $todo]} {incr i} {
10472 set x [lindex $todo $i]
10473 if {$anc($x) eq {}} {
10474 continue
10475 }
10476 foreach arc $arcnos($x) {
10477 set xd $arcstart($arc)
10478 if {$xd eq $bend} {
10479 set cached_isanc($a,$bend) 1
10480 set cached_isanc($b,$aend) 0
10481 return 1
10482 } elseif {$xd eq $aend} {
10483 set cached_isanc($b,$aend) 1
10484 set cached_isanc($a,$bend) 0
10485 return -1
10486 }
10487 if {![info exists anc($xd)]} {
10488 set anc($xd) $anc($x)
10489 lappend todo $xd
10490 } elseif {$anc($xd) ne $anc($x)} {
10491 set anc($xd) {}
10492 }
10493 }
10494 }
10495 set cached_isanc($a,$bend) 0
10496 set cached_isanc($b,$aend) 0
10497 return 0
10498}
10499
10500# This identifies whether $desc has an ancestor that is
10501# a growing tip of the graph and which is not an ancestor of $anc
10502# and returns 0 if so and 1 if not.
10503# If we subsequently discover a tag on such a growing tip, and that
10504# turns out to be a descendent of $anc (which it could, since we
10505# don't necessarily see children before parents), then $desc
10506# isn't a good choice to display as a descendent tag of
10507# $anc (since it is the descendent of another tag which is
10508# a descendent of $anc). Similarly, $anc isn't a good choice to
10509# display as a ancestor tag of $desc.
10510#
10511proc is_certain {desc anc} {
10512 global arcnos arcout arcstart arcend growing problems
10513
10514 set certain {}
10515 if {[llength $arcnos($anc)] == 1} {
10516 # tags on the same arc are certain
10517 if {$arcnos($desc) eq $arcnos($anc)} {
10518 return 1
10519 }
10520 if {![info exists arcout($anc)]} {
10521 # if $anc is partway along an arc, use the start of the arc instead
10522 set a [lindex $arcnos($anc) 0]
10523 set anc $arcstart($a)
10524 }
10525 }
10526 if {[llength $arcnos($desc)] > 1 || [info exists arcout($desc)]} {
10527 set x $desc
10528 } else {
10529 set a [lindex $arcnos($desc) 0]
10530 set x $arcend($a)
10531 }
10532 if {$x == $anc} {
10533 return 1
10534 }
10535 set anclist [list $x]
10536 set dl($x) 1
10537 set nnh 1
10538 set ngrowanc 0
10539 for {set i 0} {$i < [llength $anclist] && ($nnh > 0 || $ngrowanc > 0)} {incr i} {
10540 set x [lindex $anclist $i]
10541 if {$dl($x)} {
10542 incr nnh -1
10543 }
10544 set done($x) 1
10545 foreach a $arcout($x) {
10546 if {[info exists growing($a)]} {
10547 if {![info exists growanc($x)] && $dl($x)} {
10548 set growanc($x) 1
10549 incr ngrowanc
10550 }
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +100010551 } else {
Paul Mackerrase11f1232007-06-16 20:29:25 +100010552 set y $arcend($a)
10553 if {[info exists dl($y)]} {
10554 if {$dl($y)} {
10555 if {!$dl($x)} {
10556 set dl($y) 0
10557 if {![info exists done($y)]} {
10558 incr nnh -1
10559 }
10560 if {[info exists growanc($x)]} {
10561 incr ngrowanc -1
10562 }
10563 set xl [list $y]
10564 for {set k 0} {$k < [llength $xl]} {incr k} {
10565 set z [lindex $xl $k]
10566 foreach c $arcout($z) {
10567 if {[info exists arcend($c)]} {
10568 set v $arcend($c)
10569 if {[info exists dl($v)] && $dl($v)} {
10570 set dl($v) 0
10571 if {![info exists done($v)]} {
10572 incr nnh -1
10573 }
10574 if {[info exists growanc($v)]} {
10575 incr ngrowanc -1
10576 }
10577 lappend xl $v
10578 }
10579 }
10580 }
10581 }
10582 }
10583 }
10584 } elseif {$y eq $anc || !$dl($x)} {
10585 set dl($y) 0
10586 lappend anclist $y
10587 } else {
10588 set dl($y) 1
10589 lappend anclist $y
10590 incr nnh
10591 }
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +100010592 }
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +100010593 }
10594 }
Paul Mackerrase11f1232007-06-16 20:29:25 +100010595 foreach x [array names growanc] {
10596 if {$dl($x)} {
10597 return 0
10598 }
Paul Mackerras7eb3cb92007-06-17 14:45:00 +100010599 return 0
Paul Mackerrase11f1232007-06-16 20:29:25 +100010600 }
10601 return 1
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +100010602}
10603
Paul Mackerrase11f1232007-06-16 20:29:25 +100010604proc validate_arctags {a} {
10605 global arctags idtags
10606
10607 set i -1
10608 set na $arctags($a)
10609 foreach id $arctags($a) {
10610 incr i
10611 if {![info exists idtags($id)]} {
10612 set na [lreplace $na $i $i]
10613 incr i -1
10614 }
10615 }
10616 set arctags($a) $na
10617}
10618
10619proc validate_archeads {a} {
10620 global archeads idheads
10621
10622 set i -1
10623 set na $archeads($a)
10624 foreach id $archeads($a) {
10625 incr i
10626 if {![info exists idheads($id)]} {
10627 set na [lreplace $na $i $i]
10628 incr i -1
10629 }
10630 }
10631 set archeads($a) $na
10632}
10633
10634# Return the list of IDs that have tags that are descendents of id,
10635# ignoring IDs that are descendents of IDs already reported.
10636proc desctags {id} {
10637 global arcnos arcstart arcids arctags idtags allparents
10638 global growing cached_dtags
10639
10640 if {![info exists allparents($id)]} {
10641 return {}
10642 }
10643 set t1 [clock clicks -milliseconds]
10644 set argid $id
10645 if {[llength $arcnos($id)] == 1 && [llength $allparents($id)] == 1} {
10646 # part-way along an arc; check that arc first
10647 set a [lindex $arcnos($id) 0]
10648 if {$arctags($a) ne {}} {
10649 validate_arctags $a
10650 set i [lsearch -exact $arcids($a) $id]
10651 set tid {}
10652 foreach t $arctags($a) {
10653 set j [lsearch -exact $arcids($a) $t]
10654 if {$j >= $i} break
10655 set tid $t
10656 }
10657 if {$tid ne {}} {
10658 return $tid
10659 }
10660 }
10661 set id $arcstart($a)
10662 if {[info exists idtags($id)]} {
10663 return $id
10664 }
10665 }
10666 if {[info exists cached_dtags($id)]} {
10667 return $cached_dtags($id)
10668 }
10669
10670 set origid $id
10671 set todo [list $id]
10672 set queued($id) 1
10673 set nc 1
10674 for {set i 0} {$i < [llength $todo] && $nc > 0} {incr i} {
10675 set id [lindex $todo $i]
10676 set done($id) 1
10677 set ta [info exists hastaggedancestor($id)]
10678 if {!$ta} {
10679 incr nc -1
10680 }
10681 # ignore tags on starting node
10682 if {!$ta && $i > 0} {
10683 if {[info exists idtags($id)]} {
10684 set tagloc($id) $id
10685 set ta 1
10686 } elseif {[info exists cached_dtags($id)]} {
10687 set tagloc($id) $cached_dtags($id)
10688 set ta 1
10689 }
10690 }
10691 foreach a $arcnos($id) {
10692 set d $arcstart($a)
10693 if {!$ta && $arctags($a) ne {}} {
10694 validate_arctags $a
10695 if {$arctags($a) ne {}} {
10696 lappend tagloc($id) [lindex $arctags($a) end]
10697 }
10698 }
10699 if {$ta || $arctags($a) ne {}} {
10700 set tomark [list $d]
10701 for {set j 0} {$j < [llength $tomark]} {incr j} {
10702 set dd [lindex $tomark $j]
10703 if {![info exists hastaggedancestor($dd)]} {
10704 if {[info exists done($dd)]} {
10705 foreach b $arcnos($dd) {
10706 lappend tomark $arcstart($b)
10707 }
10708 if {[info exists tagloc($dd)]} {
10709 unset tagloc($dd)
10710 }
10711 } elseif {[info exists queued($dd)]} {
10712 incr nc -1
10713 }
10714 set hastaggedancestor($dd) 1
10715 }
10716 }
10717 }
10718 if {![info exists queued($d)]} {
10719 lappend todo $d
10720 set queued($d) 1
10721 if {![info exists hastaggedancestor($d)]} {
10722 incr nc
10723 }
10724 }
10725 }
10726 }
10727 set tags {}
10728 foreach id [array names tagloc] {
10729 if {![info exists hastaggedancestor($id)]} {
10730 foreach t $tagloc($id) {
10731 if {[lsearch -exact $tags $t] < 0} {
10732 lappend tags $t
10733 }
10734 }
10735 }
10736 }
10737 set t2 [clock clicks -milliseconds]
10738 set loopix $i
10739
10740 # remove tags that are descendents of other tags
10741 for {set i 0} {$i < [llength $tags]} {incr i} {
10742 set a [lindex $tags $i]
10743 for {set j 0} {$j < $i} {incr j} {
10744 set b [lindex $tags $j]
10745 set r [anc_or_desc $a $b]
10746 if {$r == 1} {
10747 set tags [lreplace $tags $j $j]
10748 incr j -1
10749 incr i -1
10750 } elseif {$r == -1} {
10751 set tags [lreplace $tags $i $i]
10752 incr i -1
10753 break
10754 }
10755 }
10756 }
10757
10758 if {[array names growing] ne {}} {
10759 # graph isn't finished, need to check if any tag could get
10760 # eclipsed by another tag coming later. Simply ignore any
10761 # tags that could later get eclipsed.
10762 set ctags {}
10763 foreach t $tags {
10764 if {[is_certain $t $origid]} {
10765 lappend ctags $t
10766 }
10767 }
10768 if {$tags eq $ctags} {
10769 set cached_dtags($origid) $tags
10770 } else {
10771 set tags $ctags
10772 }
10773 } else {
10774 set cached_dtags($origid) $tags
10775 }
10776 set t3 [clock clicks -milliseconds]
10777 if {0 && $t3 - $t1 >= 100} {
10778 puts "iterating descendents ($loopix/[llength $todo] nodes) took\
10779 [expr {$t2-$t1}]+[expr {$t3-$t2}]ms, $nc candidates left"
10780 }
10781 return $tags
10782}
10783
10784proc anctags {id} {
10785 global arcnos arcids arcout arcend arctags idtags allparents
10786 global growing cached_atags
10787
10788 if {![info exists allparents($id)]} {
10789 return {}
10790 }
10791 set t1 [clock clicks -milliseconds]
10792 set argid $id
10793 if {[llength $arcnos($id)] == 1 && [llength $allparents($id)] == 1} {
10794 # part-way along an arc; check that arc first
10795 set a [lindex $arcnos($id) 0]
10796 if {$arctags($a) ne {}} {
10797 validate_arctags $a
10798 set i [lsearch -exact $arcids($a) $id]
10799 foreach t $arctags($a) {
10800 set j [lsearch -exact $arcids($a) $t]
10801 if {$j > $i} {
10802 return $t
10803 }
10804 }
10805 }
10806 if {![info exists arcend($a)]} {
10807 return {}
10808 }
10809 set id $arcend($a)
10810 if {[info exists idtags($id)]} {
10811 return $id
10812 }
10813 }
10814 if {[info exists cached_atags($id)]} {
10815 return $cached_atags($id)
10816 }
10817
10818 set origid $id
10819 set todo [list $id]
10820 set queued($id) 1
10821 set taglist {}
10822 set nc 1
10823 for {set i 0} {$i < [llength $todo] && $nc > 0} {incr i} {
10824 set id [lindex $todo $i]
10825 set done($id) 1
10826 set td [info exists hastaggeddescendent($id)]
10827 if {!$td} {
10828 incr nc -1
10829 }
10830 # ignore tags on starting node
10831 if {!$td && $i > 0} {
10832 if {[info exists idtags($id)]} {
10833 set tagloc($id) $id
10834 set td 1
10835 } elseif {[info exists cached_atags($id)]} {
10836 set tagloc($id) $cached_atags($id)
10837 set td 1
10838 }
10839 }
10840 foreach a $arcout($id) {
10841 if {!$td && $arctags($a) ne {}} {
10842 validate_arctags $a
10843 if {$arctags($a) ne {}} {
10844 lappend tagloc($id) [lindex $arctags($a) 0]
10845 }
10846 }
10847 if {![info exists arcend($a)]} continue
10848 set d $arcend($a)
10849 if {$td || $arctags($a) ne {}} {
10850 set tomark [list $d]
10851 for {set j 0} {$j < [llength $tomark]} {incr j} {
10852 set dd [lindex $tomark $j]
10853 if {![info exists hastaggeddescendent($dd)]} {
10854 if {[info exists done($dd)]} {
10855 foreach b $arcout($dd) {
10856 if {[info exists arcend($b)]} {
10857 lappend tomark $arcend($b)
10858 }
10859 }
10860 if {[info exists tagloc($dd)]} {
10861 unset tagloc($dd)
10862 }
10863 } elseif {[info exists queued($dd)]} {
10864 incr nc -1
10865 }
10866 set hastaggeddescendent($dd) 1
10867 }
10868 }
10869 }
10870 if {![info exists queued($d)]} {
10871 lappend todo $d
10872 set queued($d) 1
10873 if {![info exists hastaggeddescendent($d)]} {
10874 incr nc
10875 }
10876 }
10877 }
10878 }
10879 set t2 [clock clicks -milliseconds]
10880 set loopix $i
10881 set tags {}
10882 foreach id [array names tagloc] {
10883 if {![info exists hastaggeddescendent($id)]} {
10884 foreach t $tagloc($id) {
10885 if {[lsearch -exact $tags $t] < 0} {
10886 lappend tags $t
10887 }
10888 }
10889 }
10890 }
10891
10892 # remove tags that are ancestors of other tags
10893 for {set i 0} {$i < [llength $tags]} {incr i} {
10894 set a [lindex $tags $i]
10895 for {set j 0} {$j < $i} {incr j} {
10896 set b [lindex $tags $j]
10897 set r [anc_or_desc $a $b]
10898 if {$r == -1} {
10899 set tags [lreplace $tags $j $j]
10900 incr j -1
10901 incr i -1
10902 } elseif {$r == 1} {
10903 set tags [lreplace $tags $i $i]
10904 incr i -1
10905 break
10906 }
10907 }
10908 }
10909
10910 if {[array names growing] ne {}} {
10911 # graph isn't finished, need to check if any tag could get
10912 # eclipsed by another tag coming later. Simply ignore any
10913 # tags that could later get eclipsed.
10914 set ctags {}
10915 foreach t $tags {
10916 if {[is_certain $origid $t]} {
10917 lappend ctags $t
10918 }
10919 }
10920 if {$tags eq $ctags} {
10921 set cached_atags($origid) $tags
10922 } else {
10923 set tags $ctags
10924 }
10925 } else {
10926 set cached_atags($origid) $tags
10927 }
10928 set t3 [clock clicks -milliseconds]
10929 if {0 && $t3 - $t1 >= 100} {
10930 puts "iterating ancestors ($loopix/[llength $todo] nodes) took\
10931 [expr {$t2-$t1}]+[expr {$t3-$t2}]ms, $nc candidates left"
10932 }
10933 return $tags
10934}
10935
10936# Return the list of IDs that have heads that are descendents of id,
10937# including id itself if it has a head.
10938proc descheads {id} {
10939 global arcnos arcstart arcids archeads idheads cached_dheads
Paul Mackerrasd809fb12013-01-01 16:51:03 +110010940 global allparents arcout
Paul Mackerrase11f1232007-06-16 20:29:25 +100010941
10942 if {![info exists allparents($id)]} {
10943 return {}
10944 }
Paul Mackerrasf3326b62007-06-18 22:39:21 +100010945 set aret {}
Paul Mackerrasd809fb12013-01-01 16:51:03 +110010946 if {![info exists arcout($id)]} {
Paul Mackerrase11f1232007-06-16 20:29:25 +100010947 # part-way along an arc; check it first
10948 set a [lindex $arcnos($id) 0]
10949 if {$archeads($a) ne {}} {
10950 validate_archeads $a
10951 set i [lsearch -exact $arcids($a) $id]
10952 foreach t $archeads($a) {
10953 set j [lsearch -exact $arcids($a) $t]
10954 if {$j > $i} break
Paul Mackerrasf3326b62007-06-18 22:39:21 +100010955 lappend aret $t
Paul Mackerrase11f1232007-06-16 20:29:25 +100010956 }
10957 }
10958 set id $arcstart($a)
10959 }
10960 set origid $id
10961 set todo [list $id]
10962 set seen($id) 1
Paul Mackerrasf3326b62007-06-18 22:39:21 +100010963 set ret {}
Paul Mackerrase11f1232007-06-16 20:29:25 +100010964 for {set i 0} {$i < [llength $todo]} {incr i} {
10965 set id [lindex $todo $i]
10966 if {[info exists cached_dheads($id)]} {
10967 set ret [concat $ret $cached_dheads($id)]
10968 } else {
10969 if {[info exists idheads($id)]} {
10970 lappend ret $id
10971 }
10972 foreach a $arcnos($id) {
10973 if {$archeads($a) ne {}} {
Paul Mackerras706d6c32007-06-26 11:09:49 +100010974 validate_archeads $a
10975 if {$archeads($a) ne {}} {
10976 set ret [concat $ret $archeads($a)]
10977 }
Paul Mackerrase11f1232007-06-16 20:29:25 +100010978 }
10979 set d $arcstart($a)
10980 if {![info exists seen($d)]} {
10981 lappend todo $d
10982 set seen($d) 1
10983 }
10984 }
10985 }
10986 }
10987 set ret [lsort -unique $ret]
10988 set cached_dheads($origid) $ret
Paul Mackerrasf3326b62007-06-18 22:39:21 +100010989 return [concat $ret $aret]
Paul Mackerrase11f1232007-06-16 20:29:25 +100010990}
10991
Paul Mackerrasceadfe92006-08-08 20:55:36 +100010992proc addedtag {id} {
Paul Mackerrase11f1232007-06-16 20:29:25 +100010993 global arcnos arcout cached_dtags cached_atags
Paul Mackerrasceadfe92006-08-08 20:55:36 +100010994
Paul Mackerrase11f1232007-06-16 20:29:25 +100010995 if {![info exists arcnos($id)]} return
10996 if {![info exists arcout($id)]} {
10997 recalcarc [lindex $arcnos($id) 0]
Paul Mackerrasceadfe92006-08-08 20:55:36 +100010998 }
Paul Mackerrase11f1232007-06-16 20:29:25 +100010999 catch {unset cached_dtags}
11000 catch {unset cached_atags}
Paul Mackerrasceadfe92006-08-08 20:55:36 +100011001}
11002
Paul Mackerrasca6d8f52006-08-06 21:08:05 +100011003proc addedhead {hid head} {
Paul Mackerrase11f1232007-06-16 20:29:25 +100011004 global arcnos arcout cached_dheads
Paul Mackerrasca6d8f52006-08-06 21:08:05 +100011005
Paul Mackerrase11f1232007-06-16 20:29:25 +100011006 if {![info exists arcnos($hid)]} return
11007 if {![info exists arcout($hid)]} {
11008 recalcarc [lindex $arcnos($hid) 0]
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +100011009 }
Paul Mackerrase11f1232007-06-16 20:29:25 +100011010 catch {unset cached_dheads}
Paul Mackerrasd6ac1a82006-08-02 09:41:04 +100011011}
11012
Paul Mackerrasca6d8f52006-08-06 21:08:05 +100011013proc removedhead {hid head} {
Paul Mackerrase11f1232007-06-16 20:29:25 +100011014 global cached_dheads
Paul Mackerrasca6d8f52006-08-06 21:08:05 +100011015
Paul Mackerrase11f1232007-06-16 20:29:25 +100011016 catch {unset cached_dheads}
Paul Mackerras10299152006-08-02 09:52:01 +100011017}
11018
Paul Mackerrase11f1232007-06-16 20:29:25 +100011019proc movedhead {hid head} {
11020 global arcnos arcout cached_dheads
Paul Mackerrasca6d8f52006-08-06 21:08:05 +100011021
Paul Mackerrase11f1232007-06-16 20:29:25 +100011022 if {![info exists arcnos($hid)]} return
11023 if {![info exists arcout($hid)]} {
11024 recalcarc [lindex $arcnos($hid) 0]
Paul Mackerrasca6d8f52006-08-06 21:08:05 +100011025 }
Paul Mackerrase11f1232007-06-16 20:29:25 +100011026 catch {unset cached_dheads}
Paul Mackerrasca6d8f52006-08-06 21:08:05 +100011027}
11028
Paul Mackerrascec7bec2006-08-02 09:38:10 +100011029proc changedrefs {} {
David Aguilar587277f2012-09-08 12:53:16 -070011030 global cached_dheads cached_dtags cached_atags cached_tagcontent
Paul Mackerrase11f1232007-06-16 20:29:25 +100011031 global arctags archeads arcnos arcout idheads idtags
Paul Mackerrascec7bec2006-08-02 09:38:10 +100011032
Paul Mackerrase11f1232007-06-16 20:29:25 +100011033 foreach id [concat [array names idheads] [array names idtags]] {
11034 if {[info exists arcnos($id)] && ![info exists arcout($id)]} {
11035 set a [lindex $arcnos($id) 0]
11036 if {![info exists donearc($a)]} {
11037 recalcarc $a
11038 set donearc($a) 1
11039 }
Paul Mackerrascec7bec2006-08-02 09:38:10 +100011040 }
11041 }
David Aguilar587277f2012-09-08 12:53:16 -070011042 catch {unset cached_tagcontent}
Paul Mackerrase11f1232007-06-16 20:29:25 +100011043 catch {unset cached_dtags}
11044 catch {unset cached_atags}
11045 catch {unset cached_dheads}
Paul Mackerrascec7bec2006-08-02 09:38:10 +100011046}
11047
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +100011048proc rereadrefs {} {
Paul Mackerrasfc2a2562007-12-26 23:03:43 +110011049 global idtags idheads idotherrefs mainheadid
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +100011050
11051 set refids [concat [array names idtags] \
11052 [array names idheads] [array names idotherrefs]]
11053 foreach id $refids {
11054 if {![info exists ref($id)]} {
11055 set ref($id) [listrefs $id]
11056 }
11057 }
Paul Mackerrasfc2a2562007-12-26 23:03:43 +110011058 set oldmainhead $mainheadid
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +100011059 readrefs
Paul Mackerrascec7bec2006-08-02 09:38:10 +100011060 changedrefs
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +100011061 set refids [lsort -unique [concat $refids [array names idtags] \
11062 [array names idheads] [array names idotherrefs]]]
11063 foreach id $refids {
11064 set v [listrefs $id]
Paul Mackerrasc11ff122008-05-26 10:11:33 +100011065 if {![info exists ref($id)] || $ref($id) != $v} {
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +100011066 redrawtags $id
11067 }
11068 }
Paul Mackerrasc11ff122008-05-26 10:11:33 +100011069 if {$oldmainhead ne $mainheadid} {
11070 redrawtags $oldmainhead
11071 redrawtags $mainheadid
11072 }
Paul Mackerras887c9962007-08-20 19:36:20 +100011073 run refill_reflist
Paul Mackerrasf1d83ba2005-08-19 22:14:28 +100011074}
11075
Junio C Hamano2e1ded42006-06-11 09:50:47 -070011076proc listrefs {id} {
11077 global idtags idheads idotherrefs
11078
11079 set x {}
11080 if {[info exists idtags($id)]} {
11081 set x $idtags($id)
11082 }
11083 set y {}
11084 if {[info exists idheads($id)]} {
11085 set y $idheads($id)
11086 }
11087 set z {}
11088 if {[info exists idotherrefs($id)]} {
11089 set z $idotherrefs($id)
11090 }
11091 return [list $x $y $z]
11092}
11093
Paul Mackerras4399fe32013-01-03 10:10:31 +110011094proc add_tag_ctext {tag} {
11095 global ctext cached_tagcontent tagids
11096
11097 if {![info exists cached_tagcontent($tag)]} {
11098 catch {
11099 set cached_tagcontent($tag) [exec git cat-file -p $tag]
11100 }
11101 }
11102 $ctext insert end "[mc "Tag"]: $tag\n" bold
11103 if {[info exists cached_tagcontent($tag)]} {
11104 set text $cached_tagcontent($tag)
11105 } else {
11106 set text "[mc "Id"]: $tagids($tag)"
11107 }
11108 appendwithlinks $text {}
11109}
11110
Paul Mackerras106288c2005-08-19 23:11:39 +100011111proc showtag {tag isnew} {
David Aguilar587277f2012-09-08 12:53:16 -070011112 global ctext cached_tagcontent tagids linknum tagobjid
Paul Mackerras106288c2005-08-19 23:11:39 +100011113
11114 if {$isnew} {
Paul Mackerras354af6b2008-11-23 13:14:23 +110011115 addtohistory [list showtag $tag 0] savectextpos
Paul Mackerras106288c2005-08-19 23:11:39 +100011116 }
11117 $ctext conf -state normal
Paul Mackerras3ea06f92006-05-24 10:16:03 +100011118 clear_ctext
Paul Mackerras32f1b3e2007-09-28 21:27:39 +100011119 settabs 0
Paul Mackerras106288c2005-08-19 23:11:39 +100011120 set linknum 0
Paul Mackerras4399fe32013-01-03 10:10:31 +110011121 add_tag_ctext $tag
11122 maybe_scroll_ctext 1
11123 $ctext conf -state disabled
11124 init_flist {}
11125}
11126
11127proc showtags {id isnew} {
11128 global idtags ctext linknum
11129
11130 if {$isnew} {
11131 addtohistory [list showtags $id 0] savectextpos
Paul Mackerras62d3ea62006-09-11 10:36:53 +100011132 }
Paul Mackerras4399fe32013-01-03 10:10:31 +110011133 $ctext conf -state normal
11134 clear_ctext
11135 settabs 0
11136 set linknum 0
11137 set sep {}
11138 foreach tag $idtags($id) {
11139 $ctext insert end $sep
11140 add_tag_ctext $tag
11141 set sep "\n\n"
Paul Mackerras106288c2005-08-19 23:11:39 +100011142 }
Pat Thoytsa80e82f2009-11-14 13:21:09 +000011143 maybe_scroll_ctext 1
Paul Mackerras106288c2005-08-19 23:11:39 +100011144 $ctext conf -state disabled
Paul Mackerras7fcceed2006-04-27 19:21:49 +100011145 init_flist {}
Paul Mackerras106288c2005-08-19 23:11:39 +100011146}
11147
Paul Mackerras1d10f362005-05-15 12:55:47 +000011148proc doquit {} {
11149 global stopped
Thomas Arcila314f5de2008-03-24 12:55:36 +010011150 global gitktmpdir
11151
Paul Mackerras1d10f362005-05-15 12:55:47 +000011152 set stopped 100
Mark Levedahlb6047c52007-02-08 22:22:24 -050011153 savestuff .
Paul Mackerras1d10f362005-05-15 12:55:47 +000011154 destroy .
Thomas Arcila314f5de2008-03-24 12:55:36 +010011155
11156 if {[info exists gitktmpdir]} {
11157 catch {file delete -force $gitktmpdir}
11158 }
Paul Mackerras1d10f362005-05-15 12:55:47 +000011159}
11160
Paul Mackerras9a7558f2007-10-06 20:16:06 +100011161proc mkfontdisp {font top which} {
Pat Thoytsd93f1712009-04-17 01:24:35 +010011162 global fontattr fontpref $font NS use_ttk
Paul Mackerras9a7558f2007-10-06 20:16:06 +100011163
11164 set fontpref($font) [set $font]
Pat Thoytsd93f1712009-04-17 01:24:35 +010011165 ${NS}::button $top.${font}but -text $which \
Paul Mackerras9a7558f2007-10-06 20:16:06 +100011166 -command [list choosefont $font $which]
Pat Thoytsd93f1712009-04-17 01:24:35 +010011167 ${NS}::label $top.$font -relief flat -font $font \
Paul Mackerras9a7558f2007-10-06 20:16:06 +100011168 -text $fontattr($font,family) -justify left
11169 grid x $top.${font}but $top.$font -sticky w
11170}
11171
11172proc choosefont {font which} {
11173 global fontparam fontlist fonttop fontattr
Pat Thoytsd93f1712009-04-17 01:24:35 +010011174 global prefstop NS
Paul Mackerras9a7558f2007-10-06 20:16:06 +100011175
11176 set fontparam(which) $which
11177 set fontparam(font) $font
11178 set fontparam(family) [font actual $font -family]
11179 set fontparam(size) $fontattr($font,size)
11180 set fontparam(weight) $fontattr($font,weight)
11181 set fontparam(slant) $fontattr($font,slant)
11182 set top .gitkfont
11183 set fonttop $top
11184 if {![winfo exists $top]} {
11185 font create sample
11186 eval font config sample [font actual $font]
Pat Thoytsd93f1712009-04-17 01:24:35 +010011187 ttk_toplevel $top
Alexander Gavrilove7d64002008-11-11 23:55:42 +030011188 make_transient $top $prefstop
Christian Stimmingd990ced2007-11-07 18:42:55 +010011189 wm title $top [mc "Gitk font chooser"]
Pat Thoytsd93f1712009-04-17 01:24:35 +010011190 ${NS}::label $top.l -textvariable fontparam(which)
Paul Mackerras9a7558f2007-10-06 20:16:06 +100011191 pack $top.l -side top
11192 set fontlist [lsort [font families]]
Pat Thoytsd93f1712009-04-17 01:24:35 +010011193 ${NS}::frame $top.f
Paul Mackerras9a7558f2007-10-06 20:16:06 +100011194 listbox $top.f.fam -listvariable fontlist \
11195 -yscrollcommand [list $top.f.sb set]
11196 bind $top.f.fam <<ListboxSelect>> selfontfam
Pat Thoytsd93f1712009-04-17 01:24:35 +010011197 ${NS}::scrollbar $top.f.sb -command [list $top.f.fam yview]
Paul Mackerras9a7558f2007-10-06 20:16:06 +100011198 pack $top.f.sb -side right -fill y
11199 pack $top.f.fam -side left -fill both -expand 1
11200 pack $top.f -side top -fill both -expand 1
Pat Thoytsd93f1712009-04-17 01:24:35 +010011201 ${NS}::frame $top.g
Paul Mackerras9a7558f2007-10-06 20:16:06 +100011202 spinbox $top.g.size -from 4 -to 40 -width 4 \
11203 -textvariable fontparam(size) \
11204 -validatecommand {string is integer -strict %s}
11205 checkbutton $top.g.bold -padx 5 \
Christian Stimmingd990ced2007-11-07 18:42:55 +010011206 -font {{Times New Roman} 12 bold} -text [mc "B"] -indicatoron 0 \
Paul Mackerras9a7558f2007-10-06 20:16:06 +100011207 -variable fontparam(weight) -onvalue bold -offvalue normal
11208 checkbutton $top.g.ital -padx 5 \
Christian Stimmingd990ced2007-11-07 18:42:55 +010011209 -font {{Times New Roman} 12 italic} -text [mc "I"] -indicatoron 0 \
Paul Mackerras9a7558f2007-10-06 20:16:06 +100011210 -variable fontparam(slant) -onvalue italic -offvalue roman
11211 pack $top.g.size $top.g.bold $top.g.ital -side left
11212 pack $top.g -side top
11213 canvas $top.c -width 150 -height 50 -border 2 -relief sunk \
11214 -background white
11215 $top.c create text 100 25 -anchor center -text $which -font sample \
11216 -fill black -tags text
11217 bind $top.c <Configure> [list centertext $top.c]
11218 pack $top.c -side top -fill x
Pat Thoytsd93f1712009-04-17 01:24:35 +010011219 ${NS}::frame $top.buts
11220 ${NS}::button $top.buts.ok -text [mc "OK"] -command fontok -default active
11221 ${NS}::button $top.buts.can -text [mc "Cancel"] -command fontcan -default normal
Alexander Gavrilov76f15942008-11-02 21:59:44 +030011222 bind $top <Key-Return> fontok
11223 bind $top <Key-Escape> fontcan
Paul Mackerras9a7558f2007-10-06 20:16:06 +100011224 grid $top.buts.ok $top.buts.can
11225 grid columnconfigure $top.buts 0 -weight 1 -uniform a
11226 grid columnconfigure $top.buts 1 -weight 1 -uniform a
11227 pack $top.buts -side bottom -fill x
11228 trace add variable fontparam write chg_fontparam
11229 } else {
11230 raise $top
11231 $top.c itemconf text -text $which
11232 }
11233 set i [lsearch -exact $fontlist $fontparam(family)]
11234 if {$i >= 0} {
11235 $top.f.fam selection set $i
11236 $top.f.fam see $i
11237 }
11238}
11239
11240proc centertext {w} {
11241 $w coords text [expr {[winfo width $w] / 2}] [expr {[winfo height $w] / 2}]
11242}
11243
11244proc fontok {} {
11245 global fontparam fontpref prefstop
11246
11247 set f $fontparam(font)
11248 set fontpref($f) [list $fontparam(family) $fontparam(size)]
11249 if {$fontparam(weight) eq "bold"} {
11250 lappend fontpref($f) "bold"
11251 }
11252 if {$fontparam(slant) eq "italic"} {
11253 lappend fontpref($f) "italic"
11254 }
Pat Thoyts39ddf992012-04-01 23:00:52 +010011255 set w $prefstop.notebook.fonts.$f
Paul Mackerras9a7558f2007-10-06 20:16:06 +100011256 $w conf -text $fontparam(family) -font $fontpref($f)
Pat Thoytsd93f1712009-04-17 01:24:35 +010011257
Paul Mackerras9a7558f2007-10-06 20:16:06 +100011258 fontcan
11259}
11260
11261proc fontcan {} {
11262 global fonttop fontparam
11263
11264 if {[info exists fonttop]} {
11265 catch {destroy $fonttop}
11266 catch {font delete sample}
11267 unset fonttop
11268 unset fontparam
11269 }
11270}
11271
Pat Thoytsd93f1712009-04-17 01:24:35 +010011272if {[package vsatisfies [package provide Tk] 8.6]} {
11273 # In Tk 8.6 we have a native font chooser dialog. Overwrite the above
11274 # function to make use of it.
11275 proc choosefont {font which} {
11276 tk fontchooser configure -title $which -font $font \
11277 -command [list on_choosefont $font $which]
11278 tk fontchooser show
11279 }
11280 proc on_choosefont {font which newfont} {
11281 global fontparam
11282 puts stderr "$font $newfont"
11283 array set f [font actual $newfont]
11284 set fontparam(which) $which
11285 set fontparam(font) $font
11286 set fontparam(family) $f(-family)
11287 set fontparam(size) $f(-size)
11288 set fontparam(weight) $f(-weight)
11289 set fontparam(slant) $f(-slant)
11290 fontok
11291 }
11292}
11293
Paul Mackerras9a7558f2007-10-06 20:16:06 +100011294proc selfontfam {} {
11295 global fonttop fontparam
11296
11297 set i [$fonttop.f.fam curselection]
11298 if {$i ne {}} {
11299 set fontparam(family) [$fonttop.f.fam get $i]
11300 }
11301}
11302
11303proc chg_fontparam {v sub op} {
11304 global fontparam
11305
11306 font config sample -$sub $fontparam($sub)
11307}
11308
Pat Thoyts44acce02011-12-13 14:56:49 +000011309# Create a property sheet tab page
11310proc create_prefs_page {w} {
11311 global NS
11312 set parent [join [lrange [split $w .] 0 end-1] .]
11313 if {[winfo class $parent] eq "TNotebook"} {
11314 ${NS}::frame $w
11315 } else {
11316 ${NS}::labelframe $w
11317 }
11318}
11319
11320proc prefspage_general {notebook} {
11321 global NS maxwidth maxgraphpct showneartags showlocalchanges
11322 global tabstop limitdiffs autoselect autosellen extdifftool perfile_attrs
Paul Mackerrasd34835c2013-01-01 23:08:12 +110011323 global hideremotes want_ttk have_ttk maxrefs
Pat Thoyts44acce02011-12-13 14:56:49 +000011324
11325 set page [create_prefs_page $notebook.general]
11326
11327 ${NS}::label $page.ldisp -text [mc "Commit list display options"]
11328 grid $page.ldisp - -sticky w -pady 10
11329 ${NS}::label $page.spacer -text " "
11330 ${NS}::label $page.maxwidthl -text [mc "Maximum graph width (lines)"]
11331 spinbox $page.maxwidth -from 0 -to 100 -width 4 -textvariable maxwidth
11332 grid $page.spacer $page.maxwidthl $page.maxwidth -sticky w
Alex Henrie8a1692f2015-01-22 01:19:39 -070011333 #xgettext:no-tcl-format
Pat Thoyts44acce02011-12-13 14:56:49 +000011334 ${NS}::label $page.maxpctl -text [mc "Maximum graph width (% of pane)"]
11335 spinbox $page.maxpct -from 1 -to 100 -width 4 -textvariable maxgraphpct
11336 grid x $page.maxpctl $page.maxpct -sticky w
11337 ${NS}::checkbutton $page.showlocal -text [mc "Show local changes"] \
11338 -variable showlocalchanges
11339 grid x $page.showlocal -sticky w
11340 ${NS}::checkbutton $page.autoselect -text [mc "Auto-select SHA1 (length)"] \
11341 -variable autoselect
11342 spinbox $page.autosellen -from 1 -to 40 -width 4 -textvariable autosellen
11343 grid x $page.autoselect $page.autosellen -sticky w
11344 ${NS}::checkbutton $page.hideremotes -text [mc "Hide remote refs"] \
11345 -variable hideremotes
11346 grid x $page.hideremotes -sticky w
11347
11348 ${NS}::label $page.ddisp -text [mc "Diff display options"]
11349 grid $page.ddisp - -sticky w -pady 10
11350 ${NS}::label $page.tabstopl -text [mc "Tab spacing"]
11351 spinbox $page.tabstop -from 1 -to 20 -width 4 -textvariable tabstop
11352 grid x $page.tabstopl $page.tabstop -sticky w
Paul Mackerrasd34835c2013-01-01 23:08:12 +110011353 ${NS}::checkbutton $page.ntag -text [mc "Display nearby tags/heads"] \
Pat Thoyts44acce02011-12-13 14:56:49 +000011354 -variable showneartags
11355 grid x $page.ntag -sticky w
Paul Mackerrasd34835c2013-01-01 23:08:12 +110011356 ${NS}::label $page.maxrefsl -text [mc "Maximum # tags/heads to show"]
11357 spinbox $page.maxrefs -from 1 -to 1000 -width 4 -textvariable maxrefs
11358 grid x $page.maxrefsl $page.maxrefs -sticky w
Pat Thoyts44acce02011-12-13 14:56:49 +000011359 ${NS}::checkbutton $page.ldiff -text [mc "Limit diffs to listed paths"] \
11360 -variable limitdiffs
11361 grid x $page.ldiff -sticky w
11362 ${NS}::checkbutton $page.lattr -text [mc "Support per-file encodings"] \
11363 -variable perfile_attrs
11364 grid x $page.lattr -sticky w
11365
11366 ${NS}::entry $page.extdifft -textvariable extdifftool
11367 ${NS}::frame $page.extdifff
11368 ${NS}::label $page.extdifff.l -text [mc "External diff tool" ]
11369 ${NS}::button $page.extdifff.b -text [mc "Choose..."] -command choose_extdiff
11370 pack $page.extdifff.l $page.extdifff.b -side left
11371 pack configure $page.extdifff.l -padx 10
11372 grid x $page.extdifff $page.extdifft -sticky ew
11373
11374 ${NS}::label $page.lgen -text [mc "General options"]
11375 grid $page.lgen - -sticky w -pady 10
11376 ${NS}::checkbutton $page.want_ttk -variable want_ttk \
11377 -text [mc "Use themed widgets"]
11378 if {$have_ttk} {
11379 ${NS}::label $page.ttk_note -text [mc "(change requires restart)"]
11380 } else {
11381 ${NS}::label $page.ttk_note -text [mc "(currently unavailable)"]
11382 }
11383 grid x $page.want_ttk $page.ttk_note -sticky w
11384 return $page
11385}
11386
11387proc prefspage_colors {notebook} {
11388 global NS uicolor bgcolor fgcolor ctext diffcolors selectbgcolor markbgcolor
11389
11390 set page [create_prefs_page $notebook.colors]
11391
11392 ${NS}::label $page.cdisp -text [mc "Colors: press to choose"]
11393 grid $page.cdisp - -sticky w -pady 10
11394 label $page.ui -padx 40 -relief sunk -background $uicolor
11395 ${NS}::button $page.uibut -text [mc "Interface"] \
11396 -command [list choosecolor uicolor {} $page.ui [mc "interface"] setui]
11397 grid x $page.uibut $page.ui -sticky w
11398 label $page.bg -padx 40 -relief sunk -background $bgcolor
11399 ${NS}::button $page.bgbut -text [mc "Background"] \
11400 -command [list choosecolor bgcolor {} $page.bg [mc "background"] setbg]
11401 grid x $page.bgbut $page.bg -sticky w
11402 label $page.fg -padx 40 -relief sunk -background $fgcolor
11403 ${NS}::button $page.fgbut -text [mc "Foreground"] \
11404 -command [list choosecolor fgcolor {} $page.fg [mc "foreground"] setfg]
11405 grid x $page.fgbut $page.fg -sticky w
11406 label $page.diffold -padx 40 -relief sunk -background [lindex $diffcolors 0]
11407 ${NS}::button $page.diffoldbut -text [mc "Diff: old lines"] \
11408 -command [list choosecolor diffcolors 0 $page.diffold [mc "diff old lines"] \
11409 [list $ctext tag conf d0 -foreground]]
11410 grid x $page.diffoldbut $page.diffold -sticky w
11411 label $page.diffnew -padx 40 -relief sunk -background [lindex $diffcolors 1]
11412 ${NS}::button $page.diffnewbut -text [mc "Diff: new lines"] \
11413 -command [list choosecolor diffcolors 1 $page.diffnew [mc "diff new lines"] \
11414 [list $ctext tag conf dresult -foreground]]
11415 grid x $page.diffnewbut $page.diffnew -sticky w
11416 label $page.hunksep -padx 40 -relief sunk -background [lindex $diffcolors 2]
11417 ${NS}::button $page.hunksepbut -text [mc "Diff: hunk header"] \
11418 -command [list choosecolor diffcolors 2 $page.hunksep \
11419 [mc "diff hunk header"] \
11420 [list $ctext tag conf hunksep -foreground]]
11421 grid x $page.hunksepbut $page.hunksep -sticky w
11422 label $page.markbgsep -padx 40 -relief sunk -background $markbgcolor
11423 ${NS}::button $page.markbgbut -text [mc "Marked line bg"] \
11424 -command [list choosecolor markbgcolor {} $page.markbgsep \
11425 [mc "marked line background"] \
11426 [list $ctext tag conf omark -background]]
11427 grid x $page.markbgbut $page.markbgsep -sticky w
11428 label $page.selbgsep -padx 40 -relief sunk -background $selectbgcolor
11429 ${NS}::button $page.selbgbut -text [mc "Select bg"] \
11430 -command [list choosecolor selectbgcolor {} $page.selbgsep [mc "background"] setselbg]
11431 grid x $page.selbgbut $page.selbgsep -sticky w
11432 return $page
11433}
11434
11435proc prefspage_fonts {notebook} {
11436 global NS
11437 set page [create_prefs_page $notebook.fonts]
11438 ${NS}::label $page.cfont -text [mc "Fonts: press to choose"]
11439 grid $page.cfont - -sticky w -pady 10
11440 mkfontdisp mainfont $page [mc "Main font"]
11441 mkfontdisp textfont $page [mc "Diff display font"]
11442 mkfontdisp uifont $page [mc "User interface font"]
11443 return $page
11444}
11445
Paul Mackerras712fcc02005-11-30 09:28:16 +110011446proc doprefs {} {
Pat Thoytsd93f1712009-04-17 01:24:35 +010011447 global maxwidth maxgraphpct use_ttk NS
Paul Mackerras219ea3a2006-09-07 10:21:39 +100011448 global oldprefs prefstop showneartags showlocalchanges
Guillermo S. Romero5497f7a2009-10-15 18:51:49 +020011449 global uicolor bgcolor fgcolor ctext diffcolors selectbgcolor markbgcolor
Paul Mackerras21ac8a82011-03-09 20:52:38 +110011450 global tabstop limitdiffs autoselect autosellen extdifftool perfile_attrs
Paul Mackerras0cc08ff2009-09-05 22:06:46 +100011451 global hideremotes want_ttk have_ttk
Paul Mackerras232475d2005-11-15 10:34:03 +110011452
Paul Mackerras712fcc02005-11-30 09:28:16 +110011453 set top .gitkprefs
11454 set prefstop $top
11455 if {[winfo exists $top]} {
11456 raise $top
11457 return
Paul Mackerras757f17b2005-11-21 09:56:07 +110011458 }
Paul Mackerras3de07112007-10-23 22:40:50 +100011459 foreach v {maxwidth maxgraphpct showneartags showlocalchanges \
Paul Mackerras0cc08ff2009-09-05 22:06:46 +100011460 limitdiffs tabstop perfile_attrs hideremotes want_ttk} {
Paul Mackerras712fcc02005-11-30 09:28:16 +110011461 set oldprefs($v) [set $v]
Paul Mackerras232475d2005-11-15 10:34:03 +110011462 }
Pat Thoytsd93f1712009-04-17 01:24:35 +010011463 ttk_toplevel $top
Christian Stimmingd990ced2007-11-07 18:42:55 +010011464 wm title $top [mc "Gitk preferences"]
Alexander Gavrilove7d64002008-11-11 23:55:42 +030011465 make_transient $top .
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +100011466
Pat Thoyts44acce02011-12-13 14:56:49 +000011467 if {[set use_notebook [expr {$use_ttk && [info command ::ttk::notebook] ne ""}]]} {
11468 set notebook [ttk::notebook $top.notebook]
Paul Mackerras0cc08ff2009-09-05 22:06:46 +100011469 } else {
Pat Thoyts44acce02011-12-13 14:56:49 +000011470 set notebook [${NS}::frame $top.notebook -borderwidth 0 -relief flat]
Paul Mackerras0cc08ff2009-09-05 22:06:46 +100011471 }
Paul Mackerras0cc08ff2009-09-05 22:06:46 +100011472
Pat Thoyts44acce02011-12-13 14:56:49 +000011473 lappend pages [prefspage_general $notebook] [mc "General"]
11474 lappend pages [prefspage_colors $notebook] [mc "Colors"]
11475 lappend pages [prefspage_fonts $notebook] [mc "Fonts"]
Pat Thoyts28cb7072012-04-01 23:00:51 +010011476 set col 0
Pat Thoyts44acce02011-12-13 14:56:49 +000011477 foreach {page title} $pages {
11478 if {$use_notebook} {
11479 $notebook add $page -text $title
11480 } else {
11481 set btn [${NS}::button $notebook.b_[string map {. X} $page] \
11482 -text $title -command [list raise $page]]
11483 $page configure -text $title
11484 grid $btn -row 0 -column [incr col] -sticky w
11485 grid $page -row 1 -column 0 -sticky news -columnspan 100
11486 }
11487 }
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +100011488
Pat Thoyts44acce02011-12-13 14:56:49 +000011489 if {!$use_notebook} {
11490 grid columnconfigure $notebook 0 -weight 1
11491 grid rowconfigure $notebook 1 -weight 1
11492 raise [lindex $pages 0]
11493 }
11494
11495 grid $notebook -sticky news -padx 2 -pady 2
11496 grid rowconfigure $top 0 -weight 1
11497 grid columnconfigure $top 0 -weight 1
Paul Mackerras9a7558f2007-10-06 20:16:06 +100011498
Pat Thoytsd93f1712009-04-17 01:24:35 +010011499 ${NS}::frame $top.buts
11500 ${NS}::button $top.buts.ok -text [mc "OK"] -command prefsok -default active
11501 ${NS}::button $top.buts.can -text [mc "Cancel"] -command prefscan -default normal
Alexander Gavrilov76f15942008-11-02 21:59:44 +030011502 bind $top <Key-Return> prefsok
11503 bind $top <Key-Escape> prefscan
Paul Mackerras712fcc02005-11-30 09:28:16 +110011504 grid $top.buts.ok $top.buts.can
11505 grid columnconfigure $top.buts 0 -weight 1 -uniform a
11506 grid columnconfigure $top.buts 1 -weight 1 -uniform a
11507 grid $top.buts - - -pady 10 -sticky ew
Pat Thoytsd93f1712009-04-17 01:24:35 +010011508 grid columnconfigure $top 2 -weight 1
Pat Thoyts44acce02011-12-13 14:56:49 +000011509 bind $top <Visibility> [list focus $top.buts.ok]
Paul Mackerras712fcc02005-11-30 09:28:16 +110011510}
11511
Thomas Arcila314f5de2008-03-24 12:55:36 +010011512proc choose_extdiff {} {
11513 global extdifftool
11514
Michele Ballabiob56e0a92009-03-30 21:17:25 +020011515 set prog [tk_getOpenFile -title [mc "External diff tool"] -multiple false]
Thomas Arcila314f5de2008-03-24 12:55:36 +010011516 if {$prog ne {}} {
11517 set extdifftool $prog
11518 }
11519}
11520
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +100011521proc choosecolor {v vi w x cmd} {
11522 global $v
11523
11524 set c [tk_chooseColor -initialcolor [lindex [set $v] $vi] \
Christian Stimmingd990ced2007-11-07 18:42:55 +010011525 -title [mc "Gitk: choose color for %s" $x]]
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +100011526 if {$c eq {}} return
11527 $w conf -background $c
11528 lset $v $vi $c
11529 eval $cmd $c
11530}
11531
Mark Levedahl60378c02007-05-20 12:12:48 -040011532proc setselbg {c} {
11533 global bglist cflist
11534 foreach w $bglist {
11535 $w configure -selectbackground $c
11536 }
11537 $cflist tag configure highlight \
11538 -background [$cflist cget -selectbackground]
11539 allcanvs itemconf secsel -fill $c
11540}
11541
Paul Mackerras51a7e8b2009-11-14 21:15:01 +110011542# This sets the background color and the color scheme for the whole UI.
11543# For some reason, tk_setPalette chooses a nasty dark red for selectColor
11544# if we don't specify one ourselves, which makes the checkbuttons and
11545# radiobuttons look bad. This chooses white for selectColor if the
11546# background color is light, or black if it is dark.
Guillermo S. Romero5497f7a2009-10-15 18:51:49 +020011547proc setui {c} {
Pat Thoyts2e58c942010-03-12 18:31:47 +000011548 if {[tk windowingsystem] eq "win32"} { return }
Paul Mackerras51a7e8b2009-11-14 21:15:01 +110011549 set bg [winfo rgb . $c]
11550 set selc black
11551 if {[lindex $bg 0] + 1.5 * [lindex $bg 1] + 0.5 * [lindex $bg 2] > 100000} {
11552 set selc white
11553 }
11554 tk_setPalette background $c selectColor $selc
Guillermo S. Romero5497f7a2009-10-15 18:51:49 +020011555}
11556
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +100011557proc setbg {c} {
11558 global bglist
11559
11560 foreach w $bglist {
11561 $w conf -background $c
11562 }
11563}
11564
11565proc setfg {c} {
11566 global fglist canv
11567
11568 foreach w $fglist {
11569 $w conf -foreground $c
11570 }
11571 allcanvs itemconf text -fill $c
11572 $canv itemconf circle -outline $c
Paul Mackerrasb9fdba72009-04-09 09:34:46 +100011573 $canv itemconf markid -outline $c
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +100011574}
11575
Paul Mackerras712fcc02005-11-30 09:28:16 +110011576proc prefscan {} {
Paul Mackerras94503912007-10-23 10:33:38 +100011577 global oldprefs prefstop
Paul Mackerras712fcc02005-11-30 09:28:16 +110011578
Paul Mackerras3de07112007-10-23 22:40:50 +100011579 foreach v {maxwidth maxgraphpct showneartags showlocalchanges \
Paul Mackerras0cc08ff2009-09-05 22:06:46 +100011580 limitdiffs tabstop perfile_attrs hideremotes want_ttk} {
Paul Mackerras94503912007-10-23 10:33:38 +100011581 global $v
Paul Mackerras712fcc02005-11-30 09:28:16 +110011582 set $v $oldprefs($v)
11583 }
11584 catch {destroy $prefstop}
11585 unset prefstop
Paul Mackerras9a7558f2007-10-06 20:16:06 +100011586 fontcan
Paul Mackerras712fcc02005-11-30 09:28:16 +110011587}
11588
11589proc prefsok {} {
11590 global maxwidth maxgraphpct
Paul Mackerras219ea3a2006-09-07 10:21:39 +100011591 global oldprefs prefstop showneartags showlocalchanges
Paul Mackerras9a7558f2007-10-06 20:16:06 +100011592 global fontpref mainfont textfont uifont
Paul Mackerras39ee47e2008-10-15 22:23:03 +110011593 global limitdiffs treediffs perfile_attrs
Thomas Rastffe15292009-08-03 23:53:36 +020011594 global hideremotes
Paul Mackerras712fcc02005-11-30 09:28:16 +110011595
11596 catch {destroy $prefstop}
11597 unset prefstop
Paul Mackerras9a7558f2007-10-06 20:16:06 +100011598 fontcan
11599 set fontchanged 0
11600 if {$mainfont ne $fontpref(mainfont)} {
11601 set mainfont $fontpref(mainfont)
11602 parsefont mainfont $mainfont
11603 eval font configure mainfont [fontflags mainfont]
11604 eval font configure mainfontbold [fontflags mainfont 1]
11605 setcoords
11606 set fontchanged 1
11607 }
11608 if {$textfont ne $fontpref(textfont)} {
11609 set textfont $fontpref(textfont)
11610 parsefont textfont $textfont
11611 eval font configure textfont [fontflags textfont]
11612 eval font configure textfontbold [fontflags textfont 1]
11613 }
11614 if {$uifont ne $fontpref(uifont)} {
11615 set uifont $fontpref(uifont)
11616 parsefont uifont $uifont
11617 eval font configure uifont [fontflags uifont]
11618 }
Paul Mackerras32f1b3e2007-09-28 21:27:39 +100011619 settabs
Paul Mackerras219ea3a2006-09-07 10:21:39 +100011620 if {$showlocalchanges != $oldprefs(showlocalchanges)} {
11621 if {$showlocalchanges} {
11622 doshowlocalchanges
11623 } else {
11624 dohidelocalchanges
11625 }
11626 }
Paul Mackerras39ee47e2008-10-15 22:23:03 +110011627 if {$limitdiffs != $oldprefs(limitdiffs) ||
11628 ($perfile_attrs && !$oldprefs(perfile_attrs))} {
11629 # treediffs elements are limited by path;
11630 # won't have encodings cached if perfile_attrs was just turned on
Paul Mackerras74a40c72007-10-24 10:16:56 +100011631 catch {unset treediffs}
11632 }
Paul Mackerras9a7558f2007-10-06 20:16:06 +100011633 if {$fontchanged || $maxwidth != $oldprefs(maxwidth)
Paul Mackerras712fcc02005-11-30 09:28:16 +110011634 || $maxgraphpct != $oldprefs(maxgraphpct)} {
11635 redisplay
Paul Mackerras7a39a172007-10-23 10:15:11 +100011636 } elseif {$showneartags != $oldprefs(showneartags) ||
11637 $limitdiffs != $oldprefs(limitdiffs)} {
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +100011638 reselectline
Paul Mackerras712fcc02005-11-30 09:28:16 +110011639 }
Thomas Rastffe15292009-08-03 23:53:36 +020011640 if {$hideremotes != $oldprefs(hideremotes)} {
11641 rereadrefs
11642 }
Paul Mackerras712fcc02005-11-30 09:28:16 +110011643}
11644
11645proc formatdate {d} {
Arjen Laarhovene8b5f4b2007-08-14 22:02:04 +020011646 global datetimeformat
Paul Mackerras219ea3a2006-09-07 10:21:39 +100011647 if {$d ne {}} {
Anders Kaseorg019e1632014-05-12 07:25:58 -040011648 # If $datetimeformat includes a timezone, display in the
11649 # timezone of the argument. Otherwise, display in local time.
11650 if {[string match {*%[zZ]*} $datetimeformat]} {
11651 if {[catch {set d [clock format [lindex $d 0] -timezone [lindex $d 1] -format $datetimeformat]}]} {
11652 # Tcl < 8.5 does not support -timezone. Emulate it by
11653 # setting TZ (e.g. TZ=<-0430>+04:30).
11654 global env
11655 if {[info exists env(TZ)]} {
11656 set savedTZ $env(TZ)
11657 }
11658 set zone [lindex $d 1]
11659 set sign [string map {+ - - +} [string index $zone 0]]
11660 set env(TZ) <$zone>$sign[string range $zone 1 2]:[string range $zone 3 4]
11661 set d [clock format [lindex $d 0] -format $datetimeformat]
11662 if {[info exists savedTZ]} {
11663 set env(TZ) $savedTZ
11664 } else {
11665 unset env(TZ)
11666 }
11667 }
11668 } else {
11669 set d [clock format [lindex $d 0] -format $datetimeformat]
11670 }
Paul Mackerras219ea3a2006-09-07 10:21:39 +100011671 }
11672 return $d
Paul Mackerras232475d2005-11-15 10:34:03 +110011673}
11674
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +110011675# This list of encoding names and aliases is distilled from
11676# http://www.iana.org/assignments/character-sets.
11677# Not all of them are supported by Tcl.
11678set encoding_aliases {
11679 { ANSI_X3.4-1968 iso-ir-6 ANSI_X3.4-1986 ISO_646.irv:1991 ASCII
11680 ISO646-US US-ASCII us IBM367 cp367 csASCII }
11681 { ISO-10646-UTF-1 csISO10646UTF1 }
11682 { ISO_646.basic:1983 ref csISO646basic1983 }
11683 { INVARIANT csINVARIANT }
11684 { ISO_646.irv:1983 iso-ir-2 irv csISO2IntlRefVersion }
11685 { BS_4730 iso-ir-4 ISO646-GB gb uk csISO4UnitedKingdom }
11686 { NATS-SEFI iso-ir-8-1 csNATSSEFI }
11687 { NATS-SEFI-ADD iso-ir-8-2 csNATSSEFIADD }
11688 { NATS-DANO iso-ir-9-1 csNATSDANO }
11689 { NATS-DANO-ADD iso-ir-9-2 csNATSDANOADD }
11690 { SEN_850200_B iso-ir-10 FI ISO646-FI ISO646-SE se csISO10Swedish }
11691 { SEN_850200_C iso-ir-11 ISO646-SE2 se2 csISO11SwedishForNames }
11692 { KS_C_5601-1987 iso-ir-149 KS_C_5601-1989 KSC_5601 korean csKSC56011987 }
11693 { ISO-2022-KR csISO2022KR }
11694 { EUC-KR csEUCKR }
11695 { ISO-2022-JP csISO2022JP }
11696 { ISO-2022-JP-2 csISO2022JP2 }
11697 { JIS_C6220-1969-jp JIS_C6220-1969 iso-ir-13 katakana x0201-7
11698 csISO13JISC6220jp }
11699 { JIS_C6220-1969-ro iso-ir-14 jp ISO646-JP csISO14JISC6220ro }
11700 { IT iso-ir-15 ISO646-IT csISO15Italian }
11701 { PT iso-ir-16 ISO646-PT csISO16Portuguese }
11702 { ES iso-ir-17 ISO646-ES csISO17Spanish }
11703 { greek7-old iso-ir-18 csISO18Greek7Old }
11704 { latin-greek iso-ir-19 csISO19LatinGreek }
11705 { DIN_66003 iso-ir-21 de ISO646-DE csISO21German }
11706 { NF_Z_62-010_(1973) iso-ir-25 ISO646-FR1 csISO25French }
11707 { Latin-greek-1 iso-ir-27 csISO27LatinGreek1 }
11708 { ISO_5427 iso-ir-37 csISO5427Cyrillic }
11709 { JIS_C6226-1978 iso-ir-42 csISO42JISC62261978 }
11710 { BS_viewdata iso-ir-47 csISO47BSViewdata }
11711 { INIS iso-ir-49 csISO49INIS }
11712 { INIS-8 iso-ir-50 csISO50INIS8 }
11713 { INIS-cyrillic iso-ir-51 csISO51INISCyrillic }
11714 { ISO_5427:1981 iso-ir-54 ISO5427Cyrillic1981 }
11715 { ISO_5428:1980 iso-ir-55 csISO5428Greek }
11716 { GB_1988-80 iso-ir-57 cn ISO646-CN csISO57GB1988 }
11717 { GB_2312-80 iso-ir-58 chinese csISO58GB231280 }
11718 { NS_4551-1 iso-ir-60 ISO646-NO no csISO60DanishNorwegian
11719 csISO60Norwegian1 }
11720 { NS_4551-2 ISO646-NO2 iso-ir-61 no2 csISO61Norwegian2 }
11721 { NF_Z_62-010 iso-ir-69 ISO646-FR fr csISO69French }
11722 { videotex-suppl iso-ir-70 csISO70VideotexSupp1 }
11723 { PT2 iso-ir-84 ISO646-PT2 csISO84Portuguese2 }
11724 { ES2 iso-ir-85 ISO646-ES2 csISO85Spanish2 }
11725 { MSZ_7795.3 iso-ir-86 ISO646-HU hu csISO86Hungarian }
11726 { JIS_C6226-1983 iso-ir-87 x0208 JIS_X0208-1983 csISO87JISX0208 }
11727 { greek7 iso-ir-88 csISO88Greek7 }
11728 { ASMO_449 ISO_9036 arabic7 iso-ir-89 csISO89ASMO449 }
11729 { iso-ir-90 csISO90 }
11730 { JIS_C6229-1984-a iso-ir-91 jp-ocr-a csISO91JISC62291984a }
11731 { JIS_C6229-1984-b iso-ir-92 ISO646-JP-OCR-B jp-ocr-b
11732 csISO92JISC62991984b }
11733 { JIS_C6229-1984-b-add iso-ir-93 jp-ocr-b-add csISO93JIS62291984badd }
11734 { JIS_C6229-1984-hand iso-ir-94 jp-ocr-hand csISO94JIS62291984hand }
11735 { JIS_C6229-1984-hand-add iso-ir-95 jp-ocr-hand-add
11736 csISO95JIS62291984handadd }
11737 { JIS_C6229-1984-kana iso-ir-96 csISO96JISC62291984kana }
11738 { ISO_2033-1983 iso-ir-98 e13b csISO2033 }
11739 { ANSI_X3.110-1983 iso-ir-99 CSA_T500-1983 NAPLPS csISO99NAPLPS }
11740 { ISO_8859-1:1987 iso-ir-100 ISO_8859-1 ISO-8859-1 latin1 l1 IBM819
11741 CP819 csISOLatin1 }
11742 { ISO_8859-2:1987 iso-ir-101 ISO_8859-2 ISO-8859-2 latin2 l2 csISOLatin2 }
11743 { T.61-7bit iso-ir-102 csISO102T617bit }
11744 { T.61-8bit T.61 iso-ir-103 csISO103T618bit }
11745 { ISO_8859-3:1988 iso-ir-109 ISO_8859-3 ISO-8859-3 latin3 l3 csISOLatin3 }
11746 { ISO_8859-4:1988 iso-ir-110 ISO_8859-4 ISO-8859-4 latin4 l4 csISOLatin4 }
11747 { ECMA-cyrillic iso-ir-111 KOI8-E csISO111ECMACyrillic }
11748 { CSA_Z243.4-1985-1 iso-ir-121 ISO646-CA csa7-1 ca csISO121Canadian1 }
11749 { CSA_Z243.4-1985-2 iso-ir-122 ISO646-CA2 csa7-2 csISO122Canadian2 }
11750 { CSA_Z243.4-1985-gr iso-ir-123 csISO123CSAZ24341985gr }
11751 { ISO_8859-6:1987 iso-ir-127 ISO_8859-6 ISO-8859-6 ECMA-114 ASMO-708
11752 arabic csISOLatinArabic }
11753 { ISO_8859-6-E csISO88596E ISO-8859-6-E }
11754 { ISO_8859-6-I csISO88596I ISO-8859-6-I }
11755 { ISO_8859-7:1987 iso-ir-126 ISO_8859-7 ISO-8859-7 ELOT_928 ECMA-118
11756 greek greek8 csISOLatinGreek }
11757 { T.101-G2 iso-ir-128 csISO128T101G2 }
11758 { ISO_8859-8:1988 iso-ir-138 ISO_8859-8 ISO-8859-8 hebrew
11759 csISOLatinHebrew }
11760 { ISO_8859-8-E csISO88598E ISO-8859-8-E }
11761 { ISO_8859-8-I csISO88598I ISO-8859-8-I }
11762 { CSN_369103 iso-ir-139 csISO139CSN369103 }
11763 { JUS_I.B1.002 iso-ir-141 ISO646-YU js yu csISO141JUSIB1002 }
11764 { ISO_6937-2-add iso-ir-142 csISOTextComm }
11765 { IEC_P27-1 iso-ir-143 csISO143IECP271 }
11766 { ISO_8859-5:1988 iso-ir-144 ISO_8859-5 ISO-8859-5 cyrillic
11767 csISOLatinCyrillic }
11768 { JUS_I.B1.003-serb iso-ir-146 serbian csISO146Serbian }
11769 { JUS_I.B1.003-mac macedonian iso-ir-147 csISO147Macedonian }
11770 { ISO_8859-9:1989 iso-ir-148 ISO_8859-9 ISO-8859-9 latin5 l5 csISOLatin5 }
11771 { greek-ccitt iso-ir-150 csISO150 csISO150GreekCCITT }
11772 { NC_NC00-10:81 cuba iso-ir-151 ISO646-CU csISO151Cuba }
11773 { ISO_6937-2-25 iso-ir-152 csISO6937Add }
11774 { GOST_19768-74 ST_SEV_358-88 iso-ir-153 csISO153GOST1976874 }
11775 { ISO_8859-supp iso-ir-154 latin1-2-5 csISO8859Supp }
11776 { ISO_10367-box iso-ir-155 csISO10367Box }
11777 { ISO-8859-10 iso-ir-157 l6 ISO_8859-10:1992 csISOLatin6 latin6 }
11778 { latin-lap lap iso-ir-158 csISO158Lap }
11779 { JIS_X0212-1990 x0212 iso-ir-159 csISO159JISX02121990 }
11780 { DS_2089 DS2089 ISO646-DK dk csISO646Danish }
11781 { us-dk csUSDK }
11782 { dk-us csDKUS }
11783 { JIS_X0201 X0201 csHalfWidthKatakana }
11784 { KSC5636 ISO646-KR csKSC5636 }
11785 { ISO-10646-UCS-2 csUnicode }
11786 { ISO-10646-UCS-4 csUCS4 }
11787 { DEC-MCS dec csDECMCS }
11788 { hp-roman8 roman8 r8 csHPRoman8 }
11789 { macintosh mac csMacintosh }
11790 { IBM037 cp037 ebcdic-cp-us ebcdic-cp-ca ebcdic-cp-wt ebcdic-cp-nl
11791 csIBM037 }
11792 { IBM038 EBCDIC-INT cp038 csIBM038 }
11793 { IBM273 CP273 csIBM273 }
11794 { IBM274 EBCDIC-BE CP274 csIBM274 }
11795 { IBM275 EBCDIC-BR cp275 csIBM275 }
11796 { IBM277 EBCDIC-CP-DK EBCDIC-CP-NO csIBM277 }
11797 { IBM278 CP278 ebcdic-cp-fi ebcdic-cp-se csIBM278 }
11798 { IBM280 CP280 ebcdic-cp-it csIBM280 }
11799 { IBM281 EBCDIC-JP-E cp281 csIBM281 }
11800 { IBM284 CP284 ebcdic-cp-es csIBM284 }
11801 { IBM285 CP285 ebcdic-cp-gb csIBM285 }
11802 { IBM290 cp290 EBCDIC-JP-kana csIBM290 }
11803 { IBM297 cp297 ebcdic-cp-fr csIBM297 }
11804 { IBM420 cp420 ebcdic-cp-ar1 csIBM420 }
11805 { IBM423 cp423 ebcdic-cp-gr csIBM423 }
11806 { IBM424 cp424 ebcdic-cp-he csIBM424 }
11807 { IBM437 cp437 437 csPC8CodePage437 }
11808 { IBM500 CP500 ebcdic-cp-be ebcdic-cp-ch csIBM500 }
11809 { IBM775 cp775 csPC775Baltic }
11810 { IBM850 cp850 850 csPC850Multilingual }
11811 { IBM851 cp851 851 csIBM851 }
11812 { IBM852 cp852 852 csPCp852 }
11813 { IBM855 cp855 855 csIBM855 }
11814 { IBM857 cp857 857 csIBM857 }
11815 { IBM860 cp860 860 csIBM860 }
11816 { IBM861 cp861 861 cp-is csIBM861 }
11817 { IBM862 cp862 862 csPC862LatinHebrew }
11818 { IBM863 cp863 863 csIBM863 }
11819 { IBM864 cp864 csIBM864 }
11820 { IBM865 cp865 865 csIBM865 }
11821 { IBM866 cp866 866 csIBM866 }
11822 { IBM868 CP868 cp-ar csIBM868 }
11823 { IBM869 cp869 869 cp-gr csIBM869 }
11824 { IBM870 CP870 ebcdic-cp-roece ebcdic-cp-yu csIBM870 }
11825 { IBM871 CP871 ebcdic-cp-is csIBM871 }
11826 { IBM880 cp880 EBCDIC-Cyrillic csIBM880 }
11827 { IBM891 cp891 csIBM891 }
11828 { IBM903 cp903 csIBM903 }
11829 { IBM904 cp904 904 csIBBM904 }
11830 { IBM905 CP905 ebcdic-cp-tr csIBM905 }
11831 { IBM918 CP918 ebcdic-cp-ar2 csIBM918 }
11832 { IBM1026 CP1026 csIBM1026 }
11833 { EBCDIC-AT-DE csIBMEBCDICATDE }
11834 { EBCDIC-AT-DE-A csEBCDICATDEA }
11835 { EBCDIC-CA-FR csEBCDICCAFR }
11836 { EBCDIC-DK-NO csEBCDICDKNO }
11837 { EBCDIC-DK-NO-A csEBCDICDKNOA }
11838 { EBCDIC-FI-SE csEBCDICFISE }
11839 { EBCDIC-FI-SE-A csEBCDICFISEA }
11840 { EBCDIC-FR csEBCDICFR }
11841 { EBCDIC-IT csEBCDICIT }
11842 { EBCDIC-PT csEBCDICPT }
11843 { EBCDIC-ES csEBCDICES }
11844 { EBCDIC-ES-A csEBCDICESA }
11845 { EBCDIC-ES-S csEBCDICESS }
11846 { EBCDIC-UK csEBCDICUK }
11847 { EBCDIC-US csEBCDICUS }
11848 { UNKNOWN-8BIT csUnknown8BiT }
11849 { MNEMONIC csMnemonic }
11850 { MNEM csMnem }
11851 { VISCII csVISCII }
11852 { VIQR csVIQR }
11853 { KOI8-R csKOI8R }
11854 { IBM00858 CCSID00858 CP00858 PC-Multilingual-850+euro }
11855 { IBM00924 CCSID00924 CP00924 ebcdic-Latin9--euro }
11856 { IBM01140 CCSID01140 CP01140 ebcdic-us-37+euro }
11857 { IBM01141 CCSID01141 CP01141 ebcdic-de-273+euro }
11858 { IBM01142 CCSID01142 CP01142 ebcdic-dk-277+euro ebcdic-no-277+euro }
11859 { IBM01143 CCSID01143 CP01143 ebcdic-fi-278+euro ebcdic-se-278+euro }
11860 { IBM01144 CCSID01144 CP01144 ebcdic-it-280+euro }
11861 { IBM01145 CCSID01145 CP01145 ebcdic-es-284+euro }
11862 { IBM01146 CCSID01146 CP01146 ebcdic-gb-285+euro }
11863 { IBM01147 CCSID01147 CP01147 ebcdic-fr-297+euro }
11864 { IBM01148 CCSID01148 CP01148 ebcdic-international-500+euro }
11865 { IBM01149 CCSID01149 CP01149 ebcdic-is-871+euro }
11866 { IBM1047 IBM-1047 }
11867 { PTCP154 csPTCP154 PT154 CP154 Cyrillic-Asian }
11868 { Amiga-1251 Ami1251 Amiga1251 Ami-1251 }
11869 { UNICODE-1-1 csUnicode11 }
11870 { CESU-8 csCESU-8 }
11871 { BOCU-1 csBOCU-1 }
11872 { UNICODE-1-1-UTF-7 csUnicode11UTF7 }
11873 { ISO-8859-14 iso-ir-199 ISO_8859-14:1998 ISO_8859-14 latin8 iso-celtic
11874 l8 }
11875 { ISO-8859-15 ISO_8859-15 Latin-9 }
11876 { ISO-8859-16 iso-ir-226 ISO_8859-16:2001 ISO_8859-16 latin10 l10 }
11877 { GBK CP936 MS936 windows-936 }
11878 { JIS_Encoding csJISEncoding }
Alexander Gavrilov09c70292008-10-13 12:12:31 +040011879 { Shift_JIS MS_Kanji csShiftJIS ShiftJIS Shift-JIS }
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +110011880 { Extended_UNIX_Code_Packed_Format_for_Japanese csEUCPkdFmtJapanese
11881 EUC-JP }
11882 { Extended_UNIX_Code_Fixed_Width_for_Japanese csEUCFixWidJapanese }
11883 { ISO-10646-UCS-Basic csUnicodeASCII }
11884 { ISO-10646-Unicode-Latin1 csUnicodeLatin1 ISO-10646 }
11885 { ISO-Unicode-IBM-1261 csUnicodeIBM1261 }
11886 { ISO-Unicode-IBM-1268 csUnicodeIBM1268 }
11887 { ISO-Unicode-IBM-1276 csUnicodeIBM1276 }
11888 { ISO-Unicode-IBM-1264 csUnicodeIBM1264 }
11889 { ISO-Unicode-IBM-1265 csUnicodeIBM1265 }
11890 { ISO-8859-1-Windows-3.0-Latin-1 csWindows30Latin1 }
11891 { ISO-8859-1-Windows-3.1-Latin-1 csWindows31Latin1 }
11892 { ISO-8859-2-Windows-Latin-2 csWindows31Latin2 }
11893 { ISO-8859-9-Windows-Latin-5 csWindows31Latin5 }
11894 { Adobe-Standard-Encoding csAdobeStandardEncoding }
11895 { Ventura-US csVenturaUS }
11896 { Ventura-International csVenturaInternational }
11897 { PC8-Danish-Norwegian csPC8DanishNorwegian }
11898 { PC8-Turkish csPC8Turkish }
11899 { IBM-Symbols csIBMSymbols }
11900 { IBM-Thai csIBMThai }
11901 { HP-Legal csHPLegal }
11902 { HP-Pi-font csHPPiFont }
11903 { HP-Math8 csHPMath8 }
11904 { Adobe-Symbol-Encoding csHPPSMath }
11905 { HP-DeskTop csHPDesktop }
11906 { Ventura-Math csVenturaMath }
11907 { Microsoft-Publishing csMicrosoftPublishing }
11908 { Windows-31J csWindows31J }
11909 { GB2312 csGB2312 }
11910 { Big5 csBig5 }
11911}
11912
11913proc tcl_encoding {enc} {
Paul Mackerras39ee47e2008-10-15 22:23:03 +110011914 global encoding_aliases tcl_encoding_cache
11915 if {[info exists tcl_encoding_cache($enc)]} {
11916 return $tcl_encoding_cache($enc)
11917 }
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +110011918 set names [encoding names]
11919 set lcnames [string tolower $names]
11920 set enc [string tolower $enc]
11921 set i [lsearch -exact $lcnames $enc]
11922 if {$i < 0} {
11923 # look for "isonnn" instead of "iso-nnn" or "iso_nnn"
Alexander Gavrilov09c70292008-10-13 12:12:31 +040011924 if {[regsub {^(iso|cp|ibm|jis)[-_]} $enc {\1} encx]} {
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +110011925 set i [lsearch -exact $lcnames $encx]
11926 }
11927 }
11928 if {$i < 0} {
11929 foreach l $encoding_aliases {
11930 set ll [string tolower $l]
11931 if {[lsearch -exact $ll $enc] < 0} continue
11932 # look through the aliases for one that tcl knows about
11933 foreach e $ll {
11934 set i [lsearch -exact $lcnames $e]
11935 if {$i < 0} {
Alexander Gavrilov09c70292008-10-13 12:12:31 +040011936 if {[regsub {^(iso|cp|ibm|jis)[-_]} $e {\1} ex]} {
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +110011937 set i [lsearch -exact $lcnames $ex]
11938 }
11939 }
11940 if {$i >= 0} break
11941 }
11942 break
11943 }
11944 }
Paul Mackerras39ee47e2008-10-15 22:23:03 +110011945 set tclenc {}
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +110011946 if {$i >= 0} {
Paul Mackerras39ee47e2008-10-15 22:23:03 +110011947 set tclenc [lindex $names $i]
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +110011948 }
Paul Mackerras39ee47e2008-10-15 22:23:03 +110011949 set tcl_encoding_cache($enc) $tclenc
11950 return $tclenc
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +110011951}
11952
Alexander Gavrilov09c70292008-10-13 12:12:31 +040011953proc gitattr {path attr default} {
Paul Mackerras39ee47e2008-10-15 22:23:03 +110011954 global path_attr_cache
11955 if {[info exists path_attr_cache($attr,$path)]} {
11956 set r $path_attr_cache($attr,$path)
11957 } else {
11958 set r "unspecified"
11959 if {![catch {set line [exec git check-attr $attr -- $path]}]} {
Johannes Sixt097e1112009-07-21 10:09:48 +020011960 regexp "(.*): $attr: (.*)" $line m f r
Alexander Gavrilov09c70292008-10-13 12:12:31 +040011961 }
Alexander Gavrilov4db09302008-10-13 12:12:33 +040011962 set path_attr_cache($attr,$path) $r
Paul Mackerras39ee47e2008-10-15 22:23:03 +110011963 }
11964 if {$r eq "unspecified"} {
11965 return $default
11966 }
11967 return $r
Alexander Gavrilov09c70292008-10-13 12:12:31 +040011968}
11969
Alexander Gavrilov4db09302008-10-13 12:12:33 +040011970proc cache_gitattr {attr pathlist} {
Paul Mackerras39ee47e2008-10-15 22:23:03 +110011971 global path_attr_cache
11972 set newlist {}
11973 foreach path $pathlist {
11974 if {![info exists path_attr_cache($attr,$path)]} {
11975 lappend newlist $path
Alexander Gavrilov4db09302008-10-13 12:12:33 +040011976 }
Paul Mackerras39ee47e2008-10-15 22:23:03 +110011977 }
11978 set lim 1000
11979 if {[tk windowingsystem] == "win32"} {
11980 # windows has a 32k limit on the arguments to a command...
11981 set lim 30
11982 }
11983 while {$newlist ne {}} {
11984 set head [lrange $newlist 0 [expr {$lim - 1}]]
11985 set newlist [lrange $newlist $lim end]
11986 if {![catch {set rlist [eval exec git check-attr $attr -- $head]}]} {
11987 foreach row [split $rlist "\n"] {
Johannes Sixt097e1112009-07-21 10:09:48 +020011988 if {[regexp "(.*): $attr: (.*)" $row m path value]} {
Paul Mackerras39ee47e2008-10-15 22:23:03 +110011989 if {[string index $path 0] eq "\""} {
11990 set path [encoding convertfrom [lindex $path 0]]
11991 }
11992 set path_attr_cache($attr,$path) $value
Alexander Gavrilov4db09302008-10-13 12:12:33 +040011993 }
Paul Mackerras39ee47e2008-10-15 22:23:03 +110011994 }
Alexander Gavrilov4db09302008-10-13 12:12:33 +040011995 }
Paul Mackerras39ee47e2008-10-15 22:23:03 +110011996 }
Alexander Gavrilov4db09302008-10-13 12:12:33 +040011997}
11998
Alexander Gavrilov09c70292008-10-13 12:12:31 +040011999proc get_path_encoding {path} {
Paul Mackerras39ee47e2008-10-15 22:23:03 +110012000 global gui_encoding perfile_attrs
12001 set tcl_enc $gui_encoding
12002 if {$path ne {} && $perfile_attrs} {
12003 set enc2 [tcl_encoding [gitattr $path encoding $tcl_enc]]
12004 if {$enc2 ne {}} {
12005 set tcl_enc $enc2
Alexander Gavrilov09c70292008-10-13 12:12:31 +040012006 }
Paul Mackerras39ee47e2008-10-15 22:23:03 +110012007 }
12008 return $tcl_enc
Alexander Gavrilov09c70292008-10-13 12:12:31 +040012009}
12010
Paul Mackerras5d7589d2007-10-20 21:21:03 +100012011# First check that Tcl/Tk is recent enough
12012if {[catch {package require Tk 8.4} err]} {
Bernt Hansen8d849952009-11-02 07:41:00 -050012013 show_error {} . "Sorry, gitk cannot run with this version of Tcl/Tk.\n\
12014 Gitk requires at least Tcl/Tk 8.4." list
Paul Mackerras5d7589d2007-10-20 21:21:03 +100012015 exit 1
12016}
12017
Tair Sabirgaliev76bf6ff2013-04-24 15:48:27 +060012018# on OSX bring the current Wish process window to front
12019if {[tk windowingsystem] eq "aqua"} {
12020 exec osascript -e [format {
12021 tell application "System Events"
12022 set frontmost of processes whose unix id is %d to true
12023 end tell
12024 } [pid] ]
12025}
12026
Aske Olsson0ae10352012-05-10 12:13:43 +020012027# Unset GIT_TRACE var if set
12028if { [info exists ::env(GIT_TRACE)] } {
12029 unset ::env(GIT_TRACE)
12030}
12031
Paul Mackerras1d10f362005-05-15 12:55:47 +000012032# defaults...
Chris Packhame203d1d2014-11-02 21:37:50 +130012033set wrcomcmd "git diff-tree --stdin -p --pretty=email"
Junio C Hamano671bc152005-11-27 16:12:51 -080012034
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +110012035set gitencoding {}
Junio C Hamano671bc152005-11-27 16:12:51 -080012036catch {
Paul Mackerras27cb61c2007-02-15 08:54:34 +110012037 set gitencoding [exec git config --get i18n.commitencoding]
Junio C Hamano671bc152005-11-27 16:12:51 -080012038}
Alexander Gavrilov590915d2008-11-09 18:06:07 +030012039catch {
12040 set gitencoding [exec git config --get i18n.logoutputencoding]
12041}
Junio C Hamano671bc152005-11-27 16:12:51 -080012042if {$gitencoding == ""} {
Paul Mackerrasfd8ccbe2005-12-07 23:28:22 +110012043 set gitencoding "utf-8"
12044}
12045set tclencoding [tcl_encoding $gitencoding]
12046if {$tclencoding == {}} {
12047 puts stderr "Warning: encoding $gitencoding is not supported by Tcl/Tk"
Junio C Hamano671bc152005-11-27 16:12:51 -080012048}
Paul Mackerras1d10f362005-05-15 12:55:47 +000012049
Alexander Gavrilov09c70292008-10-13 12:12:31 +040012050set gui_encoding [encoding system]
12051catch {
Paul Mackerras39ee47e2008-10-15 22:23:03 +110012052 set enc [exec git config --get gui.encoding]
12053 if {$enc ne {}} {
12054 set tclenc [tcl_encoding $enc]
12055 if {$tclenc ne {}} {
12056 set gui_encoding $tclenc
12057 } else {
12058 puts stderr "Warning: encoding $enc is not supported by Tcl/Tk"
12059 }
12060 }
Alexander Gavrilov09c70292008-10-13 12:12:31 +040012061}
12062
Marcus Karlssonb2b76d12011-10-04 22:08:13 +020012063set log_showroot true
12064catch {
12065 set log_showroot [exec git config --bool --get log.showroot]
12066}
12067
Daniel A. Steffen5fdcbb12009-03-23 12:17:38 +010012068if {[tk windowingsystem] eq "aqua"} {
12069 set mainfont {{Lucida Grande} 9}
12070 set textfont {Monaco 9}
12071 set uifont {{Lucida Grande} 9 bold}
Jonathan Nieder5c9096f2012-03-08 06:30:11 -060012072} elseif {![catch {::tk::pkgconfig get fontsystem} xft] && $xft eq "xft"} {
12073 # fontconfig!
12074 set mainfont {sans 9}
12075 set textfont {monospace 9}
12076 set uifont {sans 9 bold}
Daniel A. Steffen5fdcbb12009-03-23 12:17:38 +010012077} else {
12078 set mainfont {Helvetica 9}
12079 set textfont {Courier 9}
12080 set uifont {Helvetica 9 bold}
12081}
Mark Levedahl7e12f1a2007-05-20 11:45:50 -040012082set tabstop 8
Paul Mackerrasb74fd572005-07-16 07:46:13 -040012083set findmergefiles 0
Paul Mackerras8d858d12005-08-05 09:52:16 +100012084set maxgraphpct 50
Paul Mackerrasf6075eb2005-08-18 09:30:10 +100012085set maxwidth 16
Paul Mackerras232475d2005-11-15 10:34:03 +110012086set revlistorder 0
Paul Mackerras757f17b2005-11-21 09:56:07 +110012087set fastdate 0
Paul Mackerras6e8c8702007-07-31 21:03:06 +100012088set uparrowlen 5
12089set downarrowlen 5
12090set mingaplen 100
Paul Mackerrasf8b28a42006-05-01 09:50:57 +100012091set cmitmode "patch"
Sergey Vlasovf1b86292006-05-15 19:13:14 +040012092set wrapcomment "none"
Paul Mackerrasb8ab2e12006-06-03 19:11:13 +100012093set showneartags 1
Thomas Rastffe15292009-08-03 23:53:36 +020012094set hideremotes 0
Paul Mackerras0a4dd8b2007-06-16 21:21:57 +100012095set maxrefs 20
Max Kirillovbde4a0f2014-06-24 08:19:44 +030012096set visiblerefs {"master"}
Paul Mackerras322a8cc2006-10-15 18:03:46 +100012097set maxlinelen 200
Paul Mackerras219ea3a2006-09-07 10:21:39 +100012098set showlocalchanges 1
Paul Mackerras7a39a172007-10-23 10:15:11 +100012099set limitdiffs 1
Arjen Laarhovene8b5f4b2007-08-14 22:02:04 +020012100set datetimeformat "%Y-%m-%d %H:%M:%S"
Jeff King95293b52008-03-06 06:49:25 -050012101set autoselect 1
Paul Mackerras21ac8a82011-03-09 20:52:38 +110012102set autosellen 40
Paul Mackerras39ee47e2008-10-15 22:23:03 +110012103set perfile_attrs 0
Paul Mackerras0cc08ff2009-09-05 22:06:46 +100012104set want_ttk 1
Paul Mackerras1d10f362005-05-15 12:55:47 +000012105
Daniel A. Steffen5fdcbb12009-03-23 12:17:38 +010012106if {[tk windowingsystem] eq "aqua"} {
12107 set extdifftool "opendiff"
12108} else {
12109 set extdifftool "meld"
12110}
Thomas Arcila314f5de2008-03-24 12:55:36 +010012111
Paul Mackerras1d10f362005-05-15 12:55:47 +000012112set colors {green red blue magenta darkgrey brown orange}
Pat Thoyts1924d1b2009-11-06 23:28:01 +000012113if {[tk windowingsystem] eq "win32"} {
12114 set uicolor SystemButtonFace
Gauthier Östervall252c52d2013-03-27 14:40:51 +010012115 set uifgcolor SystemButtonText
12116 set uifgdisabledcolor SystemDisabledText
Pat Thoyts1924d1b2009-11-06 23:28:01 +000012117 set bgcolor SystemWindow
Gauthier Östervall252c52d2013-03-27 14:40:51 +010012118 set fgcolor SystemWindowText
Pat Thoyts1924d1b2009-11-06 23:28:01 +000012119 set selectbgcolor SystemHighlight
12120} else {
12121 set uicolor grey85
Gauthier Östervall252c52d2013-03-27 14:40:51 +010012122 set uifgcolor black
12123 set uifgdisabledcolor "#999"
Pat Thoyts1924d1b2009-11-06 23:28:01 +000012124 set bgcolor white
12125 set fgcolor black
12126 set selectbgcolor gray85
12127}
Paul Mackerrasf8a2c0d2006-07-05 22:56:37 +100012128set diffcolors {red "#00a000" blue}
Steffen Prohaska890fae72007-08-12 12:05:46 +020012129set diffcontext 3
Gauthier Östervall252c52d2013-03-27 14:40:51 +010012130set mergecolors {red blue green purple brown "#009090" magenta "#808000" "#009000" "#ff0080" cyan "#b07070" "#70b0f0" "#70f0b0" "#f0b070" "#ff70b0"}
Steffen Prohaskab9b86002008-01-17 23:42:55 +010012131set ignorespace 0
Thomas Rastae4e3ff2010-10-16 12:15:10 +020012132set worddiff ""
Paul Mackerrase3e901b2008-10-27 22:37:21 +110012133set markbgcolor "#e0e0ff"
Paul Mackerras1d10f362005-05-15 12:55:47 +000012134
Gauthier Östervall252c52d2013-03-27 14:40:51 +010012135set headbgcolor green
12136set headfgcolor black
12137set headoutlinecolor black
12138set remotebgcolor #ffddaa
12139set tagbgcolor yellow
12140set tagfgcolor black
12141set tagoutlinecolor black
12142set reflinecolor black
12143set filesepbgcolor #aaaaaa
12144set filesepfgcolor black
12145set linehoverbgcolor #ffff80
12146set linehoverfgcolor black
12147set linehoveroutlinecolor black
12148set mainheadcirclecolor yellow
12149set workingfilescirclecolor red
12150set indexcirclecolor green
Paul Mackerrasc11ff122008-05-26 10:11:33 +100012151set circlecolors {white blue gray blue blue}
Gauthier Östervall252c52d2013-03-27 14:40:51 +010012152set linkfgcolor blue
12153set circleoutlinecolor $fgcolor
12154set foundbgcolor yellow
12155set currentsearchhitbgcolor orange
Paul Mackerrasc11ff122008-05-26 10:11:33 +100012156
Paul Mackerrasd277e892008-09-21 18:11:37 -050012157# button for popping up context menus
12158if {[tk windowingsystem] eq "aqua"} {
12159 set ctxbut <Button-2>
12160} else {
12161 set ctxbut <Button-3>
12162}
12163
Christian Stimming663c3aa2007-11-07 18:40:59 +010012164## For msgcat loading, first locate the installation location.
12165if { [info exists ::env(GITK_MSGSDIR)] } {
12166 ## Msgsdir was manually set in the environment.
12167 set gitk_msgsdir $::env(GITK_MSGSDIR)
12168} else {
12169 ## Let's guess the prefix from argv0.
12170 set gitk_prefix [file dirname [file dirname [file normalize $argv0]]]
12171 set gitk_libdir [file join $gitk_prefix share gitk lib]
12172 set gitk_msgsdir [file join $gitk_libdir msgs]
12173 unset gitk_prefix
12174}
12175
12176## Internationalization (i18n) through msgcat and gettext. See
12177## http://www.gnu.org/software/gettext/manual/html_node/Tcl.html
12178package require msgcat
12179namespace import ::msgcat::mc
12180## And eventually load the actual message catalog
12181::msgcat::mcload $gitk_msgsdir
12182
Astril Hayato8f863392014-01-21 19:10:16 +000012183catch {
12184 # follow the XDG base directory specification by default. See
12185 # http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html
12186 if {[info exists env(XDG_CONFIG_HOME)] && $env(XDG_CONFIG_HOME) ne ""} {
12187 # XDG_CONFIG_HOME environment variable is set
12188 set config_file [file join $env(XDG_CONFIG_HOME) git gitk]
12189 set config_file_tmp [file join $env(XDG_CONFIG_HOME) git gitk-tmp]
12190 } else {
12191 # default XDG_CONFIG_HOME
12192 set config_file "~/.config/git/gitk"
12193 set config_file_tmp "~/.config/git/gitk-tmp"
12194 }
12195 if {![file exists $config_file]} {
12196 # for backward compatibility use the old config file if it exists
12197 if {[file exists "~/.gitk"]} {
12198 set config_file "~/.gitk"
12199 set config_file_tmp "~/.gitk-tmp"
12200 } elseif {![file exists [file dirname $config_file]]} {
12201 file mkdir [file dirname $config_file]
12202 }
12203 }
12204 source $config_file
12205}
Max Kirilloveaf7e832015-03-04 05:58:18 +020012206config_check_tmp_exists 50
Paul Mackerras1d10f362005-05-15 12:55:47 +000012207
Max Kirillov9fabefb2014-09-14 23:35:57 +030012208set config_variables {
12209 mainfont textfont uifont tabstop findmergefiles maxgraphpct maxwidth
12210 cmitmode wrapcomment autoselect autosellen showneartags maxrefs visiblerefs
12211 hideremotes showlocalchanges datetimeformat limitdiffs uicolor want_ttk
12212 bgcolor fgcolor uifgcolor uifgdisabledcolor colors diffcolors mergecolors
12213 markbgcolor diffcontext selectbgcolor foundbgcolor currentsearchhitbgcolor
12214 extdifftool perfile_attrs headbgcolor headfgcolor headoutlinecolor
12215 remotebgcolor tagbgcolor tagfgcolor tagoutlinecolor reflinecolor
12216 filesepbgcolor filesepfgcolor linehoverbgcolor linehoverfgcolor
12217 linehoveroutlinecolor mainheadcirclecolor workingfilescirclecolor
12218 indexcirclecolor circlecolors linkfgcolor circleoutlinecolor
12219}
Max Kirillov995f7922015-03-04 05:58:16 +020012220foreach var $config_variables {
12221 config_init_trace $var
12222 trace add variable $var write config_variable_change_cb
12223}
Max Kirillov9fabefb2014-09-14 23:35:57 +030012224
Paul Mackerras0ed1dd32007-10-06 18:27:37 +100012225parsefont mainfont $mainfont
12226eval font create mainfont [fontflags mainfont]
12227eval font create mainfontbold [fontflags mainfont 1]
12228
12229parsefont textfont $textfont
12230eval font create textfont [fontflags textfont]
12231eval font create textfontbold [fontflags textfont 1]
12232
12233parsefont uifont $uifont
12234eval font create uifont [fontflags uifont]
Paul Mackerras17386062005-05-18 22:51:00 +000012235
Paul Mackerras51a7e8b2009-11-14 21:15:01 +110012236setui $uicolor
Guillermo S. Romero5497f7a2009-10-15 18:51:49 +020012237
Paul Mackerrasb039f0a2008-01-06 15:54:46 +110012238setoptions
12239
Paul Mackerrasaa81d972006-02-28 11:27:12 +110012240# check that we can find a .git directory somewhere...
Martin von Zweigbergk86e847b2011-04-04 22:14:18 -040012241if {[catch {set gitdir [exec git rev-parse --git-dir]}]} {
Christian Stimmingd990ced2007-11-07 18:42:55 +010012242 show_error {} . [mc "Cannot find a git repository here."]
Alex Riesen6c87d602007-07-29 22:29:45 +020012243 exit 1
12244}
Paul Mackerrasaa81d972006-02-28 11:27:12 +110012245
Alexander Gavrilov39816d62008-08-23 12:27:44 +040012246set selecthead {}
12247set selectheadid {}
12248
Paul Mackerrascdaee5d2007-07-12 22:29:49 +100012249set revtreeargs {}
Paul Mackerras098dd8a2006-05-03 09:32:53 +100012250set cmdline_files {}
Paul Mackerrascdaee5d2007-07-12 22:29:49 +100012251set i 0
Yann Dirson2d480852008-02-21 21:23:31 +010012252set revtreeargscmd {}
Paul Mackerrascdaee5d2007-07-12 22:29:49 +100012253foreach arg $argv {
Yann Dirson2d480852008-02-21 21:23:31 +010012254 switch -glob -- $arg {
Paul Mackerras6ebedab2007-07-13 13:45:55 +100012255 "" { }
Paul Mackerrascdaee5d2007-07-12 22:29:49 +100012256 "--" {
12257 set cmdline_files [lrange $argv [expr {$i + 1}] end]
12258 break
12259 }
Alexander Gavrilov39816d62008-08-23 12:27:44 +040012260 "--select-commit=*" {
12261 set selecthead [string range $arg 16 end]
12262 }
Yann Dirson2d480852008-02-21 21:23:31 +010012263 "--argscmd=*" {
12264 set revtreeargscmd [string range $arg 10 end]
12265 }
Paul Mackerrascdaee5d2007-07-12 22:29:49 +100012266 default {
12267 lappend revtreeargs $arg
12268 }
12269 }
12270 incr i
12271}
12272
Alexander Gavrilov39816d62008-08-23 12:27:44 +040012273if {$selecthead eq "HEAD"} {
12274 set selecthead {}
12275}
12276
Paul Mackerrascdaee5d2007-07-12 22:29:49 +100012277if {$i >= [llength $argv] && $revtreeargs ne {}} {
Paul Mackerras3ed31a82008-04-26 16:00:00 +100012278 # no -- on command line, but some arguments (other than --argscmd)
Paul Mackerras098dd8a2006-05-03 09:32:53 +100012279 if {[catch {
Timo Hirvonen8974c6f2006-05-24 10:57:40 +030012280 set f [eval exec git rev-parse --no-revs --no-flags $revtreeargs]
Paul Mackerras098dd8a2006-05-03 09:32:53 +100012281 set cmdline_files [split $f "\n"]
12282 set n [llength $cmdline_files]
12283 set revtreeargs [lrange $revtreeargs 0 end-$n]
Paul Mackerrascdaee5d2007-07-12 22:29:49 +100012284 # Unfortunately git rev-parse doesn't produce an error when
12285 # something is both a revision and a filename. To be consistent
12286 # with git log and git rev-list, check revtreeargs for filenames.
12287 foreach arg $revtreeargs {
12288 if {[file exists $arg]} {
Christian Stimmingd990ced2007-11-07 18:42:55 +010012289 show_error {} . [mc "Ambiguous argument '%s': both revision\
12290 and filename" $arg]
Paul Mackerrascdaee5d2007-07-12 22:29:49 +100012291 exit 1
12292 }
12293 }
Paul Mackerras098dd8a2006-05-03 09:32:53 +100012294 } err]} {
12295 # unfortunately we get both stdout and stderr in $err,
12296 # so look for "fatal:".
12297 set i [string first "fatal:" $err]
12298 if {$i > 0} {
Junio C Hamanob5e09632006-05-26 00:07:15 -070012299 set err [string range $err [expr {$i + 6}] end]
Paul Mackerras098dd8a2006-05-03 09:32:53 +100012300 }
Christian Stimmingd990ced2007-11-07 18:42:55 +010012301 show_error {} . "[mc "Bad arguments to gitk:"]\n$err"
Paul Mackerras098dd8a2006-05-03 09:32:53 +100012302 exit 1
12303 }
12304}
12305
Paul Mackerras219ea3a2006-09-07 10:21:39 +100012306set nullid "0000000000000000000000000000000000000000"
Paul Mackerras8f489362007-07-13 19:49:37 +100012307set nullid2 "0000000000000000000000000000000000000001"
Thomas Arcila314f5de2008-03-24 12:55:36 +010012308set nullfile "/dev/null"
Paul Mackerras8f489362007-07-13 19:49:37 +100012309
Paul Mackerras32f1b3e2007-09-28 21:27:39 +100012310set have_tk85 [expr {[package vcompare $tk_version "8.5"] >= 0}]
Paul Mackerras0cc08ff2009-09-05 22:06:46 +100012311if {![info exists have_ttk]} {
12312 set have_ttk [llength [info commands ::ttk::style]]
Pat Thoytsd93f1712009-04-17 01:24:35 +010012313}
Paul Mackerras0cc08ff2009-09-05 22:06:46 +100012314set use_ttk [expr {$have_ttk && $want_ttk}]
Pat Thoytsd93f1712009-04-17 01:24:35 +010012315set NS [expr {$use_ttk ? "ttk" : ""}]
Paul Mackerras0cc08ff2009-09-05 22:06:46 +100012316
Anders Kaseorg7add5af2011-01-06 17:42:33 -070012317regexp {^git version ([\d.]*\d)} [exec git version] _ git_version
Paul Mackerras219ea3a2006-09-07 10:21:39 +100012318
Kirill Smelkov7defefb2010-05-20 13:50:41 +040012319set show_notes {}
12320if {[package vcompare $git_version "1.6.6.2"] >= 0} {
12321 set show_notes "--show-notes"
12322}
12323
Zbigniew Jędrzejewski-Szmek3878e632011-11-09 17:28:28 +010012324set appname "gitk"
12325
Paul Mackerras7eb3cb92007-06-17 14:45:00 +100012326set runq {}
Paul Mackerrasd6982062005-08-06 22:06:06 +100012327set history {}
12328set historyindex 0
Paul Mackerras908c3582006-05-20 09:38:11 +100012329set fh_serial 0
Paul Mackerras908c3582006-05-20 09:38:11 +100012330set nhl_names {}
Paul Mackerras63b79192006-05-20 21:31:52 +100012331set highlight_paths {}
Paul Mackerras687c8762007-09-22 12:49:33 +100012332set findpattern {}
Paul Mackerras1902c272006-05-25 21:25:13 +100012333set searchdirn -forwards
Paul Mackerras28593d32008-11-13 23:01:46 +110012334set boldids {}
12335set boldnameids {}
Paul Mackerrasa8d610a2007-04-19 11:39:12 +100012336set diffelide {0 0}
Paul Mackerras4fb0fa12007-07-04 19:43:51 +100012337set markingmatches 0
Paul Mackerras97645682007-08-23 22:24:38 +100012338set linkentercount 0
Paul Mackerras03800812007-08-29 21:45:21 +100012339set need_redisplay 0
12340set nrows_drawn 0
Paul Mackerras32f1b3e2007-09-28 21:27:39 +100012341set firsttabstop 0
Paul Mackerras9f1afe02006-02-19 22:44:47 +110012342
Paul Mackerras50b44ec2006-04-04 10:16:22 +100012343set nextviewnum 1
12344set curview 0
Paul Mackerrasa90a6d22006-04-25 17:12:46 +100012345set selectedview 0
Christian Stimmingb007ee22007-11-07 18:44:35 +010012346set selectedhlview [mc "None"]
12347set highlight_related [mc "None"]
Paul Mackerras687c8762007-09-22 12:49:33 +100012348set highlight_files {}
Paul Mackerras50b44ec2006-04-04 10:16:22 +100012349set viewfiles(0) {}
Paul Mackerrasa90a6d22006-04-25 17:12:46 +100012350set viewperm(0) 0
Max Kirillov995f7922015-03-04 05:58:16 +020012351set viewchanged(0) 0
Paul Mackerras098dd8a2006-05-03 09:32:53 +100012352set viewargs(0) {}
Yann Dirson2d480852008-02-21 21:23:31 +010012353set viewargscmd(0) {}
Paul Mackerras50b44ec2006-04-04 10:16:22 +100012354
Paul Mackerras94b4a692008-05-20 20:51:06 +100012355set selectedline {}
Paul Mackerras6df74032008-05-11 22:13:02 +100012356set numcommits 0
Paul Mackerras7fcc92b2007-12-03 10:33:01 +110012357set loginstance 0
Paul Mackerras098dd8a2006-05-03 09:32:53 +100012358set cmdlineok 0
Paul Mackerras1d10f362005-05-15 12:55:47 +000012359set stopped 0
Paul Mackerras0fba86b2005-05-16 23:54:58 +000012360set stuffsaved 0
Paul Mackerras74daedb2005-06-27 19:27:32 +100012361set patchnum 0
Paul Mackerras219ea3a2006-09-07 10:21:39 +100012362set lserial 0
Martin von Zweigbergk74cb8842011-05-23 22:44:08 -040012363set hasworktree [hasworktree]
Martin von Zweigbergkc332f442011-04-04 22:14:12 -040012364set cdup {}
Martin von Zweigbergk74cb8842011-05-23 22:44:08 -040012365if {[expr {[exec git rev-parse --is-inside-work-tree] == "true"}]} {
Martin von Zweigbergkc332f442011-04-04 22:14:12 -040012366 set cdup [exec git rev-parse --show-cdup]
12367}
Martin von Zweigbergk784b7e22011-04-04 22:14:15 -040012368set worktree [exec git rev-parse --show-toplevel]
Paul Mackerras1d10f362005-05-15 12:55:47 +000012369setcoords
Paul Mackerrasd94f8cd2006-04-06 10:18:23 +100012370makewindow
Giuseppe Bilotta37871b72009-03-19 01:54:17 -070012371catch {
12372 image create photo gitlogo -width 16 -height 16
12373
12374 image create photo gitlogominus -width 4 -height 2
12375 gitlogominus put #C00000 -to 0 0 4 2
12376 gitlogo copy gitlogominus -to 1 5
12377 gitlogo copy gitlogominus -to 6 5
12378 gitlogo copy gitlogominus -to 11 5
12379 image delete gitlogominus
12380
12381 image create photo gitlogoplus -width 4 -height 4
12382 gitlogoplus put #008000 -to 1 0 3 4
12383 gitlogoplus put #008000 -to 0 1 4 3
12384 gitlogo copy gitlogoplus -to 1 9
12385 gitlogo copy gitlogoplus -to 6 9
12386 gitlogo copy gitlogoplus -to 11 9
12387 image delete gitlogoplus
12388
Stephen Boydd38d7d42009-03-19 01:54:18 -070012389 image create photo gitlogo32 -width 32 -height 32
12390 gitlogo32 copy gitlogo -zoom 2 2
12391
12392 wm iconphoto . -default gitlogo gitlogo32
Giuseppe Bilotta37871b72009-03-19 01:54:17 -070012393}
Paul Mackerras0eafba12007-07-23 21:35:03 +100012394# wait for the window to become visible
12395tkwait visibility .
Zbigniew Jędrzejewski-Szmek3878e632011-11-09 17:28:28 +010012396wm title . "$appname: [reponame]"
Pat Thoyts478afad2009-04-15 17:14:03 +010012397update
Paul Mackerras887fe3c2005-05-21 07:35:37 +000012398readrefs
Paul Mackerrasa8aaf192006-04-23 22:45:55 +100012399
Yann Dirson2d480852008-02-21 21:23:31 +010012400if {$cmdline_files ne {} || $revtreeargs ne {} || $revtreeargscmd ne {}} {
Paul Mackerras50b44ec2006-04-04 10:16:22 +100012401 # create a view for the files/dirs specified on the command line
12402 set curview 1
Paul Mackerrasa90a6d22006-04-25 17:12:46 +100012403 set selectedview 1
Paul Mackerras50b44ec2006-04-04 10:16:22 +100012404 set nextviewnum 2
Christian Stimmingd990ced2007-11-07 18:42:55 +010012405 set viewname(1) [mc "Command line"]
Paul Mackerras50b44ec2006-04-04 10:16:22 +100012406 set viewfiles(1) $cmdline_files
Paul Mackerras098dd8a2006-05-03 09:32:53 +100012407 set viewargs(1) $revtreeargs
Yann Dirson2d480852008-02-21 21:23:31 +010012408 set viewargscmd(1) $revtreeargscmd
Paul Mackerrasa90a6d22006-04-25 17:12:46 +100012409 set viewperm(1) 0
Max Kirillov995f7922015-03-04 05:58:16 +020012410 set viewchanged(1) 0
Paul Mackerras3ed31a82008-04-26 16:00:00 +100012411 set vdatemode(1) 0
Paul Mackerrasda7c24d2006-05-02 11:15:29 +100012412 addviewmenu 1
Paul Mackerrasf2d0bbb2008-10-17 22:44:42 +110012413 .bar.view entryconf [mca "Edit view..."] -state normal
12414 .bar.view entryconf [mca "Delete view"] -state normal
Paul Mackerras50b44ec2006-04-04 10:16:22 +100012415}
Paul Mackerrasa90a6d22006-04-25 17:12:46 +100012416
12417if {[info exists permviews]} {
12418 foreach v $permviews {
12419 set n $nextviewnum
12420 incr nextviewnum
12421 set viewname($n) [lindex $v 0]
12422 set viewfiles($n) [lindex $v 1]
Paul Mackerras098dd8a2006-05-03 09:32:53 +100012423 set viewargs($n) [lindex $v 2]
Yann Dirson2d480852008-02-21 21:23:31 +010012424 set viewargscmd($n) [lindex $v 3]
Paul Mackerrasa90a6d22006-04-25 17:12:46 +100012425 set viewperm($n) 1
Max Kirillov995f7922015-03-04 05:58:16 +020012426 set viewchanged($n) 0
Paul Mackerrasda7c24d2006-05-02 11:15:29 +100012427 addviewmenu $n
Paul Mackerrasa90a6d22006-04-25 17:12:46 +100012428 }
12429}
Johannes Sixte4df5192008-12-18 08:30:49 +010012430
12431if {[tk windowingsystem] eq "win32"} {
12432 focus -force .
12433}
12434
Alexander Gavrilov567c34e2008-07-26 20:13:45 +040012435getcommits {}
Pat Thoytsadab0da2010-03-12 18:31:48 +000012436
12437# Local variables:
12438# mode: tcl
12439# indent-tabs-mode: t
12440# tab-width: 8
12441# End: